#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#5675 | He Zhenxing | 2 Dec |