Hi Chuck,
I have one main concern with this patch. Each time one of your report_ob_*()
functions is called these things happen:
- the locking thread is spawned,
- appropriate table is opened,
- data is inserted or updated,
- table is closed,
- locking thread is shut-down.
Concern 1: Efficiency - creating and destroying a thread each time single update
is done seems too expensive. Similar with opening and closing table each time.
This means that the report_ob_*() functions should not be called too often, but
on the other hand they are supposed to be used in that way.
Concern 2: Because of the above, I think we can't call any report_ob_*()
function during the synchronization phase (between lock() and unlock() calls).
Recall that we are struggling to make this phase as short as possible and here
it is even possible that a disk access will happen.
The first concern is (perhaps) not crucial as it is just efficiency issue.
However something must be done with the second concern.
I think a possible solution for the first concern is to spawn the locking thread
and open all (two) tables used only once, at the beginning of backup/restore
operation. Then the reporting functions would need access to the opened tables.
Therefore I'd turn them into methods of a class whose instance contains (and
maintains) all necessary context (i.e., the locking thread, pointers to TABLE
structures and so on). Actually, there is already a Logger class which seems
perfect for that purpose.
See below for some more detailed comments.
cbell@stripped wrote:
> Below is the list of changes that have just been committed into a local
> 6.0 repository of cbell. When cbell does a push these changes will
> be propagated to the main repository and, within 24 hours after the
> push, to the public repository.
> For information on how to access the public repository
> see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
>
> ChangeSet@stripped, 2007-11-28 23:31:29-05:00, cbell@mysql_cab_desk. +9 -0
> WL#4116 : Online Backup: Record Online Backup Progress
>
> Patch 2 of 3
>
> This patch contains the online backup progress methods. Output of
> the backup process is now recorded and can be queried at a later
> time.
>
> scripts/mysql_system_tables.sql@stripped, 2007-11-28 23:31:19-05:00,
> cbell@mysql_cab_desk. +6 -0
> WL#4116 : Online Backup: Record Online Backup Progress
>
> Adds the online backup tables to the create mysql database script.
>
> sql/backup/CMakeLists.txt@stripped, 2007-11-28 23:31:19-05:00, cbell@mysql_cab_desk. +1
> -1
> WL#4116 : Online Backup: Record Online Backup Progress
>
> Add the backup progress files to the Windows build for cmake.
>
> sql/backup/Makefile.am@stripped, 2007-11-28 23:31:20-05:00, cbell@mysql_cab_desk. +3 -1
> WL#4116 : Online Backup: Record Online Backup Progress
>
> Add the backup progress files to the make file.
>
> sql/backup/archive.h@stripped, 2007-11-28 23:31:21-05:00, cbell@mysql_cab_desk. +1 -0
> WL#4116 : Online Backup: Record Online Backup Progress
>
> Add the backup_id for use in updating the progress.
>
> sql/backup/backup_engine.h@stripped, 2007-11-28 23:31:22-05:00, cbell@mysql_cab_desk. +2
> -0
> WL#4116 : Online Backup: Record Online Backup Progress
>
> Add the backup_id for use in updating the progress.
>
> sql/backup/backup_progress.cc@stripped, 2007-11-28 23:31:24-05:00, cbell@mysql_cab_desk.
> +869 -0
> WL#4116 : Online Backup: Record Online Backup Progress
>
> New source file for backup progress methods.
>
> sql/backup/backup_progress.cc@stripped, 2007-11-28 23:31:24-05:00, cbell@mysql_cab_desk.
> +0 -0
>
> sql/backup/backup_progress.h@stripped, 2007-11-28 23:31:24-05:00, cbell@mysql_cab_desk.
> +195 -0
> WL#4116 : Online Backup: Record Online Backup Progress
>
> New header file for backup progress methods.
>
> sql/backup/backup_progress.h@stripped, 2007-11-28 23:31:24-05:00, cbell@mysql_cab_desk.
> +0 -0
>
> sql/backup/data_backup.cc@stripped, 2007-11-28 23:31:22-05:00, cbell@mysql_cab_desk. +38
> -0
> WL#4116 : Online Backup: Record Online Backup Progress
>
> Adds method calls to report progress information for backup and
> restore.
>
> sql/backup/sql_backup.cc@stripped, 2007-11-28 23:31:23-05:00, cbell@mysql_cab_desk. +68
> -59
> WL#4116 : Online Backup: Record Online Backup Progress
>
> Adds method calls to report progress information for backup and
> restore. Also changes summary to print out resulting row from
> the online_backup table.
>
> Note: this allows one to use BACKUP... \G to display as a
> vertical query. cool.
>
> diff -Nrup a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql
> --- a/scripts/mysql_system_tables.sql 2007-10-30 09:09:48 -04:00
> +++ b/scripts/mysql_system_tables.sql 2007-11-28 23:31:19 -05:00
> @@ -83,5 +83,11 @@ 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')
> DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default
> '', originator int(10) NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT
> 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32)
> collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY
> (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
>
>
> +CREATE TABLE IF NOT EXISTS online_backup ( backup_id BIGINT UNSIGNED PRIMARY KEY
> AUTO_INCREMENT COMMENT 'Surrogate key for (near) duplicate entries', process_id INT
> UNSIGNED NOT NULL COMMENT 'The process id that operation ran as', binlog_pos INT UNSIGNED
> DEFAULT 0 COMMENT 'The recorded binlog position of backup/restore', binlog_file CHAR(64)
> COMMENT 'The recorded binlog filename at time of backup/restore', backup_state
> ENUM('complete', 'starting', 'validity point', 'running', 'error', 'cancel') NOT NULL
> COMMENT 'Status of current operation', operation ENUM('backup', 'restore') NOT NULL
> COMMENT 'Type of operation', error_num INT NOT NULL DEFAULT 0 COMMENT 'The error from this
> run 0 == none', num_objects INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'The number of objects
> in the backup', total_bytes BIGINT UNSIGNED COMMENT 'The size of the backup repository in
> bytes', validity_point_time datetime COMMENT 'The time of the validity point.', start_time
> datetime COMMENT 'The date/tim
e !
> of start of operation', stop_time datetime COMMENT 'The date/time of end of
> operation', host_or_server_name CHAR (30) COMMENT 'The server name where operation ran',
> username CHAR (30) COMMENT 'The user name who ran the operation', backup_file CHAR (100)
> COMMENT 'The name of the file', user_comment VARCHAR (200) DEFAULT NULL COMMENT 'The
> comment from user entered at command line', command VARCHAR (512) COMMENT 'The command
> used to issue operation', engines VARCHAR (100) COMMENT 'The name of the storage engines
> used in the operation') ENGINE=MYISAM;
> +
> +
> +CREATE TABLE IF NOT EXISTS online_backup_progress ( backup_id BIGINT UNSIGNED NOT
> NULL COMMENT 'Key for online_backup table entries', object CHAR (30) NOT NULL COMMENT 'The
> object being operated on', start_time datetime COMMENT 'The date/time of start of
> operation', stop_time datetime COMMENT 'The date/time of end of operation', total_bytes
> BIGINT COMMENT 'The size of the object in bytes', progress BIGINT UNSIGNED COMMENT 'The
> number of bytes processed', error_num INT NOT NULL DEFAULT 0 COMMENT 'The error from this
> run 0 == none', notes CHAR(100) COMMENT 'Commentary from the backup engine')
> ENGINE=MYISAM;
> +
> +
> CREATE TABLE IF NOT EXISTS 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;
>
> diff -Nrup a/sql/backup/CMakeLists.txt b/sql/backup/CMakeLists.txt
> --- a/sql/backup/CMakeLists.txt 2007-11-16 05:05:55 -05:00
> +++ b/sql/backup/CMakeLists.txt 2007-11-28 23:31:19 -05:00
> @@ -25,7 +25,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/
> SET(BACKUP_SOURCES stream.cc logger.cc string_pool.cc
> archive.cc meta_backup.cc data_backup.cc
> sql_backup.cc be_default.cc buffer_iterator.cc
> - be_snapshot.cc be_thread.cc)
> + be_snapshot.cc be_thread.cc backup_progress.cc)
>
> IF(NOT SOURCE_SUBLIBS)
> ADD_LIBRARY(backup ${BACKUP_SOURCES})
> diff -Nrup a/sql/backup/Makefile.am b/sql/backup/Makefile.am
> --- a/sql/backup/Makefile.am 2007-11-16 05:10:35 -05:00
> +++ b/sql/backup/Makefile.am 2007-11-28 23:31:20 -05:00
> @@ -36,7 +36,8 @@ libbackup_la_SOURCES = \
> be_default.cc \
> be_snapshot.cc \
> buffer_iterator.cc \
> - be_thread.cc
> + be_thread.cc \
> + backup_progress.cc
>
> libbackupstream_la_SOURCES= \
> stream_v1_transport.c \
> @@ -59,6 +60,7 @@ noinst_HEADERS = \
> be_snapshot.h \
> buffer_iterator.h \
> be_thread.h \
> + backup_progress.h \
> stream_v1.h \
> stream_v1_services.h
>
> diff -Nrup a/sql/backup/archive.h b/sql/backup/archive.h
> --- a/sql/backup/archive.h 2007-11-09 16:19:38 -05:00
> +++ b/sql/backup/archive.h 2007-11-28 23:31:21 -05:00
> @@ -83,6 +83,7 @@ class Archive_info
> struct tm start_time; ///< the start datetime of the backup
> struct tm end_time; ///< the end datetime of the backup
> struct tm vp_time; ///< time of validation point
> + ulonglong backup_prog_id; ///< the backup_id for reporting progress
>
> // Classes representing various types of meta-data items.
>
> diff -Nrup a/sql/backup/backup_engine.h b/sql/backup/backup_engine.h
> --- a/sql/backup/backup_engine.h 2007-11-06 13:32:08 -05:00
> +++ b/sql/backup/backup_engine.h 2007-11-28 23:31:22 -05:00
> @@ -191,6 +191,8 @@ class Driver
> /// Unknown size constant used for backup image size estimates.
> static const size_t UNKNOWN_SIZE= static_cast<size_t>(-1);
>
> + ulonglong backup_prog_id;
> +
> protected:
>
> /// Refers to the list of tables passed when the driver was created.
> diff -Nrup a/sql/backup/backup_progress.cc b/sql/backup/backup_progress.cc
> --- /dev/null Wed Dec 31 16:00:00 196900
> +++ b/sql/backup/backup_progress.cc 2007-11-28 23:31:24 -05:00
> @@ -0,0 +1,869 @@
> +/* 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 "backup_progress.h"
> +#include "be_thread.h"
> +
> +extern bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists);
> +
> +/**
> + Open backup progress table.
> +
> + This method opens the online backup table specified. It uses the locking
> + thread mechanism in be_thread.cc to open the table in a separate thread.
> +
> + @param char * table_name The name of the table to open.
> + @param thr_lock_type lock The lock type -- TL_WRITE or TL_READ.
> +
> + @returns 0 = success
> + @returns 1 = failed to open table
> +
> + @todo : Replace poling loop with signal.
> + */
> +Locking_thread_st *open_backup_progress_table(const char *table_name,
> + enum thr_lock_type lock)
> +{
> + TABLE_LIST tables; // List of tables (1 in this case)
> + Locking_thread_st *locking_thd= NULL; // The locking thread
> + bool exists; // See if table exists
> +
> + DBUG_ENTER("open_backup_progress_table()");
> +
> + tables.init_one_table("mysql", table_name, lock);
> +
> + /*
> + First, check to see if table exists.
> + */
> + if (check_if_table_exists(current_thd, &tables, &exists))
> + DBUG_RETURN(locking_thd);
> +
> + /*
> + Create a new thread to open and lock the tables.
> + */
> + locking_thd= new Locking_thread_st();
> + locking_thd->tables_in_backup= &tables;
> +
> + /*
> + Start the locking thread and wait until it is ready.
> + */
> + locking_thd->start_locking_thread();
> +
> + /*
> + Poll the locking thread until ready.
> + */
> + while (locking_thd && (locking_thd->lock_state != LOCK_ACQUIRED)
> &&
> + (locking_thd->lock_state != LOCK_ERROR))
> + sleep(0);
> + if (locking_thd->lock_state == LOCK_ERROR)
> + {
> + delete locking_thd;
> + locking_thd= NULL;
> + }
> + DBUG_RETURN(locking_thd);
> +}
> +
> +/**
> + 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 table to search.
> + @param ulonglong backup_id The id of the row to locate.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +my_bool find_online_backup_row(TABLE *table, ulonglong backup_id)
> +{
> + uchar key[MAX_KEY_LENGTH]; // key buffer for search
> +
> + DBUG_ENTER("find_online_backup_row()");
> +
> + /*
> + Create key to find row. We have to use field->store() to be able to
> + handle VARCHAR and CHAR fields.
> + Assumption here is that the two first fields in the table are
> + 'db' and 'name' and the first key is the primary key over the
> + same fields.
> + */
> + table->field[ET_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))
> + {
> + DBUG_PRINT("info", ("Row not found"));
> + DBUG_RETURN(TRUE);
> + }
> +
> + DBUG_PRINT("info", ("Row found!"));
> + DBUG_RETURN(FALSE);
> +}
> +
> +/**
> + Update an integer field for 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 and updates the field specified.
> +
> + @param ulonglong backup_id The id of the row to locate.
> + @param char * table_name The name of the table to open.
> + @param enum_ob_table_field fld Field to update.
> + @param ulonglong value Value to set field to.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +int update_online_backup_int_field(ulonglong backup_id, char *table_name,
> + enum_ob_table_field fld, ulonglong value)
> +{
> + TABLE *table= NULL; // table to open
> + TABLE_LIST tables; // List of tables (1 in this case)
> + int ret= 0; // return value
> + Locking_thread_st *locking_thd= NULL; // The locking thread
> +
> + DBUG_ENTER("update_int_field()");
> +
> + locking_thd= open_backup_progress_table(table_name, TL_WRITE);
> + if (!locking_thd)
> + {
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(0);
> + }
> +
> + table= locking_thd->tables_in_backup->table;
> + table->use_all_columns();
> +
> + if (find_online_backup_row(table, backup_id))
> + {
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(1);
> + }
> +
> + store_record(table, record[1]);
> +
> + /*
> + Fill in the data.
> + */
> + table->field[fld]->store(value, TRUE);
> + table->field[fld]->set_notnull();
> +
> + /*
> + Update the row.
> + */
> + if ((ret= table->file->ha_update_row(table->record[1],
> table->record[0])))
> + table->file->print_error(ret, MYF(0));
> +
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(ret);
> +}
> +
> +/**
> + Update a datetime field for 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 and updates the field specified.
> +
> + @param ulonglong backup_id The id of the row to locate.
> + @param char * table_name The name of the table to open.
> + @param enum_ob_table_field fld Field to update.
> + @param my_time_t value Value to set field to.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +int update_online_backup_datetime_field(ulonglong backup_id, char *table_name,
> + enum_ob_table_field fld, my_time_t value)
> +{
> + TABLE *table= NULL; // table to open
> + TABLE_LIST tables; // List of tables (1 in this case)
> + int ret= 0; // return value
> + Locking_thread_st *locking_thd= NULL; // The locking thread
> +
> + DBUG_ENTER("update_int_field()");
> +
> + locking_thd= open_backup_progress_table(table_name, TL_WRITE);
> + if (!locking_thd)
> + {
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(0);
> + }
> +
> + table= locking_thd->tables_in_backup->table;
> + table->use_all_columns();
> +
> + if (find_online_backup_row(table, backup_id))
> + {
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(1);
> + }
> +
> + store_record(table, record[1]);
> +
> + /*
> + Fill in the data.
> + */
> + if (value)
> + {
> + MYSQL_TIME time;
> + my_tz_OFFSET0->gmt_sec_to_TIME(&time, value);
> +
> + table->field[fld]->set_notnull();
> + table->field[fld]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
> + }
> +
> + /*
> + Update the row.
> + */
> + if ((ret= table->file->ha_update_row(table->record[1],
> table->record[0])))
> + table->file->print_error(ret, MYF(0));
> +
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(ret);
> +}
> +
> +/**
> + 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 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 state of the operation
> + @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
> +
> + @returns long backup_id The autoincrement value for the new row.
> + */
> +ulonglong report_ob_init(int process_id,
> + enum_backup_state state,
> + enum_backup_op operation,
> + int error_num,
> + char *user_comment,
> + char *backup_file,
> + char *command)
> +{
> + ulonglong backup_id= 0;
> + int ret= 0; // return value
> + TABLE *table= NULL; // table to open
> + TABLE_LIST tables; // List of tables (1 in this case)
> + char *host= current_thd->security_ctx->host; // host name
> + char *user= current_thd->security_ctx->user; // user name
> + Locking_thread_st *locking_thd= NULL; // The locking thread
> +
> + DBUG_ENTER("report_ob_init()");
> +
> + locking_thd= open_backup_progress_table("online_backup", TL_WRITE);
> + if (!locking_thd)
> + {
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(0);
> + }
> +
> + table= locking_thd->tables_in_backup->table;
> + table->use_all_columns();
> +
> + THD *t= table->in_use;
> + table->in_use= current_thd;
> +
> + /*
> + Get defaults for new record.
> + */
> + restore_record(table, s->default_values);
> +
> + /*
> + Fill in the data.
> + */
> + table->field[ET_FIELD_PROCESS_ID]->store(process_id, TRUE);
> + table->field[ET_FIELD_PROCESS_ID]->set_notnull();
> + table->field[ET_FIELD_BACKUP_STATE]->store(state, TRUE);
> + table->field[ET_FIELD_BACKUP_STATE]->set_notnull();
> + table->field[ET_FIELD_OPER]->store(operation, TRUE);
> + table->field[ET_FIELD_OPER]->set_notnull();
> + table->field[ET_FIELD_ERROR_NUM]->store(error_num, TRUE);
> + table->field[ET_FIELD_ERROR_NUM]->set_notnull();
> +
> + if (host)
> + {
> + if(table->field[ET_FIELD_HOST_OR_SERVER]->store(host,
> + strlen(host), system_charset_info))
> + goto end;
> + table->field[ET_FIELD_HOST_OR_SERVER]->set_notnull();
> + }
> +
> + if (user)
> + {
> + if (table->field[ET_FIELD_USERNAME]->store(user,
> + strlen(user), system_charset_info))
> + goto end;
> + table->field[ET_FIELD_USERNAME]->set_notnull();
> + }
> +
> + if (user_comment)
> + {
> + if (table->field[ET_FIELD_COMMENT]->store(user_comment,
> + strlen(user_comment), system_charset_info))
> + goto end;
> + table->field[ET_FIELD_COMMENT]->set_notnull();
> + }
> +
> + if (backup_file)
> + {
> + if (table->field[ET_FIELD_BACKUP_FILE]->store(backup_file,
> + strlen(backup_file), system_charset_info))
> + goto end;
> + table->field[ET_FIELD_BACKUP_FILE]->set_notnull();
> + }
> +
> + if (command)
> + {
> + if (table->field[ET_FIELD_COMMAND]->store(command,
> + strlen(command), system_charset_info))
> + goto end;
> + table->field[ET_FIELD_COMMAND]->set_notnull();
> + }
> + table->in_use= t;
> +
> + table->next_number_field=table->found_next_number_field;
> +
> + /*
> + Write the row.
> + */
> + if ((ret= table->file->ha_write_row(table->record[0])))
> + table->file->print_error(ret, MYF(0));
> +
> + /*
> + Get last insert id for row.
> + */
> + backup_id= table->file->insert_id_for_cur_row;
> + table->file->ha_release_auto_increment();
> +
> +end:
> +
> + locking_thd->kill_locking_thread();
> + 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 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.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +int report_ob_binlog_info(ulonglong backup_id,
> + int binlog_pos,
> + char *binlog_file)
> +{
> + TABLE *table= NULL; // table to open
> + TABLE_LIST tables; // List of tables (1 in this case)
> + int ret= 0; // return value
> + Locking_thread_st *locking_thd= NULL; // The locking thread
> +
> + DBUG_ENTER("report_ob_binlog_info()");
> +
> + locking_thd= open_backup_progress_table("online_backup", TL_WRITE);
> + if (!locking_thd)
> + {
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(0);
> + }
> +
> + table= locking_thd->tables_in_backup->table;
> + table->use_all_columns();
> +
> + if (find_online_backup_row(table, backup_id))
> + {
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(1);
> + }
> +
> + store_record(table, record[1]);
> +
> + /*
> + Fill in the data.
> + */
> + table->field[ET_FIELD_BINLOG_POS]->store(binlog_pos, TRUE);
> + table->field[ET_FIELD_BINLOG_POS]->set_notnull();
> +
> + THD *t= table->in_use;
> + table->in_use= current_thd;
> +
> + if (binlog_file)
> + {
> + if(table->field[ET_FIELD_BINLOG_FILE]->store(binlog_file,
> + strlen(binlog_file), system_charset_info))
> + goto end;
> + table->field[ET_FIELD_BINLOG_FILE]->set_notnull();
> + }
> + table->in_use= t;
> +
> + /*
> + Update the row.
> + */
> + if ((ret= table->file->ha_update_row(table->record[1],
> table->record[0])))
> + table->file->print_error(ret, MYF(0));
> +
> +end:
> +
> + locking_thd->kill_locking_thread();
> + 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 ulonglong backup_id The id of the row to locate.
> + @param int error_num New error number.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +int report_ob_error(ulonglong backup_id,
> + int error_num)
> +{
> + int ret= 0; // return value
> +
> + DBUG_ENTER("report_ob_error()");
> + update_online_backup_int_field(backup_id, "online_backup",
> + ET_FIELD_ERROR_NUM, error_num);
> + 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 ulonglong backup_id The id of the row to locate.
> + @param int num_objects New error number.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +int report_ob_num_objects(ulonglong backup_id,
> + int num_objects)
> +{
> + int ret= 0; // return value
> +
> + DBUG_ENTER("report_ob_num_objects()");
> + update_online_backup_int_field(backup_id, "online_backup",
> + ET_FIELD_NUM_OBJ, num_objects);
> + 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 ulonglong backup_id The id of the row to locate.
> + @param int size New size value.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +int report_ob_size(ulonglong backup_id,
> + longlong size)
> +{
> + int ret= 0; // return value
> +
> + DBUG_ENTER("report_ob_size()");
> + update_online_backup_int_field(backup_id, "online_backup",
> + ET_FIELD_TOTAL_BYTES, size);
> + 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 ulonglong backup_id The id of the row to locate.
> + @param my_time_t start Start datetime.
> + @param my_time_t stop Stop datetime.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +int report_ob_time(ulonglong backup_id,
> + my_time_t start,
> + my_time_t stop)
> +{
> + int ret= 0; // return value
> +
> + DBUG_ENTER("report_ob_time()");
> + if (start)
> + update_online_backup_datetime_field(backup_id, "online_backup",
> + ET_FIELD_START_TIME, start);
> + if (stop)
> + update_online_backup_datetime_field(backup_id, "online_backup",
> + ET_FIELD_STOP_TIME, stop);
> + 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 ulonglong backup_id The id of the row to locate.
> + @param my_time_t vp_time Validity point datetime.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +int report_ob_vp_time(ulonglong backup_id,
> + my_time_t vp_time)
> +{
> + int ret= 0; // return value
> +
> + DBUG_ENTER("report_ob_vp_time()");
> + if (vp_time)
> + update_online_backup_datetime_field(backup_id, "online_backup",
> + ET_FIELD_VP, vp_time);
> + DBUG_RETURN(ret);
> +}
> +
> +/**
> + Update the engines string for the row that matches the backup_id.
> +
> + This method updates the engines information for the backup operation
> + identified by backup_id. This method appends to the those listed in the
> + table for the backup_id.
> +
> + @param ulonglong backup_id The id of the row to locate.
> + @param char * egnine_name The name of the engine to add.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +int report_ob_engines(ulonglong backup_id,
> + const char *engine_name)
> +{
> + TABLE *table= NULL; // table to open
> + TABLE_LIST tables; // List of tables (1 in this case)
> + int ret= 0; // return value
> + String str; // engines string
> + Locking_thread_st *locking_thd= NULL; // The locking thread
> +
> + DBUG_ENTER("report_ob_engines()");
> +
> + locking_thd= open_backup_progress_table("online_backup", TL_WRITE);
> + if (!locking_thd)
> + {
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(0);
> + }
> +
> + table= locking_thd->tables_in_backup->table;
> + table->use_all_columns();
> +
> + if (find_online_backup_row(table, backup_id))
> + {
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(1);
> + }
> +
> + store_record(table, record[1]);
> +
> + /*
> + Fill in the data.
> + */
> + THD *t= table->in_use;
> + table->in_use= current_thd;
> +
> + str.length(0);
> + table->field[ET_FIELD_ENGINES]->val_str(&str);
> + if (str.length() > 0)
> + str.append(", ");
> + str.append(engine_name);
> + if (str.length() > 0)
> + {
> + if(table->field[ET_FIELD_ENGINES]->store(str.c_ptr(),
> + str.length(), system_charset_info))
> + goto end;
> + table->field[ET_FIELD_ENGINES]->set_notnull();
> + }
> + table->in_use= t;
> +
> + /*
> + Update the row.
> + */
> + if ((ret= table->file->ha_update_row(table->record[1],
> table->record[0])))
> + table->file->print_error(ret, MYF(0));
> +
> +end:
> +
> + locking_thd->kill_locking_thread();
> + 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 ulonglong backup_id The id of the row to locate.
> + @param enum_backup_state state New state value.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +int report_ob_state(ulonglong backup_id,
> + enum_backup_state state)
> +{
> + int ret= 0; // return value
> +
> + DBUG_ENTER("report_ob_state()");
> + update_online_backup_int_field(backup_id, "online_backup",
> + ET_FIELD_BACKUP_STATE, state);
> + 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 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
> +
> + @returns 0 = success
> + @returns 1 = failed to write row
> + */
> +int report_ob_progress(ulonglong backup_id,
> + char *object,
> + my_time_t start,
> + my_time_t stop,
> + longlong size,
> + longlong progress,
> + int error_num,
> + char *notes)
> +{
> + int ret= 0; // return value
> + TABLE *table= NULL; // table to open
> + TABLE_LIST tables; // List of tables (1 in this case)
> + Locking_thread_st *locking_thd= NULL; // The locking thread
> +
> + DBUG_ENTER("report_ob_progress()");
> +
> + locking_thd= open_backup_progress_table("online_backup_progress", TL_WRITE);
> + if (!locking_thd)
> + {
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(0);
> + }
> +
> + table= locking_thd->tables_in_backup->table;
> + table->use_all_columns();
> +
> + THD *t= table->in_use;
> + table->in_use= current_thd;
> +
> + /*
> + Get defaults for new record.
> + */
> + restore_record(table, s->default_values);
> +
> + /*
> + Fill in the data.
> + */
> + table->field[ET_FIELD_BACKUP_ID_FK]->store(backup_id, TRUE);
> + table->field[ET_FIELD_BACKUP_ID_FK]->set_notnull();
> +
> + if (object)
> + {
> + if (table->field[ET_FIELD_PROG_OBJECT]->store(object,
> + strlen(object), system_charset_info))
> + goto end;
> + table->field[ET_FIELD_PROG_OBJECT]->set_notnull();
> + }
> +
> + if (notes)
> + {
> + if (table->field[ET_FIELD_PROG_NOTES]->store(notes,
> + strlen(notes), system_charset_info))
> + goto end;
> + table->field[ET_FIELD_PROG_NOTES]->set_notnull();
> + }
> + table->in_use= t;
> +
> + if (start)
> + {
> + MYSQL_TIME time;
> + my_tz_OFFSET0->gmt_sec_to_TIME(&time, start);
> +
> + table->field[ET_FIELD_PROG_START_TIME]->set_notnull();
> + table->field[ET_FIELD_PROG_START_TIME]->store_time(&time,
> MYSQL_TIMESTAMP_DATETIME);
> + }
> +
> + if (stop)
> + {
> + MYSQL_TIME time;
> + my_tz_OFFSET0->gmt_sec_to_TIME(&time, stop);
> +
> + table->field[ET_FIELD_PROG_STOP_TIME]->set_notnull();
> + table->field[ET_FIELD_PROG_STOP_TIME]->store_time(&time,
> MYSQL_TIMESTAMP_DATETIME);
> + }
> +
> + table->field[ET_FIELD_PROG_SIZE]->store(size, TRUE);
> + table->field[ET_FIELD_PROG_SIZE]->set_notnull();
> + table->field[ET_FIELD_PROGRESS]->store(progress, TRUE);
> + table->field[ET_FIELD_PROGRESS]->set_notnull();
> + table->field[ET_FIELD_PROG_ERROR_NUM]->store(error_num, TRUE);
> + table->field[ET_FIELD_PROG_ERROR_NUM]->set_notnull();
> +
> + /*
> + Write the row.
> + */
> + if ((ret= table->file->ha_write_row(table->record[0])))
> + table->file->print_error(ret, MYF(0));
> +
> +end:
> +
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(ret);
> +}
> +
> +/**
> + Sums the sizes for the row that matches the backup_id.
> +
> + This method sums the size entries from the online backup progress rows
> + for the backup operation identified by backup_id.
> +
> + @param ulonglong backup_id The id of the row to locate.
> +
> + @returns ulonglong Total size of all backup progress rows
> + */
> +ulonglong sum_progress_rows(ulonglong backup_id)
> +{
> + int last_read_res; // result of last read
> + TABLE *table= NULL; // table to open
> + TABLE_LIST tables; // List of tables (1 in this case)
> + ulonglong size= 0; // total size
> + handler *hdl; // handler pointer
> + Locking_thread_st *locking_thd= NULL; // The locking thread
> +
> + DBUG_ENTER("sum_progress_rows()");
> +
> + locking_thd= open_backup_progress_table("online_backup_progress", TL_READ);
> + if (!locking_thd)
> + {
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(0);
> + }
> +
> + table= locking_thd->tables_in_backup->table;
> + table->use_all_columns();
> +
> + hdl= table->file;
> + last_read_res= hdl->ha_rnd_init(1);
> + THD *t= table->in_use;
> + table->in_use= current_thd;
> + while (!hdl->rnd_next(table->record[0]))
> + if ((table->field[ET_FIELD_PROGRESS]->val_int() == 100) &&
> + (table->field[ET_FIELD_PROG_ERROR_NUM]->val_int() == 0) &&
> + (table->field[ET_FIELD_BACKUP_ID_FK]->val_int() == backup_id))
> + size+= table->field[ET_FIELD_PROG_SIZE]->val_int();
> + table->in_use= t;
> +
> + hdl->ha_rnd_end();
> +
> + locking_thd->kill_locking_thread();
> + DBUG_RETURN(size);
> +}
> +
> +/**
> + Print summary for the row that matches the backup_id.
> +
> + This method prints the summary information for the backup operation
> + identified by backup_id.
> +
> + @param ulonglong backup_id The id of the row to locate.
> +
> + @returns 0 = success
> + @returns 1 = failed to find row
> + */
> +int print_backup_summary(THD *thd, ulonglong backup_id)
> +{
> + Protocol *protocol= thd->protocol; // client comms
> + List<Item> field_list; // list of fields to send
> + String op_str; // operations string
> + int ret= 0; // return value
> + char buf[255]; // buffer for summary information
> + String str;
> +
> + DBUG_ENTER("print_backup_summary()");
> +
> + /*
> + Send field list.
> + */
> + op_str.length(0);
> + op_str.append("backup_id");
> + field_list.push_back(new Item_empty_string(op_str.c_ptr(), op_str.length()));
> + protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
> Protocol::SEND_EOF);
> +
> + /*
> + Send field data.
> + */
> + protocol->prepare_for_resend();
> + my_snprintf(buf, sizeof(buf), "%d", backup_id);
> + protocol->store(buf, system_charset_info);
> + protocol->write();
> +
> + send_eof(thd);
> + DBUG_RETURN(ret);
> +}
> +
> diff -Nrup a/sql/backup/backup_progress.h b/sql/backup/backup_progress.h
> --- /dev/null Wed Dec 31 16:00:00 196900
> +++ b/sql/backup/backup_progress.h 2007-11-28 23:31:24 -05:00
> @@ -0,0 +1,195 @@
> +#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.
> +*/
> +
> +#include "my_global.h"
> +#include "my_time.h"
> +#include "mysql_priv.h"
> +
> +/**
> + List of fields for online backup table.
> + */
> +enum enum_ob_table_field
> +{
> + ET_FIELD_BACKUP_ID = 0, /* start from 0 to correspond with field array */
> + ET_FIELD_PROCESS_ID,
> + ET_FIELD_BINLOG_POS,
> + ET_FIELD_BINLOG_FILE,
> + ET_FIELD_BACKUP_STATE,
> + ET_FIELD_OPER,
> + ET_FIELD_ERROR_NUM,
> + ET_FIELD_NUM_OBJ,
> + ET_FIELD_TOTAL_BYTES,
> + ET_FIELD_VP,
> + ET_FIELD_START_TIME,
> + ET_FIELD_STOP_TIME,
> + ET_FIELD_HOST_OR_SERVER,
> + ET_FIELD_USERNAME,
> + ET_FIELD_BACKUP_FILE,
> + ET_FIELD_COMMENT,
> + ET_FIELD_COMMAND,
> + ET_FIELD_ENGINES,
> + ET_FIELD_COUNT /* a cool trick to count the number of fields :) */
> +};
> +
> +/**
> + List of fields for online backup progress table.
> + */
> +enum enum_ob_progress_table_field
> +{
> + ET_FIELD_BACKUP_ID_FK = 0, /* start from 0 to correspond with field array */
> + ET_FIELD_PROG_OBJECT,
> + ET_FIELD_PROG_START_TIME,
> + ET_FIELD_PROG_STOP_TIME,
> + ET_FIELD_PROG_SIZE,
> + ET_FIELD_PROGRESS,
> + ET_FIELD_PROG_ERROR_NUM,
> + ET_FIELD_PROG_NOTES,
> + ET_FIELD_PROG_COUNT /* a cool trick to count the number of fields :) */
> +};
> +
> +/**
> + List of states for online backup table.
> + */
> +enum enum_backup_state
> +{
> + BUP_COMPLETE = 1,
> + BUP_STARTING,
> + BUP_VALIDITY_POINT,
> + BUP_RUNNING,
> + BUP_ERRORS,
> + BUP_CANCEL
> +};
> +
> +/**
> + List of operations for online backup table.
> + */
> +enum enum_backup_op
> +{
> + OP_BACKUP = 1,
> + OP_RESTORE,
> + OP_SHOW,
> + OP_OTHER
> +};
> +
> +/*
> + 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(int process_id,
> + enum_backup_state state,
> + enum_backup_op operation,
> + int error_num,
> + char *user_comment,
> + char *backup_file,
> + char *command);
> +
> +/*
> + This method updates the binary log information for the backup operation
> + identified by backup_id.
> +*/
> +int report_ob_binlog_info(ulonglong backup_id,
> + int binlog_pos,
> + char *binlog_file);
> +
> +/*
> + This method updates the error number for the backup operation identified by
> + backup_id.
> +*/
> +int report_ob_error(ulonglong backup_id,
> + int error_num);
> +
> +/*
> + This method updates the state for the backup operation identified by
> + backup_id.
> +*/
> +int report_ob_state(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(ulonglong backup_id,
> + int num_objects);
> +
> +/*
> + This method updates the size for the backup operation identified by
> + backup_id.
> +*/
> +int report_ob_size(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(ulonglong backup_id,
> + my_time_t start,
> + my_time_t stop);
> +
> +/*
> + This method updates the validity point time for the backup operation
> + identified by backup_id.
> +*/
> +int report_ob_vp_time(ulonglong backup_id,
> + my_time_t vp_time);
> +
> +/*
> + This method updates the engines information for the backup operation
> + identified by backup_id. This method appends to the those listed in the
> + table for the backup_id.
> +*/
> +int report_ob_engines(ulonglong backup_id,
> + const char *engine_name);
> +
> +/*
> + This method inserts a new row in the progress table.
> +*/
> +int report_ob_progress(ulonglong backup_id,
> + char *object,
> + my_time_t start,
> + my_time_t stop,
> + longlong size,
> + longlong progress,
> + int error_num,
> + char *notes);
> +
> +/*
> + This method sums the size entries from the online backup progress rows
> + for the backup operation identified by backup_id.
> +*/
> +ulonglong sum_progress_rows(ulonglong backup_id);
> +
> +/*
> + This method prints the summary information for the backup operation
> + identified by backup_id.
> +*/
> +int print_backup_summary(THD *thd, ulonglong backup_id);
> +
> +#endif
> +
> diff -Nrup a/sql/backup/data_backup.cc b/sql/backup/data_backup.cc
> --- a/sql/backup/data_backup.cc 2007-11-20 09:14:23 -05:00
> +++ b/sql/backup/data_backup.cc 2007-11-28 23:31:22 -05:00
> @@ -1,4 +1,5 @@
> #include "../mysql_priv.h"
> +#include "backup_progress.h"
>
> /**
> @file
> @@ -185,6 +186,19 @@ class Backup_pump
> void set_logger(Logger *log)
> { m_log= log; }
>
> + /*
> + Record the backup id for this driver.
> + */
> + void set_backup_prog_id(ulonglong backup_prog_id)
> + { m_drv->backup_prog_id= backup_prog_id; };
> +
> + /*
> + Record the engine name this driver.
> + Note: must be called after set_backup_prog_id.
> + */
> + void set_backup_prog_engine_name(const char *engine_name)
> + { report_ob_engines(m_drv->backup_prog_id, engine_name); };
I'd not add progress reporting to the responsibilities of the Pump class - it is
perfectly ok to report these things outside. Adding weakly related tasks to a
class weakens modularity of the code...
> +
> private:
>
> static const uint m_buf_size= 2048; ///< Size of buffers used for data
> transfers.
> @@ -513,6 +527,12 @@ int write_table_data(THD* thd, Backup_in
> continue;
>
> Scheduler::Pump *p= new Scheduler::Pump(no,*i,s);
> +
> + /*
> + Record the backup id and name for this driver.
> + */
> + p->set_backup_prog_id(info.backup_prog_id);
> + p->set_backup_prog_engine_name(p->m_name);
It seems pointless to pass objects member value to this objects method - if
method needs this value it can read it directly.
I opt for calling report_ob_engines() and such outside of the Pump object.
>
> if (!p || !p->is_valid())
> {
> @@ -625,6 +645,7 @@ int write_table_data(THD* thd, Backup_in
> // VP creation
> DBUG_PRINT("backup/data",("-- SYNC PHASE --"));
>
> + report_ob_state(info.backup_prog_id, BUP_VALIDITY_POINT);
PROBLEM:
I think it is not acceptable to have such complex thing happen here between
lock()/unlock() calls. Complex because inside report_ob_state() function we
spawn the locking thread, open progress table and potentially write to disk.
> /*
> Block commits.
>
> @@ -651,6 +672,8 @@ int write_table_data(THD* thd, Backup_in
> info.binlog_information.position= li.pos;
> memcpy(info.binlog_information.binlog_file_name,
> li.log_file_name, strlen(li.log_file_name));
> + if (strlen(li.log_file_name) > 0)
> + info.binlog_information.binlog_file_name[strlen(li.log_file_name)]= 0;
> DBUG_PRINT("SYNC PHASE - binlog position : ", ("%d", li.pos));
> DBUG_PRINT("SYNC PHASE - binlog filename : ", ("%s", li.log_file_name));
> }
> @@ -674,6 +697,15 @@ int write_table_data(THD* thd, Backup_in
> if (error)
> goto error;
>
> + BACKUP_BREAKPOINT("bp_validity_point");
> + report_ob_vp_time(info.backup_prog_id, (my_time_t)skr);
> + report_ob_state(info.backup_prog_id, BUP_RUNNING);
> + BACKUP_BREAKPOINT("bp_running");
> +
I think this is executed after VP has been created (after unlock() calls) which
is correct. But then the "bp_validity_point" breakpoint seems missplaced - it is
already past the validity point.
> + if (mysql_bin_log.is_open())
> + report_ob_binlog_info(info.backup_prog_id,
> (int)info.binlog_information.position,
> + info.binlog_information.binlog_file_name);
> +
Minor thing: instead of examining mysql_bin_log again (it was already done above
when binlog pos was saved in the info structure) examine the info structure to
know if there is anything to report.
> // get final data from drivers
> DBUG_PRINT("backup/data",("-- FINISH PHASE --"));
> BACKUP_BREAKPOINT("data_finish");
> @@ -1431,6 +1463,12 @@ int restore_table_data(THD*, Restore_inf
> (img->type() == Image_info::SNAPSHOT_IMAGE))
> get_default_snapshot_tables(NULL, (default_backup::Restore *)drv[no],
> &table_list, &table_list_last);
> +
> + /*
> + Record the backup id and name for this driver.
> + */
> + drv[no]->backup_prog_id= info.backup_prog_id;
> + report_ob_engines(info.backup_prog_id, img->name());
> }
>
> {
> diff -Nrup a/sql/backup/sql_backup.cc b/sql/backup/sql_backup.cc
> --- a/sql/backup/sql_backup.cc 2007-11-23 10:07:24 -05:00
> +++ b/sql/backup/sql_backup.cc 2007-11-28 23:31:23 -05:00
> @@ -31,6 +31,7 @@
> #include "be_default.h"
> #include "be_snapshot.h"
> #include "ddl_blocker.h"
> +#include "backup_progress.h"
>
> namespace backup {
>
> @@ -75,6 +76,7 @@ extern pthread_cond_t COND_DDL_blocker;
> int
> execute_backup_command(THD *thd, LEX *lex)
> {
> + ulonglong backup_prog_id= 0;
> time_t skr;
>
> DBUG_ENTER("execute_backup_command");
> @@ -114,9 +116,21 @@ execute_backup_command(THD *thd, LEX *le
> {
> backup::Restore_info info(*stream);
>
> + info.backup_prog_id= report_ob_init(thd->id, BUP_STARTING, OP_RESTORE,
> + 0, "",
> + lex->backup_dir.str, thd->query);
> + backup_prog_id= info.backup_prog_id;
> + BACKUP_BREAKPOINT("bp_starting");
> +
> if (check_info(thd,info))
> goto restore_error;
>
> + /*
> + Save starting datetime of restore for progress.
> + */
> + skr= my_time(0);
> + report_ob_time(info.backup_prog_id, (my_time_t)skr, NULL);
> +
> if (lex->sql_command == SQLCOM_SHOW_ARCHIVE)
> {
> my_error(ER_NOT_ALLOWED_COMMAND,MYF(0));
> @@ -131,6 +145,9 @@ execute_backup_command(THD *thd, LEX *le
> {
> info.report_error(backup::log_level::INFO,ER_BACKUP_RESTORE_START);
>
> + report_ob_state(info.backup_prog_id, BUP_RUNNING);
> + BACKUP_BREAKPOINT("bp_running");
> +
> /*
> Freeze all DDL operations by turning on DDL blocker.
> */
> @@ -150,12 +167,22 @@ execute_backup_command(THD *thd, LEX *le
> report_errors(thd,info,ER_BACKUP_RESTORE);
> goto restore_error;
> }
> - else
> - {
> - info.report_error(backup::log_level::INFO,ER_BACKUP_RESTORE_DONE);
> - info.total_size += info.header_size;
> - send_summary(thd,info);
> - }
> +
> + report_ob_num_objects(info.backup_prog_id, info.table_count);
> + report_ob_size(info.backup_prog_id, info.data_size);
> +
> + /*
> + Save ending datetime of restore for progress.
> + */
> + skr= my_time(0);
> + report_ob_time(info.backup_prog_id, NULL, (my_time_t)skr);
> + report_ob_state(info.backup_prog_id, BUP_COMPLETE);
> + BACKUP_BREAKPOINT("bp_complete");
> +
> + info.report_error(backup::log_level::INFO,ER_BACKUP_RESTORE_DONE);
> + info.total_size += info.header_size;
> + report_ob_size(info.backup_prog_id, info.total_size);
> + send_summary(thd,info);
>
> /*
> Unfreeze all DDL operations by turning off DDL blocker.
> @@ -177,6 +204,11 @@ execute_backup_command(THD *thd, LEX *le
> BACKUP_BREAKPOINT("DDL_unblocked");
>
> res= res ? res : backup::ERROR;
> + report_ob_error(backup_prog_id, res);
> + report_ob_state(backup_prog_id, BUP_ERRORS);
> + skr= my_time(0);
> + report_ob_time(backup_prog_id, NULL, (my_time_t)skr);
> + BACKUP_BREAKPOINT("bp_error");
>
> finish_restore:
>
> @@ -210,9 +242,18 @@ execute_backup_command(THD *thd, LEX *le
>
> backup::Backup_info info(thd);
>
> + info.backup_prog_id= report_ob_init(thd->id, BUP_STARTING, OP_BACKUP,
> + 0, "",
> + lex->backup_dir.str, thd->query);
> + backup_prog_id= info.backup_prog_id;
> + BACKUP_BREAKPOINT("bp_starting");
> +
> if (check_info(thd,info))
> goto backup_error;
>
> + report_ob_state(info.backup_prog_id, BUP_RUNNING);
> + BACKUP_BREAKPOINT("bp_running");
> +
> info.report_error(backup::log_level::INFO,ER_BACKUP_BACKUP_START);
>
> /*
> @@ -221,6 +262,8 @@ execute_backup_command(THD *thd, LEX *le
> skr= my_time(0);
> gmtime_r(&skr, &info.start_time);
>
> + report_ob_time(info.backup_prog_id, (my_time_t)skr, NULL);
> +
> info.save_errors();
>
> if (lex->db_list.is_empty())
> @@ -234,6 +277,8 @@ execute_backup_command(THD *thd, LEX *le
> info.add_dbs(lex->db_list); // backup databases specified by user
> }
>
> + report_ob_num_objects(info.backup_prog_id, info.table_count);
> +
> if (check_info(thd,info))
> goto backup_error;
>
> @@ -249,11 +294,8 @@ execute_backup_command(THD *thd, LEX *le
> report_errors(thd,info,ER_BACKUP_BACKUP);
> goto backup_error;
> }
> - else
> - {
> - info.report_error(backup::log_level::INFO,ER_BACKUP_BACKUP_DONE);
> - send_summary(thd,info);
> - }
> +
> + report_ob_size(info.backup_prog_id, info.data_size);
>
> /*
> Save ending datetime of backup.
> @@ -261,6 +303,14 @@ execute_backup_command(THD *thd, LEX *le
> skr= my_time(0);
> gmtime_r(&skr, &info.end_time);
>
> + report_ob_time(info.backup_prog_id, NULL, (my_time_t)skr);
> + report_ob_state(info.backup_prog_id, BUP_COMPLETE);
> + BACKUP_BREAKPOINT("bp_complete");
> +
> + info.report_error(backup::log_level::INFO,ER_BACKUP_BACKUP_DONE);
> + report_ob_size(info.backup_prog_id, info.total_size);
> + send_summary(thd,info);
> +
> /*
> Unfreeze all DDL operations by turning off DDL blocker.
> */
> @@ -278,7 +328,12 @@ execute_backup_command(THD *thd, LEX *le
> */
> unblock_DDL();
> res= res ? res : backup::ERROR;
> -
> + report_ob_error(backup_prog_id, res);
> + report_ob_state(backup_prog_id, BUP_ERRORS);
> + skr= my_time(0);
> + report_ob_time(backup_prog_id, NULL, (my_time_t)skr);
> + BACKUP_BREAKPOINT("bp_error");
> +
> finish_backup:
>
> if (stream)
> @@ -1319,54 +1374,8 @@ int check_info(THD *thd, Restore_info &i
> static
> bool send_summary(THD *thd, const Archive_info &info, bool backup)
> {
> - Protocol *protocol= ::current_thd->protocol; // client comms
> - List<Item> field_list; // list of fields to send
> - Item *item; // field item
> - char buf[255]; // buffer for data
> - String op_str; // operations string
> - String print_str; // string to print
> -
> DBUG_ENTER("backup::send_summary");
> -
> - DBUG_PRINT(backup?"backup":"restore", ("sending summary"));
> -
> - op_str.length(0);
> - if (backup)
> - op_str.append("Backup Summary");
> - else
> - op_str.append("Restore Summary");
> -
> -
> - field_list.push_back(item= new Item_empty_string(op_str.c_ptr(),255)); // TODO:
> use varchar field
> - item->maybe_null= TRUE;
> - protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
> Protocol::SEND_EOF);
> -
> - my_snprintf(buf,sizeof(buf)," header = %-8lu bytes",(unsigned
> long)info.header_size);
> - protocol->prepare_for_resend();
> - protocol->store(buf,system_charset_info);
> - protocol->write();
> -
> - my_snprintf(buf,sizeof(buf)," meta-data = %-8lu bytes",(unsigned
> long)info.meta_size);
> - protocol->prepare_for_resend();
> - protocol->store(buf,system_charset_info);
> - protocol->write();
> -
> - my_snprintf(buf,sizeof(buf)," data = %-8lu bytes",(unsigned
> long)info.data_size);
> - protocol->prepare_for_resend();
> - protocol->store(buf,system_charset_info);
> - protocol->write();
> -
> - my_snprintf(buf,sizeof(buf)," --------------");
> - protocol->prepare_for_resend();
> - protocol->store(buf,system_charset_info);
> - protocol->write();
> -
> - my_snprintf(buf,sizeof(buf)," total %-8lu bytes", (unsigned
> long)info.total_size);
> - protocol->prepare_for_resend();
> - protocol->store(buf,system_charset_info);
> - protocol->write();
> -
> - send_eof(thd);
> + print_backup_summary(thd, info.backup_prog_id);
> DBUG_RETURN(0);
> }
>
Rafal