From c78680b43f3d2320218d9851d70e73df9409c22c Mon Sep 17 00:00:00 2001
From: unknown <guilhem@gbichot2>
Date: Fri, 3 Oct 2003 20:07:08 +0200
Subject: [PATCH] Fix for a rpl_relayrotate failure. Changed
 Rotate_log_event::exec_event() to not increment positions when the event is
 seen in the middle of a transaction.

mysql-test/r/rpl_relayrotate.result:
  remove timeout which was too short for Valgrind
mysql-test/r/rpl_until.result:
  updated error message
mysql-test/t/rpl_relayrotate.test:
  removed timeout which was too short for Valgrind
sql/log_event.cc:
  Fix for a rpl_relayrotate failure. The problem was that Rotate_log_event::exec_event()
  believed that the relay log was corrupted. Fixed it by moving the test for
  corruption to Start_log_event::exec_event().
  Changed Rotate_log_event::exec_event() to not increment positions when the
  event is seen in the middle of a transaction (that was an old bug found by
  chance :)
---
 mysql-test/r/rpl_relayrotate.result |  6 ++--
 mysql-test/r/rpl_until.result       |  2 +-
 mysql-test/t/rpl_relayrotate.test   |  5 +--
 sql/log_event.cc                    | 51 +++++++++++++++--------------
 4 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/mysql-test/r/rpl_relayrotate.result b/mysql-test/r/rpl_relayrotate.result
index 0ad61a7687e..802be911ad7 100644
--- a/mysql-test/r/rpl_relayrotate.result
+++ b/mysql-test/r/rpl_relayrotate.result
@@ -10,9 +10,9 @@ reset slave;
 start slave;
 stop slave;
 start slave;
-select master_pos_wait('master-bin.001',3000,120)=-1;
-master_pos_wait('master-bin.001',3000,120)=-1
-0
+select master_pos_wait('master-bin.001',3000)>=0;
+master_pos_wait('master-bin.001',3000)>=0
+1
 select * from t1 where a=8000;
 a
 8000
diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result
index 3dc3de8802d..ee5ceb28bd8 100644
--- a/mysql-test/r/rpl_until.result
+++ b/mysql-test/r/rpl_until.result
@@ -69,4 +69,4 @@ ERROR HY000: Wrong parameter or combination of parameters for START SLAVE UNTIL
 start slave sql_thread;
 start slave until master_log_file='master-bin.000001', master_log_pos=561;
 Warnings:
-Note	1253	The slave was already running
+Note	1253	Slave is already running
diff --git a/mysql-test/t/rpl_relayrotate.test b/mysql-test/t/rpl_relayrotate.test
index 3f315ba9365..3aab8371ac0 100644
--- a/mysql-test/t/rpl_relayrotate.test
+++ b/mysql-test/t/rpl_relayrotate.test
@@ -53,10 +53,7 @@ start slave;
 # We must wait for the transaction to commit before
 # reading, MASTER_POS_WAIT() will do it for sure
 # (the only statement with position>=3000 is COMMIT).
-# Older versions of MySQL would hang forever in MASTER_POS_WAIT
-# because COMMIT was said to be position 0 in the master's log (bug).
-# Detect this with timeout.
-select master_pos_wait('master-bin.001',3000,120)=-1;
+select master_pos_wait('master-bin.001',3000)>=0;
 select * from t1 where a=8000;
 
 # The following DROP is a very important cleaning task:
diff --git a/sql/log_event.cc b/sql/log_event.cc
index b6964c40422..23586201dcb 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1086,6 +1086,23 @@ int Start_log_event::exec_event(struct st_relay_log_info* rli)
     */
     close_temporary_tables(thd);
     cleanup_load_tmpdir();
+    /*
+      As a transaction NEVER spans on 2 or more binlogs:
+      if we have an active transaction at this point, the master died while
+      writing the transaction to the binary log, i.e. while flushing the binlog
+      cache to the binlog. As the write was started, the transaction had been
+      committed on the master, so we lack of information to replay this
+      transaction on the slave; all we can do is stop with error.
+    */
+    if (thd->options & OPTION_BEGIN)
+    {
+      slave_print_error(rli, 0,
+                        "there is an unfinished transaction in the relay log \
+(could find neither COMMIT nor ROLLBACK in the relay log); it could be that \
+the master died while writing the transaction to its binary log. Now the slave \
+is rolling back the transaction.");
+      return(1);
+    }
     break;
 
     /* 
@@ -1871,35 +1888,19 @@ int Rotate_log_event::write_data(IO_CACHE* file)
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
 int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
 {
-  char* log_name = rli->group_master_log_name;
   DBUG_ENTER("Rotate_log_event::exec_event");
 
   pthread_mutex_lock(&rli->data_lock);
-
-  if (thd->options & OPTION_BEGIN)
-  {
-    slave_print_error(rli, 0,
-                      opt_using_transactions ?
-                      "\
-There is an unfinished transaction in the relay log (could find neither \
-COMMIT nor ROLLBACK in the relay log); It could be that the master died while \
-writing the transaction to its binary log. Now the slave is rolling back the \
-transaction." : 
-                      "\
-There is an unfinished transaction in the relay log (could find neither \
-COMMIT nor ROLLBACK in the relay log); It could be that the master died while \
-writing the transaction to its binary log.");
-    pthread_mutex_unlock(&rli->data_lock);
-    DBUG_RETURN(1);
-  }
-
-  memcpy(log_name, new_log_ident, ident_len+1);
-  rli->notify_group_master_log_name_update();
-  rli->group_master_log_pos = pos;
   rli->event_relay_log_pos += get_event_len();
-  rli->group_relay_log_pos = rli->event_relay_log_pos;
-  DBUG_PRINT("info", ("group_master_log_pos: %lu",
-		      (ulong) rli->group_master_log_pos));
+  if (!(thd->options & OPTION_BEGIN))
+  {
+    memcpy(rli->group_master_log_name, new_log_ident, ident_len+1);
+    rli->notify_group_master_log_name_update();
+    rli->group_master_log_pos = pos;
+    rli->group_relay_log_pos = rli->event_relay_log_pos;
+    DBUG_PRINT("info", ("group_master_log_pos: %lu",
+                        (ulong) rli->group_master_log_pos));
+  }
   pthread_mutex_unlock(&rli->data_lock);
   pthread_cond_broadcast(&rli->data_cond);
   flush_relay_log_info(rli);
-- 
2.30.9