=== modified file 'sql/backup/backup_kernel.h'
--- sql/backup/backup_kernel.h	2008-11-25 17:44:19 +0000
+++ sql/backup/backup_kernel.h	2008-12-10 10:45:45 +0000
@@ -99,9 +99,27 @@ 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 +147,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 +175,15 @@ 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;  
+
+  /**
+    For saving timestamp of the moment when the operation has been ended, so
+    that it can be correctly reported.
+  */ 
+  time_t m_stop_time;
+
   friend int backup_init();
   friend void backup_shutdown();
   friend bstream_byte* bstream_alloc(unsigned long int);
@@ -207,8 +231,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/data_backup.cc'
--- sql/backup/data_backup.cc	2008-11-26 10:05:19 +0000
+++ sql/backup/data_backup.cc	2008-12-10 10:46:06 +0000
@@ -1445,6 +1445,12 @@ int restore_table_data(THD *thd, Restore
   // Create restore drivers
   result_t res;
 
+  /** 
+    Mark that data is being modified here because we don't know when a restore
+    driver starts doing it, after it has been created.
+  */
+  info.m_data_changed= TRUE;
+
   for (uint n=0; n < info.snap_count(); ++n)
   {
     active[n]= drv[n]= NULL;

=== modified file 'sql/backup/kernel.cc'
--- sql/backup/kernel.cc	2008-11-28 10:10:39 +0000
+++ sql/backup/kernel.cc	2008-12-10 10:42:03 +0000
@@ -273,8 +273,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;
 }
 
@@ -379,9 +377,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_stop_time(0)
 {
   /*
     Check for progress tables.
@@ -628,9 +626,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)
   {
@@ -926,6 +921,30 @@ 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 RUNNIG state). 
+  */ 
+  if (Logger::m_state == RUNNING)
+  {
+    // If m_stop_time has not been recorded so far, do it now.
+    if (!m_stop_time)
+    {
+      m_stop_time= my_time(0);
+      if (m_catalog)
+        m_catalog->save_end_time(m_stop_time);
+    }
+
+    if (m_completed)
+      report_completed(m_stop_time);
+    else
+    {
+      const bool data_changed= m_type==RESTORE && m_catalog && 
+                         static_cast<Restore_info*>(m_catalog)->m_data_changed;
+      report_aborted(m_stop_time, data_changed);
+    }
+  }
+
+  /*
     Allow slaves connect after restore is complete.
   */
   obs::disable_slave_connections(FALSE);
@@ -936,8 +955,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
 
@@ -948,7 +965,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())
   {
@@ -956,16 +973,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
+    sucessfully.
     
-    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));
 
@@ -973,17 +987,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));
     }
   }
 
@@ -1056,23 +1061,23 @@ int Backup_restore_ctx::do_backup()
   if (ret)
     DBUG_RETURN(fatal_error(ret));
 
+  m_stop_time= my_time(0);
+  info.save_end_time(m_stop_time);
+
   DBUG_PRINT("backup",("Writing summary"));
 
   ret= write_summary(info, s);  
   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());
 }
 
 /**
@@ -1097,11 +1102,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)));
 
@@ -1110,7 +1117,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)));
 
@@ -1128,6 +1135,7 @@ int Backup_restore_ctx::restore_triggers
       
       case BSTREAM_IT_TRIGGER:
         DBUG_ASSERT(obj->m_obj_ptr);
+        info->m_data_changed= TRUE;
         if (obj->m_obj_ptr->execute(m_thd))
         {
           delete it;
@@ -1152,11 +1160,15 @@ int Backup_restore_ctx::restore_triggers
   Image_info::Obj *ev;
 
   while ((ev= it++)) 
+  {
+    // Report that we are modyfinig data.
+    info->m_data_changed= TRUE;
     if (ev->m_obj_ptr->execute(m_thd))
     {
       int ret= report_error(ER_BACKUP_CANT_RESTORE_EVENT,ev->describe(buf));
       DBUG_RETURN(fatal_error(ret));
     };
+  }
 
   DBUG_RETURN(0);
 }
@@ -1274,6 +1286,11 @@ int Backup_restore_ctx::do_restore(bool 
 
   DBUG_PRINT("restore",("Done."));
 
+  DEBUG_SYNC(m_thd, "before_restore_completed");
+  m_stop_time= my_time(0);
+  info.save_end_time(m_stop_time);
+  m_completed= TRUE;
+
   err= read_summary(info, s);
   if (err)
     DBUG_RETURN(fatal_error(report_error(ER_BACKUP_READ_SUMMARY)));
@@ -1291,7 +1308,7 @@ int Backup_restore_ctx::do_restore(bool 
 
   DEBUG_SYNC(m_thd, "before_restore_done");
 
-  DBUG_RETURN(0);
+  DBUG_RETURN(close());
 }
 
 /**
@@ -2015,6 +2032,9 @@ int bcat_create_item(st_bstream_image_he
     }
   }
 
+  // Report that we are modyfinig data.
+  info->m_data_changed= TRUE;
+
   if (sobj->execute(thd))
   {
     log.report_error(create_err, desc);

=== modified file 'sql/backup/logger.h'
--- sql/backup/logger.h	2008-11-25 17:44:19 +0000
+++ sql/backup/logger.h	2008-12-10 10:59:21 +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);
@@ -95,8 +97,8 @@ class Logger
 
 inline
 Logger::Logger(THD *thd) 
-   :m_type(BACKUP), m_state(CREATED), m_thd(thd), m_push_errors(TRUE), 
-    m_error_reported(FALSE), backup_log(0)
+   :m_type(BACKUP), m_state(CREATED), m_thd(thd), 
+    m_push_errors(TRUE), m_error_reported(FALSE), backup_log(0)
 {}
 
 inline
@@ -187,26 +189,71 @@ void Logger::report_start(time_t when)
   backup_log->state(BUP_RUNNING);
 }
 
+/** 
+  Report that the operation has completed successfully.
+
+  @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'
--- sql/backup/restore_info.h	2008-11-25 17:44:19 +0000
+++ sql/backup/restore_info.h	2008-12-10 10:33:34 +0000
@@ -58,6 +58,8 @@ class Restore_info: public backup::Image
 
   THD *m_thd;
 
+  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*,


