List:Commits« Previous MessageNext Message »
From:He Zhenxing Date:December 2 2010 7:23am
Subject:bzr commit into mysql-trunk-bugfixing branch (zhenxing.he:3378) WL#5675
View as plain text  
#At file:///media/sdb2/hezx/work/mysql/bzr/w5675/trunk-bugfixing/ based on revid:davi.arnaut@stripped

 3378 He Zhenxing	2010-12-02
      WL#5675 Replication librarification: Move to separate directory
              and define basic interfaces
      
      Move replication code to sql/rpl subdirectory.
      Make CHANGE MASTER support new options without modifying the parser.
      Defined classes Binlog, Rpl_master, Rpl_slave as the interface for
      binary log, replication master and slave respectively.

    added:
      sql/rpl/
      sql/rpl/CMakeLists.txt
      sql/rpl/binlog_priv.h
      sql/rpl/rpl.h
      sql/rpl/rpl_lex.cc
      sql/rpl/rpl_lex.h
    renamed:
      sql/binlog.cc => sql/rpl/binlog.cc
      sql/binlog.h => sql/rpl/binlog.h
      sql/log_event.cc => sql/rpl/log_event.cc
      sql/log_event.h => sql/rpl/log_event.h
      sql/log_event_old.cc => sql/rpl/log_event_old.cc
      sql/log_event_old.h => sql/rpl/log_event_old.h
      sql/rpl_constants.h => sql/rpl/rpl_constants.h
      sql/rpl_filter.cc => sql/rpl/rpl_filter.cc
      sql/rpl_filter.h => sql/rpl/rpl_filter.h
      sql/rpl_handler.cc => sql/rpl/rpl_handler.cc
      sql/rpl_handler.h => sql/rpl/rpl_handler.h
      sql/rpl_info.cc => sql/rpl/rpl_info.cc
      sql/rpl_info.h => sql/rpl/rpl_info.h
      sql/rpl_info_factory.cc => sql/rpl/rpl_info_factory.cc
      sql/rpl_info_factory.h => sql/rpl/rpl_info_factory.h
      sql/rpl_info_file.cc => sql/rpl/rpl_info_file.cc
      sql/rpl_info_file.h => sql/rpl/rpl_info_file.h
      sql/rpl_info_handler.cc => sql/rpl/rpl_info_handler.cc
      sql/rpl_info_handler.h => sql/rpl/rpl_info_handler.h
      sql/rpl_injector.cc => sql/rpl/rpl_injector.cc
      sql/rpl_injector.h => sql/rpl/rpl_injector.h
      sql/rpl_master.cc => sql/rpl/rpl_master.cc
      sql/rpl_master.h => sql/rpl/rpl_master.h
      sql/rpl_mi.cc => sql/rpl/rpl_mi.cc
      sql/rpl_mi.h => sql/rpl/rpl_mi.h
      sql/rpl_record.cc => sql/rpl/rpl_record.cc
      sql/rpl_record.h => sql/rpl/rpl_record.h
      sql/rpl_record_old.cc => sql/rpl/rpl_record_old.cc
      sql/rpl_record_old.h => sql/rpl/rpl_record_old.h
      sql/rpl_reporting.cc => sql/rpl/rpl_reporting.cc
      sql/rpl_reporting.h => sql/rpl/rpl_reporting.h
      sql/rpl_rli.cc => sql/rpl/rpl_rli.cc
      sql/rpl_rli.h => sql/rpl/rpl_rli.h
      sql/rpl_slave.cc => sql/rpl/rpl_slave.cc
      sql/rpl_slave.h => sql/rpl/rpl_slave.h
      sql/rpl_tblmap.cc => sql/rpl/rpl_tblmap.cc
      sql/rpl_tblmap.h => sql/rpl/rpl_tblmap.h
      sql/rpl_utility.cc => sql/rpl/rpl_utility.cc
      sql/rpl_utility.h => sql/rpl/rpl_utility.h
      sql/server_ids.h => sql/rpl/server_ids.h
      sql/sql_binlog.cc => sql/rpl/sql_binlog.cc
      sql/sql_binlog.h => sql/rpl/sql_binlog.h
    modified:
      CMakeLists.txt
      client/CMakeLists.txt
      client/mysqlbinlog.cc
      cmake/plugin.cmake
      libmysqld/CMakeLists.txt
      mysql-test/suite/rpl/r/rpl_heartbeat_basic.result
      mysql-test/suite/rpl/t/rpl_heartbeat_basic.test
      sql/CMakeLists.txt
      sql/ha_ndbcluster_binlog.cc
      sql/handler.cc
      sql/mysqld.cc
      sql/mysqld.h
      sql/replication.h
      sql/sp.cc
      sql/sql_acl.cc
      sql/sql_base.cc
      sql/sql_class.h
      sql/sql_delete.cc
      sql/sql_insert.cc
      sql/sql_lex.cc
      sql/sql_lex.h
      sql/sql_parse.cc
      sql/sql_reload.cc
      sql/sql_table.cc
      sql/sql_update.cc
      sql/sql_view.cc
      sql/sql_yacc.yy
      sql/sys_vars.cc
      sql/rpl/binlog.cc
      sql/rpl/binlog.h
      sql/rpl/log_event.cc
      sql/rpl/log_event.h
      sql/rpl/rpl_filter.cc
      sql/rpl/rpl_filter.h
      sql/rpl/rpl_master.cc
      sql/rpl/rpl_master.h
      sql/rpl/rpl_rli.h
      sql/rpl/rpl_slave.cc
      sql/rpl/rpl_slave.h
      sql/rpl/sql_binlog.cc
=== modified file 'CMakeLists.txt'
--- a/CMakeLists.txt	2010-11-19 13:59:45 +0000
+++ b/CMakeLists.txt	2010-12-02 07:23:18 +0000
@@ -301,6 +301,7 @@ IF(NOT WITHOUT_SERVER)
   ADD_SUBDIRECTORY(client)
   ADD_SUBDIRECTORY(sql)
   ADD_SUBDIRECTORY(sql/share)
+  ADD_SUBDIRECTORY(sql/rpl)
   ADD_SUBDIRECTORY(libservices)
   OPTION (WITH_EMBEDDED_SERVER "Compile MySQL with embedded server" OFF)
   IF(WITH_EMBEDDED_SERVER) 

=== modified file 'client/CMakeLists.txt'
--- a/client/CMakeLists.txt	2010-09-20 14:17:32 +0000
+++ b/client/CMakeLists.txt	2010-12-02 07:23:18 +0000
@@ -20,6 +20,7 @@ INCLUDE_DIRECTORIES(
   ${CMAKE_SOURCE_DIR}/libmysql
   ${CMAKE_SOURCE_DIR}/regex
   ${CMAKE_SOURCE_DIR}/sql
+  ${CMAKE_SOURCE_DIR}/sql/rpl
   ${CMAKE_SOURCE_DIR}/strings
   ${READLINE_INCLUDE_DIR}
   ${CMAKE_CURRENT_BINARY_DIR}

=== modified file 'client/mysqlbinlog.cc'
--- a/client/mysqlbinlog.cc	2010-11-18 04:37:26 +0000
+++ b/client/mysqlbinlog.cc	2010-12-02 07:23:18 +0000
@@ -52,7 +52,7 @@ ulong server_id = 0;
 ulong bytes_sent = 0L, bytes_received = 0L;
 ulong mysqld_net_retry_count = 10L;
 ulong open_files_limit;
-ulong opt_binlog_rows_event_max_size;
+//ulong opt_binlog_rows_event_max_size;
 uint test_flags = 0; 
 static uint opt_protocol= 0;
 static FILE *result_file;

=== modified file 'cmake/plugin.cmake'
--- a/cmake/plugin.cmake	2010-11-14 18:09:32 +0000
+++ b/cmake/plugin.cmake	2010-12-02 07:23:18 +0000
@@ -37,6 +37,7 @@ MACRO(MYSQL_ADD_PLUGIN)
   # Add common include directories
   INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include 
                     ${CMAKE_SOURCE_DIR}/sql
+                    ${CMAKE_SOURCE_DIR}/sql/rpl
                     ${CMAKE_SOURCE_DIR}/regex
                     ${SSL_INCLUDE_DIRS}
                     ${ZLIB_INCLUDE_DIR})

=== modified file 'libmysqld/CMakeLists.txt'
--- a/libmysqld/CMakeLists.txt	2010-11-04 15:40:18 +0000
+++ b/libmysqld/CMakeLists.txt	2010-12-02 07:23:18 +0000
@@ -21,6 +21,7 @@ ${CMAKE_SOURCE_DIR}/include 
 ${CMAKE_SOURCE_DIR}/libmysql
 ${CMAKE_SOURCE_DIR}/libmysqld
 ${CMAKE_SOURCE_DIR}/sql
+${CMAKE_SOURCE_DIR}/sql/rpl
 ${CMAKE_BINARY_DIR}/sql 
 ${CMAKE_SOURCE_DIR}/regex
 ${ZLIB_INCLUDE_DIR}
@@ -52,12 +53,12 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc l
            ../sql/item_geofunc.cc ../sql/item_row.cc ../sql/item_strfunc.cc 
            ../sql/item_subselect.cc ../sql/item_sum.cc ../sql/item_timefunc.cc 
            ../sql/item_xmlfunc.cc ../sql/key.cc ../sql/lock.cc ../sql/log.cc 
-           ../sql/log_event.cc ../sql/mf_iocache.cc ../sql/my_decimal.cc 
+           ../sql/rpl/log_event.cc ../sql/mf_iocache.cc ../sql/my_decimal.cc 
            ../sql/net_serv.cc ../sql/opt_range.cc ../sql/opt_sum.cc 
            ../sql/parse_file.cc ../sql/procedure.cc ../sql/protocol.cc 
-           ../sql/records.cc ../sql/rpl_filter.cc
-           ../sql/rpl_record.cc ../sql/sha2.cc ../sql/des_key_file.cc
-           ../sql/rpl_injector.cc ../sql/set_var.cc ../sql/spatial.cc 
+           ../sql/records.cc ../sql/rpl/rpl_filter.cc
+           ../sql/rpl/rpl_record.cc ../sql/sha2.cc ../sql/des_key_file.cc
+           ../sql/rpl/rpl_injector.cc ../sql/set_var.cc ../sql/spatial.cc 
            ../sql/sp_cache.cc ../sql/sp.cc ../sql/sp_head.cc 
            ../sql/sp_pcontext.cc ../sql/sp_rcontext.cc ../sql/sql_acl.cc 
            ../sql/sql_alloc_error_handler.cc
@@ -70,7 +71,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc l
            ../sql/sql_reload.cc
            ../sql/sql_lex.cc ../sql/keycaches.cc
            ../sql/sql_list.cc ../sql/sql_load.cc ../sql/sql_locale.cc 
-           ../sql/sql_binlog.cc ../sql/sql_manager.cc
+           ../sql/rpl/sql_binlog.cc ../sql/sql_manager.cc
            ../sql/sql_parse.cc ../sql/sql_partition.cc ../sql/sql_plugin.cc 
            ../sql/debug_sync.cc
            ../sql/sql_prepare.cc ../sql/sql_rename.cc
@@ -85,8 +86,10 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc l
            ../sql/scheduler.cc ../sql/sql_audit.cc
            ../sql/sql_alter.cc ../sql/sql_partition_admin.cc
            ../sql/event_parse_data.cc
-           ../sql/sql_signal.cc ../sql/rpl_handler.cc
-           ../sql/rpl_utility.cc ../sql/binlog.cc ../sql/sys_vars.cc
+           ../sql/sql_signal.cc ../sql/rpl/rpl_handler.cc
+	   ../sql/rpl/rpl_utility.cc ../sql/rpl/binlog.cc
+	   ../sql/rpl/rpl_lex.cc
+           ../sql/sys_vars.cc
            ../sql/gcalc_slicescan.cc ../sql/gcalc_tools.cc
            ${CMAKE_BINARY_DIR}/sql/sql_builtin.cc
            ../sql/mdl.cc ../sql/transaction.cc ../sql/sql_bootstrap.cc

=== modified file 'mysql-test/suite/rpl/r/rpl_heartbeat_basic.result'
--- a/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result	2010-10-21 11:34:17 +0000
+++ b/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result	2010-12-02 07:23:18 +0000
@@ -166,13 +166,13 @@ RESET SLAVE;
 
 *** Misc incorrect values ***
 CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD='-1';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''-1'' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
 RESET SLAVE;
 CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD='123abc';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''123abc'' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
 RESET SLAVE;
 CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD='';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '''' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
 RESET SLAVE;
 
 *** Running slave ***

=== modified file 'mysql-test/suite/rpl/t/rpl_heartbeat_basic.test'
--- a/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test	2010-08-26 16:37:57 +0000
+++ b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test	2010-12-02 07:23:18 +0000
@@ -226,15 +226,15 @@ RESET SLAVE;
 
 --echo *** Misc incorrect values ***
 --replace_result $MASTER_MYPORT MASTER_PORT
---error ER_PARSE_ERROR
+--error ER_SYNTAX_ERROR
 eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD='-1';
 RESET SLAVE;
 --replace_result $MASTER_MYPORT MASTER_PORT
---error ER_PARSE_ERROR
+--error ER_SYNTAX_ERROR
 eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD='123abc';
 RESET SLAVE;
 --replace_result $MASTER_MYPORT MASTER_PORT
---error ER_PARSE_ERROR
+--error ER_SYNTAX_ERROR
 eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD='';
 RESET SLAVE;
 --echo

=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2010-11-20 15:18:35 +0000
+++ b/sql/CMakeLists.txt	2010-12-02 07:23:18 +0000
@@ -16,6 +16,7 @@
 INCLUDE_DIRECTORIES(
 ${CMAKE_SOURCE_DIR}/include 
 ${CMAKE_SOURCE_DIR}/sql 
+${CMAKE_SOURCE_DIR}/sql/rpl 
 ${CMAKE_SOURCE_DIR}/regex 
 ${ZLIB_INCLUDE_DIR}
 ${SSL_INCLUDE_DIRS}
@@ -75,10 +76,11 @@ SET (SQL_SOURCE
                sql_signal.cc mdl.cc
                gcalc_slicescan.cc gcalc_tools.cc
                sql_alloc_error_handler.cc
-               transaction.cc sys_vars.cc  rpl_handler.cc sql_truncate.cc
+               transaction.cc sys_vars.cc  sql_truncate.cc
                datadict.cc sql_reload.cc
                sql_partition_admin.cc
                sql_admin.cc sql_alter.cc
+	       rpl/rpl_lex.cc
                ${GEN_SOURCES}
                ${MYSYS_LIBWRAP_SOURCE})
 
@@ -93,22 +95,6 @@ TARGET_LINK_LIBRARIES(sql ${MYSQLD_STATI
   ${LIBWRAP} ${LIBCRYPT} ${LIBDL}
   ${SSL_LIBRARIES})
 
-SET (BINLOG_SOURCE log_event.cc log_event_old.cc binlog.cc sql_binlog.cc
-		   rpl_filter.cc rpl_record.cc rpl_record_old.cc rpl_utility.cc
-		   sql_binlog.cc rpl_injector.cc)
-ADD_LIBRARY(binlog ${BINLOG_SOURCE})
-SET (RPL_SOURCE rpl_handler.cc rpl_tblmap.cc)
-ADD_DEPENDENCIES(binlog GenError)
-ADD_LIBRARY(rpl ${RPL_SOURCE})
-SET (MASTER_SOURCE rpl_master.cc)
-ADD_DEPENDENCIES(rpl GenError)
-ADD_LIBRARY(master ${MASTER_SOURCE})
-ADD_DEPENDENCIES(master GenError)
-SET (SLAVE_SOURCE rpl_slave.cc rpl_reporting.cc rpl_mi.cc rpl_rli.cc
-		  rpl_info_handler.cc rpl_info_file.cc rpl_info.cc
-                  rpl_info_factory.cc server_ids.h)
-ADD_LIBRARY(slave ${SLAVE_SOURCE})
-ADD_DEPENDENCIES(slave GenError)
 ADD_LIBRARY(sqlgunitlib mdl.cc sql_list.cc sql_string.cc thr_malloc.cc)
 ADD_DEPENDENCIES(sqlgunitlib GenError)
 

=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc	2010-10-21 09:49:16 +0000
+++ b/sql/ha_ndbcluster_binlog.cc	2010-12-02 07:23:18 +0000
@@ -1867,10 +1867,10 @@ static void ndb_binlog_query(THD *thd, C
     thd->server_id= schema->any_value;
   thd->db= schema->db;
   int errcode = query_error_code(thd, thd->killed == THD::NOT_KILLED);
-  thd->binlog_query(THD::STMT_QUERY_TYPE, schema->query,
-                    schema->query_length, FALSE, TRUE,
-                    schema->name[0] == 0 || thd->db[0] == 0,
-                    errcode);
+  binlog.binlog_query(thd, Binlog::STMT_QUERY_TYPE, schema->query,
+                      schema->query_length, FALSE, TRUE,
+                      schema->name[0] == 0 || thd->db[0] == 0,
+                      errcode);
   thd->server_id= thd_server_id_save;
   thd->db= thd_db_save;
 }

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2010-11-18 16:34:56 +0000
+++ b/sql/handler.cc	2010-12-02 07:23:18 +0000
@@ -67,8 +67,6 @@ st_plugin_int *hton2plugin[MAX_HA];
 
 static handlerton *installed_htons[128];
 
-#define BITMAP_STACKBUF_SIZE (128/8)
-
 KEY_CREATE_INFO default_key_create_info=
   { HA_KEY_ALG_UNDEF, 0, {NullS, 0}, {NullS, 0} };
 
@@ -5562,166 +5560,6 @@ bool ha_show_status(THD *thd, handlerton
   return result;
 }
 
-/*
-  Function to check if the conditions for row-based binlogging is
-  correct for the table.
-
-  A row in the given table should be replicated if:
-  - Row-based replication is enabled in the current thread
-  - The binlog is enabled
-  - It is not a temporary table
-  - The binary log is open
-  - The database the table resides in shall be binlogged (binlog_*_db rules)
-  - table is not mysql.event
-*/
-
-static bool check_table_binlog_row_based(THD *thd, TABLE *table)
-{
-  if (table->s->cached_row_logging_check == -1)
-  {
-    int const check(table->s->tmp_table == NO_TMP_TABLE &&
-                    binlog_filter->db_ok(table->s->db.str));
-    table->s->cached_row_logging_check= check;
-  }
-
-  DBUG_ASSERT(table->s->cached_row_logging_check == 0 ||
-              table->s->cached_row_logging_check == 1);
-
-  return (thd->is_current_stmt_binlog_format_row() &&
-          table->s->cached_row_logging_check &&
-          (thd->variables.option_bits & OPTION_BIN_LOG) &&
-          mysql_bin_log.is_open());
-}
-
-
-/** @brief
-   Write table maps for all (manually or automatically) locked tables
-   to the binary log.
-
-   SYNOPSIS
-     write_locked_table_maps()
-       thd     Pointer to THD structure
-
-   DESCRIPTION
-       This function will generate and write table maps for all tables
-       that are locked by the thread 'thd'.
-
-   RETURN VALUE
-       0   All OK
-       1   Failed to write all table maps
-
-   SEE ALSO
-       THD::lock
-*/
-
-static int write_locked_table_maps(THD *thd)
-{
-  DBUG_ENTER("write_locked_table_maps");
-  DBUG_PRINT("enter", ("thd: 0x%lx  thd->lock: 0x%lx "
-                       "thd->extra_lock: 0x%lx",
-                       (long) thd, (long) thd->lock, (long) thd->extra_lock));
-
-  DBUG_PRINT("debug", ("get_binlog_table_maps(): %d", thd->get_binlog_table_maps()));
-
-  if (thd->get_binlog_table_maps() == 0)
-  {
-    MYSQL_LOCK *locks[2];
-    locks[0]= thd->extra_lock;
-    locks[1]= thd->lock;
-    for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
-    {
-      MYSQL_LOCK const *const lock= locks[i];
-      if (lock == NULL)
-        continue;
-
-      bool need_binlog_rows_query= thd->variables.binlog_rows_query_log_events;
-      TABLE **const end_ptr= lock->table + lock->table_count;
-      for (TABLE **table_ptr= lock->table ; 
-           table_ptr != end_ptr ;
-           ++table_ptr)
-      {
-        TABLE *const table= *table_ptr;
-        DBUG_PRINT("info", ("Checking table %s", table->s->table_name.str));
-        if (table->current_lock == F_WRLCK &&
-            check_table_binlog_row_based(thd, table))
-        {
-          /*
-            We need to have a transactional behavior for SQLCOM_CREATE_TABLE
-            (e.g. CREATE TABLE... SELECT * FROM TABLE) in order to keep a
-            compatible behavior with the STMT based replication even when
-            the table is not transactional. In other words, if the operation
-            fails while executing the insert phase nothing is written to the
-            binlog.
-
-            Note that at this point, we check the type of a set of tables to
-            create the table map events. In the function binlog_log_row(),
-            which calls the current function, we check the type of the table
-            of the current row.
-          */
-          bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
-                                table->file->has_transactions();
-          int const error= thd->binlog_write_table_map(table, has_trans,
-                                                       need_binlog_rows_query);
-          /* Binlog Rows_query log event once for one statement which updates
-             two or more tables.*/
-          if (need_binlog_rows_query)
-            need_binlog_rows_query= FALSE;
-          /*
-            If an error occurs, it is the responsibility of the caller to
-            roll back the transaction.
-          */
-          if (unlikely(error))
-            DBUG_RETURN(1);
-        }
-      }
-    }
-  }
-  DBUG_RETURN(0);
-}
-
-
-typedef bool Log_func(THD*, TABLE*, bool,
-                      const uchar*, const uchar*);
-
-static int binlog_log_row(TABLE* table,
-                          const uchar *before_record,
-                          const uchar *after_record,
-                          Log_func *log_func)
-{
-  if (table->no_replicate)
-    return 0;
-  bool error= 0;
-  THD *const thd= table->in_use;
-
-  if (check_table_binlog_row_based(thd, table))
-  {
-    DBUG_DUMP("read_set 10", (uchar*) table->read_set->bitmap,
-              (table->s->fields + 7) / 8);
-
-    /*
-      If there are no table maps written to the binary log, this is
-      the first row handled in this statement. In that case, we need
-      to write table maps for all locked tables to the binary log.
-    */
-    if (likely(!(error= write_locked_table_maps(thd))))
-    {
-      /*
-        We need to have a transactional behavior for SQLCOM_CREATE_TABLE
-        (i.e. CREATE TABLE... SELECT * FROM TABLE) in order to keep a
-        compatible behavior with the STMT based replication even when
-        the table is not transactional. In other words, if the operation
-        fails while executing the insert phase nothing is written to the
-        binlog.
-      */
-      bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
-                           table->file->has_transactions();
-      error=
-        (*log_func)(thd, table, has_trans, before_record, after_record);
-    }
-  }
-  return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
-}
-
 int handler::ha_external_lock(THD *thd, int lock_type)
 {
   MYSQL_TABLE_WAIT_VARIABLES(locker, state) /* no ';' */
@@ -5823,7 +5661,6 @@ int handler::ha_reset()
 int handler::ha_write_row(uchar *buf)
 {
   int error;
-  Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
   MYSQL_TABLE_WAIT_VARIABLES(locker, state) /* no ';' */
 
   DBUG_ENTER("handler::ha_write_row");
@@ -5840,7 +5677,7 @@ int handler::ha_write_row(uchar *buf)
   if (unlikely(error))
     DBUG_RETURN(error);
 
-  if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
+  if (unlikely(error= binlog.write_row(table, buf)))
     DBUG_RETURN(error); /* purecov: inspected */
   DBUG_RETURN(0);
 }
@@ -5849,7 +5686,6 @@ int handler::ha_write_row(uchar *buf)
 int handler::ha_update_row(const uchar *old_data, uchar *new_data)
 {
   int error;
-  Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
   MYSQL_TABLE_WAIT_VARIABLES(locker, state) /* no ';' */
 
   /*
@@ -5870,7 +5706,7 @@ int handler::ha_update_row(const uchar *
   MYSQL_UPDATE_ROW_DONE(error);
   if (unlikely(error))
     return error;
-  if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
+  if (unlikely(error= binlog.update_row(table, old_data, new_data)))
     return error;
   return 0;
 }
@@ -5878,7 +5714,6 @@ int handler::ha_update_row(const uchar *
 int handler::ha_delete_row(const uchar *buf)
 {
   int error;
-  Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
   MYSQL_TABLE_WAIT_VARIABLES(locker, state) /* no ';' */
 
   MYSQL_DELETE_ROW_START(table_share->db.str, table_share->table_name.str);
@@ -5893,7 +5728,7 @@ int handler::ha_delete_row(const uchar *
   MYSQL_DELETE_ROW_DONE(error);
   if (unlikely(error))
     return error;
-  if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
+  if (unlikely(error= binlog.delete_row(table, buf)))
     return error;
   return 0;
 }

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2010-11-18 16:34:56 +0000
+++ b/sql/mysqld.cc	2010-12-02 07:23:18 +0000
@@ -53,7 +53,6 @@
 #include <m_ctype.h>
 #include <my_dir.h>
 #include <my_bit.h>
-#include "rpl_slave.h"
 #include "rpl_master.h"
 #include "rpl_mi.h"
 #include "rpl_filter.h"
@@ -433,7 +432,6 @@ volatile bool mqh_used = 0;
 my_bool opt_noacl;
 my_bool sp_automatic_privileges= 1;
 
-ulong opt_binlog_rows_event_max_size;
 const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
 #ifdef HAVE_INITGROUPS
 static bool calling_initgroups= FALSE; /**< Used in SIGSEGV handler. */
@@ -1101,7 +1099,7 @@ static void close_connections(void)
   mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list
 
   Events::deinit();
-  end_slave();
+  rpl_slave.end();
 
   if (thread_count)
     sleep(2);					// Give threads time to die
@@ -1463,7 +1461,7 @@ void clean_up(bool print_message)
   bitmap_free(&temp_pool);
   free_max_user_conn();
 #ifdef HAVE_REPLICATION
-  end_slave_list();
+  rpl_master.end();
 #endif
   delete binlog_filter;
   delete rpl_filter;
@@ -3522,18 +3520,11 @@ You should consider changing lower_case_
 			&my_charset_utf8_tolower_ci :
 			&my_charset_bin);
 
-  /*
-    Build do_table and ignore_table rules to hush
-    after the resetting of table_alias_charset
-  */
-  if (rpl_filter->build_do_table_hash() ||
-      rpl_filter->build_ignore_table_hash())
-  {
-    sql_print_error("An error occurred while building do_table"
-                    "and ignore_table rules to hush.");
+#ifdef HAVE_REPLICATION
+  if (rpl_filter->table_alias_charset_changed())
     return 1;
-  }
-
+#endif
+  
   return 0;
 }
 
@@ -3901,7 +3892,7 @@ static int init_server_components()
   setup_fpu();
   init_thr_lock();
 #ifdef HAVE_REPLICATION
-  init_slave_list();
+  rpl_master.init();
 #endif
 
   /* Setup logs */
@@ -4734,16 +4725,11 @@ int mysqld_main(int argc, char **argv)
   check_binlog_cache_size(NULL);
 
   binlog_unsafe_map_init();
+  
   /*
     init_slave() must be called after the thread keys are created.
-    Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other
-    places) assume that active_mi != 0, so let's fail if it's 0 (out of
-    memory); a message has already been printed.
   */
-  if (init_slave() && !active_mi)
-  {
-    unireg_abort(1);
-  }
+  rpl_slave.init();
 
 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
   initialize_performance_schema_acl(opt_bootstrap);
@@ -5904,16 +5890,6 @@ struct my_option my_long_options[]=
   {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
    "Tells the master that updates to the given database should not be logged to the binary log.",
    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-  {"binlog-row-event-max-size", 0,
-   "The maximum size of a row-based binary log event in bytes. Rows will be "
-   "grouped into events smaller than this size if possible. "
-   "The value has to be a multiple of 256.",
-   &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size,
-   0, GET_ULONG, REQUIRED_ARG,
-   /* def_value */ 1024, /* min_value */  256, /* max_value */ ULONG_MAX, 
-   /* sub_size */     0, /* block_size */ 256, 
-   /* app_type */ 0
-  },
 #ifndef DISABLE_GRANT_OPTIONS
   {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},

=== modified file 'sql/mysqld.h'
--- a/sql/mysqld.h	2010-11-18 16:34:56 +0000
+++ b/sql/mysqld.h	2010-12-02 07:23:18 +0000
@@ -149,6 +149,7 @@ extern char pidfile_name[FN_REFLEN], sys
 extern char default_logfile_name[FN_REFLEN];
 extern char log_error_file[FN_REFLEN], *opt_tc_log_file;
 /*Move UUID_LENGTH from item_strfunc.h*/
+#define HAVE_SERVER_UUID 1
 #define UUID_LENGTH (8+1+4+1+4+1+4+1+12)
 extern char server_uuid[UUID_LENGTH+1];
 extern const char *server_uuid_ptr;
@@ -179,7 +180,6 @@ extern ulong max_prepared_stmt_count, pr
 extern ulong binlog_cache_size, open_files_limit;
 extern ulonglong max_binlog_cache_size;
 extern ulong max_binlog_size, max_relay_log_size;
-extern ulong opt_binlog_rows_event_max_size;
 extern ulong thread_cache_size;
 extern ulong back_log;
 extern char language[FN_REFLEN];

=== modified file 'sql/replication.h'
--- a/sql/replication.h	2010-07-02 02:58:51 +0000
+++ b/sql/replication.h	2010-12-02 07:23:18 +0000
@@ -20,9 +20,7 @@
 
 typedef struct st_mysql MYSQL;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+C_MODE_START
 
 /**
    Transaction observer flags.
@@ -438,28 +436,6 @@ int register_binlog_relay_io_observer(Bi
 int unregister_binlog_relay_io_observer(Binlog_relay_IO_observer *observer, void *p);
 
 /**
-   Connect to master
-
-   This function can only used in the slave I/O thread context, and
-   will use the same master information to do the connection.
-
-   @code
-   MYSQL *mysql = mysql_init(NULL);
-   if (rpl_connect_master(mysql))
-   {
-     // do stuff with the connection
-   }
-   mysql_close(mysql); // close the connection
-   @endcode
-   
-   @param mysql address of MYSQL structure to use, pass NULL will
-   create a new one
-
-   @return address of MYSQL structure on success, NULL on failure
-*/
-MYSQL *rpl_connect_master(MYSQL *mysql);
-
-/**
    Set thread entering a condition
 
    This function should be called before putting a thread to wait for
@@ -544,9 +520,6 @@ int get_user_var_str(const char *name,
                      char *value, unsigned long len,
                      unsigned int precision, int *null_value);
 
-  
 
-#ifdef __cplusplus
-}
-#endif
+C_MODE_END
 #endif /* REPLICATION_H */

=== added directory 'sql/rpl'
=== added file 'sql/rpl/CMakeLists.txt'
--- a/sql/rpl/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ b/sql/rpl/CMakeLists.txt	2010-12-02 07:23:18 +0000
@@ -0,0 +1,46 @@
+# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+INCLUDE_DIRECTORIES(
+${CMAKE_SOURCE_DIR}/include 
+${CMAKE_SOURCE_DIR}/sql 
+${CMAKE_SOURCE_DIR}/sql/rpl 
+${CMAKE_SOURCE_DIR}/regex 
+${ZLIB_INCLUDE_DIR}
+${SSL_INCLUDE_DIRS}
+${CMAKE_BINARY_DIR}/sql
+)
+
+ADD_DEFINITIONS(-DMYSQL_SERVER -DHAVE_EVENT_SCHEDULER) 
+IF(SSL_DEFINES)
+ ADD_DEFINITIONS(${SSL_DEFINES})
+ENDIF()
+
+SET (BINLOG_SOURCE log_event.cc log_event_old.cc binlog.cc sql_binlog.cc
+		   rpl_filter.cc rpl_record.cc rpl_record_old.cc rpl_utility.cc
+		   sql_binlog.cc rpl_injector.cc)
+ADD_LIBRARY(binlog ${BINLOG_SOURCE})
+SET (RPL_SOURCE rpl_handler.cc rpl_tblmap.cc)
+ADD_DEPENDENCIES(binlog GenError)
+ADD_LIBRARY(rpl ${RPL_SOURCE})
+SET (MASTER_SOURCE rpl_master.cc)
+ADD_DEPENDENCIES(rpl GenError)
+ADD_LIBRARY(master ${MASTER_SOURCE})
+ADD_DEPENDENCIES(master GenError)
+SET (SLAVE_SOURCE rpl_slave.cc rpl_reporting.cc rpl_mi.cc rpl_rli.cc
+		  rpl_info_handler.cc rpl_info_file.cc rpl_info.cc
+                  rpl_info_factory.cc server_ids.h)
+ADD_LIBRARY(slave ${SLAVE_SOURCE})
+ADD_DEPENDENCIES(slave GenError)

=== renamed file 'sql/binlog.cc' => 'sql/rpl/binlog.cc'
--- a/sql/binlog.cc	2010-11-16 12:38:17 +0000
+++ b/sql/rpl/binlog.cc	2010-12-02 07:23:18 +0000
@@ -17,6 +17,7 @@
 #include "my_global.h"
 #include "log.h"
 #include "binlog.h"
+#include "binlog_priv.h"
 #include "log_event.h"
 #include "rpl_filter.h"
 #include "rpl_rli.h"
@@ -27,6 +28,7 @@
 #define MY_OFF_T_UNDEF (~(my_off_t)0UL)
 #define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
 
+Binlog binlog;
 handlerton *binlog_hton;
 
 const char *log_bin_index= 0;
@@ -1071,7 +1073,7 @@ bool stmt_has_updated_non_trans_table(co
   @retval FALSE success
   @retval TRUE failure
 */
-bool purge_master_logs(THD* thd, const char* to_log)
+int Binlog::purge_binary_logs(THD* thd, const char* to_log)
 {
   char search_file_name[FN_REFLEN];
   if (!mysql_bin_log.is_open())
@@ -1098,7 +1100,7 @@ bool purge_master_logs(THD* thd, const c
   @retval FALSE success
   @retval TRUE failure
 */
-bool purge_master_logs_before_date(THD* thd, time_t purge_time)
+int Binlog::purge_binary_logs_before(THD* thd, time_t purge_time)
 {
   if (!mysql_bin_log.is_open())
   {
@@ -1397,11 +1399,11 @@ err:
   @retval FALSE success
   @retval TRUE failure
 */
-bool mysql_show_binlog_events(THD* thd)
+int Binlog::show_binlog_events(THD* thd)
 {
   Protocol *protocol= thd->protocol;
   List<Item> field_list;
-  DBUG_ENTER("mysql_show_binlog_events");
+  DBUG_ENTER("Binlog::show_binlog_events");
 
   DBUG_ASSERT(thd->lex->sql_command == SQLCOM_SHOW_BINLOG_EVENTS);
 
@@ -1417,7 +1419,7 @@ bool mysql_show_binlog_events(THD* thd)
   */
   ha_binlog_wait(thd);
   
-  DBUG_RETURN(show_binlog_events(thd, &mysql_bin_log));
+  DBUG_RETURN(::show_binlog_events(thd, &mysql_bin_log));
 }
 
 #endif /* HAVE_REPLICATION */
@@ -4975,26 +4977,6 @@ int THD::binlog_flush_pending_rows_event
 }
 
 
-#if !defined(DBUG_OFF) && !defined(_lint)
-static const char *
-show_query_type(THD::enum_binlog_query_type qtype)
-{
-  switch (qtype) {
-  case THD::ROW_QUERY_TYPE:
-    return "ROW";
-  case THD::STMT_QUERY_TYPE:
-    return "STMT";
-  case THD::QUERY_TYPE_COUNT:
-  default:
-    DBUG_ASSERT(0 <= qtype && qtype < THD::QUERY_TYPE_COUNT);
-  }
-  static char buf[64];
-  sprintf(buf, "UNKNOWN#%d", qtype);
-  return buf;
-}
-#endif
-
-
 /**
   Auxiliary method used by @c binlog_query() to raise warnings.
 
@@ -5040,6 +5022,113 @@ void THD::issue_unsafe_warnings()
 }
 
 
+#endif /* !defined(MYSQL_CLIENT) */
+
+#ifdef INNODB_COMPATIBILITY_HOOKS
+/**
+  Get the file name of the MySQL binlog.
+  @return the name of the binlog file
+*/
+extern "C"
+const char* mysql_bin_log_file_name(void)
+{
+  return mysql_bin_log.get_log_fname();
+}
+/**
+  Get the current position of the MySQL binlog.
+  @return byte offset from the beginning of the binlog
+*/
+extern "C"
+ulonglong mysql_bin_log_file_pos(void)
+{
+  return (ulonglong) mysql_bin_log.get_log_file()->pos_in_file;
+}
+#endif /* INNODB_COMPATIBILITY_HOOKS */
+
+
+static MYSQL_SYSVAR_ULONG(row_event_max_size, opt_binlog_rows_event_max_size,
+       PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
+       "The maximum size of a row-based binary log event in bytes. Rows will be "
+       "grouped into events smaller than this size if possible. "
+       "The value has to be a multiple of 256.",
+       NULL,
+       NULL,
+       1024, 256, ULONG_MAX, 256);
+
+static MYSQL_THDVAR_BOOL(rows_query_log_events,
+       PLUGIN_VAR_OPCMDARG,
+      "Allow writing of Rows_query_log events into binary log.",
+       NULL,                                    /* check */
+       NULL,                                    /* update */ 
+       FALSE);                                  /* default */
+
+static struct st_mysql_sys_var* binlog_system_vars[]= {
+  MYSQL_SYSVAR(row_event_max_size),
+  MYSQL_SYSVAR(rows_query_log_events),
+  NULL,
+};
+
+struct st_mysql_storage_engine binlog_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION };
+
+mysql_declare_plugin(binlog)
+{
+  MYSQL_STORAGE_ENGINE_PLUGIN,
+  &binlog_storage_engine,
+  "binlog",
+  "MySQL AB",
+  "This is a pseudo storage engine to represent the binlog in a transaction",
+  PLUGIN_LICENSE_GPL,
+  binlog_init, /* Plugin Init */
+  NULL, /* Plugin Deinit */
+  0x0100 /* 1.0 */,
+  NULL,                       /* status variables                */
+  binlog_system_vars,         /* system variables                */
+  NULL                        /* config options                  */
+}
+mysql_declare_plugin_end;
+
+bool thd_binlog_rows_query_log_events(THD *thd)
+{
+  return THDVAR(thd, rows_query_log_events);
+}
+
+void set_binlog_rows_query_log_events(THD *thd, bool val)
+{
+  THDVAR(thd, rows_query_log_events)= val;
+}
+
+/*
+  Function to check if the conditions for row-based binlogging is
+  correct for the table.
+
+  A row in the given table should be replicated if:
+  - Row-based replication is enabled in the current thread
+  - The binlog is enabled
+  - It is not a temporary table
+  - The binary log is open
+  - The database the table resides in shall be binlogged (binlog_*_db rules)
+  - table is not mysql.event
+*/
+
+static bool check_table_binlog_row_based(THD *thd, TABLE *table)
+{
+  if (table->s->cached_row_logging_check == -1)
+  {
+    int const check(table->s->tmp_table == NO_TMP_TABLE &&
+                    binlog_filter->db_ok(table->s->db.str));
+    table->s->cached_row_logging_check= check;
+  }
+
+  DBUG_ASSERT(table->s->cached_row_logging_check == 0 ||
+              table->s->cached_row_logging_check == 1);
+
+  return (thd->is_current_stmt_binlog_format_row() &&
+          table->s->cached_row_logging_check &&
+          (thd->variables.option_bits & OPTION_BIN_LOG) &&
+          mysql_bin_log.is_open());
+}
+
 /**
   Log the current query.
 
@@ -5065,14 +5154,15 @@ void THD::issue_unsafe_warnings()
   @retval nonzero If there is a failure when writing the query (e.g.,
   write failure), then the error code is returned.
 */
-int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
-                      ulong query_len, bool is_trans, bool direct, 
-                      bool suppress_use, int errcode)
+int Binlog::binlog_query(THD* thd,
+                         enum_binlog_query_type qtype, char const *query,
+                         ulong query_len, bool is_trans, bool direct, 
+                         bool suppress_use, int errcode)
 {
-  DBUG_ENTER("THD::binlog_query");
+  DBUG_ENTER("Binlog::binlog_query");
   DBUG_PRINT("enter", ("qtype: %s  query: '%s'",
-                       show_query_type(qtype), query_arg));
-  DBUG_ASSERT(query_arg && mysql_bin_log.is_open());
+                       show_query_type(qtype), query));
+  DBUG_ASSERT(query && mysql_bin_log.is_open());
 
   /*
     If we are not in prelocked mode, mysql_unlock_tables() will be
@@ -5083,8 +5173,8 @@ int THD::binlog_query(THD::enum_binlog_q
     If we are in prelocked mode, the flushing will be done inside the
     top-most close_thread_tables().
   */
-  if (this->locked_tables_mode <= LTM_LOCK_TABLES)
-    if (int error= binlog_flush_pending_rows_event(TRUE, is_trans))
+  if (thd->locked_tables_mode <= LTM_LOCK_TABLES)
+    if (int error= thd->binlog_flush_pending_rows_event(TRUE, is_trans))
       DBUG_RETURN(error);
 
   /*
@@ -5100,7 +5190,7 @@ int THD::binlog_query(THD::enum_binlog_q
     2 - sp_head::execute_function which prints out warnings for calls
     involving functions.
 
-    3 - THD::binlog_query (here) which prints warning for top level
+    3 - Binlog::binlog_query (here) which prints warning for top level
     statements not covered by the two cases above: i.e., if not insided a
     procedure and a function.
  
@@ -5109,9 +5199,9 @@ int THD::binlog_query(THD::enum_binlog_q
     the execution is inside a function, or generaly speaking, when
     the variables.option_bits & OPTION_BIN_LOG is false.
   */
-  if ((variables.option_bits & OPTION_BIN_LOG) &&
-      spcont == NULL && !binlog_evt_union.do_union)
-    issue_unsafe_warnings();
+  if ((thd->variables.option_bits & OPTION_BIN_LOG) &&
+      thd->spcont == NULL && !thd->binlog_evt_union.do_union)
+    thd->issue_unsafe_warnings();
 
   switch (qtype) {
     /*
@@ -5121,11 +5211,11 @@ int THD::binlog_query(THD::enum_binlog_q
       statement has already been logged in row format and hence shall
       not be logged again.
     */
-  case THD::ROW_QUERY_TYPE:
+  case ROW_QUERY_TYPE:
     DBUG_PRINT("debug",
                ("is_current_stmt_binlog_format_row: %d",
-                is_current_stmt_binlog_format_row()));
-    if (is_current_stmt_binlog_format_row())
+                thd->is_current_stmt_binlog_format_row()));
+    if (thd->is_current_stmt_binlog_format_row())
       DBUG_RETURN(0);
     /* Fall through */
 
@@ -5139,13 +5229,13 @@ int THD::binlog_query(THD::enum_binlog_q
       STMT_QUERY_TYPE and current_stmt_binlog_format is row.  Fix those
       places and add assert to ensure correct behavior. /Sven
     */
-  case THD::STMT_QUERY_TYPE:
+  case STMT_QUERY_TYPE:
     /*
       The MYSQL_LOG::write() function will set the STMT_END_F flag and
       flush the pending rows event if necessary.
     */
     {
-      Query_log_event qinfo(this, query_arg, query_len, is_trans, direct,
+      Query_log_event qinfo(thd, query, query_len, is_trans, direct,
                             suppress_use, errcode);
       /*
         Binlog table maps will be irrelevant after a Query_log_event
@@ -5154,58 +5244,272 @@ int THD::binlog_query(THD::enum_binlog_q
         table maps were written.
        */
       int error= mysql_bin_log.write(&qinfo);
-      binlog_table_maps= 0;
+      thd->binlog_table_maps= 0;
       DBUG_RETURN(error);
     }
     break;
 
-  case THD::QUERY_TYPE_COUNT:
+  case QUERY_TYPE_COUNT:
   default:
     DBUG_ASSERT(0 <= qtype && qtype < QUERY_TYPE_COUNT);
   }
   DBUG_RETURN(0);
 }
 
-#endif /* !defined(MYSQL_CLIENT) */
-
-#ifdef INNODB_COMPATIBILITY_HOOKS
 /**
-  Get the file name of the MySQL binlog.
-  @return the name of the binlog file
+  Execute a SHOW BINARY LOGS statement.
+
+  @param thd Pointer to THD object for the client thread executing the
+  statement.
+
+  @retval FALSE success
+  @retval TRUE failure
 */
-extern "C"
-const char* mysql_bin_log_file_name(void)
+int Binlog::show_binary_logs(THD* thd)
 {
-  return mysql_bin_log.get_log_fname();
+  IO_CACHE *index_file;
+  LOG_INFO cur;
+  File file;
+  char fname[FN_REFLEN];
+  List<Item> field_list;
+  uint length;
+  int cur_dir_len;
+  Protocol *protocol= thd->protocol;
+  DBUG_ENTER("show_binlogs");
+
+  if (!mysql_bin_log.is_open())
+  {
+    my_message(ER_NO_BINARY_LOGGING, ER(ER_NO_BINARY_LOGGING), MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+
+  field_list.push_back(new Item_empty_string("Log_name", 255));
+  field_list.push_back(new Item_return_int("File_size", 20,
+                                           MYSQL_TYPE_LONGLONG));
+  if (protocol->send_result_set_metadata(&field_list,
+                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+    DBUG_RETURN(TRUE);
+  
+  mysql_mutex_lock(mysql_bin_log.get_log_lock());
+  mysql_bin_log.lock_index();
+  index_file=mysql_bin_log.get_index_file();
+  
+  mysql_bin_log.raw_get_current_log(&cur); // dont take mutex
+  mysql_mutex_unlock(mysql_bin_log.get_log_lock()); // lockdep, OK
+  
+  cur_dir_len= dirname_length(cur.log_file_name);
+
+  reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 0);
+
+  /* The file ends with EOF or empty line */
+  while ((length=my_b_gets(index_file, fname, sizeof(fname))) > 1)
+  {
+    int dir_len;
+    ulonglong file_length= 0;                   // Length if open fails
+    fname[--length] = '\0';                     // remove the newline
+
+    protocol->prepare_for_resend();
+    dir_len= dirname_length(fname);
+    length-= dir_len;
+    protocol->store(fname + dir_len, length, &my_charset_bin);
+
+    if (!(strncmp(fname+dir_len, cur.log_file_name+cur_dir_len, length)))
+      file_length= cur.pos;  /* The active log, use the active position */
+    else
+    {
+      /* this is an old log, open it and find the size */
+      if ((file= mysql_file_open(key_file_binlog,
+                                 fname, O_RDONLY | O_SHARE | O_BINARY,
+                                 MYF(0))) >= 0)
+      {
+        file_length= (ulonglong) mysql_file_seek(file, 0L, MY_SEEK_END, MYF(0));
+        mysql_file_close(file, MYF(0));
+      }
+    }
+    protocol->store(file_length);
+    if (protocol->write())
+      goto err;
+  }
+  mysql_bin_log.unlock_index();
+  my_eof(thd);
+  DBUG_RETURN(FALSE);
+
+err:
+  mysql_bin_log.unlock_index();
+  DBUG_RETURN(TRUE);
 }
-/**
-  Get the current position of the MySQL binlog.
-  @return byte offset from the beginning of the binlog
+
+#define BITMAP_STACKBUF_SIZE (128/8)
+
+int Binlog::log_row(TABLE* table,
+                    const uchar *before_record,
+                    const uchar *after_record,
+                    Log_func *log_func)
+{
+  if (table->no_replicate)
+    return 0;
+  bool error= 0;
+  THD *const thd= table->in_use;
+
+  if (check_table_binlog_row_based(thd, table))
+  {
+    DBUG_DUMP("read_set 10", (uchar*) table->read_set->bitmap,
+              (table->s->fields + 7) / 8);
+
+    /*
+      If there are no table maps written to the binary log, this is
+      the first row handled in this statement. In that case, we need
+      to write table maps for all locked tables to the binary log.
+    */
+    if (likely(!(error= write_locked_table_maps(thd))))
+    {
+      /*
+        We need to have a transactional behavior for SQLCOM_CREATE_TABLE
+        (i.e. CREATE TABLE... SELECT * FROM TABLE) in order to keep a
+        compatible behavior with the STMT based replication even when
+        the table is not transactional. In other words, if the operation
+        fails while executing the insert phase nothing is written to the
+        binlog.
+      */
+      bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
+                           table->file->has_transactions();
+      error=
+        (*log_func)(thd, table, has_trans, before_record, after_record);
+    }
+  }
+  return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
+}
+
+/** @brief
+   Write table maps for all (manually or automatically) locked tables
+   to the binary log.
+
+   SYNOPSIS
+     write_locked_table_maps()
+       thd     Pointer to THD structure
+
+   DESCRIPTION
+       This function will generate and write table maps for all tables
+       that are locked by the thread 'thd'.
+
+   RETURN VALUE
+       0   All OK
+       1   Failed to write all table maps
+
+   SEE ALSO
+       THD::lock
 */
-extern "C"
-ulonglong mysql_bin_log_file_pos(void)
+
+int Binlog::write_locked_table_maps(THD *thd)
 {
-  return (ulonglong) mysql_bin_log.get_log_file()->pos_in_file;
+  DBUG_ENTER("write_locked_table_maps");
+  DBUG_PRINT("enter", ("thd: 0x%lx  thd->lock: 0x%lx "
+                       "thd->extra_lock: 0x%lx",
+                       (long) thd, (long) thd->lock, (long) thd->extra_lock));
+
+  DBUG_PRINT("debug", ("get_binlog_table_maps(): %d", thd->get_binlog_table_maps()));
+
+  if (thd->get_binlog_table_maps() == 0)
+  {
+    MYSQL_LOCK *locks[2];
+    locks[0]= thd->extra_lock;
+    locks[1]= thd->lock;
+    for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
+    {
+      MYSQL_LOCK const *const lock= locks[i];
+      if (lock == NULL)
+        continue;
+
+      bool need_binlog_rows_query= thd_binlog_rows_query_log_events(thd);
+      TABLE **const end_ptr= lock->table + lock->table_count;
+      for (TABLE **table_ptr= lock->table ; 
+           table_ptr != end_ptr ;
+           ++table_ptr)
+      {
+        TABLE *const table= *table_ptr;
+        DBUG_PRINT("info", ("Checking table %s", table->s->table_name.str));
+        if (table->current_lock == F_WRLCK &&
+            check_table_binlog_row_based(thd, table))
+        {
+          /*
+            We need to have a transactional behavior for SQLCOM_CREATE_TABLE
+            (e.g. CREATE TABLE... SELECT * FROM TABLE) in order to keep a
+            compatible behavior with the STMT based replication even when
+            the table is not transactional. In other words, if the operation
+            fails while executing the insert phase nothing is written to the
+            binlog.
+
+            Note that at this point, we check the type of a set of tables to
+            create the table map events. In the function binlog_log_row(),
+            which calls the current function, we check the type of the table
+            of the current row.
+          */
+          bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
+                                table->file->has_transactions();
+          int const error= thd->binlog_write_table_map(table, has_trans,
+                                                       need_binlog_rows_query);
+          /* Binlog Rows_query log event once for one statement which updates
+             two or more tables.*/
+          if (need_binlog_rows_query)
+            need_binlog_rows_query= FALSE;
+          /*
+            If an error occurs, it is the responsibility of the caller to
+            roll back the transaction.
+          */
+          if (unlikely(error))
+            DBUG_RETURN(1);
+        }
+      }
+    }
+  }
+  DBUG_RETURN(0);
 }
-#endif /* INNODB_COMPATIBILITY_HOOKS */
 
+int Binlog::get_delayed_row_data(THD *thd, TABLE* table,
+                                 void **row_binlog_data, LEX_STRING* query, bool log_on)
+{
+  Delayed_row_binlog_data *row_data= new Delayed_row_binlog_data;
+  if (!row_data)
+    return 1;
+  row_data->binlog_rows_query_log_events= thd_binlog_rows_query_log_events(thd);
+  *row_binlog_data= row_data;
+  return 0;
+}
 
-struct st_mysql_storage_engine binlog_storage_engine=
-{ MYSQL_HANDLERTON_INTERFACE_VERSION };
+int Binlog::before_handle_delayed_row(THD* thd, TABLE* table,
+                                      void* row_binlog_data,
+                                      LEX_STRING* query,
+                                      bool log_query)
+{
+  if (log_query)
+  {
+    if (thd->is_current_stmt_binlog_format_row())
+    {
+      /* Flush rows of previous statement*/
+      if (thd->binlog_flush_pending_rows_event(TRUE, FALSE))
+        return 1;
+      /* Set query for Rows_query_log event in RBR*/
+      thd->set_query(query->str, query->length);
+      set_binlog_rows_query_log_events(thd,
+                                       ((Delayed_row_binlog_data*)row_binlog_data)->binlog_rows_query_log_events);
+    }
+  }
+  return 0;
+}
 
-mysql_declare_plugin(binlog)
+int Binlog::after_handle_delayed_row(THD* thd,
+                                     TABLE* table,
+                                     void* row_binlog_data,
+                                     LEX_STRING* query,
+                                     bool log_query)
 {
-  MYSQL_STORAGE_ENGINE_PLUGIN,
-  &binlog_storage_engine,
-  "binlog",
-  "MySQL AB",
-  "This is a pseudo storage engine to represent the binlog in a transaction",
-  PLUGIN_LICENSE_GPL,
-  binlog_init, /* Plugin Init */
-  NULL, /* Plugin Deinit */
-  0x0100 /* 1.0 */,
-  NULL,                       /* status variables                */
-  NULL,                       /* system variables                */
-  NULL                        /* config options                  */
+  delete (Delayed_row_binlog_data*)row_binlog_data;
+  return 0;
+}
+
+int Binlog::flush_binary_log(THD* thd)
+{
+  if (mysql_bin_log.is_open())
+    mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+  return 0;
 }
-mysql_declare_plugin_end;

=== renamed file 'sql/binlog.h' => 'sql/rpl/binlog.h'
--- a/sql/binlog.h	2010-11-16 09:38:43 +0000
+++ b/sql/rpl/binlog.h	2010-12-02 07:23:18 +0000
@@ -246,25 +246,117 @@ typedef struct st_load_file_info
 } LOAD_FILE_INFO;
 
 extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
-
-bool trans_has_updated_trans_table(const THD* thd);
-bool stmt_has_updated_trans_table(const THD *thd);
-bool use_trans_cache(const THD* thd, bool is_transactional);
-bool ending_trans(THD* thd, const bool all);
-bool ending_single_stmt_trans(THD* thd, const bool all);
-bool trans_has_updated_non_trans_table(const THD* thd);
-bool stmt_has_updated_non_trans_table(const THD* thd);
+extern const char *log_bin_index;
+extern const char *log_bin_basename;
 
 int log_loaded_block(IO_CACHE* file);
-File open_binlog(IO_CACHE *log, const char *log_file_name,
-                 const char **errmsg);
-int check_binlog_magic(IO_CACHE* log, const char** errmsg);
-bool purge_master_logs(THD* thd, const char* to_log);
-bool purge_master_logs_before_date(THD* thd, time_t purge_time);
-bool show_binlog_events(THD *thd, MYSQL_BIN_LOG *binary_log);
 void check_binlog_cache_size(THD *thd);
 
-extern const char *log_bin_index;
-extern const char *log_bin_basename;
+bool thd_binlog_rows_query_log_events(THD *thd);
+void set_binlog_rows_query_log_events(THD *thd, bool val);
+
+class Delayed_row_binlog_data {
+public:
+  bool binlog_rows_query_log_events;
+};
+
+typedef bool Log_func(THD*, TABLE*, bool,
+                      const uchar*, const uchar*);
+
+class Binlog {
+public:
+  enum enum_binlog_query_type {
+    /* The query can be logged in row format or in statement format. */
+    ROW_QUERY_TYPE,
+    
+    /* The query has to be logged in statement format. */
+    STMT_QUERY_TYPE,
+    
+    QUERY_TYPE_COUNT
+  };
+
+public:
+  int init_pthread_objects()
+  {
+    mysql_bin_log.init_pthread_objects();
+    return 0;
+  }
+  void cleanup()
+  {
+    mysql_bin_log.cleanup();
+  }
+  bool enabled()
+  {
+    return mysql_bin_log.is_open();
+  }
+  bool enabled(THD* thd)
+  {
+    return enabled() && (thd->variables.option_bits & OPTION_BIN_LOG);
+  }
+  int flush_binary_log(THD* thd);
+  int show_binary_logs(THD* thd);
+  int show_binlog_events(THD* thd);
+  int purge_binary_logs(THD* thd, const char* to_log);
+  int purge_binary_logs_before(THD* thd, time_t before_time);
+  int write_event(Log_event* event)
+  {
+    return mysql_bin_log.write(event);
+  }
+  int binlog_query(THD* thd,
+                   enum_binlog_query_type qtype, char const *query,
+                   ulong query_len, bool is_trans, bool direct, 
+                   bool suppress_use, int errcode);
+  int write_row(TABLE* table, const uchar* record)
+  {
+    Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
+    return log_row(table, 0, record, log_func);
+  }
+  int update_row(TABLE* table, const uchar* before_record,
+                 const uchar* after_record)
+  {
+    Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
+    return log_row(table, before_record, after_record, log_func);
+  }
+  int delete_row(TABLE* table, const uchar* record)
+  {
+    Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
+    return log_row(table, record, 0, log_func);
+  }
+  int get_delayed_row_data(THD* thd, TABLE* table,
+                           void** row_binlog_data,
+                           LEX_STRING* query, bool log_on);
+  int before_handle_delayed_row(THD* thd, TABLE* table,
+                                void* row_binlog_data,
+                                LEX_STRING* query, bool log_query);
+  int after_handle_delayed_row(THD* thd, TABLE* table,
+                               void* row_binlog_data,
+                               LEX_STRING* query, bool log_query);
+
+private:
+#if !defined(DBUG_OFF) && !defined(_lint)
+  const char* show_query_type(enum_binlog_query_type qtype)
+  {
+    switch (qtype) {
+    case ROW_QUERY_TYPE:
+      return "ROW";
+    case STMT_QUERY_TYPE:
+      return "STMT";
+    case QUERY_TYPE_COUNT:
+    default:
+      DBUG_ASSERT(0 <= qtype && qtype < QUERY_TYPE_COUNT);
+    }
+    static char buf[64];
+    sprintf(buf, "UNKNOWN#%d", qtype);
+    return buf;
+  }
+#endif
+  int write_locked_table_maps(THD* thd);
+  int log_row(TABLE* table,
+              const uchar* before_record,
+              const uchar* after_record,
+              Log_func* log_func);
+};
+
+extern MYSQL_PLUGIN_IMPORT Binlog binlog;
 
 #endif /* BINLOG_H_INCLUDED */

=== added file 'sql/rpl/binlog_priv.h'
--- a/sql/rpl/binlog_priv.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl/binlog_priv.h	2010-12-02 07:23:18 +0000
@@ -0,0 +1,35 @@
+#ifndef BINLOG_PRIV_H_INCLUDED
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#define BINLOG_PRIV_H_INCLUDED
+
+bool trans_has_updated_trans_table(const THD* thd);
+bool stmt_has_updated_trans_table(const THD *thd);
+bool use_trans_cache(const THD* thd, bool is_transactional);
+bool ending_trans(THD* thd, const bool all);
+bool ending_single_stmt_trans(THD* thd, const bool all);
+bool trans_has_updated_non_trans_table(const THD* thd);
+bool stmt_has_updated_non_trans_table(const THD* thd);
+
+File open_binlog(IO_CACHE *log, const char *log_file_name,
+                 const char **errmsg);
+bool show_binlog_events(THD* THD, MYSQL_BIN_LOG* binary_log);
+int check_binlog_magic(IO_CACHE* log, const char** errmsg);
+
+bool thd_binlog_rows_query_log_events(THD *thd);
+void set_binlog_rows_query_log_events(THD *thd, bool val);
+
+#endif /* BINLOG_PRIV_H_INCLUDED */

=== renamed file 'sql/log_event.cc' => 'sql/rpl/log_event.cc'
--- a/sql/log_event.cc	2010-11-18 16:34:56 +0000
+++ b/sql/rpl/log_event.cc	2010-12-02 07:23:18 +0000
@@ -55,6 +55,7 @@
 
 #define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
 
+ulong opt_binlog_rows_event_max_size;
 
 /*
   Size of buffer for printing a double in format %.<PREC>g

=== renamed file 'sql/log_event.h' => 'sql/rpl/log_event.h'
--- a/sql/log_event.h	2010-11-08 02:49:16 +0000
+++ b/sql/rpl/log_event.h	2010-12-02 07:23:18 +0000
@@ -49,6 +49,8 @@
 #include "sql_class.h"                          /* THD */
 #endif
 
+extern ulong opt_binlog_rows_event_max_size;
+
 /* Forward declarations */
 class String;
 

=== renamed file 'sql/log_event_old.cc' => 'sql/rpl/log_event_old.cc'
=== renamed file 'sql/log_event_old.h' => 'sql/rpl/log_event_old.h'
=== added file 'sql/rpl/rpl.h'
--- a/sql/rpl/rpl.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl/rpl.h	2010-12-02 07:23:18 +0000
@@ -0,0 +1,83 @@
+#ifndef RPL_H_INCLUDED
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#define RPL_H_INCLUDED
+
+#ifdef HAVE_REPLICATION
+
+#if 1
+class Rpl_master {
+public:
+  int init();
+  void end();
+  int register_slave(THD* thd, char* packet, uint packet_length);
+  int show_slave_hosts(THD* thd);
+  int binlog_dump(THD* thd, char* packet, uint packet_length);
+  int show_master_status(THD* thd);
+  int reset_master(THD* thd);
+};
+
+class Rpl_slave {
+public:
+  int init();
+  void end();
+  int change_master(THD* thd);
+  int start_slave(THD* thd);
+  int stop_slave(THD* thd);
+  int reset_slave(THD* thd);
+  int show_slave_status(THD* thd);
+  int flush_relay_log(THD* thd);
+  int show_relay_log_events(THD* thd);
+};
+
+extern Rpl_master rpl_master;
+extern Rpl_slave rpl_slave;
+
+#else
+C_MODE_START
+
+typedef struct Rpl_master {
+  uint32 len;
+  int (*init)();
+  void (*end)();
+  int (*register_slave)(MYSQL_THD, char* packet, uint packet_length);
+  int (*show_slave_hosts)(MYSQL_THD);
+  int (*binlog_dump)(MYSQL_THD, char* packet, uint packet_length);
+  int (*show_master_status)(MYSQL_THD);
+  int (*reset_master)(MYSQL_THD);
+} Rpl_master;
+
+typedef struct Rpl_slave {
+  uint32 len;
+  int (*init)();
+  void (*end)();
+  int (*change_master)(MYSQL_THD);
+  int (*start_slave)(MYSQL_THD);
+  int (*stop_slave)(MYSQL_THD);
+  int (*reset_slave)(MYSQL_THD);
+  int (*show_slave_status)(MYSQL_THD);
+  int (*flush_relay_log)(MYSQL_THD);
+  int (*show_relay_log_events)(MYSQL_THD);
+} Rpl_slave;
+
+extern Rpl_master rpl_master;
+extern Rpl_slave rpl_slave;
+
+C_MODE_END
+#endif
+
+#endif /*HAVE_REPLICATION */
+#endif /* RPL_H_INCLUDED */

=== renamed file 'sql/rpl_constants.h' => 'sql/rpl/rpl_constants.h'
=== renamed file 'sql/rpl_filter.cc' => 'sql/rpl/rpl_filter.cc'
--- a/sql/rpl_filter.cc	2010-10-26 09:10:59 +0000
+++ b/sql/rpl/rpl_filter.cc	2010-12-02 07:23:18 +0000
@@ -18,6 +18,7 @@
 #include "rpl_filter.h"
 #include "hash.h"                               // my_hash_free
 #include "table.h"                              // TABLE_LIST
+#include "log.h"                                // sql_print_error
 
 #define TABLE_RULE_HASH_SIZE   16
 #define TABLE_RULE_ARR_SIZE   16
@@ -687,3 +688,19 @@ Rpl_filter::get_ignore_db()
 {
   return &ignore_db;
 }
+
+int Rpl_filter::table_alias_charset_changed()
+{
+  /*
+    Build do_table and ignore_table rules to hush
+    after the resetting of table_alias_charset
+  */
+  if (rpl_filter->build_do_table_hash() ||
+      rpl_filter->build_ignore_table_hash())
+  {
+    sql_print_error("An error occurred while building do_table"
+                    "and ignore_table rules to hush.");
+    return 1;
+  }
+  return 0;
+}

=== renamed file 'sql/rpl_filter.h' => 'sql/rpl/rpl_filter.h'
--- a/sql/rpl_filter.h	2010-10-13 23:16:09 +0000
+++ b/sql/rpl/rpl_filter.h	2010-12-02 07:23:18 +0000
@@ -58,7 +58,11 @@ public:
   int build_do_table_hash();
   int build_ignore_table_hash();
 
+  int add_do_table(const char* table_spec)
+  { return add_do_table_array(table_spec); }
   int add_do_table_array(const char* table_spec);
+  int add_ignore_table(const char* table_spec)
+  { return add_ignore_table_array(table_spec); }
   int add_ignore_table_array(const char* table_spec);
 
   int add_wild_do_table(const char* table_spec);
@@ -82,6 +86,8 @@ public:
   I_List<i_string>* get_do_db();
   I_List<i_string>* get_ignore_db();
 
+  int table_alias_charset_changed();
+
 private:
   bool table_rules_on;
 

=== renamed file 'sql/rpl_handler.cc' => 'sql/rpl/rpl_handler.cc'
=== renamed file 'sql/rpl_handler.h' => 'sql/rpl/rpl_handler.h'
=== renamed file 'sql/rpl_info.cc' => 'sql/rpl/rpl_info.cc'
=== renamed file 'sql/rpl_info.h' => 'sql/rpl/rpl_info.h'
=== renamed file 'sql/rpl_info_factory.cc' => 'sql/rpl/rpl_info_factory.cc'
=== renamed file 'sql/rpl_info_factory.h' => 'sql/rpl/rpl_info_factory.h'
=== renamed file 'sql/rpl_info_file.cc' => 'sql/rpl/rpl_info_file.cc'
=== renamed file 'sql/rpl_info_file.h' => 'sql/rpl/rpl_info_file.h'
=== renamed file 'sql/rpl_info_handler.cc' => 'sql/rpl/rpl_info_handler.cc'
=== renamed file 'sql/rpl_info_handler.h' => 'sql/rpl/rpl_info_handler.h'
=== renamed file 'sql/rpl_injector.cc' => 'sql/rpl/rpl_injector.cc'
=== renamed file 'sql/rpl_injector.h' => 'sql/rpl/rpl_injector.h'
=== added file 'sql/rpl/rpl_lex.cc'
--- a/sql/rpl/rpl_lex.cc	1970-01-01 00:00:00 +0000
+++ b/sql/rpl/rpl_lex.cc	2010-12-02 07:23:18 +0000
@@ -0,0 +1,305 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#include "sql_priv.h"
+#include "unireg.h"                    // REQUIRED: for other includes
+#include "sql_class.h"
+#include "rpl_lex.h"
+#include "rpl_slave.h"
+
+class OptionBase;
+class OptionList
+{
+public:
+  OptionList()
+    :first(NULL), last(NULL)
+  {}
+  void append(OptionBase* option);
+  OptionBase* get_option(const char* name);
+private:
+  OptionBase* first;
+  OptionBase* last;
+};
+
+static OptionList all_options;
+
+class OptionBase {
+public:
+  OptionBase(const char* name_arg, bool is_list_arg)
+    :next(NULL), name(name_arg), is_list(is_list_arg)
+  {
+    all_options.append(this);
+  }
+
+  bool is_list_value() const
+  {
+    return is_list;
+  }
+  const char* get_name() const { return name; }
+  virtual int set_value(THD* thd, Item* item)=0;
+  virtual int begin(THD* thd) { return 0; }
+  virtual int end(THD* thd) { return 0; }
+  virtual ~OptionBase();
+
+  OptionBase* next;
+private:
+  const char* name;
+  /* If the option accepts a list of values */
+  bool is_list;
+};
+
+OptionBase::~OptionBase() {}
+
+void OptionList::append(OptionBase* option)
+{
+  DBUG_ASSERT(option->next == NULL);
+  if (last)
+    last->next= option;
+  else
+    first= option;
+  last= option;
+}
+
+OptionBase* OptionList::get_option(const char* name)
+{
+  OptionBase *option= first;
+  while (option)
+  {
+    if (!strcasecmp(option->get_name(), name))
+      return option;
+    option= option->next;
+  }
+  return NULL;
+}
+
+template<class T> class Option :public OptionBase {
+public:
+  typedef int (*func_type)(THD*, T);
+  Option(const char* name_arg, func_type func_arg, bool is_list=false)
+    :OptionBase(name_arg, is_list), func(func_arg)
+  {}
+
+  int check_item(Item* item) { return 0; }
+
+  T get_item_value(Item* item);
+
+  int set_value(THD* thd, Item* item)
+  {
+    if (check_item(item))
+    {
+      my_error(ER_SYNTAX_ERROR, MYF(0));
+      return -1;
+    }
+    T value= this->get_item_value(item);
+    return func(thd, value);
+  }
+
+  virtual ~Option() {}
+private:
+  func_type func;
+};
+
+template<> inline int Option<char*>::check_item(Item* item)
+{
+  if (item->type() == Item::STRING_ITEM)
+    return 0;
+  return 1;
+}
+template<> inline int Option<ulong>::check_item(Item* item)
+{
+  if (item->type() == Item::INT_ITEM ||
+      item->type() == Item::DECIMAL_ITEM ||
+      item->type() == Item::REAL_ITEM ||
+      item->type() == Item::VARBIN_ITEM)
+  {
+    if (!item->unsigned_flag && item->val_int() < 0)
+      return 1;
+    return 0;
+  }
+  return 1;
+}
+template<> inline int Option<float>::check_item(Item* item)
+{
+  if (item->type() == Item::REAL_ITEM ||
+      item->type() == Item::INT_ITEM ||
+      item->type() == Item::DECIMAL_ITEM)
+    return 0;
+  return 1;
+}
+template<>  inline char* Option<char*>::get_item_value(Item* item)
+{
+  return item->val_str((String*)0)->c_ptr_safe();
+}
+template<>  inline ulong Option<ulong>::get_item_value(Item* item)
+{
+  return (ulong)item->val_uint();
+}
+template<>  inline float Option<float>::get_item_value(Item* item)
+{
+  return (float)item->val_real();
+}
+
+/* Explicitly instanciate templates */
+template class Option<char*>;
+template class Option<ulong>;
+template class Option<float>;
+
+#define MASTER_OPTION(n, t)                                             \
+  inline int set_master_ ## n(THD* thd, t value)                        \
+  {                                                                     \
+    return thd->lex->mi.set_ ## n(thd, value);                          \
+  }                                                                     \
+  static Option<t> option_master_ ## n("master_" # n, set_master_ ## n)
+
+MASTER_OPTION(host, char*);
+MASTER_OPTION(user, char*);
+MASTER_OPTION(password, char*);
+MASTER_OPTION(port, ulong);
+MASTER_OPTION(connect_retry, ulong);
+MASTER_OPTION(retry_count, ulong);
+MASTER_OPTION(delay, ulong);
+MASTER_OPTION(ssl, ulong);
+MASTER_OPTION(ssl_ca, char*);
+MASTER_OPTION(ssl_capath, char*);
+MASTER_OPTION(ssl_cert, char*);
+MASTER_OPTION(ssl_cipher, char*);
+MASTER_OPTION(ssl_key, char*);
+MASTER_OPTION(ssl_verify_server_cert, ulong);
+MASTER_OPTION(heartbeat_period, float);
+MASTER_OPTION(log_file, char*);
+MASTER_OPTION(log_pos, ulong);
+MASTER_OPTION(relay_log_file, char*);
+MASTER_OPTION(relay_log_pos, ulong);
+
+inline int add_ignore_server_id(THD* thd, ulong value)
+{
+  return thd->lex->mi.add_ignore_server_id(thd, value);
+}
+
+class Ignore_server_ids_option :public Option<ulong> {
+public:
+  Ignore_server_ids_option()
+    :Option<ulong>("ignore_server_ids", add_ignore_server_id, true)
+  {}
+
+  int begin(THD* thd)
+  {
+    thd->lex->mi.repl_ignore_server_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
+    return 0;
+  }
+} option_igore_server_ids;
+
+// static Option<ulong> option_ignore_server_ids("ignore_server_ids",
+//                                               add_ignore_server_id,
+//                                               true /* is_list */);
+
+int st_lex_master_info::start_option(THD* thd, char* name)
+{
+  DBUG_ASSERT(!current_option);
+  current_option= all_options.get_option(name);
+  if (current_option)
+    return current_option->begin(thd);
+  my_error(ER_SYNTAX_ERROR, MYF(0));
+  return 1;
+}
+
+int st_lex_master_info::set_option_value(THD* thd, Item* item)
+{
+  DBUG_ASSERT(current_option);
+  if (current_option->is_list_value())
+  {
+    my_error(ER_SYNTAX_ERROR, MYF(0));
+    return 1;
+  }
+  return current_option->set_value(thd, item);
+}
+
+int st_lex_master_info::add_option_value(THD* thd, Item* item)
+{
+  DBUG_ASSERT(current_option);
+  if (!current_option->is_list_value())
+  {
+    my_error(ER_SYNTAX_ERROR, MYF(0));
+    return 1;
+  }
+  return current_option->set_value(thd, item);
+}
+
+int st_lex_master_info::end_option(THD* thd, char* name)
+{
+  DBUG_ASSERT(!strcasecmp(current_option->get_name(), name));
+  int res= current_option->end(thd);
+  current_option= NULL;
+  return res;
+}
+
+int st_lex_master_info::set_heartbeat_period(THD* thd, float value)
+{
+  heartbeat_period= value;
+  if (heartbeat_period > SLAVE_MAX_HEARTBEAT_PERIOD ||
+      heartbeat_period < 0.0)
+  {
+    const char format[]= "%d";
+    char buf[4*sizeof(SLAVE_MAX_HEARTBEAT_PERIOD) + sizeof(format)];
+    sprintf(buf, format, SLAVE_MAX_HEARTBEAT_PERIOD);
+    my_error(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, MYF(0), buf);
+    return 1;
+  }
+  if (heartbeat_period > slave_net_timeout)
+  {
+    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                        ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX,
+                        ER(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX));
+  }
+  if (heartbeat_period < 0.001)
+  {
+    if (heartbeat_period != 0.0)
+    {
+      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                          ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN,
+                          ER(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN));
+      heartbeat_period= 0.0;
+    }
+    heartbeat_opt=  LEX_MI_DISABLE;
+  }
+  heartbeat_opt=  LEX_MI_ENABLE;
+  return 0;
+}
+
+int st_lex_master_info::set_delay(THD* thd, ulong value)
+{
+  if (value > MASTER_DELAY_MAX)
+  {
+    my_error(ER_MASTER_DELAY_VALUE_OUT_OF_RANGE, MYF(0),
+             value, MASTER_DELAY_MAX);
+    return 1;
+  }
+  sql_delay= value;
+  return 0;
+}
+
+int st_lex_master_info::check_slave_until_opts(THD* thd)
+{
+  if (((log_file_name || pos) &&
+       (relay_log_name || relay_log_pos)) ||
+      !((log_file_name && pos) ||
+        (relay_log_name && relay_log_pos)))
+  {
+    my_message(ER_BAD_SLAVE_UNTIL_COND,
+               ER(ER_BAD_SLAVE_UNTIL_COND), MYF(0));
+    return 1;
+  }
+  return 0;
+}

=== added file 'sql/rpl/rpl_lex.h'
--- a/sql/rpl/rpl_lex.h	1970-01-01 00:00:00 +0000
+++ b/sql/rpl/rpl_lex.h	2010-12-02 07:23:18 +0000
@@ -0,0 +1,152 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#ifndef RPL_LEX_H
+#define RPL_LEX_H
+
+class OptionBase;
+
+/**
+  Structure to hold parameters for CHANGE MASTER or START/STOP SLAVE
+  or SHOW NEW MASTER.
+
+  Remark: this should not be confused with Master_info (and perhaps
+  would better be renamed to st_lex_replication_info).  Some fields,
+  e.g., delay, are saved in Relay_log_info, not in Master_info.
+*/
+typedef struct st_lex_master_info
+{
+  char *host, *user, *password, *log_file_name;
+  uint port, connect_retry;
+  float heartbeat_period;
+  int sql_delay;
+  ulonglong pos;
+  ulong server_id, retry_count;
+  /*
+    Enum is used for making it possible to detect if the user
+    changed variable or if it should be left at old value
+   */
+  enum {LEX_MI_UNCHANGED= 0, LEX_MI_DISABLE, LEX_MI_ENABLE}
+    ssl, ssl_verify_server_cert, heartbeat_opt, repl_ignore_server_ids_opt, 
+    retry_count_opt;
+  char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher;
+  char *relay_log_name;
+  ulong relay_log_pos;
+  DYNAMIC_ARRAY repl_ignore_server_ids;
+
+  /**
+     Set all fields to their "unspecified" value.
+  */
+  void init(enum_sql_command command)
+  {
+    /*
+      Clear LEX_MASTER_INFO struct and allocate memory for
+      repl_ignore_server_ids. repl_ignore_server_ids is freed
+      at the end of change_master. So it is guaranteed to be
+      uninitialized before here.
+    */
+    bzero((char*) this, sizeof(*this));
+    sql_delay= -1;
+    if (command ==SQLCOM_CHANGE_MASTER)
+      my_init_dynamic_array(&repl_ignore_server_ids,
+                            sizeof(::server_id), 16, 16);
+  }
+
+  /*
+    This is called when start parsing an option
+  */
+  int start_option(THD* thd, char* name);
+  /*
+    This is called to set the value for an option.
+  */
+  int set_option_value(THD* thd, Item* value);
+  /*
+    This is for options that accept a list of values
+    (e.g. IGNORE_SERVER_IDS), this will be called for each value in
+    the list.
+   */
+  int add_option_value(THD* thd, Item* value);
+  /*
+    This is called after parsed value(s) of the option
+  */
+  int end_option(THD* thd, char* name);
+
+  int set_host(THD* thd, char* value) { host= value; return 0; }
+  int set_user(THD* thd, char* value) { user= value; return 0; }
+  int set_password(THD* thd, char* value) { password= value; return 0; }
+  int set_port(THD* thd, ulong value) { port= value; return 0; }
+  int set_connect_retry(THD* thd, ulong value) { connect_retry= value; return 0; }
+  int set_retry_count(THD* thd, ulong value)
+  {
+    retry_count= value;
+    retry_count_opt= LEX_MI_ENABLE;
+    return 0;
+  }
+  int set_delay(THD* thd, ulong value);
+  int set_ssl(THD* thd, ulong value) { ssl= value ? LEX_MI_ENABLE : LEX_MI_DISABLE; return 0; }
+  int set_ssl_ca(THD* thd, char* value) { ssl_ca= value; return 0; }
+  int set_ssl_capath(THD* thd, char* value) { ssl_capath= value; return 0; }
+  int set_ssl_cert(THD* thd, char* value) { ssl_cert= value; return 0; }
+  int set_ssl_cipher(THD* thd, char* value) { ssl_cipher= value; return 0;}
+  int set_ssl_key(THD* thd, char* value) { ssl_key= value; return 0; }
+  int set_ssl_verify_server_cert(THD* thd, ulong value)
+  {
+    ssl_verify_server_cert= value ? LEX_MI_ENABLE : LEX_MI_DISABLE;
+    return 0;
+  }
+  int set_heartbeat_period(THD* thd, float value);
+  int add_ignore_server_id(THD* thd, ulong value)
+  {
+    insert_dynamic(&repl_ignore_server_ids, (uchar*)&value);
+    return 0;
+  }
+  int set_log_file(THD* thd, char* value)
+  {
+    log_file_name= value;
+    return 0;
+  }
+  int set_log_pos(THD* thd, ulonglong value) 
+  {
+    /* 
+       If the user specified a value < BIN_LOG_HEADER_SIZE, adjust it
+       instead of causing subsequent errors. 
+       We need to do it in this file, because only there we know that 
+       MASTER_LOG_POS has been explicitely specified. On the contrary
+       in change_master() (sql_repl.cc) we cannot distinguish between 0
+       (MASTER_LOG_POS explicitely specified as 0) and 0 (unspecified),
+       whereas we want to distinguish (specified 0 means "read the binlog
+       from 0" (4 in fact), unspecified means "don't change the position
+       (keep the preceding value)").
+    */
+    pos = max(BIN_LOG_HEADER_SIZE, value);
+    return 0;
+  }
+  int set_relay_log_file(THD* thd, char* value)
+  {
+    relay_log_name= value;
+    return 0;
+  }
+  int set_relay_log_pos(THD* thd, ulonglong value)
+  {
+    /* Adjust if < BIN_LOG_HEADER_SIZE */
+    relay_log_pos = max(BIN_LOG_HEADER_SIZE, value);
+    return 0;
+  }
+  int check_slave_until_opts(THD* thd);
+private:
+  OptionBase* current_option;
+} LEX_MASTER_INFO;
+
+#endif /* RPL_LEX_H */

=== renamed file 'sql/rpl_master.cc' => 'sql/rpl/rpl_master.cc'
--- a/sql/rpl_master.cc	2010-09-28 15:17:29 +0000
+++ b/sql/rpl/rpl_master.cc	2010-12-02 07:23:18 +0000
@@ -16,16 +16,40 @@
 
 #include "sql_priv.h"
 #include "unireg.h"
-#include "sql_parse.h"                          // check_access
 #ifdef HAVE_REPLICATION
 
-#include "sql_acl.h"                            // SUPER_ACL
 #include "log_event.h"
+#include "binlog_priv.h"
 #include "rpl_filter.h"
 #include <my_dir.h>
 #include "rpl_handler.h"
 #include "rpl_master.h"
 
+typedef struct st_slave_info
+{
+  uint32 server_id;
+  uint32 rpl_recovery_rank, master_id;
+  char host[HOSTNAME_LENGTH+1];
+  char user[USERNAME_LENGTH+1];
+  char password[MAX_PASSWORD_LENGTH+1];
+  uint16 port;
+  THD* thd;
+} SLAVE_INFO;
+
+static void init_slave_list();
+static void end_slave_list();
+static void unregister_slave(THD* thd, bool only_mine, bool need_mutex);
+
+#if HAVE_SERVER_UUID
+static String *get_slave_uuid(THD *thd, String *value);
+static void kill_zombie_dump_threads(String *slave_uuid);
+#else
+static void kill_zombie_dump_threads(uint32 slave_server_id);
+#endif
+
+static void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags);
+
+
 int max_binlog_dump_events = 0; // unlimited
 my_bool opt_sporadic_binlog_dump_fail = 0;
 
@@ -83,7 +107,7 @@ static void init_all_slave_list_mutexes(
 }
 #endif /* HAVE_PSI_INTERFACE */
 
-void init_slave_list()
+static void init_slave_list()
 {
 #ifdef HAVE_PSI_INTERFACE
   init_all_slave_list_mutexes();
@@ -95,7 +119,7 @@ void init_slave_list()
   mysql_mutex_init(key_LOCK_slave_list, &LOCK_slave_list, MY_MUTEX_INIT_FAST);
 }
 
-void end_slave_list()
+static void end_slave_list()
 {
   /* No protection by a mutex needed as we are only called at shutdown */
   if (my_hash_inited(&slave_list))
@@ -114,15 +138,13 @@ void end_slave_list()
     1	Error.   Error message sent to client
 */
 
-int register_slave(THD* thd, uchar* packet, uint packet_length)
+int Rpl_master::register_slave(THD* thd, char* packet, uint packet_length)
 {
   int res;
   SLAVE_INFO *si;
-  uchar *p= packet, *p_end= packet + packet_length;
+  char *p= packet, *p_end= packet + packet_length;
   const char *errmsg= "Wrong parameters to function register_slave";
 
-  if (check_access(thd, REPL_SLAVE_ACL, any_db, NULL, NULL, 0, 0))
-    return 1;
   if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME))))
     goto err2;
 
@@ -159,7 +181,7 @@ err2:
   return 1;
 }
 
-void unregister_slave(THD* thd, bool only_mine, bool need_mutex)
+static void unregister_slave(THD* thd, bool only_mine, bool need_mutex)
 {
   if (thd->server_id)
   {
@@ -187,7 +209,7 @@ void unregister_slave(THD* thd, bool onl
   @retval FALSE success
   @retval TRUE failure
 */
-bool show_slave_hosts(THD* thd)
+int Rpl_master::show_slave_hosts(THD* thd)
 {
   List<Item> field_list;
   Protocol *protocol= thd->protocol;
@@ -204,8 +226,9 @@ bool show_slave_hosts(THD* thd)
   field_list.push_back(new Item_return_int("Port", 7, MYSQL_TYPE_LONG));
   field_list.push_back(new Item_return_int("Master_id", 10,
 					   MYSQL_TYPE_LONG));
+#if HAVE_SERVER_UUID
   field_list.push_back(new Item_empty_string("Slave_UUID", UUID_LENGTH));
-
+#endif
   if (protocol->send_result_set_metadata(&field_list,
                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
     DBUG_RETURN(TRUE);
@@ -226,10 +249,12 @@ bool show_slave_hosts(THD* thd)
     protocol->store((uint32) si->port);
     protocol->store((uint32) si->master_id);
 
+#if HAVE_SERVER_UUID
     /* get slave's UUID */
     String slave_uuid;
     if (get_slave_uuid(si->thd, &slave_uuid))
       protocol->store(slave_uuid.c_ptr_safe(), &my_charset_bin);
+#endif
     if (protocol->write())
     {
       mysql_mutex_unlock(&LOCK_slave_list);
@@ -491,11 +516,12 @@ static int send_heartbeat_event(NET* net
   DBUG_RETURN(0);
 }
 
+
 /*
   TODO: Clean up loop to only have one call to send_file()
 */
 
-void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
+static void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
 		       ushort flags)
 {
   LOG_INFO linfo;
@@ -1118,7 +1144,7 @@ String *get_slave_uuid(THD *thd, String 
 
 */
 
-
+#if HAVE_SERVER_UUID
 void kill_zombie_dump_threads(String *slave_uuid)
 {
   if (slave_uuid->length() == 0)
@@ -1155,6 +1181,36 @@ void kill_zombie_dump_threads(String *sl
   }
 }
 
+#else /* HAVE_SERVER_UUID */
+
+void kill_zombie_dump_threads(uint32 slave_server_id)
+{
+  mysql_mutex_lock(&LOCK_thread_count);
+  I_List_iterator<THD> it(threads);
+  THD *tmp;
+
+  while ((tmp=it++))
+  {
+    if (tmp->command == COM_BINLOG_DUMP &&
+       tmp->server_id == slave_server_id)
+    {
+      mysql_mutex_lock(&tmp->LOCK_thd_data);    // Lock from delete
+      break;
+    }
+  }
+  mysql_mutex_unlock(&LOCK_thread_count);
+  if (tmp)
+  {
+    /*
+      Here we do not call kill_one_thread() as
+      it will be slow because it will iterate through the list
+      again. We just to do kill the thread ourselves.
+    */
+    tmp->awake(THD::KILL_QUERY);
+    mysql_mutex_unlock(&tmp->LOCK_thd_data);
+  }
+}
+#endif /* HAVE_SERVER_UUID */
 
 /**
   Execute a RESET MASTER statement.
@@ -1165,7 +1221,7 @@ void kill_zombie_dump_threads(String *sl
   @retval 0 success
   @retval 1 error
 */
-int reset_master(THD* thd)
+int Rpl_master::reset_master(THD* thd)
 {
   if (!mysql_bin_log.is_open())
   {
@@ -1180,23 +1236,6 @@ int reset_master(THD* thd)
   return 0;
 }
 
-int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
-		   const char* log_file_name2, ulonglong log_pos2)
-{
-  int res;
-  size_t log_file_name1_len=  strlen(log_file_name1);
-  size_t log_file_name2_len=  strlen(log_file_name2);
-
-  //  We assume that both log names match up to '.'
-  if (log_file_name1_len == log_file_name2_len)
-  {
-    if ((res= strcmp(log_file_name1, log_file_name2)))
-      return res;
-    return (log_pos1 < log_pos2) ? -1 : (log_pos1 == log_pos2) ? 0 : 1;
-  }
-  return ((log_file_name1_len < log_file_name2_len) ? -1 : 1);
-}
-
 
 /**
   Execute a SHOW MASTER STATUS statement.
@@ -1239,88 +1278,55 @@ bool show_binlog_info(THD* thd)
   DBUG_RETURN(FALSE);
 }
 
-
-/**
-  Execute a SHOW BINARY LOGS statement.
-
-  @param thd Pointer to THD object for the client thread executing the
-  statement.
-
-  @retval FALSE success
-  @retval TRUE failure
-*/
-bool show_binlogs(THD* thd)
+int Rpl_master::init()
 {
-  IO_CACHE *index_file;
-  LOG_INFO cur;
-  File file;
-  char fname[FN_REFLEN];
-  List<Item> field_list;
-  uint length;
-  int cur_dir_len;
-  Protocol *protocol= thd->protocol;
-  DBUG_ENTER("show_binlogs");
+  init_slave_list();
+  return 0;
+}
 
-  if (!mysql_bin_log.is_open())
-  {
-    my_message(ER_NO_BINARY_LOGGING, ER(ER_NO_BINARY_LOGGING), MYF(0));
-    DBUG_RETURN(TRUE);
-  }
+void Rpl_master::end()
+{
+  end_slave_list();
+}
 
-  field_list.push_back(new Item_empty_string("Log_name", 255));
-  field_list.push_back(new Item_return_int("File_size", 20,
-                                           MYSQL_TYPE_LONGLONG));
-  if (protocol->send_result_set_metadata(&field_list,
-                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
-    DBUG_RETURN(TRUE);
-  
-  mysql_mutex_lock(mysql_bin_log.get_log_lock());
-  mysql_bin_log.lock_index();
-  index_file=mysql_bin_log.get_index_file();
-  
-  mysql_bin_log.raw_get_current_log(&cur); // dont take mutex
-  mysql_mutex_unlock(mysql_bin_log.get_log_lock()); // lockdep, OK
-  
-  cur_dir_len= dirname_length(cur.log_file_name);
-
-  reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 0);
-
-  /* The file ends with EOF or empty line */
-  while ((length=my_b_gets(index_file, fname, sizeof(fname))) > 1)
-  {
-    int dir_len;
-    ulonglong file_length= 0;                   // Length if open fails
-    fname[--length] = '\0';                     // remove the newline
+int Rpl_master::binlog_dump(THD* thd, char* packet, uint packet_length)
+{
+  ulong pos;
+  ushort flags;
+#if HAVE_SERVER_UUID
+  String slave_uuid;
+#else
+  uint32 slave_server_id;
+#endif
 
-    protocol->prepare_for_resend();
-    dir_len= dirname_length(fname);
-    length-= dir_len;
-    protocol->store(fname + dir_len, length, &my_charset_bin);
+  /* TODO: The following has to be changed to an 8 byte integer */
+  pos = uint4korr(packet);
+  flags = uint2korr(packet + 4);
+
+#if HAVE_SERVER_UUID
+  thd->server_id= uint4korr(packet+6);
+  get_slave_uuid(thd, &slave_uuid);
+  kill_zombie_dump_threads(&slave_uuid);
+#else
+  thd->server_id=0; /* avoid suicide */
+  if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0
+    kill_zombie_dump_threads(slave_server_id);
+  thd->server_id = slave_server_id;
+#endif
 
-    if (!(strncmp(fname+dir_len, cur.log_file_name+cur_dir_len, length)))
-      file_length= cur.pos;  /* The active log, use the active position */
-    else
-    {
-      /* this is an old log, open it and find the size */
-      if ((file= mysql_file_open(key_file_binlog,
-                                 fname, O_RDONLY | O_SHARE | O_BINARY,
-                                 MYF(0))) >= 0)
-      {
-        file_length= (ulonglong) mysql_file_seek(file, 0L, MY_SEEK_END, MYF(0));
-        mysql_file_close(file, MYF(0));
-      }
-    }
-    protocol->store(file_length);
-    if (protocol->write())
-      goto err;
-  }
-  mysql_bin_log.unlock_index();
-  my_eof(thd);
-  DBUG_RETURN(FALSE);
+  general_log_print(thd, COM_BINLOG_DUMP, "Log: '%s'  Pos: %ld", packet+10,
+                    (long) pos);
+  mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags);
+  unregister_slave(thd,1,1);
+  /*  fake COM_QUIT -- if we get here, the thread needs to terminate */
+  return 1;
+}
 
-err:
-  mysql_bin_log.unlock_index();
-  DBUG_RETURN(TRUE);
+int Rpl_master::show_master_status(THD* thd)
+{
+  return show_binlog_info(thd);
 }
 
+Rpl_master rpl_master;
+
 #endif /* HAVE_REPLICATION */

=== renamed file 'sql/rpl_master.h' => 'sql/rpl/rpl_master.h'
--- a/sql/rpl_master.h	2010-07-19 16:09:51 +0000
+++ b/sql/rpl/rpl_master.h	2010-12-02 07:23:18 +0000
@@ -16,32 +16,12 @@
 
 
 #define RPL_MASTER_H_INCLUDED
+
+#include "rpl.h"
+
 extern bool server_id_supplied;
 extern int max_binlog_dump_events;
 extern my_bool opt_sporadic_binlog_dump_fail;
 extern my_bool opt_show_slave_auth_info;
 
-typedef struct st_slave_info
-{
-  uint32 server_id;
-  uint32 rpl_recovery_rank, master_id;
-  char host[HOSTNAME_LENGTH+1];
-  char user[USERNAME_LENGTH+1];
-  char password[MAX_PASSWORD_LENGTH+1];
-  uint16 port;
-  THD* thd;
-} SLAVE_INFO;
-
-void init_slave_list();
-void end_slave_list();
-int register_slave(THD* thd, uchar* packet, uint packet_length);
-void unregister_slave(THD* thd, bool only_mine, bool need_mutex);
-bool show_slave_hosts(THD* thd);
-
-String *get_slave_uuid(THD *thd, String *value);
-bool mysql_show_binlog_events(THD* thd);
-bool show_binlogs(THD* thd);
-void kill_zombie_dump_threads(String *slave_uuid);
-void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags);
-int reset_master(THD* thd);
 #endif /* RPL_MASTER_H_INCLUDED */

=== renamed file 'sql/rpl_mi.cc' => 'sql/rpl/rpl_mi.cc'
=== renamed file 'sql/rpl_mi.h' => 'sql/rpl/rpl_mi.h'
=== renamed file 'sql/rpl_record.cc' => 'sql/rpl/rpl_record.cc'
=== renamed file 'sql/rpl_record.h' => 'sql/rpl/rpl_record.h'
=== renamed file 'sql/rpl_record_old.cc' => 'sql/rpl/rpl_record_old.cc'
=== renamed file 'sql/rpl_record_old.h' => 'sql/rpl/rpl_record_old.h'
=== renamed file 'sql/rpl_reporting.cc' => 'sql/rpl/rpl_reporting.cc'
=== renamed file 'sql/rpl_reporting.h' => 'sql/rpl/rpl_reporting.h'
=== renamed file 'sql/rpl_rli.cc' => 'sql/rpl/rpl_rli.cc'
=== renamed file 'sql/rpl_rli.h' => 'sql/rpl/rpl_rli.h'
--- a/sql/rpl_rli.h	2010-10-21 12:18:25 +0000
+++ b/sql/rpl/rpl_rli.h	2010-12-02 07:23:18 +0000
@@ -24,6 +24,7 @@
 #include "rpl_utility.h"
 #include "log.h"                         /* LOG_INFO */
 #include "binlog.h"                      /* MYSQL_BIN_LOG */
+#include "binlog_priv.h"
 #include "sql_class.h"                   /* THD */
 
 struct RPL_TABLE_LIST;

=== renamed file 'sql/rpl_slave.cc' => 'sql/rpl/rpl_slave.cc'
--- a/sql/rpl_slave.cc	2010-11-18 16:34:56 +0000
+++ b/sql/rpl/rpl_slave.cc	2010-12-02 07:23:18 +0000
@@ -158,7 +158,9 @@ static int connect_to_master(THD* thd, M
 static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
                       void* thread_killed_arg);
 static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi);
+#if HAVE_SERVER_UUID
 static int get_master_uuid(MYSQL *mysql, Master_info *mi);
+#endif
 int io_thread_init_commands(MYSQL *mysql, Master_info *mi);
 static Log_event* next_event(Relay_log_info* rli);
 static int queue_event(Master_info* mi,const char* buf,ulong event_len);
@@ -1153,6 +1155,7 @@ bool is_network_error(uint errorno)
   return FALSE;   
 }
 
+#if HAVE_SERVER_UUID
 /**
   Set user variables after connecting to the master.
 
@@ -1278,6 +1281,7 @@ static int get_master_uuid(MYSQL *mysql,
     mysql_free_result(master_res);
   return ret;
 }
+#endif /* HAVE_SERVER_UUID */
 
 /*
   Note that we rely on the master's version (3.23, 4.0.14 etc) instead of
@@ -1904,7 +1908,9 @@ bool show_master_info(THD* thd, Master_i
                                              FN_REFLEN));
   field_list.push_back(new Item_return_int("Master_Server_Id", sizeof(ulong),
                                            MYSQL_TYPE_LONG));
+#if HAVE_SERVER_UUID
   field_list.push_back(new Item_empty_string("Master_UUID", UUID_LENGTH));
+#endif
   field_list.push_back(new Item_empty_string("Master_Info_File",
                                              2 * FN_REFLEN));
   field_list.push_back(new Item_return_int("SQL_Delay", 10, MYSQL_TYPE_LONG));
@@ -2080,7 +2086,9 @@ bool show_master_info(THD* thd, Master_i
     }
     // Master_Server_id
     protocol->store((uint32) mi->master_id);
+#if HAVE_SERVER_UUID
     protocol->store(mi->master_uuid, &my_charset_bin);
+#endif
     // Master_Info_File
     protocol->store(mi->get_description_info(), &my_charset_bin);
     // SQL_Delay
@@ -2783,7 +2791,7 @@ static int exec_relay_log_event(THD* thd
     */
     if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
     {
-      if (thd->variables.binlog_rows_query_log_events)
+      if (thd_binlog_rows_query_log_events(thd))
         handle_rows_query_log_event(ev, rli);
 
       DBUG_PRINT("info", ("Deleting the event after it has been executed"));
@@ -3099,10 +3107,12 @@ connected:
   thd->slave_net = &mysql->net;
   thd_proc_info(thd, "Checking master version");
   ret= get_master_version_and_clock(mysql, mi);
+#if HAVE_SERVER_UUID
   if (!ret)
     ret= get_master_uuid(mysql, mi);
   if (!ret)
     io_thread_init_commands(mysql, mi);
+#endif
 
   if (ret == 1)
     /* Fatal error */
@@ -4544,71 +4554,6 @@ static int safe_reconnect(THD* thd, MYSQ
 }
 
 
-MYSQL *rpl_connect_master(MYSQL *mysql)
-{
-  THD *thd= current_thd;
-  Master_info *mi= my_pthread_getspecific_ptr(Master_info*, RPL_MASTER_INFO);
-  if (!mi)
-  {
-    sql_print_error("'rpl_connect_master' must be called in slave I/O thread context.");
-    return NULL;
-  }
-
-  bool allocated= false;
-  
-  if (!mysql)
-  {
-    if(!(mysql= mysql_init(NULL)))
-    {
-      sql_print_error("rpl_connect_master: failed in mysql_init()");
-      return NULL;
-    }
-    allocated= true;
-  }
-
-  /*
-    XXX: copied from connect_to_master, this function should not
-    change the slave status, so we cannot use connect_to_master
-    directly
-    
-    TODO: make this part a seperate function to eliminate duplication
-  */
-  mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout);
-  mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout);
-
-#ifdef HAVE_OPENSSL
-  if (mi->ssl)
-  {
-    mysql_ssl_set(mysql,
-                  mi->ssl_key[0]?mi->ssl_key:0,
-                  mi->ssl_cert[0]?mi->ssl_cert:0,
-                  mi->ssl_ca[0]?mi->ssl_ca:0,
-                  mi->ssl_capath[0]?mi->ssl_capath:0,
-                  mi->ssl_cipher[0]?mi->ssl_cipher:0);
-    mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
-                  &mi->ssl_verify_server_cert);
-  }
-#endif
-
-  mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->csname);
-  /* This one is not strictly needed but we have it here for completeness */
-  mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir);
-
-  if (io_slave_killed(thd, mi)
-      || !mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0,
-                             mi->port, 0, 0))
-  {
-    if (!io_slave_killed(thd, mi))
-      sql_print_error("rpl_connect_master: error connecting to master: %s (server_error: %d)",
-                      mysql_error(mysql), mysql_errno(mysql));
-    
-    if (allocated)
-      mysql_close(mysql);                       // this will free the object
-    return NULL;
-  }
-  return mysql;
-}
-
 /*
   Called when we notice that the current "hot" log got rotated under our feet.
 */
@@ -5253,8 +5198,6 @@ int start_slave(THD* thd , Master_info* 
   int thread_mask;
   DBUG_ENTER("start_slave");
 
-  if (check_access(thd, SUPER_ACL, any_db, NULL, NULL, 0, 0))
-    DBUG_RETURN(1);
   lock_slave_threads(mi);  // this allows us to cleanly read slave_running
   // Get a mask of _stopped_ threads
   init_thread_mask(&thread_mask,mi,1 /* inverse */);
@@ -5391,8 +5334,6 @@ int stop_slave(THD* thd, Master_info* mi
   if (!thd)
     thd = current_thd;
 
-  if (check_access(thd, SUPER_ACL, any_db, NULL, NULL, 0, 0))
-    DBUG_RETURN(1);
   thd_proc_info(thd, "Killing slave");
   int thread_mask;
   lock_slave_threads(mi);
@@ -5570,7 +5511,9 @@ bool change_master(THD* thd, Master_info
   if ((lex_mi->host && strcmp(lex_mi->host, mi->host)) ||
       (lex_mi->port && lex_mi->port != mi->port))
   {
+#if HAVE_SERVER_UUID
     mi->master_uuid[0]= 0;
+#endif
     mi->master_id= 0;
   }
 
@@ -5799,6 +5742,137 @@ err:
   DBUG_RETURN(ret);
 }
 
+int Rpl_slave::change_master(THD* thd)
+{
+  int res= 0;
+  mysql_mutex_lock(&LOCK_active_mi);
+  res = ::change_master(thd,active_mi);
+  mysql_mutex_unlock(&LOCK_active_mi);
+  return res;
+}
+
+int Rpl_slave::start_slave(THD*thd)
+{
+  mysql_mutex_lock(&LOCK_active_mi);
+  ::start_slave(thd,active_mi,1 /* net report*/);
+  mysql_mutex_unlock(&LOCK_active_mi);
+  return 0;
+}
+
+int Rpl_slave::stop_slave(THD* thd)
+{
+  /*
+    If the client thread has locked tables, a deadlock is possible.
+    Assume that
+    - the client thread does LOCK TABLE t READ.
+    - then the master updates t.
+    - then the SQL slave thread wants to update t,
+      so it waits for the client thread because t is locked by it.
+    - then the client thread does SLAVE STOP.
+      SLAVE STOP waits for the SQL slave thread to terminate its
+      update t, which waits for the client thread because t is locked by it.
+    To prevent that, refuse SLAVE STOP if the
+    client thread has locked tables
+  */
+  if (thd->locked_tables_mode ||
+      thd->in_active_multi_stmt_transaction() || thd->global_read_lock.is_acquired())
+  {
+    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
+    return 1;
+  }
+  mysql_mutex_lock(&LOCK_active_mi);
+  int res= ::stop_slave(thd,active_mi,1/* net report*/);
+  mysql_mutex_unlock(&LOCK_active_mi);
+  return res;
+}
+
+int Rpl_slave::show_slave_status(THD* thd)
+{
+  int res= 0;
+  mysql_mutex_lock(&LOCK_active_mi);
+  if (active_mi != NULL)
+  {
+    res = show_master_info(thd, active_mi);
+  }
+  else
+  {
+    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                 WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO));
+    my_ok(thd);
+  }
+  mysql_mutex_unlock(&LOCK_active_mi);
+  return res;
+}
+
+int Rpl_slave::flush_relay_log(THD* thd)
+{
+  int res= 0;
+  mysql_mutex_lock(&LOCK_active_mi);
+  rotate_relay_log(active_mi);
+  mysql_mutex_unlock(&LOCK_active_mi);
+  return res;
+}
+
+int Rpl_slave::reset_slave(THD* thd)
+{
+  int res= 0;
+  mysql_mutex_lock(&LOCK_active_mi);
+  res= ::reset_slave(thd, active_mi);
+  mysql_mutex_unlock(&LOCK_active_mi);
+  return res;
+}
+
+/**
+  Execute a SHOW RELAYLOG EVENTS statement.
+
+  @param thd Pointer to THD object for the client thread executing the
+  statement.
+
+  @retval FALSE success
+  @retval TRUE failure
+*/
+int Rpl_slave::show_relay_log_events(THD* thd)
+{
+  Protocol *protocol= thd->protocol;
+  List<Item> field_list;
+  DBUG_ENTER("mysql_show_relaylog_events");
+
+  DBUG_ASSERT(thd->lex->sql_command == SQLCOM_SHOW_RELAYLOG_EVENTS);
+
+  Log_event::init_show_field_list(&field_list);
+  if (protocol->send_result_set_metadata(&field_list,
+                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+    DBUG_RETURN(TRUE);
+
+  if (!active_mi)
+    DBUG_RETURN(TRUE);
+  
+  DBUG_RETURN(show_binlog_events(thd, &active_mi->rli->relay_log));
+}
+
+int Rpl_slave::init()
+{
+  /*
+    init_slave() must be called after the thread keys are created.
+    Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other
+    places) assume that active_mi != 0, so let's fail if it's 0 (out of
+    memory); a message has already been printed.
+  */
+  if (init_slave() && !active_mi)
+  {
+    unireg_abort(1);
+  }
+  return 0;
+}
+
+void Rpl_slave::end()
+{
+  end_slave();
+}
+
+Rpl_slave rpl_slave;
+
 /**
   @} (end of group Replication)
 */

=== renamed file 'sql/rpl_slave.h' => 'sql/rpl/rpl_slave.h'
--- a/sql/rpl_slave.h	2010-11-16 09:38:43 +0000
+++ b/sql/rpl/rpl_slave.h	2010-12-02 07:23:18 +0000
@@ -48,6 +48,7 @@
 #include "my_list.h"
 #include "rpl_filter.h"
 #include "rpl_tblmap.h"
+#include "rpl.h"
 
 #define SLAVE_NET_TIMEOUT  3600
 
@@ -158,8 +159,6 @@ extern const char *relay_log_basename;
 int start_slave(THD* thd, Master_info* mi, bool net_report);
 int stop_slave(THD* thd, Master_info* mi, bool net_report);
 bool change_master(THD* thd, Master_info* mi);
-int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
-		   const char* log_file_name2, ulonglong log_pos2);
 int reset_slave(THD *thd, Master_info* mi);
 int init_slave();
 int init_recovery(Master_info* mi, const char** errmsg);

=== renamed file 'sql/rpl_tblmap.cc' => 'sql/rpl/rpl_tblmap.cc'
=== renamed file 'sql/rpl_tblmap.h' => 'sql/rpl/rpl_tblmap.h'
=== renamed file 'sql/rpl_utility.cc' => 'sql/rpl/rpl_utility.cc'
=== renamed file 'sql/rpl_utility.h' => 'sql/rpl/rpl_utility.h'
=== renamed file 'sql/server_ids.h' => 'sql/rpl/server_ids.h'
=== renamed file 'sql/sql_binlog.cc' => 'sql/rpl/sql_binlog.cc'
--- a/sql/sql_binlog.cc	2010-10-04 10:16:31 +0000
+++ b/sql/rpl/sql_binlog.cc	2010-12-02 07:23:18 +0000
@@ -279,7 +279,7 @@ void mysql_client_binlog_statement(THD* 
       */
       if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
       {
-        if (thd->variables.binlog_rows_query_log_events)
+        if (thd_binlog_rows_query_log_events(thd))
           handle_rows_query_log_event(ev, rli);
         if (ev->get_type_code() != ROWS_QUERY_LOG_EVENT)
         {

=== renamed file 'sql/sql_binlog.h' => 'sql/rpl/sql_binlog.h'
=== modified file 'sql/sp.cc'
--- a/sql/sp.cc	2010-11-18 16:34:56 +0000
+++ b/sql/sp.cc	2010-12-02 07:23:18 +0000
@@ -1154,9 +1154,9 @@ sp_create_routine(THD *thd, int type, sp
       /* restore sql_mode when binloging */
       thd->variables.sql_mode= saved_mode;
       /* Such a statement can always go directly to binlog, no trans cache */
-      if (thd->binlog_query(THD::STMT_QUERY_TYPE,
-                            log_query.c_ptr(), log_query.length(),
-                            FALSE, FALSE, FALSE, 0))
+      if (binlog.binlog_query(thd, Binlog::STMT_QUERY_TYPE,
+                              log_query.c_ptr(), log_query.length(),
+                              FALSE, FALSE, FALSE, 0))
         ret= SP_INTERNAL_ERROR;
       thd->variables.sql_mode= 0;
     }

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2010-11-19 14:53:42 +0000
+++ b/sql/sql_acl.cc	2010-12-02 07:23:18 +0000
@@ -1914,8 +1914,8 @@ bool change_password(THD *thd, const cha
                           acl_user->host.hostname ? acl_user->host.hostname : "",
                           new_password);
     thd->clear_error();
-    result= thd->binlog_query(THD::STMT_QUERY_TYPE, buff, query_length,
-                              FALSE, FALSE, FALSE, 0);
+    result= binlog.binlog_query(thd, Binlog::STMT_QUERY_TYPE, buff, query_length,
+                                FALSE, FALSE, FALSE, 0);
   }
 end:
   close_mysql_tables(thd);

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2010-11-18 16:34:56 +0000
+++ b/sql/sql_base.cc	2010-12-02 07:23:18 +0000
@@ -3761,9 +3761,9 @@ static bool open_table_entry_fini(THD *t
         end = strxmov(strmov(query, "DELETE FROM `"),
                       share->db.str,"`.`",share->table_name.str,"`", NullS);
         int errcode= query_error_code(thd, TRUE);
-        if (thd->binlog_query(THD::STMT_QUERY_TYPE,
-                              query, (ulong)(end-query),
-                              FALSE, FALSE, FALSE, errcode))
+        if (binlog.binlog_query(thd, Binlog::STMT_QUERY_TYPE,
+                                query, (ulong)(end-query),
+                                FALSE, FALSE, FALSE, errcode))
         {
           my_free(query);
           return TRUE;

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2010-11-18 16:34:56 +0000
+++ b/sql/sql_class.h	2010-12-02 07:23:18 +0000
@@ -510,7 +510,6 @@ typedef struct system_variables
   Time_zone *time_zone;
 
   my_bool sysdate_is_now;
-  my_bool binlog_rows_query_log_events;
 
   double long_query_time_double;
 
@@ -1682,12 +1681,12 @@ private:
   */
   uint32 binlog_unsafe_warning_flags;
 
+public:
   /*
     Number of outstanding table maps, i.e., table maps in the
     transaction cache.
   */
   uint binlog_table_maps;
-public:
   void issue_unsafe_warnings();
 
   uint get_binlog_table_maps() const {
@@ -2236,23 +2235,6 @@ public:
 #endif
   void awake(THD::killed_state state_to_set);
 
-#ifndef MYSQL_CLIENT
-  enum enum_binlog_query_type {
-    /* The query can be logged in row format or in statement format. */
-    ROW_QUERY_TYPE,
-    
-    /* The query has to be logged in statement format. */
-    STMT_QUERY_TYPE,
-    
-    QUERY_TYPE_COUNT
-  };
-  
-  int binlog_query(enum_binlog_query_type qtype,
-                   char const *query, ulong query_len, bool is_trans,
-                   bool direct, bool suppress_use,
-                   int errcode);
-#endif
-
   /*
     For enter_cond() / exit_cond() to work the mutex must be got before
     enter_cond(); this mutex is then released by exit_cond().

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	2010-10-21 11:34:17 +0000
+++ b/sql/sql_delete.cc	2010-12-02 07:23:18 +0000
@@ -65,7 +65,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
   uint usable_index= MAX_KEY;
   SELECT_LEX   *select_lex= &thd->lex->select_lex;
   THD::killed_state killed_status= THD::NOT_KILLED;
-  THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
+  Binlog::enum_binlog_query_type query_type= Binlog::ROW_QUERY_TYPE;
   DBUG_ENTER("mysql_delete");
 
   if (open_and_lock_tables(thd, table_list, TRUE, 0))
@@ -151,7 +151,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
         If delete_all_rows() is used, it is not possible to log the
         query in row format, so we have to log it in statement format.
       */
-      query_type= THD::STMT_QUERY_TYPE;
+      query_type= Binlog::STMT_QUERY_TYPE;
       error= -1;
       deleted= maybe_deleted;
       goto cleanup;
@@ -392,10 +392,10 @@ cleanup:
         statement-based; otherwise, 'ha_delete_row()' was used to
         delete specific rows which we might log row-based.
       */
-      int log_result= thd->binlog_query(query_type,
-                                        thd->query(), thd->query_length(),
-                                        transactional_table, FALSE, FALSE,
-                                        errcode);
+      int log_result= binlog.binlog_query(thd, query_type,
+                                          thd->query(), thd->query_length(),
+                                          transactional_table, FALSE, FALSE,
+                                          errcode);
 
       if (log_result)
       {
@@ -813,9 +813,9 @@ void multi_delete::abort_result_set()
     {
       int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
       /* possible error of writing binary log is ignored deliberately */
-      (void) thd->binlog_query(THD::ROW_QUERY_TYPE,
-                               thd->query(), thd->query_length(),
-                               transactional_tables, FALSE, FALSE, errcode);
+      (void) binlog.binlog_query(thd, Binlog::ROW_QUERY_TYPE,
+                                 thd->query(), thd->query_length(),
+                                 transactional_tables, FALSE, FALSE, errcode);
     }
   }
   DBUG_VOID_RETURN;
@@ -989,9 +989,9 @@ bool multi_delete::send_eof()
         thd->clear_error();
       else
         errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
-      if (thd->binlog_query(THD::ROW_QUERY_TYPE,
-                            thd->query(), thd->query_length(),
-                            transactional_tables, FALSE, FALSE, errcode) &&
+      if (binlog.binlog_query(thd, Binlog::ROW_QUERY_TYPE,
+                              thd->query(), thd->query_length(),
+                              transactional_tables, FALSE, FALSE, errcode) &&
           !normal_tables)
       {
 	local_error=1;  // Log write failed: roll back the SQL statement

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2010-11-18 16:34:56 +0000
+++ b/sql/sql_insert.cc	2010-12-02 07:23:18 +0000
@@ -1031,16 +1031,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
 
             error= 1;
           }
-          else if (thd->binlog_query(THD::ROW_QUERY_TYPE,
-                                     log_query.c_ptr(), log_query.length(),
-                                     transactional_table, FALSE, FALSE,
-                                     errcode))
+          else if (binlog.binlog_query(thd, Binlog::ROW_QUERY_TYPE,
+                                       log_query.c_ptr(), log_query.length(),
+                                       transactional_table, FALSE, FALSE,
+                                       errcode))
             error= 1;
         }
-        else if (thd->binlog_query(THD::ROW_QUERY_TYPE,
-			           thd->query(), thd->query_length(),
-			           transactional_table, FALSE, FALSE,
-                                   errcode))
+        else if (binlog.binlog_query(thd, Binlog::ROW_QUERY_TYPE,
+                                     thd->query(), thd->query_length(),
+                                     transactional_table, FALSE, FALSE,
+                                     errcode))
 	  error= 1;
       }
     }
@@ -1831,7 +1831,7 @@ public:
   time_t start_time;
   ulong sql_mode;
   bool auto_increment_field_not_null;
-  bool query_start_used, ignore, log_query, binlog_rows_query_log_events;
+  bool query_start_used, ignore, log_query;
   bool stmt_depends_on_first_successful_insert_id_in_prev_stmt;
   MY_BITMAP write_set;
   ulonglong first_successful_insert_id_in_prev_stmt;
@@ -1841,11 +1841,11 @@ public:
   timestamp_auto_set_type timestamp_field_type;
   LEX_STRING query;
   Time_zone *time_zone;
+  void* binlog_data;
 
   delayed_row(LEX_STRING const query_arg, enum_duplicates dup_arg,
               bool ignore_arg, bool log_query_arg)
     : record(0), dup(dup_arg), ignore(ignore_arg), log_query(log_query_arg),
-      binlog_rows_query_log_events(FALSE),
       forced_insert_id(0), query(query_arg), time_zone(0)
     {}
   ~delayed_row()
@@ -2426,7 +2426,6 @@ int write_delayed(THD *thd, TABLE *table
   row->auto_increment_offset=    thd->variables.auto_increment_offset;
   row->sql_mode=                 thd->variables.sql_mode;
   row->auto_increment_field_not_null= table->auto_increment_field_not_null;
-  row->binlog_rows_query_log_events= thd->variables.binlog_rows_query_log_events;
 
   /* Copy the next forced auto increment value, if any. */
   if ((forced_auto_inc= thd->auto_inc_intervals_forced.get_next()))
@@ -2445,6 +2444,10 @@ int write_delayed(THD *thd, TABLE *table
   bitmap_clear_all(&row->write_set);
   bitmap_union(&row->write_set, table->write_set);
 
+  if(binlog.get_delayed_row_data(thd, table,
+                                 &row->binlog_data, &query, log_on))
+    goto err;
+
   di->rows.push_back(row);
   di->stacked_inserts++;
   di->status=1;
@@ -2944,18 +2947,11 @@ bool Delayed_insert::handle_inserts(void
     DBUG_PRINT("delayed", ("query: '%s'  length: %lu", row->query.str ?
                            row->query.str : "[NULL]",
                            (ulong) row->query.length));
+    if (binlog.before_handle_delayed_row(&thd, table, row->binlog_data,
+                                         &row->query, log_query))
+      goto err;
     if (log_query)
     {
-      if (thd.is_current_stmt_binlog_format_row())
-      {
-        /* Flush rows of previous statement*/
-        if (thd.binlog_flush_pending_rows_event(TRUE, FALSE))
-          goto err;
-        /* Set query for Rows_query_log event in RBR*/
-        thd.set_query(row->query.str, row->query.length);
-        thd.variables.binlog_rows_query_log_events= row->binlog_rows_query_log_events;
-      }
-
       /*
         This is the first value of an INSERT statement.
         It is the right place to clear a forced insert_id.
@@ -3023,6 +3019,10 @@ bool Delayed_insert::handle_inserts(void
       table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
     }
 
+    if (binlog.after_handle_delayed_row(&thd, table, row->binlog_data,
+                                        &row->query, log_query))
+      goto err;
+    
     if (log_query && mysql_bin_log.is_open() &&
         !thd.is_current_stmt_binlog_format_row())
     {
@@ -3044,9 +3044,9 @@ bool Delayed_insert::handle_inserts(void
         In SBR, only the query which has one single value
         will be binlogged here.
       */
-      if (thd.binlog_query(THD::STMT_QUERY_TYPE,
-                           row->query.str, row->query.length,
-                           FALSE, FALSE, FALSE, errcode))
+      if (binlog.binlog_query(&thd, Binlog::STMT_QUERY_TYPE,
+                              row->query.str, row->query.length,
+                              FALSE, FALSE, FALSE, errcode))
         goto err;
 
       thd.time_zone_used = backup_time_zone_used;
@@ -3586,7 +3586,7 @@ bool select_insert::send_eof()
       thd->clear_error();
     else
       errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
-    if (thd->binlog_query(THD::ROW_QUERY_TYPE,
+    if (binlog.binlog_query(thd, Binlog::ROW_QUERY_TYPE,
                       thd->query(), thd->query_length(),
                       trans_table, FALSE, FALSE, errcode))
     {
@@ -3666,9 +3666,9 @@ void select_insert::abort_result_set() {
         {
           int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
           /* error of writing binary log is ignored */
-          (void) thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(),
-                                   thd->query_length(),
-                                   transactional_table, FALSE, FALSE, errcode);
+          (void) binlog.binlog_query(thd, Binlog::ROW_QUERY_TYPE, thd->query(),
+                                     thd->query_length(),
+                                     transactional_table, FALSE, FALSE, errcode);
         }
 	if (changed)
 	  query_cache_invalidate3(thd, table, 1);
@@ -4045,12 +4045,12 @@ select_create::binlog_show_create_table(
   if (mysql_bin_log.is_open())
   {
     int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
-    result= thd->binlog_query(THD::STMT_QUERY_TYPE,
-                              query.ptr(), query.length(),
-                              /* is_trans */ TRUE,
-                              /* direct */ FALSE,
-                              /* suppress_use */ FALSE,
-                              errcode);
+    result= binlog.binlog_query(thd, Binlog::STMT_QUERY_TYPE,
+                                query.ptr(), query.length(),
+                                /* is_trans */ TRUE,
+                                /* direct */ FALSE,
+                                /* suppress_use */ FALSE,
+                                errcode);
   }
   return result;
 }

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2010-11-18 16:34:56 +0000
+++ b/sql/sql_lex.cc	2010-12-02 07:23:18 +0000
@@ -3173,15 +3173,6 @@ bool LEX::is_partition_management() cons
 }
 
 
-/**
-  Set all fields to their "unspecified" value.
-*/
-void st_lex_master_info::set_unspecified()
-{
-  bzero((char*) this, sizeof(*this));
-  sql_delay= -1;
-}
-
 #ifdef MYSQL_SERVER
 uint binlog_unsafe_map[256];
 

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2010-11-18 16:34:56 +0000
+++ b/sql/sql_lex.h	2010-12-02 07:23:18 +0000
@@ -123,6 +123,7 @@ struct sys_var_with_base
 #endif
 
 #include "sql_cmd.h"
+#include "rpl_lex.h"
 
 // describe/explain types
 #define DESCRIBE_NONE		0 // Not explain query
@@ -195,38 +196,6 @@ typedef struct st_lex_server_options
 } LEX_SERVER_OPTIONS;
 
 
-/**
-  Structure to hold parameters for CHANGE MASTER or START/STOP SLAVE
-  or SHOW NEW MASTER.
-
-  Remark: this should not be confused with Master_info (and perhaps
-  would better be renamed to st_lex_replication_info).  Some fields,
-  e.g., delay, are saved in Relay_log_info, not in Master_info.
-*/
-typedef struct st_lex_master_info
-{
-  char *host, *user, *password, *log_file_name;
-  uint port, connect_retry;
-  float heartbeat_period;
-  int sql_delay;
-  ulonglong pos;
-  ulong server_id, retry_count;
-  /*
-    Enum is used for making it possible to detect if the user
-    changed variable or if it should be left at old value
-   */
-  enum {LEX_MI_UNCHANGED= 0, LEX_MI_DISABLE, LEX_MI_ENABLE}
-    ssl, ssl_verify_server_cert, heartbeat_opt, repl_ignore_server_ids_opt, 
-    retry_count_opt;
-  char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher;
-  char *relay_log_name;
-  ulong relay_log_pos;
-  DYNAMIC_ARRAY repl_ignore_server_ids;
-
-  void set_unspecified();
-} LEX_MASTER_INFO;
-
-
 enum sub_select_type
 {
   UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE,

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-11-18 16:34:56 +0000
+++ b/sql/sql_parse.cc	2010-12-02 07:23:18 +0000
@@ -957,7 +957,9 @@ bool dispatch_command(enum enum_server_c
 #ifdef HAVE_REPLICATION
   case COM_REGISTER_SLAVE:
   {
-    if (!register_slave(thd, (uchar*)packet, packet_length))
+    if (check_global_access(thd, REPL_SLAVE_ACL))
+      break;
+    if (!rpl_master.register_slave(thd, packet, packet_length))
       my_ok(thd);
     break;
   }
@@ -1214,29 +1216,11 @@ bool dispatch_command(enum enum_server_c
 #ifndef EMBEDDED_LIBRARY
   case COM_BINLOG_DUMP:
     {
-      ulong pos;
-      ushort flags;
-      String slave_uuid;
-
       status_var_increment(thd->status_var.com_other);
       thd->enable_slow_log= opt_log_slow_admin_statements;
       if (check_global_access(thd, REPL_SLAVE_ACL))
 	break;
-
-      /* TODO: The following has to be changed to an 8 byte integer */
-      pos = uint4korr(packet);
-      flags = uint2korr(packet + 4);
-      thd->server_id= uint4korr(packet+6);
-
-      get_slave_uuid(thd, &slave_uuid);
-      kill_zombie_dump_threads(&slave_uuid);
-
-      general_log_print(thd, command, "Log: '%s'  Pos: %ld", packet+10,
-                      (long) pos);
-      mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags);
-      unregister_slave(thd,1,1);
-      /*  fake COM_QUIT -- if we get here, the thread needs to terminate */
-      error = TRUE;
+      error = rpl_master.binlog_dump(thd, packet, packet_length);
       break;
     }
 #endif
@@ -2110,7 +2094,7 @@ case SQLCOM_PREPARE:
     if (check_global_access(thd, SUPER_ACL))
       goto error;
     /* PURGE MASTER LOGS TO 'file' */
-    res = purge_master_logs(thd, lex->to_log);
+    res = binlog.purge_binary_logs(thd, lex->to_log);
     break;
   }
   case SQLCOM_PURGE_BEFORE:
@@ -2133,7 +2117,7 @@ case SQLCOM_PREPARE:
       value of constant
     */
     it->quick_fix_field();
-    res = purge_master_logs_before_date(thd, (ulong)it->val_int());
+    res = binlog.purge_binary_logs_before(thd, (ulong)it->val_int());
     break;
   }
 #endif
@@ -2179,21 +2163,21 @@ case SQLCOM_PREPARE:
   {
     if (check_global_access(thd, REPL_SLAVE_ACL))
       goto error;
-    res = show_slave_hosts(thd);
+    res = rpl_master.show_slave_hosts(thd);
     break;
   }
   case SQLCOM_SHOW_RELAYLOG_EVENTS:
   {
     if (check_global_access(thd, REPL_SLAVE_ACL))
       goto error;
-    res = mysql_show_relaylog_events(thd);
+    res = rpl_slave.show_relay_log_events(thd);
     break;
   }
   case SQLCOM_SHOW_BINLOG_EVENTS:
   {
     if (check_global_access(thd, REPL_SLAVE_ACL))
       goto error;
-    res = mysql_show_binlog_events(thd);
+    res = binlog.show_binlog_events(thd);
     break;
   }
 #endif
@@ -2225,9 +2209,7 @@ case SQLCOM_PREPARE:
   {
     if (check_global_access(thd, SUPER_ACL))
       goto error;
-    mysql_mutex_lock(&LOCK_active_mi);
-    res = change_master(thd,active_mi);
-    mysql_mutex_unlock(&LOCK_active_mi);
+    res = rpl_slave.change_master(thd);
     break;
   }
   case SQLCOM_SHOW_SLAVE_STAT:
@@ -2235,18 +2217,7 @@ case SQLCOM_PREPARE:
     /* Accept one of two privileges */
     if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
       goto error;
-    mysql_mutex_lock(&LOCK_active_mi);
-    if (active_mi != NULL)
-    {
-      res = show_master_info(thd, active_mi);
-    }
-    else
-    {
-      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-                   WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO));
-      my_ok(thd);
-    }
-    mysql_mutex_unlock(&LOCK_active_mi);
+    res = rpl_slave.show_slave_status(thd);
     break;
   }
   case SQLCOM_SHOW_MASTER_STAT:
@@ -2254,7 +2225,7 @@ case SQLCOM_PREPARE:
     /* Accept one of two privileges */
     if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
       goto error;
-    res = show_binlog_info(thd);
+    res = rpl_master.show_master_status(thd);
     break;
   }
 
@@ -2524,36 +2495,18 @@ end_with_restore_list:
 #ifdef HAVE_REPLICATION
   case SQLCOM_SLAVE_START:
   {
-    mysql_mutex_lock(&LOCK_active_mi);
-    start_slave(thd,active_mi,1 /* net report*/);
-    mysql_mutex_unlock(&LOCK_active_mi);
+    if (check_global_access(thd, SUPER_ACL))
+      goto error;
+    if (rpl_slave.start_slave(thd))
+      goto error;
     break;
   }
   case SQLCOM_SLAVE_STOP:
-  /*
-    If the client thread has locked tables, a deadlock is possible.
-    Assume that
-    - the client thread does LOCK TABLE t READ.
-    - then the master updates t.
-    - then the SQL slave thread wants to update t,
-      so it waits for the client thread because t is locked by it.
-    - then the client thread does SLAVE STOP.
-      SLAVE STOP waits for the SQL slave thread to terminate its
-      update t, which waits for the client thread because t is locked by it.
-    To prevent that, refuse SLAVE STOP if the
-    client thread has locked tables
-  */
-  if (thd->locked_tables_mode ||
-      thd->in_active_multi_stmt_transaction() || thd->global_read_lock.is_acquired())
-  {
-    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
-               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
-    goto error;
-  }
   {
-    mysql_mutex_lock(&LOCK_active_mi);
-    stop_slave(thd,active_mi,1/* net report*/);
-    mysql_mutex_unlock(&LOCK_active_mi);
+    if (check_global_access(thd, SUPER_ACL))
+      goto error;
+    if (rpl_slave.stop_slave(thd))
+      goto error;
     break;
   }
 #endif /* HAVE_REPLICATION */
@@ -2602,7 +2555,7 @@ end_with_restore_list:
     {
       if (check_global_access(thd, SUPER_ACL))
 	goto error;
-      res = show_binlogs(thd);
+      res = binlog.show_binary_logs(thd);
       break;
     }
 #endif

=== modified file 'sql/sql_reload.cc'
--- a/sql/sql_reload.cc	2010-10-01 10:23:16 +0000
+++ b/sql/sql_reload.cc	2010-12-02 07:23:18 +0000
@@ -23,8 +23,9 @@
 #include "sql_base.h"    // close_cached_tables
 #include "sql_db.h"      // my_dbopt_cleanup
 #include "hostname.h"    // hostname_cache_refresh
+#include "binlog.h"
+#include "replication.h"
 #include "rpl_master.h"  // reset_master, reset_slave
-#include "rpl_rli.h"     // rotate_relay_log
 #include "debug_sync.h"
 
 
@@ -136,15 +137,14 @@ bool reload_acl_and_cache(THD *thd, unsi
       than it would help them)
     */
     tmp_write_to_binlog= 0;
-    if (mysql_bin_log.is_open())
-      mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+    if (binlog.flush_binary_log(thd))
+      result= 1;
   }
   if (options & REFRESH_RELAY_LOG)
   {
 #ifdef HAVE_REPLICATION
-    mysql_mutex_lock(&LOCK_active_mi);
-    rotate_relay_log(active_mi);
-    mysql_mutex_unlock(&LOCK_active_mi);
+    if (rpl_slave.flush_relay_log(thd))
+      result= 1;
 #endif
   }
 #ifdef HAVE_QUERY_CACHE
@@ -250,7 +250,7 @@ bool reload_acl_and_cache(THD *thd, unsi
   {
     DBUG_ASSERT(thd);
     tmp_write_to_binlog= 0;
-    if (reset_master(thd))
+    if (rpl_master.reset_master(thd))
     {
       result=1;
     }
@@ -267,10 +267,8 @@ bool reload_acl_and_cache(THD *thd, unsi
  if (options & REFRESH_SLAVE)
  {
    tmp_write_to_binlog= 0;
-   mysql_mutex_lock(&LOCK_active_mi);
-   if (reset_slave(thd, active_mi))
+   if (rpl_slave.reset_slave(thd))
      result=1;
-   mysql_mutex_unlock(&LOCK_active_mi);
  }
 #endif
  if (options & REFRESH_USER_RESOURCES)

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2010-11-19 09:15:30 +0000
+++ b/sql/sql_table.cc	2010-12-02 07:23:18 +0000
@@ -1990,9 +1990,9 @@ int write_bin_log(THD *thd, bool clear_e
       thd->clear_error();
     else
       errcode= query_error_code(thd, TRUE);
-    error= thd->binlog_query(THD::STMT_QUERY_TYPE,
-                             query, query_length, is_trans, FALSE, FALSE,
-                             errcode);
+    error= binlog.binlog_query(thd, Binlog::STMT_QUERY_TYPE,
+                               query, query_length, is_trans, FALSE, FALSE,
+                               errcode);
   }
   return error;
 }
@@ -2471,20 +2471,20 @@ err:
           /* Chop of the last comma */
           built_non_trans_tmp_query.chop();
           built_non_trans_tmp_query.append(" /* generated by server */");
-          error |= thd->binlog_query(THD::STMT_QUERY_TYPE,
-                                     built_non_trans_tmp_query.ptr(),
-                                     built_non_trans_tmp_query.length(),
-                                     FALSE, FALSE, FALSE, 0);
+          error |= binlog.binlog_query(thd, Binlog::STMT_QUERY_TYPE,
+                                       built_non_trans_tmp_query.ptr(),
+                                       built_non_trans_tmp_query.length(),
+                                       FALSE, FALSE, FALSE, 0);
       }
       if (trans_tmp_table_deleted)
       {
           /* Chop of the last comma */
           built_trans_tmp_query.chop();
           built_trans_tmp_query.append(" /* generated by server */");
-          error |= thd->binlog_query(THD::STMT_QUERY_TYPE,
-                                     built_trans_tmp_query.ptr(),
-                                     built_trans_tmp_query.length(),
-                                     TRUE, FALSE, FALSE, 0);
+          error |= binlog.binlog_query(thd, Binlog::STMT_QUERY_TYPE,
+                                       built_trans_tmp_query.ptr(),
+                                       built_trans_tmp_query.length(),
+                                       TRUE, FALSE, FALSE, 0);
       }
       if (non_tmp_table_deleted)
       {
@@ -2493,11 +2493,11 @@ err:
           built_query.append(" /* generated by server */");
           int error_code = (non_tmp_error ?
             (foreign_key_error ? ER_ROW_IS_REFERENCED : ER_BAD_TABLE_ERROR) : 0);
-          error |= thd->binlog_query(THD::STMT_QUERY_TYPE,
-                                     built_query.ptr(),
-                                     built_query.length(),
-                                     TRUE, FALSE, FALSE,
-                                     error_code);
+          error |= binlog.binlog_query(thd, Binlog::STMT_QUERY_TYPE,
+                                       built_query.ptr(),
+                                       built_query.length(),
+                                       TRUE, FALSE, FALSE,
+                                       error_code);
       }
     }
   }

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2010-11-18 16:34:56 +0000
+++ b/sql/sql_update.cc	2010-12-02 07:23:18 +0000
@@ -872,9 +872,9 @@ int mysql_update(THD *thd,
       else
         errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
 
-      if (thd->binlog_query(THD::ROW_QUERY_TYPE,
-                            thd->query(), thd->query_length(),
-                            transactional_table, FALSE, FALSE, errcode))
+      if (binlog.binlog_query(thd, Binlog::ROW_QUERY_TYPE,
+                              thd->query(), thd->query_length(),
+                              transactional_table, FALSE, FALSE, errcode))
       {
         error=1;				// Rollback update
       }
@@ -1882,9 +1882,9 @@ void multi_update::abort_result_set()
       */
       int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
       /* the error of binary logging is ignored */
-      (void)thd->binlog_query(THD::ROW_QUERY_TYPE,
-                        thd->query(), thd->query_length(),
-                        transactional_tables, FALSE, FALSE, errcode);
+      (void)binlog.binlog_query(thd, Binlog::ROW_QUERY_TYPE,
+                                thd->query(), thd->query_length(),
+                                transactional_tables, FALSE, FALSE, errcode);
     }
     thd->transaction.all.modified_non_trans_table= TRUE;
   }
@@ -2111,9 +2111,9 @@ bool multi_update::send_eof()
         thd->clear_error();
       else
         errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
-      if (thd->binlog_query(THD::ROW_QUERY_TYPE,
-                            thd->query(), thd->query_length(),
-                            transactional_tables, FALSE, FALSE, errcode))
+      if (binlog.binlog_query(thd, Binlog::ROW_QUERY_TYPE,
+                              thd->query(), thd->query_length(),
+                              transactional_tables, FALSE, FALSE, errcode))
       {
 	local_error= 1;				// Rollback update
       }

=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc	2010-11-18 16:34:56 +0000
+++ b/sql/sql_view.cc	2010-12-02 07:23:18 +0000
@@ -689,8 +689,8 @@ bool mysql_create_view(THD *thd, TABLE_L
     buff.append(views->source.str, views->source.length);
 
     int errcode= query_error_code(thd, TRUE);
-    if (thd->binlog_query(THD::STMT_QUERY_TYPE,
-                          buff.ptr(), buff.length(), FALSE, FALSE, FALSE, errcode))
+    if (binlog.binlog_query(thd, Binlog::STMT_QUERY_TYPE,
+                            buff.ptr(), buff.length(), FALSE, FALSE, FALSE, errcode))
       res= TRUE;
   }
 

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2010-11-18 16:34:56 +0000
+++ b/sql/sql_yacc.yy	2010-12-02 07:23:18 +0000
@@ -1424,7 +1424,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
         IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
         NCHAR_STRING opt_component key_cache_name
         sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
-        opt_constraint constraint opt_ident
+        opt_constraint constraint opt_ident master_option_name
 
 %type <lex_str_ptr>
         opt_table_alias
@@ -1488,6 +1488,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
         function_call_generic
         function_call_conflict
         signal_allowed_expr
+	master_option_single_value
 
 %type <item_num>
         NUM_literal
@@ -1532,7 +1533,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 
 %type <cast_type> cast_type
 
-%type <symbol> keyword keyword_sp
+%type <symbol> keyword keyword_sp master_option_sym
 
 %type <lex_user> user grant_user
 
@@ -1870,15 +1871,7 @@ change:
           {
             LEX *lex = Lex;
             lex->sql_command = SQLCOM_CHANGE_MASTER;
-            /*
-              Clear LEX_MASTER_INFO struct and allocate memory for
-              repl_ignore_server_ids. repl_ignore_server_ids is freed
-              at the end of change_master. So it is guaranteed to be
-              uninitialized before here.
-            */
-            lex->mi.set_unspecified();
-            my_init_dynamic_array(&Lex->mi.repl_ignore_server_ids,
-                                  sizeof(::server_id), 16, 16);
+            lex->mi.init(lex->sql_command);
           }
           master_defs
           {}
@@ -1890,153 +1883,95 @@ master_defs:
         ;
 
 master_def:
-          MASTER_HOST_SYM EQ TEXT_STRING_sys
-          {
-            Lex->mi.host = $3.str;
-          }
-        | MASTER_USER_SYM EQ TEXT_STRING_sys
-          {
-            Lex->mi.user = $3.str;
-          }
-        | MASTER_PASSWORD_SYM EQ TEXT_STRING_sys
-          {
-            Lex->mi.password = $3.str;
-          }
-        | MASTER_PORT_SYM EQ ulong_num
-          {
-            Lex->mi.port = $3;
-          }
-        | MASTER_CONNECT_RETRY_SYM EQ ulong_num
-          {
-            Lex->mi.connect_retry = $3;
-          }
-        | MASTER_RETRY_COUNT_SYM EQ ulong_num
-          {
-            Lex->mi.retry_count= $3;
-            Lex->mi.retry_count_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
-          }
-        | MASTER_DELAY_SYM EQ ulong_num
-          {
-            if ($3 > MASTER_DELAY_MAX)
-            {
-              my_error(ER_MASTER_DELAY_VALUE_OUT_OF_RANGE, MYF(0),
-                       $3, MASTER_DELAY_MAX);
-            }
-            else
-              Lex->mi.sql_delay = $3;
-          }
-        | MASTER_SSL_SYM EQ ulong_num
-          {
-            Lex->mi.ssl= $3 ? 
-              LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE;
-          }
-        | MASTER_SSL_CA_SYM EQ TEXT_STRING_sys
-          {
-            Lex->mi.ssl_ca= $3.str;
-          }
-        | MASTER_SSL_CAPATH_SYM EQ TEXT_STRING_sys
-          {
-            Lex->mi.ssl_capath= $3.str;
-          }
-        | MASTER_SSL_CERT_SYM EQ TEXT_STRING_sys
-          {
-            Lex->mi.ssl_cert= $3.str;
-          }
-        | MASTER_SSL_CIPHER_SYM EQ TEXT_STRING_sys
-          {
-            Lex->mi.ssl_cipher= $3.str;
-          }
-        | MASTER_SSL_KEY_SYM EQ TEXT_STRING_sys
-          {
-            Lex->mi.ssl_key= $3.str;
-          }
-        | MASTER_SSL_VERIFY_SERVER_CERT_SYM EQ ulong_num
-          {
-            Lex->mi.ssl_verify_server_cert= $3 ?
-              LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE;
-          }
-
-        | MASTER_HEARTBEAT_PERIOD_SYM EQ NUM_literal
-          {
-            Lex->mi.heartbeat_period= (float) $3->val_real();
-            if (Lex->mi.heartbeat_period > SLAVE_MAX_HEARTBEAT_PERIOD ||
-                Lex->mi.heartbeat_period < 0.0)
-            {
-               const char format[]= "%d";
-               char buf[4*sizeof(SLAVE_MAX_HEARTBEAT_PERIOD) + sizeof(format)];
-               sprintf(buf, format, SLAVE_MAX_HEARTBEAT_PERIOD);
-               my_error(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, MYF(0), buf);
-               MYSQL_YYABORT;
-            }
-            if (Lex->mi.heartbeat_period > slave_net_timeout)
-            {
-              push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_WARN,
-                                  ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX,
-                                  ER(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX));
-            }
-            if (Lex->mi.heartbeat_period < 0.001)
-            {
-              if (Lex->mi.heartbeat_period != 0.0)
-              {
-                push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_WARN,
-                                    ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN,
-                                    ER(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN));
-                Lex->mi.heartbeat_period= 0.0;
-              }
-              Lex->mi.heartbeat_opt=  LEX_MASTER_INFO::LEX_MI_DISABLE;
-            }
-            Lex->mi.heartbeat_opt=  LEX_MASTER_INFO::LEX_MI_ENABLE;
-          }
-        | IGNORE_SERVER_IDS_SYM EQ '(' ignore_server_id_list ')'
-          {
-            Lex->mi.repl_ignore_server_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
-           }
-        |
-        master_file_def
-        ;
+	  master_option_name EQ master_option_value
+	  {
+	    if (Lex->mi.end_option(YYTHD, ($1).str))
+	      MYSQL_YYABORT;
+	  }
+	| master_file_def
+	;
+
+master_option_name:
+	  master_option_sym
+	  {
+            THD *thd= YYTHD;
+            $$.str= thd->strmake($1.str, $1.length);
+            if ($$.str == NULL)
+              MYSQL_YYABORT;
+            $$.length= $1.length;
+	    if (Lex->mi.start_option(YYTHD, $$.str))
+	      MYSQL_YYABORT;
+	  }
+	| IDENT_sys
+	;
+
+master_option_sym:
+	  MASTER_HOST_SYM			{}
+	| MASTER_USER_SYM 		 	{}
+	| MASTER_PASSWORD_SYM 		 	{}
+	| MASTER_PORT_SYM 		 	{}
+	| MASTER_CONNECT_RETRY_SYM 		{}
+	| MASTER_RETRY_COUNT_SYM 		{}
+	| MASTER_DELAY_SYM 			{}
+	| MASTER_SSL_SYM 			{}
+	| MASTER_SSL_CA_SYM 			{}
+	| MASTER_SSL_CAPATH_SYM 		{}
+	| MASTER_SSL_CERT_SYM 			{}
+	| MASTER_SSL_CIPHER_SYM 		{}
+	| MASTER_SSL_KEY_SYM 			{}
+	| MASTER_SSL_VERIFY_SERVER_CERT_SYM 	{}
+	| MASTER_HEARTBEAT_PERIOD_SYM 		{}
+	| IGNORE_SERVER_IDS_SYM 		{}
+	;
+
+master_option_value:
+	  master_option_single_value
+	  {
+	    if(Lex->mi.set_option_value(YYTHD, $1))
+	      MYSQL_YYABORT;
+	  }
+	| '(' master_option_value_list ')'
+	;
 
-ignore_server_id_list:
-          /* Empty */
-          | ignore_server_id
-          | ignore_server_id_list ',' ignore_server_id
-        ;
+master_option_single_value:
+          literal
+	{ $$= $1; }
+	;
 
-ignore_server_id:
-          ulong_num
-          {
-            insert_dynamic(&Lex->mi.repl_ignore_server_ids, (uchar*) &($1));
-          }
+master_option_value_list:
+	  /* Empty */
+	| master_option_single_value
+	  {
+	    if (Lex->mi.add_option_value(YYTHD, $1))
+	      MYSQL_YYABORT;
+	  }
+	| master_option_value_list ',' master_option_single_value
+	  {
+	    if (Lex->mi.add_option_value(YYTHD, $3))
+	      MYSQL_YYABORT;
+	  }
+	;
 
 master_file_def:
           MASTER_LOG_FILE_SYM EQ TEXT_STRING_sys
           {
-            Lex->mi.log_file_name = $3.str;
+            if (Lex->mi.set_log_file(YYTHD, $3.str))
+	      MYSQL_YYABORT;
           }
         | MASTER_LOG_POS_SYM EQ ulonglong_num
           {
-            Lex->mi.pos = $3;
-            /* 
-               If the user specified a value < BIN_LOG_HEADER_SIZE, adjust it
-               instead of causing subsequent errors. 
-               We need to do it in this file, because only there we know that 
-               MASTER_LOG_POS has been explicitely specified. On the contrary
-               in change_master() (sql_repl.cc) we cannot distinguish between 0
-               (MASTER_LOG_POS explicitely specified as 0) and 0 (unspecified),
-               whereas we want to distinguish (specified 0 means "read the binlog
-               from 0" (4 in fact), unspecified means "don't change the position
-               (keep the preceding value)").
-            */
-            Lex->mi.pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.pos);
+            if (Lex->mi.set_log_pos(YYTHD, $3))
+	      MYSQL_YYABORT;
           }
         | RELAY_LOG_FILE_SYM EQ TEXT_STRING_sys
           {
-            Lex->mi.relay_log_name = $3.str;
+            if (Lex->mi.set_relay_log_file(YYTHD, $3.str))
+	      MYSQL_YYABORT;
           }
         | RELAY_LOG_POS_SYM EQ ulong_num
           {
-            Lex->mi.relay_log_pos = $3;
-            /* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */
-            Lex->mi.relay_log_pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos);
+            if (Lex->mi.set_relay_log_pos(YYTHD, $3))
+	      MYSQL_YYABORT;
           }
         ;
 
@@ -6909,7 +6844,7 @@ slave:
             lex->sql_command = SQLCOM_SLAVE_START;
             lex->type = 0;
             /* We'll use mi structure for UNTIL options */
-            lex->mi.set_unspecified();
+            lex->mi.init(lex->sql_command);
             /* If you change this code don't forget to update SLAVE START too */
           }
           slave_until
@@ -6962,15 +6897,8 @@ slave_until:
         | UNTIL_SYM slave_until_opts
           {
             LEX *lex=Lex;
-            if (((lex->mi.log_file_name || lex->mi.pos) &&
-                (lex->mi.relay_log_name || lex->mi.relay_log_pos)) ||
-                !((lex->mi.log_file_name && lex->mi.pos) ||
-                  (lex->mi.relay_log_name && lex->mi.relay_log_pos)))
-            {
-               my_message(ER_BAD_SLAVE_UNTIL_COND,
-                          ER(ER_BAD_SLAVE_UNTIL_COND), MYF(0));
+	    if (lex->mi.check_slave_until_opts(YYTHD))
                MYSQL_YYABORT;
-            }
           }
         ;
 

=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc	2010-11-16 09:38:43 +0000
+++ b/sql/sys_vars.cc	2010-12-02 07:23:18 +0000
@@ -425,11 +425,11 @@ static Sys_var_enum Sys_rli_repository(
        , READ_ONLY GLOBAL_VAR(opt_rli_repository_id), CMD_LINE(REQUIRED_ARG),
        repository_names, DEFAULT(0));
 
-static Sys_var_mybool Sys_binlog_rows_query(
-       "binlog_rows_query_log_events",
-       "Allow writing of Rows_query_log events into binary log.",
-       SESSION_VAR(binlog_rows_query_log_events),
-       CMD_LINE(OPT_ARG), DEFAULT(FALSE));
+// static Sys_var_mybool Sys_binlog_rows_query(
+//        "binlog_rows_query_log_events",
+//        "Allow writing of Rows_query_log events into binary log.",
+//        SESSION_VAR(binlog_rows_query_log_events),
+//        CMD_LINE(OPT_ARG), DEFAULT(FALSE));
 
 static Sys_var_ulong Sys_bulk_insert_buff_size(
        "bulk_insert_buffer_size", "Size of tree cache used in bulk "


Attachment: [text/bzr-bundle] bzr/zhenxing.he@sun.com-20101202072318-1mxmd4jkb3dislc0.bundle
Thread
bzr commit into mysql-trunk-bugfixing branch (zhenxing.he:3378) WL#5675He Zhenxing2 Dec