List:Commits« Previous MessageNext Message »
From:Rafal Somla Date:January 8 2009 12:25pm
Subject:bzr commit into mysql-6.0-backup branch (Rafal.Somla:2741) Bug#40305
View as plain text  
#At file:///ext/mysql/bzr/backup/bug40305/

 2741 Rafal Somla	2009-01-08
      Bug #40305 - Backup: Bad feedback when BACKUP/RESTORE operation aborted.
      
      This patch refactors the code reporting termination of BACKUP/RESTORE statement. 
      After the changes "Backup/Restore completed" is shown only if operation has been 
      completed. In case of abnormal termination (error, interruption) a warning 
      "Operation aborted" or "Operation aborted - data might be corrupted" is logged. 
      The latter is in the case of RESTORE operation which has modified some data in 
      the server.
      
      The main changes are:
      - Function backup::Logger::report_stop() is replaced by 2 new functions: 
        report_completed() and report_aborted() to differentiate the feedback given in 
        the two situations.
      - Make sure that a call to report_completed() or report_aborted() always matches 
        a previous call to report_start(). This is done in Backup_restore_ctx::close() 
        which is called from the destructor.
      - Change the logic for removing backup file (in case BACKUP operation is not 
        completed). Before this was guarded by explicit m_remove_loc flag. Now we can 
        directly check if BACKUP operation has been completed successfully (i.e. 
        report_completed() was called) or not.
      
      Note: the new functionality is covered by existing test cases.
modified:
  mysql-test/lib/mtr_report.pl
  mysql-test/suite/backup/r/backup_errors.result
  mysql-test/suite/backup/r/backup_logs_purge.result
  mysql-test/suite/backup/t/backup_errors.test
  mysql-test/suite/backup/t/backup_logs_purge.test
  sql/backup/backup_kernel.h
  sql/backup/kernel.cc
  sql/backup/logger.h
  sql/backup/restore_info.h
  sql/share/errmsg.txt

per-file messages:
  mysql-test/lib/mtr_report.pl
    Filter out the abort warnings.
  mysql-test/suite/backup/r/backup_errors.result
    Result change - now additional warning about statement interruption is pushed on 
    the error stack.
  mysql-test/suite/backup/t/backup_logs_purge.test
    Update debug synchronization points - BACKUP/RESTORE must be stopped before 
    state change to "Completed" is reported in backup progress log. This state 
    change is reported by report_completed().
  sql/backup/backup_kernel.h
    - Document the states of Backup_restore_ctx class.
    - Remove m_remove_loc member which is no longer used.
  sql/backup/kernel.cc
    - Update Backup_restore_ctx::close() (which is called from Backup_restore_ctx
      destructor) so that it calls either report_completed() or report_aborted() to 
      match the report_start() call made in Backuo_restor_ctx::prepare_for...() 
      method.
    - Change the logic for removing backup file: instead of using explicit 
      m_remove_loc flag, decide based on whether BACKUP operation has completed 
      successfully or not (as now this information is available).
    - Call Backup_restore_ctx::close() in do_backup() and do_restore(), when 
      operation is completed - no need to wait any longer.
    - Report data changes when objects are created in bcat_create_item() and  
      restore_triggers_and_events().
  sql/backup/logger.h
    Replace backup::Logger::report_stop() with two new methods: report_completed() 
    and report_aborted().
  sql/backup/restore_info.h
    Add flag for recording the fact that data has been modified during
    restore operation.
  sql/share/errmsg.txt
    Add messages for reporting early termination of a statement.
=== modified file 'mysql-test/lib/mtr_report.pl'
--- a/mysql-test/lib/mtr_report.pl	2008-11-21 15:02:34 +0000
+++ b/mysql-test/lib/mtr_report.pl	2009-01-08 12:25:04 +0000
@@ -328,6 +328,9 @@ sub mtr_report_stats ($) {
 		/Slave: Can't drop database.* database doesn't exist/ or
                 /Slave SQL:.*(?:Error_code: \d+|Query:.*)/ or
 		
+		# Ignore warnings issued when backup/restore operation is aborted.
+		/\[Warning\] (Backup|Restore): Operation aborted/ or
+		
 		# backup_errors test is supposed to trigger lots of backup related errors
 		($testname eq 'backup.backup_errors') and
 		(

=== modified file 'mysql-test/suite/backup/r/backup_errors.result'
--- a/mysql-test/suite/backup/r/backup_errors.result	2008-12-15 12:18:24 +0000
+++ b/mysql-test/suite/backup/r/backup_errors.result	2009-01-08 12:25:04 +0000
@@ -10,12 +10,14 @@ ERROR HY000: Malformed file path ''
 SHOW WARNINGS;
 Level	Code	Message
 Error	#	Malformed file path ''
+Warning	#	Operation aborted
 BACKUP DATABASE adb TO "bdb/t1.frm";
 ERROR HY000: Can't create/write to file 'MYSQLTEST_VARDIR/master-data/bdb/t1.frm' (Errcode: #)
 SHOW WARNINGS;
 Level	Code	Message
 Error	#	Can't create/write to file 'MYSQLTEST_VARDIR/master-data/bdb/t1.frm' (Errcode: #)
 Error	#	Can't write to backup location 'bdb/t1.frm'
+Warning	#	Operation aborted
 BACKUP DATABASE adb TO "test.bak";
 backup_id
 #
@@ -25,18 +27,21 @@ SHOW WARNINGS;
 Level	Code	Message
 Error	#	Can't create/write to file 'MYSQLTEST_VARDIR/master-data/test.bak' (Errcode: #)
 Error	#	Can't write to backup location 'test.bak'
+Warning	#	Operation aborted
 DROP DATABASE IF EXISTS foo;
 DROP DATABASE IF EXISTS bar;
 BACKUP DATABASE foo TO 'test.bak';
 ERROR 42000: Unknown database 'foo'
 SHOW WARNINGS;
 Level	Code	Message
-Error	1049	Unknown database 'foo'
+Error	#	Unknown database 'foo'
+Warning	#	Operation aborted
 BACKUP DATABASE test,foo,bdb,bar TO 'test.bak';
 ERROR 42000: Unknown database 'foo,bar'
 SHOW WARNINGS;
 Level	Code	Message
 Error	#	Unknown database 'foo,bar'
+Warning	#	Operation aborted
 BACKUP DATABASE foo,test,bar,foo TO 'test.bak';
 ERROR 42000: Not unique database: 'foo'
 use adb;
@@ -69,36 +74,42 @@ ERROR HY000: Database 'mysql' cannot be 
 SHOW WARNINGS;
 Level	Code	Message
 Error	#	Database 'mysql' cannot be included in a backup
+Warning	#	Operation aborted
 Backup of mysql, information_schema scenario 2
 BACKUP DATABASE information_schema TO 't.bak';
 ERROR HY000: Database 'information_schema' cannot be included in a backup
 SHOW WARNINGS;
 Level	Code	Message
 Error	#	Database 'information_schema' cannot be included in a backup
+Warning	#	Operation aborted
 Backup of mysql, information_schema scenario 3
 BACKUP DATABASE mysql, information_schema TO 't.bak';
 ERROR HY000: Database 'mysql' cannot be included in a backup
 SHOW WARNINGS;
 Level	Code	Message
 Error	#	Database 'mysql' cannot be included in a backup
+Warning	#	Operation aborted
 Backup of mysql, information_schema scenario 4
 BACKUP DATABASE mysql, test TO 't.bak';
 ERROR HY000: Database 'mysql' cannot be included in a backup
 SHOW WARNINGS;
 Level	Code	Message
 Error	#	Database 'mysql' cannot be included in a backup
+Warning	#	Operation aborted
 Backup of mysql, information_schema scenario 5
 BACKUP DATABASE information_schema, test TO 't.bak';
 ERROR HY000: Database 'information_schema' cannot be included in a backup
 SHOW WARNINGS;
 Level	Code	Message
 Error	#	Database 'information_schema' cannot be included in a backup
+Warning	#	Operation aborted
 Backup of mysql, information_schema scenario 6
 BACKUP DATABASE mysql, information_schema, test TO 't.bak';
 ERROR HY000: Database 'mysql' cannot be included in a backup
 SHOW WARNINGS;
 Level	Code	Message
 Error	#	Database 'mysql' cannot be included in a backup
+Warning	#	Operation aborted
 Making copies of progress tables.
 CREATE TABLE IF NOT EXISTS test.ob_copy LIKE mysql.backup_history;
 CREATE TABLE IF NOT EXISTS test.obp_copy LIKE mysql.backup_progress;

=== modified file 'mysql-test/suite/backup/r/backup_logs_purge.result'
--- a/mysql-test/suite/backup/r/backup_logs_purge.result	2008-11-17 09:57:51 +0000
+++ b/mysql-test/suite/backup/r/backup_logs_purge.result	2009-01-08 12:25:04 +0000
@@ -252,7 +252,7 @@ count(*)
 24
 SET SESSION debug="+d,set_backup_id";
 con2: Activate sync points for the backup statement.
-SET DEBUG_SYNC= 'before_backup_done SIGNAL ready WAIT_FOR proceed';
+SET DEBUG_SYNC= 'before_backup_completed SIGNAL ready WAIT_FOR proceed';
 BACKUP DATABASE backup_logs to 'backup5.bak';
 con1: Wait for the backup to be ready.
 SET DEBUG_SYNC= 'now WAIT_FOR ready';
@@ -305,7 +305,7 @@ SELECT count(*) FROM mysql.backup_progre
 count(*)
 13
 con2: Activate sync points for the backup statement.
-SET DEBUG_SYNC= 'before_restore_done SIGNAL ready WAIT_FOR proceed';
+SET DEBUG_SYNC= 'before_restore_completed SIGNAL ready WAIT_FOR proceed';
 RESTORE FROM 'backup5.bak' OVERWRITE;
 con1: Wait for the backup to be ready.
 SET DEBUG_SYNC= 'now WAIT_FOR ready';

=== modified file 'mysql-test/suite/backup/t/backup_errors.test'
--- a/mysql-test/suite/backup/t/backup_errors.test	2008-12-15 12:18:24 +0000
+++ b/mysql-test/suite/backup/t/backup_errors.test	2009-01-08 12:25:04 +0000
@@ -66,6 +66,7 @@ DROP DATABASE IF EXISTS bar;
 
 -- error ER_BAD_DB_ERROR
 BACKUP DATABASE foo TO 'test.bak';
+--replace_column 2 #
 SHOW WARNINGS;
 -- error ER_BAD_DB_ERROR
 BACKUP DATABASE test,foo,bdb,bar TO 'test.bak';

=== modified file 'mysql-test/suite/backup/t/backup_logs_purge.test'
--- a/mysql-test/suite/backup/t/backup_logs_purge.test	2008-11-17 09:57:51 +0000
+++ b/mysql-test/suite/backup/t/backup_logs_purge.test	2009-01-08 12:25:04 +0000
@@ -274,7 +274,7 @@ SET SESSION debug="+d,set_backup_id";
 # it writes the history log and last complete log entry.
 #
 --echo con2: Activate sync points for the backup statement.
-SET DEBUG_SYNC= 'before_backup_done SIGNAL ready WAIT_FOR proceed';
+SET DEBUG_SYNC= 'before_backup_completed SIGNAL ready WAIT_FOR proceed';
 SEND BACKUP DATABASE backup_logs to 'backup5.bak';
 
 connection con1;
@@ -328,7 +328,7 @@ connection con2;
 # it writes the history log and last complete log entry.
 #
 --echo con2: Activate sync points for the backup statement.
-SET DEBUG_SYNC= 'before_restore_done SIGNAL ready WAIT_FOR proceed';
+SET DEBUG_SYNC= 'before_restore_completed SIGNAL ready WAIT_FOR proceed';
 SEND RESTORE FROM 'backup5.bak' OVERWRITE;
 
 connection con1;

=== modified file 'sql/backup/backup_kernel.h'
--- a/sql/backup/backup_kernel.h	2008-11-25 17:44:19 +0000
+++ b/sql/backup/backup_kernel.h	2009-01-08 12:25:04 +0000
@@ -99,9 +99,31 @@ class Backup_restore_ctx: public backup:
 
   /** 
     @brief State of a context object. 
-    
-    Backup/restore can be performed only if object is prepared for that 
-    operation.
+
+    The following diagram illustrates the states in which a context object
+    can be and how the state changes as a result of calling public methods.
+    Methods which are not listed are forbidden in a given state.
+    @verbatim
+    CREATED
+        prepare_for_backup()   -> PREPARED_FOR_BACKUP
+        prepare_for_restore()  -> PREPARED_FOR_RESTORE
+        close()                -> CLOSED
+
+    PREPARED_FOR_BACKUP
+        do_backup()            -> CLOSED
+        close()                -> CLOSED
+
+    PREPARED_FOR_RESTORE
+        do_restore()           -> CLOSED
+        close()                -> CLOSED
+
+    CLOSED
+        close()                -> CLOSED
+    @endverbatim
+
+    @note An instance of the context class can be used only once -- when it 
+    moves to CLOSED state no methods can be called except for close() which does
+    nothing in that case.
    */
   enum { CREATED,
          PREPARED_FOR_BACKUP,
@@ -129,9 +151,6 @@ class Backup_restore_ctx: public backup:
   
   ::String  m_path;   ///< Path to where the backup image file is located.
 
-  /** If true, the backup image file is deleted at clean-up time. */
-  bool m_remove_loc;
-
   backup::Stream *m_stream; ///< Pointer to the backup stream object, if opened.
   backup::Image_info *m_catalog;  ///< Pointer to the image catalogue object.
 
@@ -160,6 +179,9 @@ class Backup_restore_ctx: public backup:
   
   int report_stream_open_failure(int open_error, const LEX_STRING *location);
 
+  /// Indicates if the operation has been successfully completed.  
+  bool m_completed;  
+
   friend int backup_init();
   friend void backup_shutdown();
   friend bstream_byte* bstream_alloc(unsigned long int);
@@ -207,8 +229,6 @@ void Backup_restore_ctx::disable_fkey_co
 inline
 int Backup_restore_ctx::fatal_error(int error_code)
 {
-  m_remove_loc= TRUE;
-
   if (m_error)
     return m_error;
 

=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc	2008-12-10 15:53:06 +0000
+++ b/sql/backup/kernel.cc	2009-01-08 12:25:04 +0000
@@ -276,8 +276,6 @@ int send_error(Backup_restore_ctx &conte
     va_end(args);
   }
 
-  if (context.backup::Logger::m_state == backup::Logger::RUNNING)
-    context.report_stop(my_time(0), FALSE); // FASLE = no success
   return error_code;
 }
 
@@ -382,9 +380,9 @@ 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_error(0), m_stream(NULL),
   m_catalog(NULL), mem_alloc(NULL), m_tables_locked(FALSE),
-  m_engage_binlog(FALSE)
+  m_engage_binlog(FALSE), m_completed(FALSE)
 {
   /*
     Check for progress tables.
@@ -631,9 +629,6 @@ Backup_restore_ctx::prepare_for_backup(S
     return NULL;
   }
 
-  // Mark that the file should be removed unless operation completes successfuly
-  m_remove_loc= TRUE;
-
   int my_open_status= s->open();
   if (my_open_status != 0)
   {
@@ -929,6 +924,31 @@ int Backup_restore_ctx::close()
   using namespace backup;
 
   /*
+    Report end of the operation which has started if it has not been done 
+    before (Logger is in RUNNING state). 
+  */ 
+  if (Logger::m_state == RUNNING)
+  {
+    time_t  now= my_time(0);
+    if (m_catalog)
+      m_catalog->save_end_time(now);
+
+    // Report either completion or interruption depending on m_completed flag.
+    if (m_completed)
+      report_completed(now);
+    else
+    {
+      /*
+        If this is restore operation then m_data_changed flag in the 
+        Restore_info object tells if data has been modified or not.
+       */ 
+      const bool data_changed= m_type==RESTORE && m_catalog && 
+                         static_cast<Restore_info*>(m_catalog)->m_data_changed;
+      report_aborted(now, data_changed);
+    }
+  }
+
+  /*
     Allow slaves connect after restore is complete.
   */
   obs::disable_slave_connections(FALSE);
@@ -939,8 +959,6 @@ int Backup_restore_ctx::close()
   if (m_engage_binlog)
     obs::engage_binlog(TRUE);
 
-  time_t when= my_time(0);
-
   // unlock tables if they are still locked
   unlock_tables();                              // Never errors
 
@@ -951,7 +969,7 @@ int Backup_restore_ctx::close()
 
   m_thd->options= m_thd_options;
 
-  // close stream
+  // close stream if not closed already (in which case m_steam is NULL)
 
   if (m_stream && !m_stream->close())
   {
@@ -959,16 +977,13 @@ int Backup_restore_ctx::close()
     fatal_error(report_error(ER_BACKUP_CLOSE));
   }
 
-  if (m_catalog)
-    m_catalog->save_end_time(when); // Note: no errors.
-
   /* 
-    Remove the location, if asked for.
+    Remove the location if it is BACKUP operation and it has not completed
+    successfully.
     
-    Important: This is done only for backup operation - RESTORE should never
-    remove the specified backup image!
+    Important: RESTORE should never remove the specified backup image!
    */
-  if (m_remove_loc && m_state == PREPARED_FOR_BACKUP)
+  if (m_state == PREPARED_FOR_BACKUP && !m_completed)
   {
     int ret= my_delete(m_path.c_ptr(), MYF(0));
 
@@ -976,17 +991,8 @@ int Backup_restore_ctx::close()
       Ignore ENOENT error since it is ok if the file doesn't exist.
      */
     if (ret && my_errno != ENOENT)
-      fatal_error(report_error(ER_CANT_DELETE_FILE, m_path.c_ptr(), my_errno));
-  }
-
-  /* We report completion of the operation only if no errors were detected,
-     and logger has been initialized.
-  */
-  if (!m_error)
-  {
-    if (backup::Logger::m_state == backup::Logger::RUNNING)
     {
-      report_stop(when, TRUE);
+      fatal_error(report_error(ER_CANT_DELETE_FILE, m_path.c_ptr(), my_errno));
     }
   }
 
@@ -1065,17 +1071,14 @@ int Backup_restore_ctx::do_backup()
   if (ret)
     DBUG_RETURN(fatal_error(report_error(ER_BACKUP_WRITE_SUMMARY)));
 
-  /*
-    Now backup image has been written. Set m_remove_loc to FALSE, so that the
-    backup file is not removed in Backup_restore_ctx::close().
-  */
-  m_remove_loc= FALSE;
+  DEBUG_SYNC(m_thd, "before_backup_completed");
+  m_completed= TRUE;
   report_stats_post(info);                      // Never errors
 
   DBUG_PRINT("backup",("Backup done."));
   DEBUG_SYNC(m_thd, "before_backup_done");
 
-  DBUG_RETURN(0);
+  DBUG_RETURN(close());
 }
 
 /**
@@ -1100,11 +1103,13 @@ int Backup_restore_ctx::restore_triggers
 
   DBUG_ENTER("restore_triggers_and_events");
 
+  DBUG_ASSERT(m_type == RESTORE);
+  Restore_info *info= static_cast<Restore_info*>(m_catalog);
   Image_info::Obj *obj;
   List<Image_info::Obj> events;
   Image_info::Obj::describe_buf buf;
 
-  Image_info::Iterator *dbit= m_catalog->get_dbs();
+  Image_info::Iterator *dbit= info->get_dbs();
   if (!dbit)
     DBUG_RETURN(fatal_error(report_error(ER_OUT_OF_RESOURCES)));
 
@@ -1113,7 +1118,7 @@ int Backup_restore_ctx::restore_triggers
   while ((obj= (*dbit)++)) 
   {
     Image_info::Iterator *it=
-                    m_catalog->get_db_objects(*static_cast<Image_info::Db*>(obj));
+                       info->get_db_objects(*static_cast<Image_info::Db*>(obj));
     if (!it)
       DBUG_RETURN(fatal_error(report_error(ER_OUT_OF_RESOURCES)));
 
@@ -1131,6 +1136,8 @@ int Backup_restore_ctx::restore_triggers
       
       case BSTREAM_IT_TRIGGER:
         DBUG_ASSERT(obj->m_obj_ptr);
+        // Mark that data is being changed.
+        info->m_data_changed= TRUE;
         if (obj->m_obj_ptr->create(m_thd))
         {
           delete it;
@@ -1155,11 +1162,15 @@ int Backup_restore_ctx::restore_triggers
   Image_info::Obj *ev;
 
   while ((ev= it++)) 
+  {
+    // Mark that data is being changed.
+    info->m_data_changed= TRUE;
     if (ev->m_obj_ptr->create(m_thd))
     {
       int ret= report_error(ER_BACKUP_CANT_RESTORE_EVENT,ev->describe(buf));
       DBUG_RETURN(fatal_error(ret));
     };
+  }
 
   DBUG_RETURN(0);
 }
@@ -1247,7 +1258,11 @@ int Backup_restore_ctx::do_restore(bool 
   if (err)
     DBUG_RETURN(fatal_error(err));
 
-  // Here restore drivers are created to restore table data
+  /* 
+   Here restore drivers are created to restore table data. Data is being
+   (potentially) changed so we set m_data_changed flag.
+  */
+  info.m_data_changed= TRUE;
   err= restore_table_data(m_thd, info, s);      // logs errors
 
   unlock_tables();                              // Never errors
@@ -1277,6 +1292,9 @@ int Backup_restore_ctx::do_restore(bool 
 
   DBUG_PRINT("restore",("Done."));
 
+  DEBUG_SYNC(m_thd, "before_restore_completed");
+  m_completed= TRUE;
+
   err= read_summary(info, s);
   if (err)
     DBUG_RETURN(fatal_error(report_error(ER_BACKUP_READ_SUMMARY)));
@@ -1294,7 +1312,7 @@ int Backup_restore_ctx::do_restore(bool 
 
   DEBUG_SYNC(m_thd, "before_restore_done");
 
-  DBUG_RETURN(0);
+  DBUG_RETURN(close());
 }
 
 /**
@@ -2025,6 +2043,9 @@ int bcat_create_item(st_bstream_image_he
     }
   }
 
+  // Mark that data is being changed.
+  info->m_data_changed= TRUE;
+
   if (sobj->create(thd))
   {
     log.report_error(create_err, desc);

=== modified file 'sql/backup/logger.h'
--- a/sql/backup/logger.h	2008-12-10 15:53:06 +0000
+++ b/sql/backup/logger.h	2009-01-08 12:25:04 +0000
@@ -54,7 +54,8 @@ class Logger
    int log_error(int error_code, ...);
 
    void report_start(time_t);
-   void report_stop(time_t, bool);
+   void report_completed(time_t);
+   void report_aborted(time_t, bool data_changed);
    void report_state(enum_backup_state);
    void report_vp_time(time_t, bool);
    void report_binlog_pos(const st_bstream_binlog_pos&);
@@ -63,6 +64,7 @@ class Logger
    void report_backup_file(char * path);
    void report_stats_pre(const Image_info&);
    void report_stats_post(const Image_info&);
+
    ulonglong get_op_id() const 
    {
      DBUG_ASSERT(backup_log);
@@ -187,26 +189,73 @@ void Logger::report_start(time_t when)
   backup_log->state(BUP_RUNNING);
 }
 
+/** 
+  Report that the operation has completed successfully.
+
+  @param[in] when       the time when operation has completed.
+
+  @note This method can be called only after @c report_start(). It can not be
+  called after end of operation has been logged with either this method or
+  @c report_aborted().
+*/
+inline
+void Logger::report_completed(time_t when)
+{
+   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_state(BUP_COMPLETE);
+  
+  // Report stop time to backup logs.
+  backup_log->stop(when);
+  /* 
+    Since the operation has completed, we can now write the backup history log
+    entry describing it.
+  */
+  backup_log->write_history();
+}
+
 /**
-  Report end of the operation.
+  Report that backup/restore operation has been aborted.
+
+  @param[in] when  time when the operation has ended.
+  @param[in] data_changed  tells if data has been already modified in case
+                           this is restore operation.
+
+  This method should be called when backup/restore operation has been aborted
+  before its completion, e.g., because of an error or user interruption.
   
-  @param[in] success indicates if the operation ended successfuly
+  The method will log the stop time and ER_OPERATION_ABORTED warning.
+  However, if a restore operation has been interrupted and @c data_changed flag
+  is true, ER_OPERATION_ABORTED_CORRUPTED warning will be logged, to warn the 
+  user about the possibility of data corruption.
+  
+  @note This method must be called after @c report_start(). It can not be
+  called after end of operation has been logged with either this method or
+  @c report_completed().
  */
 inline
-void Logger::report_stop(time_t when, bool success)
+void Logger::report_aborted(time_t when, bool data_changed)
 {
-  if (m_state == DONE)
-    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);  
+ if (m_type == RESTORE && data_changed)
+   report_error(log_level::WARNING, ER_OPERATION_ABORTED_CORRUPTED);
+ else
+   report_error(log_level::WARNING, ER_OPERATION_ABORTED);
+
+  // Report stop time to backup logs.
 
   backup_log->stop(when);
-  backup_log->state(success ? BUP_COMPLETE : BUP_ERRORS);
+  /* 
+    Since the operation has ended, we can now write the backup history log
+    entry describing it.
+  */
   backup_log->write_history();
+
   m_state= DONE;
 }
 

=== modified file 'sql/backup/restore_info.h'
--- a/sql/backup/restore_info.h	2008-11-25 17:44:19 +0000
+++ b/sql/backup/restore_info.h	2009-01-08 12:25:04 +0000
@@ -58,6 +58,9 @@ class Restore_info: public backup::Image
 
   THD *m_thd;
 
+  /// A flag to indicate that data has been modified during restore operation.
+  bool m_data_changed;
+
   friend int backup::restore_table_data(THD*, Restore_info&, 
                                         backup::Input_stream&);
   friend int ::bcat_add_item(st_bstream_image_header*,
@@ -71,7 +74,7 @@ class Restore_info: public backup::Image
 
 inline
 Restore_info::Restore_info(backup::Logger &log, THD *thd)
-  :m_log(log), m_thd(thd)
+  :m_log(log), m_thd(thd), m_data_changed(FALSE)
 {}
 
 inline

=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt	2008-12-15 09:22:24 +0000
+++ b/sql/share/errmsg.txt	2009-01-08 12:25:04 +0000
@@ -6447,4 +6447,7 @@ ER_BACKUP_RESTORE_DBS
   eng "Restoring %u database(s) %.220s"
 ER_BACKUP_SYNCHRONIZE
   eng "Backup failed to synchronize table images."
-
+ER_OPERATION_ABORTED
+  eng "Operation aborted"
+ER_OPERATION_ABORTED_CORRUPTED
+  eng "Operation aborted - data might be corrupted"

Thread
bzr commit into mysql-6.0-backup branch (Rafal.Somla:2741) Bug#40305Rafal Somla8 Jan