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;
>
>