List:Commits« Previous MessageNext Message »
From:Dao-Gang.Qu Date:May 4 2010 8:34am
Subject:bzr commit into mysql-5.1-rep+2 branch (Dao-Gang.Qu:3185) WL#344
View as plain text  
#At file:///home/daogangqu/mysql/bzrwork/wl4033/mysql-5.1-rep%2B2/ based on revid:li-bing.song@stripped

 3185 Dao-Gang.Qu@stripped	2010-05-04
      WL#344 Support for informational log events
      
      Adding a new ignorable event, and its incremental sub-hierarchy,
      which have as default that if their type code are not recognized,
      these events are just ignored and replication keeps going as usual.
     @ mysql-test/suite/rpl/r/rpl_ignorable_event.result
        Test result for wl#4033.
     @ mysql-test/suite/rpl/t/rpl_ignorable_event.test
        Added test to verify if the 'Comment_log_event' is
        written into binlog with its row event.
     @ sql/log.cc
        Added code to write ignorable log event to binlog.
     @ sql/log_event.cc
        Added code to create an object of 'Ignorable_log_event' for unrecognized
        sub-class. So that SLAVE SQL THREAD can ignore an unrecognized one.
     @ sql/log_event.h
        Added Ignorable_log_event class and its sub-class 'Comment_log_event' 
        to send over ignorable data to the slave.
     @ sql/slave.cc
        Added code to handle recognized sub-class of Ignorable_log_event
        according to its logic and treat unrecognized sub-class as its
        base class 'Ignorable_log_event' and ignore it after update
        the positions of the relay log.
     @ sql/sql_class.cc
        Added code to write the 'Comment_log_event' into binlog
        with its row event.

    added:
      mysql-test/suite/rpl/r/rpl_ignorable_event.result
      mysql-test/suite/rpl/t/rpl_ignorable_event.test
    modified:
      sql/log.cc
      sql/log.h
      sql/log_event.cc
      sql/log_event.h
      sql/slave.cc
      sql/sql_class.cc
=== added file 'mysql-test/suite/rpl/r/rpl_ignorable_event.result'
--- a/mysql-test/suite/rpl/r/rpl_ignorable_event.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_ignorable_event.result	2010-05-04 08:34:02 +0000
@@ -0,0 +1,48 @@
+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 table t1(a int, b int);
+insert into t1(a,b) values(1,1),(2,1),(3,1);
+update t1 set a = a + 5 where b = 1;
+delete from t1 where a = 6;
+insert into t1(a,b) values(1,2);
+insert into t1(a,b) values(1,3);
+insert into t1(a,b) values(1,4);
+SHOW BINLOG EVENTS;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	4	Format_desc	1	109	Server ver: 5.1.46-debug-log, Binlog ver: 4
+master-bin.000001	109	Query	1	201	use `test`; create table t1(a int, b int)
+master-bin.000001	201	Ignorable	1	264	#insert into t1(a,b) values(1,1),(2,1),(3,1)
+master-bin.000001	264	Query	1	332	BEGIN
+master-bin.000001	332	Table_map	1	374	table_id: 23 (test.t1)
+master-bin.000001	374	Write_rows	1	430	table_id: 23 flags: STMT_END_F
+master-bin.000001	430	Query	1	499	COMMIT
+master-bin.000001	499	Ignorable	1	554	#update t1 set a = a + 5 where b = 1
+master-bin.000001	554	Query	1	622	BEGIN
+master-bin.000001	622	Table_map	1	664	table_id: 23 (test.t1)
+master-bin.000001	664	Update_rows	1	748	table_id: 23 flags: STMT_END_F
+master-bin.000001	748	Query	1	817	COMMIT
+master-bin.000001	817	Ignorable	1	863	#delete from t1 where a = 6
+master-bin.000001	863	Query	1	931	BEGIN
+master-bin.000001	931	Table_map	1	973	table_id: 23 (test.t1)
+master-bin.000001	973	Delete_rows	1	1011	table_id: 23 flags: STMT_END_F
+master-bin.000001	1011	Query	1	1080	COMMIT
+master-bin.000001	1080	Ignorable	1	1131	#insert into t1(a,b) values(1,2)
+master-bin.000001	1131	Query	1	1199	BEGIN
+master-bin.000001	1199	Table_map	1	1241	table_id: 23 (test.t1)
+master-bin.000001	1241	Write_rows	1	1279	table_id: 23 flags: STMT_END_F
+master-bin.000001	1279	Query	1	1348	COMMIT
+master-bin.000001	1348	Ignorable	1	1399	#insert into t1(a,b) values(1,3)
+master-bin.000001	1399	Query	1	1467	BEGIN
+master-bin.000001	1467	Table_map	1	1509	table_id: 23 (test.t1)
+master-bin.000001	1509	Write_rows	1	1547	table_id: 23 flags: STMT_END_F
+master-bin.000001	1547	Query	1	1616	COMMIT
+master-bin.000001	1616	Ignorable	1	1667	#insert into t1(a,b) values(1,4)
+master-bin.000001	1667	Query	1	1735	BEGIN
+master-bin.000001	1735	Table_map	1	1777	table_id: 23 (test.t1)
+master-bin.000001	1777	Write_rows	1	1815	table_id: 23 flags: STMT_END_F
+master-bin.000001	1815	Query	1	1884	COMMIT
+DROP TABLE t1;

=== added file 'mysql-test/suite/rpl/t/rpl_ignorable_event.test'
--- a/mysql-test/suite/rpl/t/rpl_ignorable_event.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_ignorable_event.test	2010-05-04 08:34:02 +0000
@@ -0,0 +1,16 @@
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+create table t1(a int, b int);
+
+insert into t1(a,b) values(1,1),(2,1),(3,1);
+update t1 set a = a + 5 where b = 1;
+delete from t1 where a = 6;
+insert into t1(a,b) values(1,2);
+insert into t1(a,b) values(1,3);
+insert into t1(a,b) values(1,4);
+SHOW BINLOG EVENTS;
+
+DROP TABLE t1;
+sync_slave_with_master;
+

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2010-03-17 11:31:50 +0000
+++ b/sql/log.cc	2010-05-04 08:34:02 +0000
@@ -5031,6 +5031,25 @@ bool MYSQL_BIN_LOG::write_incident(THD *
   DBUG_RETURN(error);
 }
 
+bool MYSQL_BIN_LOG::write_ignorable_event(Ignorable_log_event* ev, bool lock)
+{
+  uint error= 0;
+  DBUG_ENTER("MYSQL_BIN_LOG::write_information");
+  if (lock)
+    pthread_mutex_lock(&LOCK_log);
+  error= ev->write(&log_file);
+  if (lock)
+  {
+    if (!error && !(error= flush_and_sync(0)))
+    {
+      signal_update();
+      rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
+    }
+    pthread_mutex_unlock(&LOCK_log);
+  }
+  DBUG_RETURN(error);
+}
+
 /**
   Write a cached log entry to the binary log.
   - To support transaction over replication, we wrap the transaction

=== modified file 'sql/log.h'
--- a/sql/log.h	2010-02-13 09:42:41 +0000
+++ b/sql/log.h	2010-05-04 08:34:02 +0000
@@ -19,6 +19,7 @@
 class Relay_log_info;
 
 class Format_description_log_event;
+class Ignorable_log_event;
 
 bool trans_has_updated_trans_table(const THD* thd);
 bool stmt_has_updated_trans_table(const THD *thd);
@@ -395,6 +396,7 @@ public:
   bool write(Log_event* event_info);
   bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
   bool write_incident(THD *thd, bool lock);
+  bool write_ignorable_event(Ignorable_log_event* ev, bool lock);
 
   int  write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
   void set_write_error(THD *thd);

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2010-03-03 14:43:35 +0000
+++ b/sql/log_event.cc	2010-05-04 08:34:02 +0000
@@ -644,6 +644,8 @@ const char* Log_event::get_type_str(Log_
   case BEGIN_LOAD_QUERY_EVENT: return "Begin_load_query";
   case EXECUTE_LOAD_QUERY_EVENT: return "Execute_load_query";
   case INCIDENT_EVENT: return "Incident";
+  case IGNORABLE_LOG_EVENT: return "Ignorable";
+  case COMMENT_LOG_EVENT: return "Ignorable";
   default: return "Unknown";				/* impossible */
   }
 }
@@ -1294,7 +1296,19 @@ Log_event* Log_event::read_log_event(con
     case INCIDENT_EVENT:
       ev = new Incident_log_event(buf, event_len, description_event);
       break;
+    case COMMENT_LOG_EVENT:
+      ev= new Comment_log_event(buf, event_len, description_event);
+      break;
     default:
+      /*
+        Create an object of Ignorable_log_event for unrecognized sub-class.
+        So that SLAVE SQL THREAD can ignore the unrecognized one.
+      */
+      if (uint2korr(buf + FLAGS_OFFSET) & LOG_EVENT_IGNORABLE_F)
+      {
+        ev= new Ignorable_log_event(buf, description_event);
+        DBUG_RETURN(ev);
+      }
       DBUG_PRINT("error",("Unknown event code: %d",
                           (int) buf[EVENT_TYPE_OFFSET]));
       ev= NULL;
@@ -3811,6 +3825,8 @@ Format_description_log_event(uint8 binlo
                       post_header_len[DELETE_ROWS_EVENT-1]= 6;);
       post_header_len[INCIDENT_EVENT-1]= INCIDENT_HEADER_LEN;
       post_header_len[HEARTBEAT_LOG_EVENT-1]= 0;
+      post_header_len[IGNORABLE_LOG_EVENT-1]= IGNORABLE_HEADER_LEN;
+      post_header_len[COMMENT_LOG_EVENT-1]= IGNORABLE_HEADER_LEN;
 
       // Sanity-check that all post header lengths are initialized.
       IF_DBUG({
@@ -9639,6 +9655,80 @@ Incident_log_event::write_data_body(IO_C
 }
 
 
+Ignorable_log_event::Ignorable_log_event(const char *buf,
+                                         const Format_description_log_event *descr_event)
+  : Log_event(buf, descr_event)
+{
+  DBUG_ENTER("Ignorable_log_event::Ignorable_log_event");
+  DBUG_VOID_RETURN;
+}
+
+Ignorable_log_event::~Ignorable_log_event()
+{
+}
+
+
+Comment_log_event::Comment_log_event(const char *buf, uint event_len,
+                                       const Format_description_log_event *descr_event)
+  : Ignorable_log_event(buf, descr_event)
+{
+  DBUG_ENTER("Comment_log_event::Comment_log_event");
+  uint8 const common_header_len=
+    descr_event->common_header_len;
+  uint8 const post_header_len=
+    descr_event->post_header_len[COMMENT_LOG_EVENT-1];
+
+  DBUG_PRINT("info",("event_len: %u; common_header_len: %d; post_header_len: %d",
+                     event_len, common_header_len, post_header_len));
+
+  char const *ptr= buf + common_header_len + post_header_len;
+  char const *const str_end= buf + event_len;
+  uint8 len= 0;                   // Assignment to keep compiler happy
+  const char *str= NULL;          // Assignment to keep compiler happy
+  read_str(&ptr, str_end, &str, &len);
+  m_comment.str= const_cast<char*>(str);
+  m_comment.length= len;
+  DBUG_PRINT("info", ("m_comment: %s", m_comment.str));
+  DBUG_VOID_RETURN;
+}
+
+Comment_log_event::~Comment_log_event()
+{
+}
+
+#ifndef MYSQL_CLIENT
+void Comment_log_event::pack_info(Protocol *protocol)
+{
+  char buf[256];
+  size_t bytes;
+  bytes= my_snprintf(buf, sizeof(buf), "#%s", m_comment.str);
+  protocol->store(buf, bytes, &my_charset_bin);
+}
+#endif
+
+#ifdef MYSQL_CLIENT
+void
+Comment_log_event::print(FILE *file,
+                         PRINT_EVENT_INFO *print_event_info)
+{
+  if (print_event_info->short_form)
+    return;
+
+  Write_on_release_cache cache(&print_event_info->head_cache, file);
+  print_header(&cache, print_event_info, FALSE);
+  my_b_printf(&cache, "\tIgnorable\n");
+  my_b_printf(&cache, "# comment: %s\n", m_comment.str);
+}
+#endif
+
+bool
+Comment_log_event::write_data_body(IO_CACHE *file)
+{
+  DBUG_ENTER("Comment_log_event::write_data_body");
+  DBUG_RETURN(write_str(file, m_comment.str, (uint) m_comment.length));
+}
+
+
 #ifdef MYSQL_CLIENT
 /**
   The default values for these variables should be values that are

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2010-02-14 01:14:36 +0000
+++ b/sql/log_event.h	2010-05-04 08:34:02 +0000
@@ -251,6 +251,7 @@ struct sql_ex_info
 #define EXECUTE_LOAD_QUERY_HEADER_LEN  (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN)
 #define INCIDENT_HEADER_LEN    2
 #define HEARTBEAT_HEADER_LEN   0
+#define IGNORABLE_HEADER_LEN 0
 /* 
   Max number of possible extra bytes in a replication event compared to a
   packet (i.e. a query) sent from client to master;
@@ -489,6 +490,13 @@ struct sql_ex_info
 #define LOG_EVENT_RELAY_LOG_F 0x40
 
 /**
+   @def LOG_EVENT_IGNORABLE_F
+
+   Events with this flag set are ignorable on slave
+*/
+#define LOG_EVENT_IGNORABLE_F 0x80
+
+/**
   @def OPTIONS_WRITTEN_TO_BIN_LOG
 
   OPTIONS_WRITTEN_TO_BIN_LOG are the bits of thd->options which must
@@ -585,7 +593,16 @@ enum Log_event_type
     to ensure master's online status to slave 
   */
   HEARTBEAT_LOG_EVENT= 27,
-  
+
+  /*
+    In some situations, it is necessary to send over ignorable
+    data to the slave: data that a slave can handle in case there
+    is code for handling it, but which can be ignored if it is not
+    recognized.
+  */
+  IGNORABLE_LOG_EVENT= 28,
+  COMMENT_LOG_EVENT= 29,
+
   /*
     Add new events here - right above this comment!
     Existing events (except ENUM_END_EVENT) should never change their numbers
@@ -1065,6 +1082,7 @@ public:
   void set_relay_log_event() { flags |= LOG_EVENT_RELAY_LOG_F; }
   bool is_artificial_event() const { return flags & LOG_EVENT_ARTIFICIAL_F; }
   bool is_relay_log_event() const { return flags & LOG_EVENT_RELAY_LOG_F; }
+  bool is_ignorable_event() const { return flags & LOG_EVENT_IGNORABLE_F; }
   inline bool use_trans_cache() const
   { 
     return (cache_type == Log_event::EVENT_TRANSACTIONAL_CACHE);
@@ -3994,6 +4012,86 @@ private:
   LEX_STRING m_message;
 };
 
+
+/**
+  @class Ignorable_log_event
+  Ignorable log event to send over ignorable data to the slave,
+  and its incremental sub-hierarchy, which have as default that if
+  their type code are not recognized, these events are just ignored
+  and replication keeps going as usual.
+**/
+class Ignorable_log_event : public Log_event {
+public:
+#ifndef MYSQL_CLIENT
+  Ignorable_log_event(THD *thd_arg) : Log_event(thd_arg, 0, FALSE)
+  {
+    DBUG_ENTER("Ignorable_log_event::Ignorable_log_event");
+    set_ignorable_event();
+    DBUG_VOID_RETURN;
+  }
+#endif
+
+  Ignorable_log_event(const char *buf,
+                      const Format_description_log_event *descr_event);
+
+  virtual ~Ignorable_log_event();
+
+#ifdef MYSQL_CLIENT
+  virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info) { return; }
+#endif
+
+  virtual Log_event_type get_type_code() { return IGNORABLE_LOG_EVENT; }
+
+  virtual bool is_valid() const { return 1; }
+
+  virtual int get_data_size() { return IGNORABLE_HEADER_LEN; }
+
+private:
+  void set_ignorable_event() { flags |= LOG_EVENT_IGNORABLE_F; }
+};
+
+
+class Comment_log_event : public Ignorable_log_event {
+public:
+#ifndef MYSQL_CLIENT
+  Comment_log_event(THD *thd_arg, LEX_STRING const comment)
+    : Ignorable_log_event(thd_arg)
+  {
+    DBUG_ENTER("Comment_log_event::Comment_log_event");
+    DBUG_PRINT("enter", ("comment: %s", comment.str));
+    m_comment= comment;
+    DBUG_VOID_RETURN;
+  }
+#endif
+
+#ifndef MYSQL_CLIENT
+  void pack_info(Protocol*);
+#endif
+
+  Comment_log_event(const char *buf, uint event_len,
+                     const Format_description_log_event *descr_event);
+
+  virtual ~Comment_log_event();
+
+#ifdef MYSQL_CLIENT
+  virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info);
+#endif
+  virtual bool write_data_body(IO_CACHE *file);
+
+  virtual Log_event_type get_type_code() { return COMMENT_LOG_EVENT; }
+
+  virtual int get_data_size()
+  {
+    return IGNORABLE_HEADER_LEN + 1 + (uint) m_comment.length;
+  }
+
+private:
+
+  LEX_STRING m_comment;
+};
+
+
+
 static inline bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache,
                                                        FILE *file)
 {

=== modified file 'sql/slave.cc'
--- a/sql/slave.cc	2010-02-12 23:30:44 +0000
+++ b/sql/slave.cc	2010-05-04 08:34:02 +0000
@@ -2369,6 +2369,51 @@ static int exec_relay_log_event(THD* thd
     delete ev;
     DBUG_RETURN(1);
   }
+
+  /*
+     Every concrete sub-class of Ignorable_log_event will be handled
+     according to its logic if the SLAVE SQL THREAD can recognize it.
+     Else the unrecognized one is treated as an Ignorable_log_event
+     and is ignored after update the positions of the relay log.
+  */
+  if (ev && ev->is_ignorable_event())
+  {
+    int err_update_pos= 0;
+    pthread_mutex_unlock(&rli->data_lock);
+    switch(ev->get_type_code()) {
+    case IGNORABLE_LOG_EVENT:
+    case COMMENT_LOG_EVENT:
+      err_update_pos= ev->update_pos(rli);
+      delete ev;
+      break;
+    /*
+      TODO: Added new ignorable event and handle it 
+            according to the concrete class
+      case table_checksum_log_event:
+        ......
+      case lock_log_event:
+        ......
+    */
+    default:
+      rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR,
+                  "It should never be happened.");
+      DBUG_RETURN(1);
+    }
+    if (err_update_pos)
+    {
+      char buf[22];
+      rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR,
+                  "It was not possible to update the positions"
+                  " of the relay log information: the slave may"
+                  " be in an inconsistent state."
+                  " Stopped in %s position %s",
+                  rli->group_relay_log_name,
+                  llstr(rli->group_relay_log_pos, buf));
+      DBUG_RETURN(1);
+    }
+    DBUG_RETURN(0);
+  }
+
   if (ev)
   {
     int exec_res;

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2010-03-03 14:43:35 +0000
+++ b/sql/sql_class.cc	2010-05-04 08:34:02 +0000
@@ -4359,7 +4359,12 @@ int THD::binlog_query(THD::enum_binlog_q
                ("is_current_stmt_binlog_format_row: %d",
                 is_current_stmt_binlog_format_row()));
     if (is_current_stmt_binlog_format_row())
-      DBUG_RETURN(0);
+    {
+      /* Write the 'query' information even into binlog with its row event */
+      LEX_STRING const comment= { const_cast<char*>(query_arg), query_len };
+      Comment_log_event* ev= new Comment_log_event(this, comment);
+      DBUG_RETURN(mysql_bin_log.write_ignorable_event(ev, TRUE));
+    }
     /* Fall through */
 
     /*


Attachment: [text/bzr-bundle] bzr/dao-gang.qu@sun.com-20100504083402-emdti8zzjstl0z9s.bundle
Thread
bzr commit into mysql-5.1-rep+2 branch (Dao-Gang.Qu:3185) WL#344Dao-Gang.Qu4 May