summaryrefslogtreecommitdiffstats
path: root/sql/rpl_mi.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/rpl_mi.h')
-rw-r--r--sql/rpl_mi.h475
1 files changed, 475 insertions, 0 deletions
diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h
new file mode 100644
index 00000000..6058b7fb
--- /dev/null
+++ b/sql/rpl_mi.h
@@ -0,0 +1,475 @@
+/* Copyright (c) 2006, 2012, Oracle and/or its affiliates.
+
+ 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-1335 USA */
+
+#ifndef RPL_MI_H
+#define RPL_MI_H
+
+#ifdef HAVE_REPLICATION
+
+#include "rpl_rli.h"
+#include "rpl_reporting.h"
+#include <my_sys.h>
+#include "rpl_filter.h"
+#include "keycaches.h"
+
+typedef struct st_mysql MYSQL;
+
+/**
+ Domain id based filter to handle DO_DOMAIN_IDS and IGNORE_DOMAIN_IDS used to
+ set filtering on replication slave based on event's GTID domain_id.
+*/
+class Domain_id_filter
+{
+private:
+ /*
+ Flag to tell whether the events in the current GTID group get written to
+ the relay log. It is set according to the domain_id based filtering rule
+ on every GTID_EVENT and reset at the end of current GTID event group.
+ */
+ bool m_filter;
+
+public:
+ /* domain id list types */
+ enum enum_list_type {
+ DO_DOMAIN_IDS= 0,
+ IGNORE_DOMAIN_IDS
+ };
+
+ /*
+ DO_DOMAIN_IDS (0):
+ Ignore all the events which do not belong to any of the domain ids in the
+ list.
+
+ IGNORE_DOMAIN_IDS (1):
+ Ignore the events which belong to one of the domain ids in the list.
+ */
+ DYNAMIC_ARRAY m_domain_ids[2];
+
+ Domain_id_filter();
+
+ ~Domain_id_filter();
+
+ /*
+ Returns whether the current group needs to be filtered.
+ */
+ bool is_group_filtered() { return m_filter; }
+
+ /*
+ Checks whether the group with the specified domain_id needs to be
+ filtered and updates m_filter flag accordingly.
+ */
+ void do_filter(ulong domain_id);
+
+ /*
+ Reset m_filter. It should be called when IO thread receives COMMIT_EVENT or
+ XID_EVENT.
+ */
+ void reset_filter();
+
+ /*
+ Clear do_ids and ignore_ids to disable domain id filtering
+ */
+ void clear_ids();
+
+ /*
+ Update the do/ignore domain id filter lists.
+
+ @param do_ids [IN] domain ids to be kept
+ @param ignore_ids [IN] domain ids to be filtered out
+ @param using_gtid [IN] use GTID?
+
+ @retval false Success
+ true Error
+ */
+ bool update_ids(DYNAMIC_ARRAY *do_ids, DYNAMIC_ARRAY *ignore_ids,
+ bool using_gtid);
+
+ /*
+ Serialize and store the ids from domain id lists into the thd's protocol
+ buffer.
+
+ @param thd [IN] thread handler
+
+ @retval void
+ */
+ void store_ids(THD *thd);
+
+ /*
+ Initialize the given domain id list (DYNAMIC_ARRAY) with the
+ space-separated list of numbers from the specified IO_CACHE where
+ the first number is the total number of entries to follows.
+
+ @param f [IN] IO_CACHE file
+ @param type [IN] domain id list type
+
+ @retval false Success
+ true Error
+ */
+ bool init_ids(IO_CACHE *f, enum_list_type type);
+
+ /*
+ Return the elements of the give domain id list type as string.
+
+ @param type [IN] domain id list type
+
+ @retval a string buffer storing the total number
+ of elements followed by the individual
+ elements (space-separated) in the
+ specified list.
+
+ Note: Its caller's responsibility to free the returned string buffer.
+ */
+ char *as_string(enum_list_type type);
+
+};
+
+
+extern TYPELIB slave_parallel_mode_typelib;
+
+typedef struct st_rows_event_tracker
+{
+ char binlog_file_name[FN_REFLEN];
+ my_off_t first_seen;
+ my_off_t last_seen;
+ bool stmt_end_seen;
+ void update(const char *file_name, my_off_t pos,
+ const uchar *buf,
+ const Format_description_log_event *fdle);
+ void reset();
+ bool check_and_report(const char* file_name, my_off_t pos);
+} Rows_event_tracker;
+
+/*****************************************************************************
+ Replication IO Thread
+
+ Master_info contains:
+ - information about how to connect to a master
+ - current master log name
+ - current master log offset
+ - misc control variables
+
+ Master_info is initialized once from the master.info file if such
+ exists. Otherwise, data members corresponding to master.info fields
+ are initialized with defaults specified by master-* options. The
+ initialization is done through init_master_info() call.
+
+ The format of master.info file:
+
+ log_name
+ log_pos
+ master_host
+ master_user
+ master_pass
+ master_port
+ master_connect_retry
+
+ To write out the contents of master.info file to disk ( needed every
+ time we read and queue data from the master ), a call to
+ flush_master_info() is required.
+
+ To clean up, call end_master_info()
+
+*****************************************************************************/
+
+class Master_info : public Slave_reporting_capability
+{
+ public:
+ enum enum_using_gtid {
+ USE_GTID_NO= 0, USE_GTID_CURRENT_POS= 1, USE_GTID_SLAVE_POS= 2
+ };
+
+ Master_info(LEX_CSTRING *connection_name, bool is_slave_recovery);
+ ~Master_info();
+ bool shall_ignore_server_id(ulong s_id);
+ void clear_in_memory_info(bool all);
+ bool error()
+ {
+ /* If malloc() in initialization failed */
+ return connection_name.str == 0;
+ }
+ static const char *using_gtid_astext(enum enum_using_gtid arg);
+ bool using_parallel()
+ {
+ return opt_slave_parallel_threads > 0 &&
+ parallel_mode > SLAVE_PARALLEL_NONE;
+ }
+ void release();
+ void wait_until_free();
+ void lock_slave_threads();
+ void unlock_slave_threads();
+
+ /* the variables below are needed because we can change masters on the fly */
+ char master_log_name[FN_REFLEN+6]; /* Room for multi-*/
+ char host[HOSTNAME_LENGTH*SYSTEM_CHARSET_MBMAXLEN+1];
+ char user[USERNAME_LENGTH+1];
+ char password[MAX_PASSWORD_LENGTH*SYSTEM_CHARSET_MBMAXLEN+1];
+ LEX_CSTRING connection_name; /* User supplied connection name */
+ LEX_CSTRING cmp_connection_name; /* Connection name in lower case */
+ bool ssl; // enables use of SSL connection if true
+ char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN];
+ char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN];
+ char ssl_crl[FN_REFLEN], ssl_crlpath[FN_REFLEN];
+ bool ssl_verify_server_cert;
+
+ my_off_t master_log_pos;
+ File fd; // we keep the file open, so we need to remember the file pointer
+ IO_CACHE file;
+
+ mysql_mutex_t data_lock, run_lock, sleep_lock, start_stop_lock, start_alter_lock, start_alter_list_lock;
+ mysql_cond_t data_cond, start_cond, stop_cond, sleep_cond;
+ THD *io_thd;
+ MYSQL* mysql;
+ uint32 file_id; /* for 3.23 load data infile */
+ Relay_log_info rli;
+ uint port;
+ Rpl_filter* rpl_filter; /* Each replication can set its filter rule*/
+ /*
+ to hold checksum alg in use until IO thread has received FD.
+ Initialized to novalue, then set to the queried from master
+ @@global.binlog_checksum and deactivated once FD has been received.
+ */
+ enum enum_binlog_checksum_alg checksum_alg_before_fd;
+ uint connect_retry;
+#ifndef DBUG_OFF
+ int events_till_disconnect;
+
+ /*
+ The following are auxiliary DBUG variables used to kill IO thread in the
+ middle of a group/transaction (see "kill_slave_io_after_2_events").
+ */
+ bool dbug_do_disconnect;
+ int dbug_event_counter;
+#endif
+ bool inited;
+ volatile bool abort_slave;
+ volatile uint slave_running;
+ volatile ulong slave_run_id;
+ /*
+ The difference in seconds between the clock of the master and the clock of
+ the slave (second - first). It must be signed as it may be <0 or >0.
+ clock_diff_with_master is computed when the I/O thread starts; for this the
+ I/O thread does a SELECT UNIX_TIMESTAMP() on the master.
+ "how late the slave is compared to the master" is computed like this:
+ clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master
+
+ */
+ long clock_diff_with_master;
+ /*
+ Keeps track of the number of events before fsyncing.
+ The option --sync-master-info determines how many
+ events should happen before fsyncing.
+ */
+ uint sync_counter;
+ float heartbeat_period; // interface with CHANGE MASTER or master.info
+ ulonglong received_heartbeats; // counter of received heartbeat events
+ DYNAMIC_ARRAY ignore_server_ids;
+ ulong master_id;
+ /*
+ At reconnect and until the first rotate event is seen, prev_master_id is
+ the value of master_id during the previous connection, used to detect
+ silent change of master server during reconnects.
+ */
+ ulong prev_master_id;
+ /*
+ Which kind of GTID position (if any) is used when connecting to master.
+
+ Note that you can not change the numeric values of these, they are used
+ in master.info.
+ */
+ enum enum_using_gtid using_gtid;
+
+ /*
+ This GTID position records how far we have fetched into the relay logs.
+ This is used to continue fetching when the IO thread reconnects to the
+ master.
+
+ (Full slave stop/start does not use it, as it resets the relay logs).
+ */
+ slave_connection_state gtid_current_pos;
+ /*
+ If events_queued_since_last_gtid is non-zero, it is the number of events
+ queued so far in the relaylog of a GTID-prefixed event group.
+ It is zero when no partial event group has been queued at the moment.
+ */
+ uint64 events_queued_since_last_gtid;
+ /*
+ The GTID of the partially-queued event group, when
+ events_queued_since_last_gtid is non-zero.
+ */
+ rpl_gtid last_queued_gtid;
+ /* Whether last_queued_gtid had the FL_STANDALONE flag set. */
+ bool last_queued_gtid_standalone;
+ /*
+ When slave IO thread needs to reconnect, gtid_reconnect_event_skip_count
+ counts number of events to skip from the first GTID-prefixed event group,
+ to avoid duplicating events in the relay log.
+ */
+ uint64 gtid_reconnect_event_skip_count;
+ /* gtid_event_seen is false until we receive first GTID event from master. */
+ bool gtid_event_seen;
+ /**
+ The struct holds some history of Rows- log-event reading/queuing
+ by the receiver thread. Its fields are updated per each such event
+ at time of queue_event(), and they are checked to detect
+ the Rows- event group integrity violation at time of first non-Rows-
+ event gets handled.
+ */
+ Rows_event_tracker rows_event_tracker;
+ bool in_start_all_slaves, in_stop_all_slaves;
+ bool in_flush_all_relay_logs;
+ uint users; /* Active user for object */
+ uint killed;
+
+
+ /* No of DDL event group */
+ Atomic_counter<uint64> total_ddl_groups;
+
+ /* No of non-transactional event group*/
+ Atomic_counter<uint64> total_non_trans_groups;
+
+ /* No of transactional event group*/
+ Atomic_counter<uint64> total_trans_groups;
+
+ /* domain-id based filter */
+ Domain_id_filter domain_id_filter;
+
+ /* The parallel replication mode. */
+ enum_slave_parallel_mode parallel_mode;
+ /*
+ semi_ack is used to identify if the current binlog event needs an
+ ACK from slave, or if delay_master is enabled.
+ */
+ int semi_ack;
+ /*
+ The flag has replicate_same_server_id semantics and is raised to accept
+ a same-server-id event group by the gtid strict mode semisync slave.
+ Own server-id events can normally appear as result of EITHER
+ A. this server semisync (failover to) slave crash-recovery:
+ the transaction was created on this server then being master,
+ got replicated elsewhere right before the crash before commit,
+ and finally at recovery the transaction gets evicted from the
+ server's binlog and its gtid (slave) state; OR
+ B. in a general circular configuration and then when a recieved (returned
+ to slave) gtid exists in the server's binlog. Then, in gtid strict mode,
+ it must be ignored similarly to the replicate-same-server-id rule.
+ */
+ bool do_accept_own_server_id= false;
+ List <start_alter_info> start_alter_list;
+ MEM_ROOT mem_root;
+ /*
+ Flag is raised at the parallel worker slave stop. Its purpose
+ is to mark the whole start_alter_list when slave stops.
+ The flag is read by Start Alter event to self-mark its state accordingly
+ at time its alter info struct is about to be appened to the list.
+ */
+ bool is_shutdown= false;
+
+ /*
+ A replica will default to Slave_Pos for using Using_Gtid; however, we
+ first need to test if the master supports GTIDs. If not, fall back to 'No'.
+ Cache the value so future RESET SLAVE commands don't revert to Slave_Pos.
+ */
+ bool master_supports_gtid= true;
+
+ /*
+ When TRUE, transition this server from being an active master to a slave.
+ This updates the replication state to account for any transactions which
+ were committed into the binary log. In particular, it merges
+ gtid_binlog_pos into gtid_slave_pos.
+ */
+ bool is_demotion= false;
+};
+
+struct start_alter_thd_args
+{
+ rpl_group_info *rgi;
+ LEX_CSTRING query;
+ LEX_CSTRING *db;
+ char *catalog;
+ bool shutdown;
+ CHARSET_INFO *cs;
+};
+
+int init_master_info(Master_info* mi, const char* master_info_fname,
+ const char* slave_info_fname,
+ bool abort_if_no_master_info_file,
+ int thread_mask);
+void end_master_info(Master_info* mi);
+int flush_master_info(Master_info* mi,
+ bool flush_relay_log_cache,
+ bool need_lock_relay_log);
+void copy_filter_setting(Rpl_filter* dst_filter, Rpl_filter* src_filter);
+void update_change_master_ids(DYNAMIC_ARRAY *new_ids, DYNAMIC_ARRAY *old_ids);
+void prot_store_ids(THD *thd, DYNAMIC_ARRAY *ids);
+
+/*
+ Multi master are handled trough this struct.
+ Changes to this needs to be protected by LOCK_active_mi;
+*/
+
+class Master_info_index
+{
+private:
+ IO_CACHE index_file;
+ char index_file_name[FN_REFLEN];
+
+public:
+ Master_info_index();
+ ~Master_info_index();
+
+ HASH master_info_hash;
+
+ bool init_all_master_info();
+ bool write_master_name_to_index_file(LEX_CSTRING *connection_name,
+ bool do_sync);
+
+ bool check_duplicate_master_info(LEX_CSTRING *connection_name,
+ const char *host, uint port);
+ bool add_master_info(Master_info *mi, bool write_to_file);
+ bool remove_master_info(Master_info *mi, bool clear_log_files);
+ Master_info *get_master_info(const LEX_CSTRING *connection_name,
+ Sql_condition::enum_warning_level warning);
+ bool start_all_slaves(THD *thd);
+ bool stop_all_slaves(THD *thd);
+ void free_connections();
+ bool flush_all_relay_logs();
+};
+
+
+/*
+ The class rpl_io_thread_info is the THD::system_thread_info for the IO thread.
+*/
+class rpl_io_thread_info
+{
+public:
+};
+
+
+Master_info *get_master_info(const LEX_CSTRING *connection_name,
+ Sql_condition::enum_warning_level warning);
+bool check_master_connection_name(LEX_CSTRING *name);
+void create_logfile_name_with_suffix(char *res_file_name, size_t length,
+ const char *info_file,
+ bool append,
+ LEX_CSTRING *suffix);
+
+uchar *get_key_master_info(Master_info *mi, size_t *length,
+ my_bool not_used __attribute__((unused)));
+void free_key_master_info(Master_info *mi);
+uint any_slave_sql_running(bool already_locked);
+bool give_error_if_slave_running(bool already_lock);
+
+#endif /* HAVE_REPLICATION */
+#endif /* RPL_MI_H */