Patch looks good. Approved.
--
Øystein
Chuck Bell wrote:
> #At file:///C:/source/bzr/mysql-6.0-wl-4209/
>
> 2720 Chuck Bell 2008-10-29
> WL#4209 : Integrate Backup with Replication
>
> This patch makes changes to the backup system to allow backup to
> be used with replication.
> added:
> mysql-test/suite/rpl/r/rpl_backup.result
> mysql-test/suite/rpl/t/rpl_backup.test
> modified:
> sql/backup/backup_kernel.h
> sql/backup/data_backup.cc
> sql/backup/kernel.cc
> sql/backup/logger.h
> sql/log.cc
> sql/share/errmsg.txt
> sql/si_logs.cc
> sql/si_logs.h
>
> per-file messages:
> mysql-test/suite/rpl/r/rpl_backup.result
> New result file.
> mysql-test/suite/rpl/t/rpl_backup.test
> New test for backup and replication integration.
> sql/backup/backup_kernel.h
> Added attribute to allow close() to reengage the binlog if it was turned off.
> sql/backup/data_backup.cc
> Add code to record master's binlog information when backup run on a slave.
> sql/backup/kernel.cc
> Add calls to service interface to allow the following during restore:
> * Disable slave connections when running with connected slaves
> * Issue incident report when binlog is engaged
> * Issue error if restore run on a slave
> * Enable slave connections after restore
> * Save master's binlog information when restore run on a (disconnected) slave :
> used when slave is connected to master after restore begins.
> sql/backup/logger.h
> Added new method to report master's binlog position in backup_progress log.
> sql/log.cc
> Add code to disable binlog of backup log entries.
> sql/share/errmsg.txt
> New error message added.
> sql/si_logs.cc
> Added method definition for writing master's binlog information to progress log.
> sql/si_logs.h
> Added method declaration for writing master's binlog information to progress
> log.
> === added file 'mysql-test/suite/rpl/r/rpl_backup.result'
> --- a/mysql-test/suite/rpl/r/rpl_backup.result 1970-01-01 00:00:00 +0000
> +++ b/mysql-test/suite/rpl/r/rpl_backup.result 2008-10-29 19:10:00 +0000
> @@ -0,0 +1,220 @@
> +stop slave;
> +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
> +reset master;
> +reset slave;
> +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
> +start slave;
> +Create some data...
> +CREATE DATABASE rpl_backup;
> +CREATE TABLE rpl_backup.t1 (a int) ENGINE=MEMORY;
> +INSERT INTO rpl_backup.t1 VALUES (1), (2), (3), (4), (5);
> +Remove all entries in the backup logs.
> +FLUSH BACKUP LOGS;
> +PURGE BACKUP LOGS;
> +Remove all entries in the backup logs.
> +FLUSH BACKUP LOGS;
> +PURGE BACKUP LOGS;
> +Get master's binlog position from the slave before backup.
> +Get master's binlog position before backup.
> +SET SESSION debug="+d,set_backup_id";
> +Backup_id = 500.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_m1.bak';
> +backup_id
> +500
> +SET SESSION debug="-d";
> +Show any events issued as a result of backup.
> +Note: There should be none!
> +Log_name Pos Event_type Server_id End_log_pos Info
> +Verify backup run on master does not advance binlog pos.
> +Get master's binlog position after backup.
> +Compute the difference of the binlog positions.
> +Result should be 0.
> +Compare the before position of the master's binlog to
> +the after position of the master's binlog. The result
> +should be 0.
> +Delta
> +0
> +Should have count(*) = 0.
> +SELECT count(*) FROM mysql.backup_history;
> +count(*)
> +0
> +Verify backup run on master does not advance binlog pos.
> +Get master's binlog position on the slave after backup.
> +Compute the difference of the binlog positions.
> +Result should be 0.
> +Compare the before position of the master's binlog to
> +the after position of the master's binlog as shown on
> +on the slave. The result should be 0.
> +Delta
> +0
> +Ensure replication is still working...
> +Cleanup from last error on master and slave.
> +DROP TABLE rpl_backup.t1;
> +CREATE TABLE rpl_backup.t1 (a int) ENGINE=MEMORY;
> +INSERT INTO rpl_backup.t1 VALUES (11), (22), (33);
> +SELECT count(*) FROM rpl_backup.t1;
> +count(*)
> +3
> +SELECT count(*) FROM rpl_backup.t1;
> +count(*)
> +3
> +Cleanup backup logs.
> +FLUSH BACKUP LOGS;
> +PURGE BACKUP LOGS;
> +SET SESSION debug="+d,set_backup_id";
> +Backup_id = 600.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_s1.bak';
> +backup_id
> +600
> +SET SESSION debug="-d";
> +Check saving of master's binlog information.
> +Should have count(*) = 1.
> +SELECT count(*) FROM mysql.backup_progress
> +WHERE backup_id = 600 AND notes LIKE 'Recording master binlog information%';
> +count(*)
> +1
> +Should have count(*) = 1.
> +SELECT count(*) FROM mysql.backup_history;
> +count(*)
> +1
> +Backup_id = 501.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_m2.bak';
> +backup_id
> +501
> +Ensure replication is still working...
> +INSERT INTO rpl_backup.t1 VALUES (10), (20), (30);
> +Backup_id = 502.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_m3.bak';
> +backup_id
> +502
> +SELECT count(*) FROM rpl_backup.t1;
> +count(*)
> +6
> +SELECT count(*) FROM rpl_backup.t1;
> +count(*)
> +6
> +Make a backup for later use.
> +backup_id = 601.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_s2.bak';
> +backup_id
> +601
> +DROP DATABASE rpl_backup;
> +Get master's binlog position before restore.
> +backup_id = 503.
> +RESTORE FROM 'rpl_bup_m3.bak';
> +backup_id
> +503
> +Show the incident event issued as a result of restore.
> +Log_name Pos Event_type Server_id End_log_pos Info
> +master-bin.000001 # Incident 1 # #2 ((null))
> +master-bin.000001 # Rotate 1 # master-bin.000002;pos=4
> +Showing databases on master.
> +SHOW DATABASES LIKE 'rpl_backup%';
> +Database (rpl_backup%)
> +rpl_backup
> +SELECT count(*) FROM rpl_backup.t1;
> +count(*)
> +6
> +STOP SLAVE;
> +Show the slave stopped with an error.
> +Last_SQL_Error
> +The incident (null) occured on the master. Message: A restore operation was
> initiated on the master.
> +SET global sql_slave_skip_counter=1;
> +START SLAVE;
> +Showing databases on slave.
> +SHOW DATABASES LIKE 'rpl_backup%';
> +Database (rpl_backup%)
> +STOP SLAVE;
> +backup_id = 602.
> +RESTORE FROM 'rpl_bup_s2.bak';
> +backup_id
> +602
> +Showing databases on slave.
> +SHOW DATABASES LIKE 'rpl_backup%';
> +Database (rpl_backup%)
> +rpl_backup
> +SELECT count(*) FROM rpl_backup.t1;
> +count(*)
> +6
> +START SLAVE;
> +Make a backup for later use.
> +backup_id = 603.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_s3.bak';
> +backup_id
> +603
> +Test restore on slave while replication turned on.
> +RESTORE FROM 'rpl_bup_s1.bak';
> +ERROR HY000: A restore operation was attempted on a slave during replication. You
> must stop the slave prior to running a restore.
> +Stop slave and restart after restore.
> +STOP SLAVE;
> +RESTORE FROM 'rpl_bup_s3.bak';
> +backup_id
> +#
> +START SLAVE;
> +Checking affect on replication.
> +INSERT INTO rpl_backup.t1 VALUES (44), (55), (66);
> +SELECT * FROM rpl_backup.t1 ORDER BY a;
> +a
> +10
> +11
> +20
> +22
> +30
> +33
> +44
> +55
> +66
> +SELECT * FROM rpl_backup.t1 ORDER BY a;
> +a
> +10
> +11
> +20
> +22
> +30
> +33
> +44
> +55
> +66
> +Stop replication and turn off binary log.
> +STOP SLAVE;
> +SET @orig_sql_log_bin= @@sql_log_bin;
> +Turn off binlog.
> +SET @@sql_log_bin= 0;
> +SHOW VARIABLES LIKE '%log_bin';
> +Variable_name Value
> +log_bin ON
> +sql_log_bin OFF
> +backup_id = 504.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_m4.bak';
> +backup_id
> +504
> +Turn on binlog;
> +SET @@sql_log_bin= @orig_sql_log_bin;
> +SHOW VARIABLES LIKE '%log_bin';
> +Variable_name Value
> +log_bin ON
> +sql_log_bin ON
> +RESET MASTER;
> +Get master's binlog position before restore.
> +backup_id = 505.
> +RESTORE FROM 'rpl_bup_m4.bak';
> +backup_id
> +505
> +Get master's binlog position after restore.
> +Show the incident event issued as a result of restore.
> +Log_name Pos Event_type Server_id End_log_pos Info
> +master-bin.000001 # Incident 1 # #2 ((null))
> +master-bin.000001 # Rotate 1 # master-bin.000002;pos=4
> +Compute the difference of the binlog positions.
> +Result should be 0.
> +Compare the before position of the master's binlog to
> +the after position of the master's binlog. The result
> +should be 0.
> +Delta
> +0
> +FLUSH BACKUP LOGS;
> +PURGE BACKUP LOGS;
> +DROP DATABASE rpl_backup;
> +FLUSH BACKUP LOGS;
> +PURGE BACKUP LOGS;
> +DROP DATABASE rpl_backup;
>
> === added file 'mysql-test/suite/rpl/t/rpl_backup.test'
> --- a/mysql-test/suite/rpl/t/rpl_backup.test 1970-01-01 00:00:00 +0000
> +++ b/mysql-test/suite/rpl/t/rpl_backup.test 2008-10-29 19:10:00 +0000
> @@ -0,0 +1,359 @@
> +#
> +# Test backup and replication integration.
> +#
> +
> +--source include/master-slave.inc
> +--source include/not_embedded.inc
> +--source include/have_debug_sync.inc
> +--source include/have_debug.inc
> +
> +connection master;
> +
> +--echo Create some data...
> +CREATE DATABASE rpl_backup;
> +CREATE TABLE rpl_backup.t1 (a int) ENGINE=MEMORY;
> +INSERT INTO rpl_backup.t1 VALUES (1), (2), (3), (4), (5);
> +
> +#
> +# Use Case 1 - Backup performed on a master.
> +# When a backup is performed on a master, the master shall not log
> +# the backup event nor shall the master replicate any data produced
> +# (logged) by the backup.
> +
> +--echo Remove all entries in the backup logs.
> +FLUSH BACKUP LOGS;
> +PURGE BACKUP LOGS;
> +
> +connection slave;
> +
> +--echo Remove all entries in the backup logs.
> +FLUSH BACKUP LOGS;
> +PURGE BACKUP LOGS;
> +
> +--echo Get master's binlog position from the slave before backup.
> +let $slave_before_pos =
> + query_get_value("SHOW SLAVE STATUS", Read_Master_Log_Pos, 1);
> +
> +connection master;
> +
> +--echo Get master's binlog position before backup.
> +let $master_before_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
> +
> +#
> +# Now test read of backupid with known id using debug insertion
> +#
> +SET SESSION debug="+d,set_backup_id";
> +
> +# We are using debug insertion to set the first backup_id to
> +# 500 so we can expect the output of this operation to be 500.
> +--echo Backup_id = 500.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_m1.bak';
> +
> +SET SESSION debug="-d";
> +
> +--echo Show any events issued as a result of backup.
> +--echo Note: There should be none!
> +--disable_query_log
> +eval SHOW BINLOG EVENTS FROM $master_before_pos;
> +--enable_query_log
> +
> +--echo Verify backup run on master does not advance binlog pos.
> +--echo Get master's binlog position after backup.
> +let $master_after_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
> +
> +--echo Compute the difference of the binlog positions.
> +--echo Result should be 0.
> +--disable_query_log
> +--echo Compare the before position of the master's binlog to
> +--echo the after position of the master's binlog. The result
> +--echo should be 0.
> +eval SELECT $master_after_pos - $master_before_pos AS Delta;
> +--enable_query_log
> +
> +#
> +# Now check slave to see if backup logs are affected.
> +# Check slave's master position.
> +# Ensure replication is still working.
> +#
> +sync_slave_with_master;
> +connection slave;
> +
> +--echo Should have count(*) = 0.
> +SELECT count(*) FROM mysql.backup_history;
> +
> +--echo Verify backup run on master does not advance binlog pos.
> +--echo Get master's binlog position on the slave after backup.
> +let $slave_after_pos =
> + query_get_value("SHOW SLAVE STATUS", Read_Master_Log_Pos, 1);
> +
> +--echo Compute the difference of the binlog positions.
> +--echo Result should be 0.
> +--disable_query_log
> +--echo Compare the before position of the master's binlog to
> +--echo the after position of the master's binlog as shown on
> +--echo on the slave. The result should be 0.
> +eval SELECT $slave_after_pos - $slave_before_pos AS Delta;
> +--enable_query_log
> +
> +connection master;
> +
> +--echo Ensure replication is still working...
> +--echo Cleanup from last error on master and slave.
> +DROP TABLE rpl_backup.t1;
> +
> +CREATE TABLE rpl_backup.t1 (a int) ENGINE=MEMORY;
> +
> +INSERT INTO rpl_backup.t1 VALUES (11), (22), (33);
> +
> +SELECT count(*) FROM rpl_backup.t1;
> +
> +sync_slave_with_master;
> +connection slave;
> +
> +SELECT count(*) FROM rpl_backup.t1;
> +
> +--echo Cleanup backup logs.
> +FLUSH BACKUP LOGS;
> +PURGE BACKUP LOGS;
> +
> +#
> +# Use Case 3 - Backup performed on a slave (part 1 of 2)
> +# Test backup on slave where slave has no slaves.
> +# Also, verify master's binlog information is saved to
> +# the progress log.
> +#
> +
> +#
> +# Now test read of backupid with known id using debug insertion
> +#
> +
> +SET SESSION debug="+d,set_backup_id";
> +
> +# We are using debug insertion to set the first backup_id to
> +# 600 so we can expect the output of this operation to be 600.
> +--echo Backup_id = 600.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_s1.bak';
> +
> +SET SESSION debug="-d";
> +
> +--echo Check saving of master's binlog information.
> +--echo Should have count(*) = 1.
> +SELECT count(*) FROM mysql.backup_progress
> +WHERE backup_id = 600 AND notes LIKE 'Recording master binlog information%';
> +
> +--echo Should have count(*) = 1.
> +SELECT count(*) FROM mysql.backup_history;
> +
> +connection master;
> +
> +--echo Backup_id = 501.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_m2.bak';
> +
> +--echo Ensure replication is still working...
> +
> +INSERT INTO rpl_backup.t1 VALUES (10), (20), (30);
> +
> +--echo Backup_id = 502.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_m3.bak';
> +
> +SELECT count(*) FROM rpl_backup.t1;
> +
> +sync_slave_with_master;
> +connection slave;
> +
> +SELECT count(*) FROM rpl_backup.t1;
> +
> +--echo Make a backup for later use.
> +--echo backup_id = 601.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_s2.bak';
> +
> +#
> +# Use Case 2 - Restore performed on a master.
> +#
> +
> +# To ensure the master does not log anything in the binary log
> +# during a restore, we first drop the database on the slave
> +# then run the restore and after slave is restarted check to
> +# see if database is still missing (it should be).
> +
> +connection slave;
> +
> +DROP DATABASE rpl_backup;
> +
> +connection master;
> +
> +--echo Get master's binlog position before restore.
> +let $master_before_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
> +
> +--echo backup_id = 503.
> +RESTORE FROM 'rpl_bup_m3.bak';
> +
> +--echo Show the incident event issued as a result of restore.
> +--replace_column 2 # 5 #
> +--disable_query_log
> +eval SHOW BINLOG EVENTS FROM $master_before_pos;
> +--enable_query_log
> +
> +--echo Showing databases on master.
> +SHOW DATABASES LIKE 'rpl_backup%';
> +
> +SELECT count(*) FROM rpl_backup.t1;
> +
> +source include/wait_for_slave_sql_to_stop.inc;
> +
> +connection slave;
> +
> +STOP SLAVE;
> +--source include/wait_for_slave_to_stop.inc
> +
> +--echo Show the slave stopped with an error.
> +LET $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
> +disable_query_log;
> +eval SELECT "$last_error" AS Last_SQL_Error;
> +enable_query_log;
> +
> +SET global sql_slave_skip_counter=1;
> +
> +START SLAVE;
> +--source include/wait_for_slave_to_start.inc
> +
> +# Sync with master to ensure nothing is replicated after incident event.
> +sync_with_master;
> +
> +--echo Showing databases on slave.
> +SHOW DATABASES LIKE 'rpl_backup%';
> +
> +# Now stop the slave, do the restore, then restart.
> +STOP SLAVE;
> +--source include/wait_for_slave_to_stop.inc
> +
> +--echo backup_id = 602.
> +RESTORE FROM 'rpl_bup_s2.bak';
> +
> +--echo Showing databases on slave.
> +SHOW DATABASES LIKE 'rpl_backup%';
> +
> +SELECT count(*) FROM rpl_backup.t1;
> +
> +START SLAVE;
> +--source include/wait_for_slave_to_start.inc
> +
> +--echo Make a backup for later use.
> +--echo backup_id = 603.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_s3.bak';
> +
> +#
> +# Use Case 4 - Restore performed on a slave.
> +#
> +
> +connection slave;
> +
> +--echo Test restore on slave while replication turned on.
> +
> +--error ER_RESTORE_ON_SLAVE
> +RESTORE FROM 'rpl_bup_s1.bak';
> +
> +--echo Stop slave and restart after restore.
> +STOP SLAVE;
> +
> +--replace_column 1 #
> +RESTORE FROM 'rpl_bup_s3.bak';
> +
> +START SLAVE;
> +--source include/wait_for_slave_to_start.inc
> +
> +connection master;
> +
> +--echo Checking affect on replication.
> +INSERT INTO rpl_backup.t1 VALUES (44), (55), (66);
> +SELECT * FROM rpl_backup.t1 ORDER BY a;
> +
> +sync_slave_with_master;
> +connection slave;
> +SELECT * FROM rpl_backup.t1 ORDER BY a;
> +
> +#
> +# Use Case 3 - Backup performed on a slave (part 2 of 2)
> +# Test backup on slave with another slave attached.
> +#
> +# Note: To be added as part of WL#4612
> +
> +#
> +# Use Case 5 - Backup run with no binary log.
> +#
> +
> +--echo Stop replication and turn off binary log.
> +connection slave;
> +
> +STOP SLAVE;
> +--source include/wait_for_slave_to_stop.inc
> +
> +connection master;
> +
> +SET @orig_sql_log_bin= @@sql_log_bin;
> +
> +--echo Turn off binlog.
> +SET @@sql_log_bin= 0;
> +SHOW VARIABLES LIKE '%log_bin';
> +
> +--echo backup_id = 504.
> +BACKUP DATABASE rpl_backup TO 'rpl_bup_m4.bak';
> +
> +--echo Turn on binlog;
> +SET @@sql_log_bin= @orig_sql_log_bin;
> +SHOW VARIABLES LIKE '%log_bin';
> +
> +#
> +# Use Case 6 - Restore run with binary log turned on but no slaves attached.
> +#
> +
> +RESET MASTER;
> +
> +--echo Get master's binlog position before restore.
> +let $master_before_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
> +
> +--echo backup_id = 505.
> +RESTORE FROM 'rpl_bup_m4.bak';
> +
> +--echo Get master's binlog position after restore.
> +let $master_after_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
> +
> +--echo Show the incident event issued as a result of restore.
> +--replace_column 2 # 5 #
> +--disable_query_log
> +eval SHOW BINLOG EVENTS FROM $master_before_pos;
> +--enable_query_log
> +
> +--echo Compute the difference of the binlog positions.
> +--echo Result should be 0.
> +--disable_query_log
> +--echo Compare the before position of the master's binlog to
> +--echo the after position of the master's binlog. The result
> +--echo should be 0.
> +eval SELECT $master_after_pos - $master_before_pos AS Delta;
> +--enable_query_log
> +
> +#
> +# Cleanup
> +#
> +connection master;
> +
> +FLUSH BACKUP LOGS;
> +PURGE BACKUP LOGS;
> +DROP DATABASE rpl_backup;
> +
> +--remove_file $MYSQLTEST_VARDIR/master-data/rpl_bup_m1.bak
> +--remove_file $MYSQLTEST_VARDIR/master-data/rpl_bup_m2.bak
> +--remove_file $MYSQLTEST_VARDIR/master-data/rpl_bup_m3.bak
> +--remove_file $MYSQLTEST_VARDIR/master-data/rpl_bup_m4.bak
> +
> +connection slave;
> +
> +FLUSH BACKUP LOGS;
> +PURGE BACKUP LOGS;
> +DROP DATABASE rpl_backup;
> +
> +--remove_file $MYSQLTEST_VARDIR/slave-data/rpl_bup_s1.bak
> +--remove_file $MYSQLTEST_VARDIR/slave-data/rpl_bup_s2.bak
> +--remove_file $MYSQLTEST_VARDIR/slave-data/rpl_bup_s3.bak
> +
>
> === modified file 'sql/backup/backup_kernel.h'
> --- a/sql/backup/backup_kernel.h 2008-10-27 13:06:21 +0000
> +++ b/sql/backup/backup_kernel.h 2008-10-29 19:10:00 +0000
> @@ -134,6 +134,12 @@ class Backup_restore_ctx: public backup:
> */
> bool m_tables_locked;
>
> + /**
> + Indicates we must turn binlog back on in the close method. This is
> + set to TRUE in the prepare_for_restore() method.
> + */
> + bool m_engage_binlog;
> +
> int lock_tables_for_restore();
> void unlock_tables();
>
>
> === modified file 'sql/backup/data_backup.cc'
> --- a/sql/backup/data_backup.cc 2008-10-14 12:08:56 +0000
> +++ b/sql/backup/data_backup.cc 2008-10-29 19:10:00 +0000
> @@ -627,6 +627,13 @@ int write_table_data(THD* thd, Backup_in
> info.m_ctx.report_binlog_pos(info.binlog_pos);
> }
>
> + /*
> + If we are a connected slave, write master's binlog information to
> + the progress log for later use.
> + */
> + if (obs::is_slave())
> + info.m_ctx.report_master_binlog_pos(active_mi);
> +
> info.m_ctx.report_state(BUP_RUNNING);
> DEBUG_SYNC(thd, "after_backup_binlog");
>
>
> === modified file 'sql/backup/kernel.cc'
> --- a/sql/backup/kernel.cc 2008-10-28 14:17:05 +0000
> +++ b/sql/backup/kernel.cc 2008-10-29 19:10:00 +0000
> @@ -211,6 +211,14 @@ execute_backup_command(THD *thd, LEX *le
>
> case SQLCOM_RESTORE:
> {
> + bool turn_on_binlog= FALSE;
> +
> + /*
> + Restore cannot be run on a slave while connected to a master.
> + */
> + if (obs::is_slave())
> + DBUG_RETURN(send_error(context, ER_RESTORE_ON_SLAVE));
> +
> Restore_info *info= context.prepare_for_restore(backupdir, lex->backup_dir,
> thd->query);
>
> @@ -378,7 +386,8 @@ pthread_mutex_t Backup_restore_ctx::run_
> Backup_restore_ctx::Backup_restore_ctx(THD *thd)
> :Logger(thd), m_state(CREATED), m_thd_options(thd->options),
> m_error(0), m_remove_loc(FALSE), m_stream(NULL),
> - m_catalog(NULL), mem_alloc(NULL), m_tables_locked(FALSE)
> + m_catalog(NULL), mem_alloc(NULL), m_tables_locked(FALSE),
> + m_engage_binlog(FALSE)
> {
> /*
> Check for progress tables.
> @@ -785,6 +794,25 @@ Backup_restore_ctx::prepare_for_restore(
>
> m_state= PREPARED_FOR_RESTORE;
>
> + /*
> + Do not allow slaves to connect during a restore.
> +
> + If the binlog is turned on, write a RESTORE_EVENT as an
> + incident report into the binary log.
> +
> + Turn off binlog during restore.
> + */
> + if (obs::is_binlog_engaged())
> + {
> + obs::disable_slave_connections(TRUE);
> +
> + DEBUG_SYNC(m_thd, "after_disable_slave_connections");
> +
> + obs::write_incident_event(m_thd, obs::RESTORE_EVENT);
> + m_engage_binlog= TRUE;
> + obs::engage_binlog(FALSE);
> + }
> +
> return info;
> }
>
> @@ -922,6 +950,17 @@ int Backup_restore_ctx::close()
> return 0;
>
> using namespace backup;
> +
> + /*
> + Allow slaves connect after restore is complete.
> + */
> + obs::disable_slave_connections(FALSE);
> +
> + /*
> + Turn binlog back on iff it was turned off earlier.
> + */
> + if (m_engage_binlog)
> + obs::engage_binlog(TRUE);
>
> time_t when= my_time(0);
>
>
> === modified file 'sql/backup/logger.h'
> --- a/sql/backup/logger.h 2008-10-27 13:06:21 +0000
> +++ b/sql/backup/logger.h 2008-10-29 19:10:00 +0000
> @@ -5,6 +5,7 @@
> #include <backup_stream.h>
> #include <backup/error.h>
> #include "si_logs.h"
> +#include "rpl_mi.h"
>
> namespace backup {
>
> @@ -56,6 +57,7 @@ class Logger
> void report_state(enum_backup_state);
> void report_vp_time(time_t, bool);
> void report_binlog_pos(const st_bstream_binlog_pos&);
> + void report_master_binlog_pos(Master_info *active_mi);
> void report_driver(const char *driver);
> void report_backup_file(char * path);
> void report_stats_pre(const Image_info&);
> @@ -220,6 +222,10 @@ void Logger::report_stop(time_t when, bo
> backup_log->stop(when);
> backup_log->state(success ? BUP_COMPLETE : BUP_ERRORS);
> backup_log->write_history();
> + /*
> + Record master's binlog file and position if recorded earlier.
> + */
> + backup_log->write_master_binlog_info();
> m_state= DONE;
> }
>
> @@ -267,6 +273,21 @@ void Logger::report_binlog_pos(const st_
> DBUG_ASSERT(backup_log);
> backup_log->binlog_pos(pos.pos);
> backup_log->binlog_file(pos.file);
> +}
> +
> +/**
> + Report master's binlog information.
> +
> + @todo Write this information to the backup image file.
> +*/
> +inline
> +void Logger::report_master_binlog_pos(Master_info *active_mi)
> +{
> + if (active_mi)
> + {
> + backup_log->master_binlog_pos((ulong)active_mi->master_log_pos);
> + backup_log->master_binlog_file(active_mi->master_log_name);
> + }
> }
>
> /**
>
> === modified file 'sql/log.cc'
> --- a/sql/log.cc 2008-10-28 14:17:05 +0000
> +++ b/sql/log.cc 2008-10-29 19:10:00 +0000
> @@ -29,6 +29,7 @@
> #include "rpl_filter.h"
> #include "rpl_rli.h"
> #include "sql_audit.h"
> +#include "si_objects.h"
>
> #include <my_dir.h>
> #include <stdarg.h>
> @@ -778,10 +779,18 @@ bool Log_to_csv_event_handler::
> bool need_close= FALSE;
> bool need_rnd_end= FALSE;
> Open_tables_state open_tables_backup;
> + ulonglong save_thd_options;
> bool save_time_zone_used;
> char *host= current_thd->security_ctx->host; // host name
> char *user= current_thd->security_ctx->user; // user name
>
> + /*
> + Turn the binlog off and don't replicate the
> + updates to the backup logs.
> + */
> + save_thd_options= thd->options;
> + thd->options&= ~OPTION_BIN_LOG;
> +
> 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;
> @@ -956,6 +965,12 @@ err:
> close_performance_schema_table(thd, & open_tables_backup);
>
> thd->time_zone_used= save_time_zone_used;
> +
> + /*
> + Turn binlog back on if disengaged.
> + */
> + thd->options= save_thd_options;
> +
> return result;
> }
>
> @@ -2101,6 +2116,7 @@ bool LOGGER::backup_progress_log_write(T
> else
> id= 0; /* Log from connect handler */
>
> +
> lock_shared();
> while (*current_handler)
> error|= (*current_handler++)->
> @@ -4055,7 +4071,7 @@ ulonglong MYSQL_BACKUP_LOG::get_next_bac
> else // increment the counter
> id= m_next_id + 1;
>
> - DBUG_EXECUTE_IF("set_backup_id", id= 500;);
> + DBUG_EXECUTE_IF("set_backup_id", id= obs::is_slave() ? 600 : 500;);
>
> /*
> Write the new value to the file
>
> === modified file 'sql/share/errmsg.txt'
> --- a/sql/share/errmsg.txt 2008-10-28 18:14:14 +0000
> +++ b/sql/share/errmsg.txt 2008-10-29 19:10:00 +0000
> @@ -6416,3 +6416,5 @@ ER_MASTER_BLOCKING_SLAVES
> eng "The master is not allowing slave connections."
> ER_RESTORE_ON_MASTER
> eng "A restore operation was initiated on the master."
> +ER_RESTORE_ON_SLAVE
> + eng "A restore operation was attempted on a slave during replication. You must
> stop the slave prior to running a restore."
>
> === modified file 'sql/si_logs.cc'
> --- a/sql/si_logs.cc 2008-10-15 20:00:48 +0000
> +++ b/sql/si_logs.cc 2008-10-29 19:10:00 +0000
> @@ -133,6 +133,26 @@ bool Backup_log::write_progress(const ch
> error_num, notes);
> }
>
> +/**
> + Write master's binlog file and position to progress log.
> +
> + @returns results of logging function (i.e., TRUE if error)
> +*/
> +bool Backup_log::write_master_binlog_info()
> +{
> + char buff[1024];
> + bool ret= FALSE;
> +
> + if (m_op_hist.master_binlog_file || m_op_hist.master_binlog_pos)
> + {
> + sprintf(buff,
> + "Recording master binlog information. binlog file = '%s', position = %d.",
> + m_op_hist.master_binlog_file, m_op_hist.master_binlog_pos);
> + ret= write_progress(0, 0, 0, 0, 0, 0, (char *)&buff);
> + }
> + return ret;
> +}
> +
> /**
> Report change of the state of operation
>
>
> === modified file 'sql/si_logs.h'
> --- a/sql/si_logs.h 2008-10-15 20:00:48 +0000
> +++ b/sql/si_logs.h 2008-10-29 19:10:00 +0000
> @@ -58,6 +58,8 @@ struct st_backup_history
> 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
> + int master_binlog_pos; ///< position in the binary log
> + char *master_binlog_file; ///< name of the master's binary log file
> };
>
>
> @@ -112,6 +114,12 @@ public:
> longlong progress,
> int error_num,
> const char *notes);
> +
> + /*
> + Write master's binlog position and file if recorded earlier.
> + */
> + bool write_master_binlog_info();
> +
> /*
> Check the backup logs (as tables).
> */
> @@ -126,6 +134,8 @@ public:
> 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 master_binlog_pos(unsigned long int pos) { m_op_hist.binlog_pos= pos; }
> + void master_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);
> @@ -190,6 +200,22 @@ void Backup_log::binlog_file(char *file)
> {
> if (strlen(file) > 0)
> m_op_hist.binlog_file= file;
> +}
> +
> +/**
> + Report master's 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::master_binlog_file(char *file)
> +{
> + if (strlen(file) > 0)
> + m_op_hist.master_binlog_file= file;
> }
>
> #endif // SI_LOGS_H_
>
>