List:Commits« Previous MessageNext Message »
From:Øystein Grøvlen Date:August 28 2008 7:20am
Subject:Re: bzr commit into mysql-6.0-backup branch (cbell:2684) WL#4296
View as plain text  
Thank you for addressing my suggestions.  Patch approved.

Chuck Bell wrote:
> #At file:///C:/source/bzr/mysql-6.0-wl-4296/
> 
>  2684 Chuck Bell	2008-08-27
>       WL#4296 : Online Backup : Refine backup progress mechanism
>       
>       PATCH 1 of 2 : Code changes.
>       
>       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:
>   sql/si_logs.cc
>   sql/si_logs.h
> modified:
>   client/mysqldump.c
>   include/mysql_com.h
>   scripts/mysql_system_tables.sql
>   sql/CMakeLists.txt
>   sql/Makefile.am
>   sql/backup/CMakeLists.txt
>   sql/backup/Makefile.am
>   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
> 
> per-file messages:
>   client/mysqldump.c
>     Changed backup log file names (previously known as tables).
>   include/mysql_com.h
>     Added #define for the refresh backup logs flag.
>   scripts/mysql_system_tables.sql
>     Added create statements for the new logs replacing the existing create statements
> for old progress tables.
>   sql/CMakeLists.txt
>     Added new service interface si_logs.
>   sql/Makefile.am
>     Added new service interface si_logs.
>   sql/backup/CMakeLists.txt
>     Removed backup_progress files from cmake file.
>   sql/backup/Makefile.am
>     Removed backup_progress files from make file.
>   sql/backup/backup_kernel.h
>     Removed m_op_id (reference to backup_id). Changed to get the id from the
> Backup_log class.
>   sql/backup/backup_progress.cc
>     Removed file.
>   sql/backup/backup_progress.h
>     Removed file.
>   sql/backup/data_backup.cc
>     Removed reference to deleted header file.
>   sql/backup/kernel.cc
>     Modified call to check backup logs to call the backup log class.
>   sql/backup/logger.cc
>     Added implementation of code changes to call the service interface class
> Backup_log.
>   sql/backup/logger.h
>     Added instance of new service interface class to process the backup log calls. 
>     Changed report_* methods to call new Backup_log class methods.
>   sql/log.cc
>     Added implementation of logging mechanism for backup logs.
>   sql/log.h
>     Added new class and method definitions for the new backup logs. These new methods
> extend the logging functionality to permit reuse of the existing mechanisms for writing
> logs to file or tables or both.
>   sql/mysql_priv.h
>     Added references to the history log 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).
>     --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
>     Added error messages for log file errors.
>   sql/si_logs.cc
>     Added implementation for new service interface of Backup_log class.
>   sql/si_logs.h
>     Added new header file for service interface for the backup logs as supported by
> the server.
>   sql/sql_parse.cc
>     Added command to flush logs.
>   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.
> === modified file 'client/mysqldump.c'
> --- a/client/mysqldump.c	2008-05-29 15:44:11 +0000
> +++ b/client/mysqldump.c	2008-08-27 17:30:49 +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/mysql_com.h'
> --- a/include/mysql_com.h	2008-06-17 20:04:19 +0000
> +++ b/include/mysql_com.h	2008-08-27 17:30:49 +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 'scripts/mysql_system_tables.sql'
> --- a/scripts/mysql_system_tables.sql	2008-08-11 16:06:30 +0000
> +++ b/scripts/mysql_system_tables.sql	2008-08-27 17:30:49 +0000
> @@ -82,12 +82,9 @@ 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 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 validity
 !
>  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 DEFAULT CHARACTER SET utf8;
>  
> -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/time
 !
>  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', drivers VARCHAR (100) COMMENT 'The name of the storage engine
> backup drivers used in the operation') ENGINE=MYISAM DEFAULT CHARACTER SET utf8;
> -
> -
> -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
> DEFAULT CHARACTER SET utf8;
> -
> +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 DEFAULT CHARACTER SET utf8;
>  
>  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/CMakeLists.txt'
> --- a/sql/CMakeLists.txt	2008-07-09 07:12:43 +0000
> +++ b/sql/CMakeLists.txt	2008-08-27 17:30:49 +0000
> @@ -76,7 +76,7 @@ ADD_EXECUTABLE(mysqld
>                 partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc
>                 rpl_rli.cc rpl_mi.cc sql_servers.cc sql_audit.cc
>                 sql_connect.cc scheduler.cc 
> -               ddl_blocker.cc si_objects.cc
> +               ddl_blocker.cc si_objects.cc si_logs.cc
>                 sql_profile.cc event_parse_data.cc mdl.cc
>                 ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
>                 ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
> 
> === modified file 'sql/Makefile.am'
> --- a/sql/Makefile.am	2008-07-09 07:12:43 +0000
> +++ b/sql/Makefile.am	2008-08-27 17:30:49 +0000
> @@ -89,7 +89,7 @@ noinst_HEADERS =	item.h item_func.h item
>  			sql_partition.h partition_info.h partition_element.h \
>  			probes.h sql_audit.h \
>  			contributors.h sql_servers.h ddl_blocker.h \
> -			si_objects.h sql_plist.h mdl.h
> +			si_objects.h si_logs.h sql_plist.h mdl.h
>  
>  mysqld_SOURCES =	sql_lex.cc sql_handler.cc sql_partition.cc \
>  			item.cc item_sum.cc item_buff.cc item_func.cc \
> @@ -135,7 +135,7 @@ mysqld_SOURCES =	sql_lex.cc sql_handler.
>  			sql_plugin.cc sql_binlog.cc \
>  			sql_builtin.cc sql_tablespace.cc partition_info.cc \
>  			sql_servers.cc sql_audit.cc sha2.cc \
> -			ddl_blocker.cc si_objects.cc event_parse_data.cc \
> +			ddl_blocker.cc si_objects.cc si_logs.cc event_parse_data.cc \
>  			mdl.cc
>  
>  if HAVE_DTRACE
> 
> === modified file 'sql/backup/CMakeLists.txt'
> --- a/sql/backup/CMakeLists.txt	2008-05-27 19:47:15 +0000
> +++ b/sql/backup/CMakeLists.txt	2008-08-27 17:30:49 +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-07-07 12:51:56 +0000
> +++ b/sql/backup/Makefile.am	2008-08-27 17:30:49 +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'
> --- a/sql/backup/backup_kernel.h	2008-08-08 17:21:31 +0000
> +++ b/sql/backup/backup_kernel.h	2008-08-27 17:30:49 +0000
> @@ -148,7 +148,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 get_op_id(); // inherited from Logger class
>  }
>  
>  /// Disable foreign key constraint checks (needed during restore).
> 
> === removed file 'sql/backup/backup_progress.cc'
> --- a/sql/backup/backup_progress.cc	2008-07-09 18:37:42 +0000
> +++ b/sql/backup/backup_progress.cc	1970-01-01 00:00:00 +0000
> @@ -1,917 +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", 5, "online_backup", 13,
> -                        "online_backup", TL_READ);
> -  alloc_mdl_locks(&tables, thd->mem_root);
> -  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", 5, "online_backup_progress", 13,
> -                        "online_backup_progress", TL_READ);
> -  alloc_mdl_locks(&tables, thd->mem_root);
> -  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;
> -
> -  alloc_mdl_locks(&table_list, thd->mem_root);
> -
> -  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;
> -
> -  alloc_mdl_locks(&table_list, thd->mem_root);
> -
> -  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_DRIVERS:
> -    {
> -      String str;    // drivers 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;
> -
> -  alloc_mdl_locks(&table_list, thd->mem_root);
> -
> -  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 drivers string for the row that matches the backup_id.
> -
> -   This method updates the drivers 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_drivers(THD *thd,
> -                      ulonglong backup_id,
> -                      const char *driver_name)
> -{
> -  int ret= 0;  // return value
> -  DBUG_ENTER("report_ob_drivers()");
> -
> -  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_DRIVERS, 
> -                                 0, 0, driver_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-07-09 18:37:42 +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_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
> -};
> -
> -/*
> -  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 drivers 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_drivers(THD *thd,
> -                      ulonglong backup_id,
> -                      const char *driver_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-08-11 16:06:30 +0000
> +++ b/sql/backup/data_backup.cc	2008-08-27 17:30:49 +0000
> @@ -29,7 +29,6 @@
>  #include "backup_kernel.h"
>  #include "backup_engine.h"
>  #include "stream.h"
> -#include "backup_progress.h"
>  #include "be_default.h"  // needed for table locking code
>  
>  /***********************************************
> 
> === modified file 'sql/backup/kernel.cc'
> --- a/sql/backup/kernel.cc	2008-08-21 11:36:09 +0000
> +++ b/sql/backup/kernel.cc	2008-08-27 17:30:49 +0000
> @@ -83,7 +83,6 @@
>  #include "be_snapshot.h"
>  #include "be_nodata.h"
>  #include "ddl_blocker.h"
> -#include "backup_progress.h"
>  
>  
>  /** 
> @@ -322,6 +321,7 @@ int send_reply(Backup_restore_ctx &conte
>    // FIXME: detect errors if  reported.
>    // FIXME: error logging.
>    my_eof(context.thd());
> +  context.report_cleanup();
>    DBUG_RETURN(0);
>  }
>  
> @@ -374,7 +374,8 @@ Backup_restore_ctx::Backup_restore_ctx(T
>    /*
>      Check for progress tables.
>    */
> -  if (check_ob_progress_tables(thd))
> +  MYSQL_BACKUP_LOG *backup_log= logger.get_backup_history_log_file_handler();
> +  if (backup_log->check_backup_logs(thd))
>      m_error= ER_BACKUP_PROGRESS_TABLES;
>  }
>  
> 
> === modified file 'sql/backup/logger.cc'
> --- a/sql/backup/logger.cc	2008-03-21 09:57:45 +0000
> +++ b/sql/backup/logger.cc	2008-08-27 17:30:49 +0000
> @@ -10,7 +10,6 @@
>  
>  namespace backup {
>  
> -
>  /**
>    Output message on a given level.
>  
> @@ -55,7 +54,12 @@ 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);
> +     {
> +       time_t ts = my_time(0);
> +
> +       backup_log->error_num(error_code);
> +       backup_log->write_progress(0, ts, ts, 0, 0, error_code, out);
> +     }
>       
>       return 0;
>  
> @@ -114,8 +118,7 @@ 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());
> +  backup_log->num_objects(info.table_count());
>  }
>  
>  /**
> @@ -125,8 +128,7 @@ 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);
> +  backup_log->size(info.data_size);
>  }
>  
>  } // backup namespace
> 
> === modified file 'sql/backup/logger.h'
> --- a/sql/backup/logger.h	2008-07-09 18:37:42 +0000
> +++ b/sql/backup/logger.h	2008-08-27 17:30:49 +0000
> @@ -4,8 +4,7 @@
>  #include "mysql_priv.h"
>  #include <backup_stream.h>
>  #include <backup/error.h>
> -#include <backup/backup_progress.h>
> -
> +#include "si_logs.h"
>  
>  namespace backup {
>  
> @@ -19,7 +18,6 @@ struct log_level {
>  
>  };
>  
> -
>  class Image_info;
>  
>  /**
> @@ -41,12 +39,12 @@ class Logger
>  {
>   public:
>  
> -   enum enum_type { BACKUP, RESTORE } m_type;
> +   enum enum_type { BACKUP = 1, RESTORE } m_type;
>     enum { CREATED, READY, RUNNING, DONE } m_state;
>  
>     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,9 +56,15 @@ 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_driver(const char *driver);
>     void report_stats_pre(const Image_info&);
>     void report_stats_post(const Image_info&);
> +   ulonglong get_op_id() const 
> +   {
> +     DBUG_ASSERT(backup_log);
> +     return backup_log->get_backup_id(); 
> +   }
> +   void report_cleanup() { delete backup_log; }
>     
>     void save_errors();
>     void stop_save_errors();
> @@ -72,15 +76,6 @@ 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;
> -
>    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);
> @@ -89,12 +84,13 @@ class Logger
>  
>    List<MYSQL_ERROR> errors;  ///< Used to store saved errors.
>    bool m_save_errors;        ///< Flag telling if errors should be saved.
> +  Backup_log *backup_log;    ///< Backup log interface class.
>  };
>  
>  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), backup_log(0)
>  {}
>  
>  inline
> @@ -103,38 +99,6 @@ Logger::~Logger()
>    clear_saved_errors();
>  }
>  
> -/**
> -  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.
> - */ 
> -inline
> -int Logger::init(enum_type type, const LEX_STRING path, const char *query)
> -{
> -  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);  
> -  DEBUG_SYNC(m_thd, "after_backup_log_init");
> -  return 0;
> -}
> -
> -
>  inline
>  int Logger::write_message(log_level::value level, const char *msg, ...)
>  {
> @@ -224,12 +188,13 @@ inline
>  void Logger::report_start(time_t when)
>  {
>    DBUG_ASSERT(m_state == READY);
> +  DBUG_ASSERT(backup_log);
>    m_state= RUNNING;
>    
>    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);
> -  report_state(BUP_RUNNING);
> +  backup_log->start(when);
> +  backup_log->state(BUP_RUNNING);
>  }
>  
>  /**
> @@ -244,19 +209,21 @@ void Logger::report_stop(time_t when, bo
>      return;
>  
>    DBUG_ASSERT(m_state == RUNNING);
> +  DBUG_ASSERT(backup_log);
>  
>    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);
> -  report_state(success ? BUP_COMPLETE : BUP_ERRORS);
> +
> +  backup_log->stop(when);
> +  backup_log->state(success ? BUP_COMPLETE : BUP_ERRORS);
> +  backup_log->write_history();
>    m_state= DONE;
>  }
>  
>  /** 
>    Report change of the state of operation
>   
> -  For possible states see definition of @c enum_backup_state in 
> -  backup_progress.h
> +  For possible states see definition of @c enum_backup_state 
>  
>    @todo Consider reporting state changes in the server error log (as info
>    entries).
> @@ -264,10 +231,10 @@ void Logger::report_stop(time_t when, bo
>  inline
>  void Logger::report_state(enum_backup_state state)
>  {
> -  DBUG_ASSERT(m_state == RUNNING);
> -  
> -  // TODO: info about state change in the log?
> -  report_ob_state(m_thd, m_op_id, state);
> +  DBUG_ASSERT(m_state == RUNNING || m_state == READY);
> +  DBUG_ASSERT(backup_log);
> + 
> +  backup_log->state(state);
>  }
>  
>  /// Report validity point creation time.
> @@ -275,8 +242,8 @@ inline
>  void Logger::report_vp_time(time_t when)
>  {
>    DBUG_ASSERT(m_state == RUNNING);
> -  
> -  report_ob_vp_time(m_thd, m_op_id, when);
> +  DBUG_ASSERT(backup_log);
> +  backup_log->vp_time(when);
>  }
>  
>  /** 
> @@ -288,18 +255,51 @@ inline
>  void Logger::report_binlog_pos(const st_bstream_binlog_pos &pos)
>  {
>    DBUG_ASSERT(m_state == RUNNING);
> -  
> -  // TODO: write to the log
> -  report_ob_binlog_info(m_thd, m_op_id, pos.pos, pos.file);
> +  DBUG_ASSERT(backup_log);
> +  backup_log->binlog_pos(pos.pos);
> +  backup_log->binlog_file(pos.file);
>  }
>  
> -/// Report name of a driver used in backup/restore operation.
> +/**
> +  Report driver.
> +*/
> +inline 
> +void Logger::report_driver(const char *driver) 
> +{ 
> +  DBUG_ASSERT(m_state == RUNNING);
> +  DBUG_ASSERT(backup_log);
> +  backup_log->add_driver(driver); 
> +}
> +
> +/**
> +  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
> +    
> +  @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
> -void Logger::report_driver(const char *name)
> +int Logger::init(enum_type type, const LEX_STRING path, const char *query)
>  {
> -  DBUG_ASSERT(m_state == READY || m_state == RUNNING);
> -  
> -  report_ob_drivers(m_thd, m_op_id, name);
> +  ulonglong backup_id= 0;
> +
> +  if (m_state != CREATED)
> +    return 0;
> +
> +  m_type= type;
> +  m_state= READY;
> +  backup_log = new Backup_log(m_thd, (enum_backup_operation)type, path, query);
> +  backup_log->state(BUP_STARTING);
> +  DEBUG_SYNC(m_thd, "after_backup_log_init");
> +  return 0;
>  }
>  
>  } // backup namespace
> 
> === modified file 'sql/log.cc'
> --- a/sql/log.cc	2008-07-25 17:21:55 +0000
> +++ b/sql/log.cc	2008-08-27 17:30:49 +0000
> @@ -39,6 +39,7 @@
>  #endif
>  
>  #include <mysql/plugin.h>
> +#include "si_logs.h"
>  
>  /* max size of the log message */
>  #define MAX_LOG_BUFFER_SIZE 1024
> @@ -113,6 +114,25 @@ char *make_default_log_name(char *buff,c
>                     MYF(MY_UNPACK_FILENAME|MY_REPLACE_EXT));
>  }
>  
> +/**
> +  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_real_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 +702,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 +753,339 @@ 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)
> +{
> +  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->driver_name.length())
> +  {
> +    if (table->field[ET_OBH_FIELD_DRIVERS]->store(
> +        history_data->driver_name.c_ptr(),
> +        history_data->driver_name.length(), 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 +1105,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 +1150,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 +1220,44 @@ 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 
> +
> +    Where TRUE means perform open on history file (backup_history) and
> +    FALSE means perform open on the progress file (backkup_progress).
> +  */
> +  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 +1376,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 +1553,105 @@ 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.
> @@ -2335,6 +3070,576 @@ bool MYSQL_QUERY_LOG::write(THD *thd, ti
>    }
>    (void) pthread_mutex_unlock(&LOCK_log);
>    DBUG_RETURN(error);
> +}
> +
> +
> +/**
> +  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 unsigned 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(uint 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 an unsigned longlong 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_long(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_long(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_long(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->driver_name.ptr()))
> +      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_long(backup_id))
> +      goto err;
> +    if (write_str(object))
> +      goto err;
> +    if (write_datetime(start))
> +      goto err;
> +    if (write_datetime(stop))
> +      goto err;
> +    if (write_long(size))
> +      goto err;
> +    if (write_long(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;
> +}
> +
> +
> +/**
> +  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 MYSQL_BACKUP_LOG::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", strlen("mysql"), 
> +                        "backup_history", strlen("backup_history"),
> +                        "backup_history", TL_READ);
> +  alloc_mdl_locks(&tables, thd->mem_root);
> +  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", strlen("mysql"), 
> +                        "backup_progress", strlen("backup_progress"),
> +                        "backup_progress", TL_READ);
> +  alloc_mdl_locks(&tables, thd->mem_root);
> +  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);
> +}
> +
> +/**
> +  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?
> +  @todo Do we need to version the file?
> +
> +  @returns next backup id or 0 if failure
> +*/
> +ulonglong MYSQL_BACKUP_LOG::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
> +  */
> +  pthread_mutex_lock(&LOCK_backupid);
> +  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
> +    {
> +      ulonglong read_id= 0;
> +      my_seek(file, 0, 0, MYF(MY_WME));
> +      size_t read_len= my_read(file, (uchar *)&read_id, sizeof(ulonglong), 
> +        MYF(MY_WME|MY_NABP));
> +      id= uint8korr(&read_id);
> +      id++;
> +    }
> +  }
> +  else  // increment the counter
> +    id= m_next_id + 1;
> +
> +  DBUG_EXECUTE_IF("set_backup_id", id= 500;);
> +
> +  /* 
> +    Write the new value to the file
> +  */
> +  if ((m_next_id != id) && id)
> +  {
> +    ulonglong write_id= 0;
> +
> +    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));
> +    int8store(&write_id, id);
> +    my_write(file, (uchar *)&write_id, sizeof(ulonglong), MYF(MY_WME));
> +  }
> +err:
> +  if (file > 0)
> +    my_close(file,MYF(MY_WME));
> +  
> +err_end:
> +  m_next_id= id;
> +  pthread_mutex_unlock(&LOCK_backupid);
> +  DBUG_PRINT("backup_log",("The next id is %lu.\n", id));
> +  return id;
> +}
> +
> +
> +/**
> +  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;
>  }
>  
>  
> 
> === modified file 'sql/log.h'
> --- a/sql/log.h	2008-06-27 20:56:54 +0000
> +++ b/sql/log.h	2008-08-27 17:30:49 +0000
> @@ -16,6 +16,50 @@
>  #ifndef LOG_H
>  #define LOG_H
>  
> +struct st_backup_history;
> +
> +/**
> +  List of fields for online backup table.
> +*/
> +enum enum_backup_history_log_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_log_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 :) */
> +};
> +
>  class Relay_log_info;
>  
>  class Format_description_log_event;
> @@ -223,6 +267,56 @@ private:
>    time_t last_time;
>  };
>  
> +class MYSQL_BACKUP_LOG: public MYSQL_LOG
> +{
> +public:
> +  MYSQL_BACKUP_LOG () 
> +  { 
> +    headers_written= FALSE; 
> +    pthread_mutex_init(&LOCK_backupid, MY_MUTEX_INIT_FAST);
> +    m_next_id= 0;
> +  }
> +  ~MYSQL_BACKUP_LOG()
> +  {
> +    pthread_mutex_destroy(&LOCK_backupid);
> +  }
> +  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 get_next_backup_id();
> +  my_bool check_backup_logs(THD *thd);
> +
> +private:
> +  bool write_int(uint num);
> +  bool write_long(ulonglong num);
> +  bool write_datetime(time_t time_val);
> +  bool write_str(const char *str);
> +  bool headers_written;
> +  ulonglong m_next_id;       ///< the next available backup_id
> +  pthread_mutex_t LOCK_backupid; ///< mutex for backupid generation
> +};
> +
>  class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
>  {
>   private:
> @@ -411,6 +505,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 +549,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 +598,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 +642,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 +667,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 +681,29 @@ 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 +716,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-08-19 15:35:29 +0000
> +++ b/sql/mysql_priv.h	2008-08-27 17:30:49 +0000
> @@ -903,6 +903,7 @@ int end_trans(THD *thd, enum enum_mysql_
>  Item *negate_expression(THD *thd, Item *expr);
>  
>  /* log.cc */
> +
>  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);
> @@ -1447,6 +1448,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);
> @@ -1649,6 +1653,7 @@ bool rename_temporary_table(THD* thd, TA
>  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);
>  
>  #ifdef WITH_PARTITION_STORAGE_ENGINE
>  uint fast_alter_partition_table(THD *thd, TABLE *table,
> @@ -2030,7 +2035,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;
> @@ -2059,11 +2067,15 @@ extern uint opt_large_page_size;
>  #endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */
>  #ifdef MYSQL_SERVER
>  extern char *opt_logname, *opt_slow_logname;
> -extern const char *log_output_str;
> +extern char *opt_backup_history_logname, *opt_backup_progress_logname,
> +            *opt_backup_settings_name;
> +extern const char *og_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-08-11 16:06:30 +0000
> +++ b/sql/mysqld.cc	2008-08-27 17:30:49 +0000
> @@ -429,7 +429,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;
> @@ -571,6 +574,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,
> @@ -715,6 +719,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 */
>  
> @@ -1363,8 +1369,10 @@ 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_slow_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
>    my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
> @@ -2878,6 +2886,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)
>        {
> @@ -2895,6 +2905,7 @@ pthread_handler_t signal_hand(void *arg 
>        }
>        break;
>      case SIGHUP:
> +    {
>        if (!abort_loop)
>        {
>          bool not_used;
> @@ -2918,7 +2929,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.
> @@ -3578,10 +3596,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);
> @@ -4102,7 +4145,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();
>  
> @@ -4134,9 +4180,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
>  
>    /*
> @@ -5739,10 +5817,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,
> @@ -5799,6 +5880,12 @@ struct my_option my_long_options[] =
>     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,
> @@ -6049,6 +6136,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.",
> @@ -7667,6 +7759,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;
> @@ -7754,6 +7847,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";
> @@ -8118,6 +8213,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-08-19 15:35:29 +0000
> +++ b/sql/set_var.cc	2008-08-27 17:30:49 +0000
> @@ -147,11 +147,18 @@ 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);
> +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
> @@ -764,6 +771,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);
> @@ -776,13 +789,19 @@ sys_var_str sys_var_general_log_path(&va
>  				     sys_update_general_log_path,
>  				     sys_default_general_log_path,
>  				     opt_logname);
> -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);
> -
> +/*
> +  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.
>  */
> @@ -792,6 +811,18 @@ sys_var_str sys_var_backupdir(&vars, "ba
>                                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);
> +
>  
>  /*
>    Additional variables (not derived from sys_var class, not accessible as
> @@ -2476,8 +2507,18 @@ static int  sys_check_log_path(THD *thd,
>    return 0;
>  
>  err:
> -  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, 
> -           res ? log_file_str : "NULL");
> +  /*
> +    If this is one of the backup logs, process the backup specific
> +    error message.
> +  */
> +  if ((my_strcasecmp(system_charset_info, var->var->name, 
> +       "backup_history_log_file") == 0) ||
> +      (my_strcasecmp(system_charset_info, var->var->name,
> +       "backup_progress_log_file") == 0))
> +    my_error(ER_BACKUP_LOGPATH_INVALID, MYF(0), var->var->name, path); 
> +  else
> +    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, 
> +             res ? log_file_str : "NULL");
>    return 1;
>  }
>  
> @@ -2487,11 +2528,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();
> @@ -2499,13 +2544,38 @@ 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
>    }
>  
>    if (!old_value)
>    {
> -    old_value= make_default_log_name(buff, log_ext);
> +    /*
> +      Added support for backup log types.
> +    */
> +    switch (log_type) {
> +    case QUERY_LOG_SLOW:
> +    case QUERY_LOG_GENERAL:
> +      old_value= make_default_log_name(buff, log_ext);
> +      break;
> +    case BACKUP_HISTORY_LOG:
> +      old_value= make_backup_log_name(buff, BACKUP_HISTORY_LOG_NAME.str, log_ext);
> +      break;
> +    case BACKUP_PROGRESS_LOG:
> +      old_value= make_backup_log_name(buff, BACKUP_PROGRESS_LOG_NAME.str, log_ext);
> +      break;
> +    default:
> +      assert(0);                                  // Impossible
> +    }
>      str_length= strlen(old_value);
>    }
>    if (!(res= my_strndup(old_value, str_length, MYF(MY_FAE+MY_WME))))
> @@ -2517,14 +2587,35 @@ bool update_sys_var_str_path(THD *thd, s
>    pthread_mutex_lock(&LOCK_global_system_variables);
>    logger.lock_exclusive();
>  
> -  if (file_log && log_state)
> -    file_log->close(0);
> +  /*
> +    Added support for backup log types.
> +  */
> +  switch (log_type) {
> +  case QUERY_LOG_SLOW:
> +  case QUERY_LOG_GENERAL:
> +    if (file_log && log_state)
> +      file_log->close(0);
> +    break;
> +  /*
> +    Close the backup logs if specified.
> +  */
> +  case BACKUP_HISTORY_LOG:
> +  case BACKUP_PROGRESS_LOG:
> +    if (backup_log && log_state)
> +      backup_log->close(0);
> +    break;
> +  default:
> +    assert(0);                                  // Impossible
> +  }
>    old_value= var_str->value;
>    var_str->value= res;
>    var_str->value_length= str_length;
>    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);
> @@ -2532,6 +2623,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);
>      }
> @@ -2559,6 +2659,63 @@ 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)
> +{
> +  char buff[STRING_BUFFER_USUAL_SIZE];
> +  String str(buff,sizeof(buff), system_charset_info), *res;
> +
> +  res= var->value->val_str(&str);
> +  if (my_strcasecmp(system_charset_info, res->c_ptr(), 
> +      sys_var_backup_progress_log_path.value) == 0)
> +  {
> +    my_error(ER_BACKUP_LOGPATHS, MYF(0));
> +    return 1;
> +  }
> +  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)
> +{
> +  char buff[STRING_BUFFER_USUAL_SIZE];
> +  String str(buff,sizeof(buff), system_charset_info), *res;
> +
> +  res= var->value->val_str(&str);
> +  if (my_strcasecmp(system_charset_info, res->c_ptr(), 
> +      sys_var_backup_history_log_path.value) == 0)
> +  {
> +    my_error(ER_BACKUP_LOGPATHS, MYF(0));
> +    return 1;
> +  }
> +  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,
> @@ -2602,6 +2759,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);
> 
> === modified file 'sql/set_var.h'
> --- a/sql/set_var.h	2008-08-19 15:35:29 +0000
> +++ b/sql/set_var.h	2008-08-27 17:30:49 +0000
> @@ -960,6 +960,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; }
> +};
> +
>  
>  /* Variable that you can only read from */
>  
> @@ -1371,6 +1397,7 @@ uchar* find_named(I_List<NAMED_LIST> *li
>  		NAMED_LIST **found);
>  
>  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 */
> 
> === modified file 'sql/share/errmsg.txt'
> --- a/sql/share/errmsg.txt	2008-08-20 13:23:10 +0000
> +++ b/sql/share/errmsg.txt	2008-08-27 17:30:49 +0000
> @@ -6251,7 +6251,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"
> @@ -6388,3 +6388,7 @@ ER_BACKUP_GRANT_SKIPPED
>          eng "The grant '%-.64s' was skipped because the user does not exist."
>  ER_BACKUP_GRANT_WRONG_DB
>          eng "The grant '%-.64s' failed. Database not included in the backup image."
> +ER_BACKUP_LOGPATHS
> +  eng "The log names for backup_history and backup_progress must be unique."
> +ER_BACKUP_LOGPATH_INVALID
> +  eng "The path specified for the %-.64s is invalid. ref: %-.64s"
> 
> === added file 'sql/si_logs.cc'
> --- a/sql/si_logs.cc	1970-01-01 00:00:00 +0000
> +++ b/sql/si_logs.cc	2008-08-27 17:30:49 +0000
> @@ -0,0 +1,174 @@
> +/**
> +   @file
> +
> +   This file defines the API for the following object services:
> +     - table|file|both logging services for backup
> +
> +  The methods defined below are used to provide server functionality to
> +  and permitting an isolation layer for the client (caller).
> +*/
> +
> +#include "mysql_priv.h"
> +#include "si_logs.h"
> +#include "log.h"
> +
> +/**
> +  Initialize the class for logging backup or restore operation.
> +  
> +  This constructor initializes the m_op_hist structure with the
> +  information passed during instantiation.
> +
> +  @param[in]  THD   current thread
> +  @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
> +    
> +  @todo Add code to get the user comment from command.
> +
> +*/ 
> +Backup_log::Backup_log(THD *thd, 
> +                       enum_backup_operation type, 
> +                       const LEX_STRING path, 
> +                       const char *query)
> +{
> +  ulonglong backup_id= 0;
> +  m_thd= thd;
> +
> +  bzero(&m_op_hist, sizeof(st_backup_history));
> +  m_op_hist.process_id= m_thd->id;
> +  m_op_hist.state= BUP_STARTING;
> +  m_op_hist.operation= type;
> +
> +  if (path.length > 0)
> +     m_op_hist.backup_file= path.str;
> +
> +  if (strlen(query) > 0)
> +    m_op_hist.command= (char *)query;
> +
> +  MYSQL_BACKUP_LOG *backup_log= logger.get_backup_history_log_file_handler();
> +  m_op_hist.backup_id= backup_log->get_next_backup_id();
> +}
> +
> +/**
> +  Report name of a driver used in backup/restore operation.
> +
> +  This method updates the drivers information in the history data. This method 
> +  appends to the those drivers listed in the history data.
> +
> +  @param[IN] char *            driver_name  The name of the engine to add.
> +*/
> +void Backup_log::add_driver(const char *driver_name)
> +{
> +  String str;    // drivers string
> +
> +  str.length(0);
> +  if (m_op_hist.driver_name.length())
> +    str.append(m_op_hist.driver_name);
> +  if ((str.length() > 0) && (strlen(driver_name) > 0))
> +    str.append(", ");
> +  if (strlen(driver_name) > 0)
> +    str.append(driver_name);
> +  m_op_hist.driver_name.copy(str);
> +}
> +
> +/**
> +  Write history data.
> +
> +  This method calls the server's logger to write the backup_history log
> +  information.
> +
> +  @returns results of logging function (i.e., TRUE if error)
> +
> +  @note This method should be called after all data has been set for the
> +  history data.
> +*/
> +bool Backup_log::write_history() 
> +{ 
> +  return logger.backup_history_log_write(m_thd, &m_op_hist); 
> +}
> +
> +/**
> +  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]   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 backup kernel
> +
> +  @returns results of logging function (i.e., TRUE if error)
> +*/
> +bool Backup_log::write_progress(const char *object,
> +                                time_t start,
> +                                time_t stop,
> +                                longlong size,
> +                                longlong progress,
> +                                int error_num,
> +                                const char *notes)
> +{
> +  /* Write the message to the backup progress log */
> +  return logger.backup_progress_log_write(m_thd, m_op_hist.backup_id, object, 
> +                                          start, stop, size, progress, 
> +                                          error_num, notes);
> +}
> +
> +/** 
> +  Report change of the state of operation
> + 
> +  For possible states see definition of @c enum_backup_state 
> +
> +  @todo Consider reporting state changes in the server error log (as info
> +  entries).
> + */
> +void Backup_log::state(enum_backup_state state)
> +{
> +  m_op_hist.state= state;
> +  logger.backup_progress_log_write(m_thd, m_op_hist.backup_id, "backup kernel", 0, 
> +                            0, 0, 0, 0, get_state_string(state));
> +}
> +
> +/**
> +  Report validity point creation time.
> +
> +  This method saves the validation point time in the history data and writes
> +  a message to the progress log.
> +
> +  @param[IN]  when  Time of validity point.
> +
> +  @note If the time is 0|NULL, nothing is saved in the history data.
> +*/
> +void Backup_log::vp_time(time_t when)
> +{
> +  if (when)
> +  {
> +    m_op_hist.vp_time= when; 
> +    logger.backup_progress_log_write(m_thd, m_op_hist.backup_id, "backup kernel", 
> +                                     when, 0, 0, 0, 0, "vp time");
> +  }
> +}
> +
> +/**
> +  Get text string for state.
> +
> +  @param[IN]  state  The current state of the operation
> +
> +  @returns char * a text string for state.
> +*/
> +inline
> +const char *Backup_log::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");
> +  }
> +}
> 
> === added file 'sql/si_logs.h'
> --- a/sql/si_logs.h	1970-01-01 00:00:00 +0000
> +++ b/sql/si_logs.h	2008-08-27 17:30:49 +0000
> @@ -0,0 +1,194 @@
> +#ifndef SI_LOGS_H_
> +#define SI_LOGS_H_
> +
> +/**
> +   @file
> +
> +   This file defines the API for the following object services:
> +     - table|file|both logging services for backup
> +*/
> +
> +/**
> +  List of operations for backup history log.
> +*/
> +enum enum_backup_operation
> +{
> +  OP_BACKUP = 1,
> +  OP_RESTORE,
> +  OP_SHOW,
> +  OP_OTHER
> +};
> +
> +/**
> +  List of states for backup logs.
> +*/
> +enum enum_backup_state
> +{
> +  BUP_UNKNOWN = 0,
> +  BUP_COMPLETE,
> +  BUP_STARTING,
> +  BUP_VALIDITY_POINT,
> +  BUP_RUNNING,
> +  BUP_ERRORS,
> +  BUP_CANCEL
> +};
> +
> +/**
> +  Structure for holding backup history data.
> +
> +  This structure is used to collect the information needed to write a
> +  single row of information to the backup_history log.
> +*/
> +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 operation
> +  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
> +  String driver_name;              ///< list of backup engines used
> +};
> +
> +
> +/**
> +  Class Backup_log defines the basic set of operations for server logs.
> +
> +  This class is used to write information to the backup_history and 
> +  backup_progress logs. While the log output control is determined by the 
> +  server, this class is used as an interface to allow the backup to write 
> +  messages to the logs without regard to how they are stored or how the 
> +  logging mechanisms of the server behave.
> +
> +  To use this class, one must instantiate the class. When instantiated, the
> +  constructor gets the next backup_id from the server and initializes the 
> +  history data stored in m_op_hist.
> +
> +  Use the set methods below to store the information for the logs. When the
> +  caller is ready to write information to the logs, call the write_*() 
> +  method for the appropriate log.
> +
> +  The write_history() method is used to write the history data to the 
> +  backup_history log. It should be called at the end of the backup or 
> +  restore operation.
> +
> +  The write_progress() method is used to write miscellaneous messages to
> +  the backup_progress log. It may be called at any time.
> +
> +  The state() method is designed to change the state of the operation and
> +  to write a message to the backup_progress log.
> +
> +  @todo Add method to set the user comment from the command-line.
> +*/
> +class Backup_log
> +{
> +public:
> +  Backup_log(THD *thd, 
> +             enum_backup_operation type, 
> +             const LEX_STRING path, 
> +             const char *query); 
> +
> +  /* 
> +    Write the backup history data to the backup_history log. 
> +  */
> +  bool write_history();
> +
> +  /* 
> +    Write a message to the backup_progress log.
> +  */
> +  bool write_progress(const char *object,
> +                      time_t start,
> +                      time_t stop,
> +                      longlong size,
> +                      longlong progress,
> +                      int error_num,
> +                      const char *notes);
> +  /*
> +    Check the backup logs (as tables).
> +  */
> +  bool check_logs();
> +
> +  /*
> +    The following get/set methods populate the history data for
> +    the backup_history log.
> +  */
> +  ulonglong get_backup_id() { return m_op_hist.backup_id; }
> +  void state(enum_backup_state);
> +  void error_num(int code) { m_op_hist.error_num= code; }
> +  void binlog_pos(unsigned long int pos) { m_op_hist.binlog_pos= pos; }
> +  void binlog_file(char *file);
> +  void num_objects(int num) { m_op_hist.num_objects= num; }
> +  void size(longlong s) { m_op_hist.size= s; }
> +  void start(time_t when);
> +  void stop(time_t when);
> +  void vp_time(time_t when);
> +  void add_driver(const char* driver);
> +
> +private:
> +  st_backup_history m_op_hist;  ///< history log information
> +  THD *m_thd;                   ///< current thread
> +
> +  /*
> +    Helper method to provide string constants for states.
> +  */
> +  const char *get_state_string(enum_backup_state state);
> +};
> +
> +/**
> +  Report start of an operation.
> +
> +  This method saves the start time in the history data.
> +  
> +  @param[IN]  when  The start time.
> +
> +  @note If the time is 0|NULL, nothing is saved in the history data.
> +*/
> +inline
> +void Backup_log::start(time_t when)
> +{
> +  if (when)
> +    m_op_hist.start= when;
> +}
> +
> +/**
> +  Report stop of an operation.
> +
> +  This method saves the stop time in the history data.
> +  
> +  @param[IN]  when  The stop time.
> +
> +  @note If the time is 0|NULL, nothing is saved in the history data.
> +*/
> +inline
> +void Backup_log::stop(time_t when)
> +{
> +  if (when)
> +    m_op_hist.stop= when;
> +}
> +
> +/** 
> +  Report binlog position at validity point.
> +
> +  This method saves the binlog file name in the history data.
> +
> +  @param[IN] file Binlog file name.
> +
> +  @note If the file name is 0|NULL, nothing is saved in the history data.
> +*/
> +inline
> +void Backup_log::binlog_file(char *file)
> +{
> +  if (strlen(file) > 0)
> +    m_op_hist.binlog_file= file;
> +}
> +
> +#endif // SI_LOGS_H_
> 
> === modified file 'sql/sql_parse.cc'
> --- a/sql/sql_parse.cc	2008-08-19 15:35:29 +0000
> +++ b/sql/sql_parse.cc	2008-08-27 17:30:49 +0000
> @@ -6746,6 +6746,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-07-25 17:21:55 +0000
> +++ b/sql/sql_yacc.yy	2008-08-27 17:30:49 +0000
> @@ -9996,6 +9996,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-07-29 12:08:01 +0000
> +++ b/sql/table.cc	2008-08-27 17:30:49 +0000
> @@ -33,9 +33,19 @@ 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 */
> @@ -238,6 +248,30 @@ TABLE_CATEGORY get_table_category(const 
>      if ((name->length == GENERAL_LOG_NAME.length) &&
>          (my_strcasecmp(system_charset_info,
>                        GENERAL_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;
> 
> 
Thread
bzr commit into mysql-6.0-backup branch (cbell:2684) WL#4296Chuck Bell27 Aug
  • Re: bzr commit into mysql-6.0-backup branch (cbell:2684) WL#4296Øystein Grøvlen28 Aug