List:Commits« Previous MessageNext Message »
From:Ingo Struewing Date:March 6 2009 3:26pm
Subject:bzr commit into mysql-6.0 branch (ingo.struewing:2777) Bug#41722
View as plain text  
#At file:///home2/mydev/bzrroot/mysql-6.0-bug41722-1/ based on revid:ingo.struewing@stripped

 2777 Ingo Struewing	2009-03-06
      Bug#41722 - Restore crashes with backup of Falcon tables
      
      Partial fix. It defeats the server crash in the reported test case.
      
      The main problem is that Falcon sporadically reports
      "out of record memory". See the bug report for further information.
      
      The cause for the crash was incomplete implementation of error
      handling during restore of table data. Restore::send_data() did not
      take into account that a reported error will not immediately stop
      the restore progress, but instead retry to call send_data() for a
      couple of times.
      
      Fixed by setting up status variables so that re-entering send_data()
      after an error does not take a wrong path.
     @ mysql-test/suite/backup/r/backup_default_debug.result
        Bug#41722 - Restore crashes with backup of Falcon tables
        New test result.
     @ mysql-test/suite/backup/t/backup_default_debug.test
        Bug#41722 - Restore crashes with backup of Falcon tables
        New test case.
     @ sql/backup/be_default.cc
        Bug#41722 - Restore crashes with backup of Falcon tables
        Added error injection to fake a deterministic write error.
        Report engine write errors as warnings to the error log.
        Reset 'mode' and 'cur_blob' so that re-entering send_data()
        does not take a wrong code path.

    added:
      mysql-test/suite/backup/r/backup_default_debug.result
      mysql-test/suite/backup/t/backup_default_debug.test
    modified:
      sql/backup/be_default.cc
=== added file 'mysql-test/suite/backup/r/backup_default_debug.result'
--- a/mysql-test/suite/backup/r/backup_default_debug.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_default_debug.result	2009-03-06 15:26:16 +0000
@@ -0,0 +1,19 @@
+DROP DATABASE IF EXISTS mysql_db1;
+#
+# Bug#41722 - Restore crashes with backup of Falcon tables
+#
+CREATE DATABASE mysql_db1;
+CREATE TABLE mysql_db1.t1 (c1 TEXT) ENGINE=Falcon;
+INSERT INTO mysql_db1.t1 VALUES('fdafdsfdsfdsfdsfdsfd');
+BACKUP DATABASE mysql_db1 TO 'mysqltest.bak';
+backup_id
+#
+DROP DATABASE mysql_db1;
+#
+# Inject error Restore__send_data_write_error
+#
+SET debug='d,Restore__send_data_write_error';
+RESTORE FROM 'mysqltest.bak';
+ERROR HY000: Error when sending data (for table #1) to Snapshot restore driver
+SET debug= '';
+DROP DATABASE mysql_db1;

=== added file 'mysql-test/suite/backup/t/backup_default_debug.test'
--- a/mysql-test/suite/backup/t/backup_default_debug.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_default_debug.test	2009-03-06 15:26:16 +0000
@@ -0,0 +1,37 @@
+###########################################################################
+# Purpose: To test backup using default driver with error injection
+###############################################################################
+--source include/have_debug.inc
+--source include/have_falcon.inc
+--source include/not_embedded.inc
+
+--let $BACKUPDIR= `SELECT @@backupdir`
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysql_db1;
+--error 0, 1
+--remove_file $BACKUPDIR/mysqltest.bak
+--enable_warnings
+
+--echo #
+--echo # Bug#41722 - Restore crashes with backup of Falcon tables
+--echo #
+CREATE DATABASE mysql_db1;
+CREATE TABLE mysql_db1.t1 (c1 TEXT) ENGINE=Falcon;
+INSERT INTO mysql_db1.t1 VALUES('fdafdsfdsfdsfdsfdsfd');
+#
+--replace_column 1 #
+BACKUP DATABASE mysql_db1 TO 'mysqltest.bak';
+#
+DROP DATABASE mysql_db1;
+#
+--echo #
+--echo # Inject error Restore__send_data_write_error
+--echo #
+SET debug='d,Restore__send_data_write_error';
+--error ER_BACKUP_SEND_DATA
+RESTORE FROM 'mysqltest.bak';
+#
+SET debug= '';
+DROP DATABASE mysql_db1;
+--remove_file $BACKUPDIR/mysqltest.bak

=== modified file 'sql/backup/be_default.cc'
--- a/sql/backup/be_default.cc	2009-02-13 13:25:43 +0000
+++ b/sql/backup/be_default.cc	2009-03-06 15:26:16 +0000
@@ -702,7 +702,7 @@ result_t Restore::send_data(Buffer &buf)
   DBUG_EXECUTE_IF("restore_default_send_data", DBUG_RETURN(ERROR););
 
   /* 
-    get_data() should not be called after cancel has been called.
+    send_data() should not be called after cancel has been called.
   */
   DBUG_ASSERT(mode != CANCEL);
 
@@ -845,7 +845,11 @@ result_t Restore::send_data(Buffer &buf)
     }
     if (write_row)
     {
+      /* Error injection. */
+      DBUG_EXECUTE_IF("Restore__send_data_write_error",
+                      last_write_res= -1; goto write_skip;);
       last_write_res = hdl->ha_write_row(cur_table->record[0]);
+      IF_DBUG(write_skip:); /* Label for error injection. */
       DBUG_PRINT("backup_default_write", ("%d", last_write_res));
 
       /*
@@ -861,7 +865,28 @@ result_t Restore::send_data(Buffer &buf)
       if (last_write_res == 0)
         mode= WRITE_RCD;
       else
+      {
+        /* Error from ha_write_row(). */
+        DBUG_PRINT("error", ("error from ha_write_row(): %d  "
+                             "my_errno: %d  errno: %d",
+                             last_write_res, my_errno, errno));
+        sql_print_warning("RESTORE: error from ha_write_row(): %d  "
+                          "my_errno: %d  errno: %d",
+                          last_write_res, my_errno, errno);
+        /*
+          Restore does not stop on first error. Undo blob increment and
+          mode change. Otherwise we would go to WRITE_BLOB with the
+          current (invalid) cur_blob. Since ha_write_row() failed, the
+          only reasonable retry attempt would be to run into
+          ha_write_row() again.
+        */
+        if (cur_table->s->blob_fields > 0)
+        {
+          mode= CHECK_BLOBS;
+          cur_blob--;
+        }
         DBUG_RETURN(ERROR);
+      }
     }
     break;
   }
@@ -882,6 +907,7 @@ result_t Restore::send_data(Buffer &buf)
     */
     case BLOB_ONCE:
     {
+      DBUG_ASSERT(cur_blob < last_blob_ptr && *cur_blob < cur_table->s->fields);
       blob_ptrs[blob_ptr_index]= (byte *)my_malloc(size, MYF(MY_WME));
       memcpy(blob_ptrs[blob_ptr_index], (byte *)buf.data + META_SIZE, size);
       ((Field_blob*) cur_table->field[*cur_blob])->set_ptr(size, 
@@ -921,6 +947,7 @@ result_t Restore::send_data(Buffer &buf)
     */
     case BLOB_LAST:
     {
+      DBUG_ASSERT(cur_blob < last_blob_ptr && *cur_blob < cur_table->s->fields);
       blob_buffer.put_next((byte *)buf.data + META_SIZE, size);
       ptr= (byte *)blob_buffer.get_base_ptr();
       ((Field_blob*) cur_table->field[*cur_blob])->set_ptr(max_blob_size, 


Attachment: [text/bzr-bundle] bzr/ingo.struewing@sun.com-20090306152616-kia8lbmhh11c25si.bundle
Thread
bzr commit into mysql-6.0 branch (ingo.struewing:2777) Bug#41722Ingo Struewing6 Mar
  • Re: bzr commit into mysql-6.0 branch (ingo.struewing:2777) Bug#41722Rafal Somla11 Mar