1 /* Copyright (c) 2006, 2012, Oracle and/or its affiliates.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; version 2 of the License.
6 
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11 
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA */
15 
16 #ifndef RPL_MI_H
17 #define RPL_MI_H
18 
19 #ifdef HAVE_REPLICATION
20 
21 #include "rpl_rli.h"
22 #include "rpl_reporting.h"
23 #include <my_sys.h>
24 #include "rpl_filter.h"
25 #include "keycaches.h"
26 
27 typedef struct st_mysql MYSQL;
28 
29 /**
30   Domain id based filter to handle DO_DOMAIN_IDS and IGNORE_DOMAIN_IDS used to
31   set filtering on replication slave based on event's GTID domain_id.
32 */
33 class Domain_id_filter
34 {
35 private:
36   /*
37     Flag to tell whether the events in the current GTID group get written to
38     the relay log. It is set according to the domain_id based filtering rule
39     on every GTID_EVENT and reset at the end of current GTID event group.
40    */
41   bool m_filter;
42 
43   /*
44     DO_DOMAIN_IDS (0):
45       Ignore all the events which do not belong to any of the domain ids in the
46       list.
47 
48     IGNORE_DOMAIN_IDS (1):
49       Ignore the events which belong to one of the domain ids in the list.
50   */
51   DYNAMIC_ARRAY m_domain_ids[2];
52 
53 public:
54   /* domain id list types */
55   enum enum_list_type {
56     DO_DOMAIN_IDS= 0,
57     IGNORE_DOMAIN_IDS
58   };
59 
60   Domain_id_filter();
61 
62   ~Domain_id_filter();
63 
64   /*
65     Returns whether the current group needs to be filtered.
66   */
is_group_filtered()67   bool is_group_filtered() { return m_filter; }
68 
69   /*
70     Checks whether the group with the specified domain_id needs to be
71     filtered and updates m_filter flag accordingly.
72   */
73   void do_filter(ulong domain_id);
74 
75   /*
76     Reset m_filter. It should be called when IO thread receives COMMIT_EVENT or
77     XID_EVENT.
78   */
79   void reset_filter();
80 
81   /*
82     Clear do_ids and ignore_ids to disable domain id filtering
83   */
84   void clear_ids();
85 
86   /*
87     Update the do/ignore domain id filter lists.
88 
89     @param do_ids     [IN]            domain ids to be kept
90     @param ignore_ids [IN]            domain ids to be filtered out
91     @param using_gtid [IN]            use GTID?
92 
93     @retval false                     Success
94             true                      Error
95   */
96   bool update_ids(DYNAMIC_ARRAY *do_ids, DYNAMIC_ARRAY *ignore_ids,
97                   bool using_gtid);
98 
99   /*
100     Serialize and store the ids from domain id lists into the thd's protocol
101     buffer.
102 
103     @param thd [IN]                   thread handler
104 
105     @retval void
106   */
107   void store_ids(THD *thd);
108 
109   /*
110     Initialize the given domain id list (DYNAMIC_ARRAY) with the
111     space-separated list of numbers from the specified IO_CACHE where
112     the first number is the total number of entries to follows.
113 
114     @param f    [IN]                  IO_CACHE file
115     @param type [IN]                  domain id list type
116 
117     @retval false                     Success
118             true                      Error
119   */
120   bool init_ids(IO_CACHE *f, enum_list_type type);
121 
122   /*
123     Return the elements of the give domain id list type as string.
124 
125     @param type [IN]                  domain id list type
126 
127     @retval                           a string buffer storing the total number
128                                       of elements followed by the individual
129                                       elements (space-separated) in the
130                                       specified list.
131 
132     Note: Its caller's responsibility to free the returned string buffer.
133   */
134   char *as_string(enum_list_type type);
135 
136 };
137 
138 
139 extern TYPELIB slave_parallel_mode_typelib;
140 
141 typedef struct st_rows_event_tracker
142 {
143   char binlog_file_name[FN_REFLEN];
144   my_off_t first_seen;
145   my_off_t last_seen;
146   bool stmt_end_seen;
147   void update(const char* file_name, my_off_t pos,
148               const char* buf,
149               const Format_description_log_event *fdle);
150   void reset();
151   bool check_and_report(const char* file_name, my_off_t pos);
152 } Rows_event_tracker;
153 
154 /*****************************************************************************
155   Replication IO Thread
156 
157   Master_info contains:
158     - information about how to connect to a master
159     - current master log name
160     - current master log offset
161     - misc control variables
162 
163   Master_info is initialized once from the master.info file if such
164   exists. Otherwise, data members corresponding to master.info fields
165   are initialized with defaults specified by master-* options. The
166   initialization is done through init_master_info() call.
167 
168   The format of master.info file:
169 
170   log_name
171   log_pos
172   master_host
173   master_user
174   master_pass
175   master_port
176   master_connect_retry
177 
178   To write out the contents of master.info file to disk ( needed every
179   time we read and queue data from the master ), a call to
180   flush_master_info() is required.
181 
182   To clean up, call end_master_info()
183 
184 *****************************************************************************/
185 
186 class Master_info : public Slave_reporting_capability
187 {
188  public:
189   enum enum_using_gtid {
190     USE_GTID_NO= 0, USE_GTID_CURRENT_POS= 1, USE_GTID_SLAVE_POS= 2
191   };
192 
193   Master_info(LEX_CSTRING *connection_name, bool is_slave_recovery);
194   ~Master_info();
195   bool shall_ignore_server_id(ulong s_id);
196   void clear_in_memory_info(bool all);
error()197   bool error()
198   {
199     /* If malloc() in initialization failed */
200     return connection_name.str == 0;
201   }
202   static const char *using_gtid_astext(enum enum_using_gtid arg);
using_parallel()203   bool using_parallel()
204   {
205     return opt_slave_parallel_threads > 0 &&
206       parallel_mode > SLAVE_PARALLEL_NONE;
207   }
208   void release();
209   void wait_until_free();
210   void lock_slave_threads();
211   void unlock_slave_threads();
212 
213   /* the variables below are needed because we can change masters on the fly */
214   char master_log_name[FN_REFLEN+6]; /* Room for multi-*/
215   char host[HOSTNAME_LENGTH*SYSTEM_CHARSET_MBMAXLEN+1];
216   char user[USERNAME_LENGTH+1];
217   char password[MAX_PASSWORD_LENGTH*SYSTEM_CHARSET_MBMAXLEN+1];
218   LEX_CSTRING connection_name; 		/* User supplied connection name */
219   LEX_CSTRING cmp_connection_name;	/* Connection name in lower case */
220   bool ssl; // enables use of SSL connection if true
221   char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN];
222   char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN];
223   char ssl_crl[FN_REFLEN], ssl_crlpath[FN_REFLEN];
224   bool ssl_verify_server_cert;
225 
226   my_off_t master_log_pos;
227   File fd; // we keep the file open, so we need to remember the file pointer
228   IO_CACHE file;
229 
230   mysql_mutex_t data_lock, run_lock, sleep_lock, start_stop_lock;
231   mysql_cond_t data_cond, start_cond, stop_cond, sleep_cond;
232   THD *io_thd;
233   MYSQL* mysql;
234   uint32 file_id;				/* for 3.23 load data infile */
235   Relay_log_info rli;
236   uint port;
237   Rpl_filter* rpl_filter;      /* Each replication can set its filter rule*/
238   /*
239     to hold checksum alg in use until IO thread has received FD.
240     Initialized to novalue, then set to the queried from master
241     @@global.binlog_checksum and deactivated once FD has been received.
242   */
243   enum enum_binlog_checksum_alg checksum_alg_before_fd;
244   uint connect_retry;
245 #ifndef DBUG_OFF
246   int events_till_disconnect;
247 
248   /*
249     The following are auxiliary DBUG variables used to kill IO thread in the
250     middle of a group/transaction (see "kill_slave_io_after_2_events").
251   */
252   bool dbug_do_disconnect;
253   int dbug_event_counter;
254 #endif
255   bool inited;
256   volatile bool abort_slave;
257   volatile uint slave_running;
258   volatile ulong slave_run_id;
259   /*
260      The difference in seconds between the clock of the master and the clock of
261      the slave (second - first). It must be signed as it may be <0 or >0.
262      clock_diff_with_master is computed when the I/O thread starts; for this the
263      I/O thread does a SELECT UNIX_TIMESTAMP() on the master.
264      "how late the slave is compared to the master" is computed like this:
265      clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master
266 
267   */
268   long clock_diff_with_master;
269   /*
270     Keeps track of the number of events before fsyncing.
271     The option --sync-master-info determines how many
272     events should happen before fsyncing.
273   */
274   uint sync_counter;
275   float heartbeat_period;         // interface with CHANGE MASTER or master.info
276   ulonglong received_heartbeats;  // counter of received heartbeat events
277   DYNAMIC_ARRAY ignore_server_ids;
278   ulong master_id;
279   /*
280     At reconnect and until the first rotate event is seen, prev_master_id is
281     the value of master_id during the previous connection, used to detect
282     silent change of master server during reconnects.
283   */
284   ulong prev_master_id;
285   /*
286     Which kind of GTID position (if any) is used when connecting to master.
287 
288     Note that you can not change the numeric values of these, they are used
289     in master.info.
290   */
291   enum enum_using_gtid using_gtid;
292 
293   /*
294     This GTID position records how far we have fetched into the relay logs.
295     This is used to continue fetching when the IO thread reconnects to the
296     master.
297 
298     (Full slave stop/start does not use it, as it resets the relay logs).
299   */
300   slave_connection_state gtid_current_pos;
301   /*
302     If events_queued_since_last_gtid is non-zero, it is the number of events
303     queued so far in the relaylog of a GTID-prefixed event group.
304     It is zero when no partial event group has been queued at the moment.
305   */
306   uint64 events_queued_since_last_gtid;
307   /*
308     The GTID of the partially-queued event group, when
309     events_queued_since_last_gtid is non-zero.
310   */
311   rpl_gtid last_queued_gtid;
312   /* Whether last_queued_gtid had the FL_STANDALONE flag set. */
313   bool last_queued_gtid_standalone;
314   /*
315     When slave IO thread needs to reconnect, gtid_reconnect_event_skip_count
316     counts number of events to skip from the first GTID-prefixed event group,
317     to avoid duplicating events in the relay log.
318   */
319   uint64 gtid_reconnect_event_skip_count;
320   /* gtid_event_seen is false until we receive first GTID event from master. */
321   bool gtid_event_seen;
322   /**
323     The struct holds some history of Rows- log-event reading/queuing
324     by the receiver thread. Its fields are updated per each such event
325     at time of queue_event(), and they are checked to detect
326     the Rows- event group integrity violation at time of first non-Rows-
327     event gets handled.
328   */
329   Rows_event_tracker rows_event_tracker;
330   bool in_start_all_slaves, in_stop_all_slaves;
331   bool in_flush_all_relay_logs;
332   uint users;                                   /* Active user for object */
333   uint killed;
334 
335 
336   /* No of DDL event group */
337   volatile uint64 total_ddl_groups;
338 
339   /* No of non-transactional event group*/
340   volatile uint64 total_non_trans_groups;
341 
342   /* No of transactional event group*/
343   volatile uint64 total_trans_groups;
344 
345   /* domain-id based filter */
346   Domain_id_filter domain_id_filter;
347 
348   /* The parallel replication mode. */
349   enum_slave_parallel_mode parallel_mode;
350   /*
351     semi_ack is used to identify if the current binlog event needs an
352     ACK from slave, or if delay_master is enabled.
353   */
354   int semi_ack;
355 };
356 
357 int init_master_info(Master_info* mi, const char* master_info_fname,
358 		     const char* slave_info_fname,
359 		     bool abort_if_no_master_info_file,
360 		     int thread_mask);
361 void end_master_info(Master_info* mi);
362 int flush_master_info(Master_info* mi,
363                       bool flush_relay_log_cache,
364                       bool need_lock_relay_log);
365 void copy_filter_setting(Rpl_filter* dst_filter, Rpl_filter* src_filter);
366 void update_change_master_ids(DYNAMIC_ARRAY *new_ids, DYNAMIC_ARRAY *old_ids);
367 void prot_store_ids(THD *thd, DYNAMIC_ARRAY *ids);
368 
369 /*
370   Multi master are handled trough this struct.
371   Changes to this needs to be protected by LOCK_active_mi;
372 */
373 
374 class Master_info_index
375 {
376 private:
377   IO_CACHE index_file;
378   char index_file_name[FN_REFLEN];
379 
380 public:
381   Master_info_index();
382   ~Master_info_index();
383 
384   HASH master_info_hash;
385 
386   bool init_all_master_info();
387   bool write_master_name_to_index_file(LEX_CSTRING *connection_name,
388                                        bool do_sync);
389 
390   bool check_duplicate_master_info(LEX_CSTRING *connection_name,
391                                    const char *host, uint port);
392   bool add_master_info(Master_info *mi, bool write_to_file);
393   bool remove_master_info(Master_info *mi);
394   Master_info *get_master_info(const LEX_CSTRING *connection_name,
395                                Sql_condition::enum_warning_level warning);
396   bool start_all_slaves(THD *thd);
397   bool stop_all_slaves(THD *thd);
398   void free_connections();
399   bool flush_all_relay_logs();
400 };
401 
402 
403 /*
404   The class rpl_io_thread_info is the THD::system_thread_info for the IO thread.
405 */
406 class rpl_io_thread_info
407 {
408 public:
409 };
410 
411 
412 Master_info *get_master_info(const LEX_CSTRING *connection_name,
413                              Sql_condition::enum_warning_level warning);
414 bool check_master_connection_name(LEX_CSTRING *name);
415 void create_logfile_name_with_suffix(char *res_file_name, size_t length,
416                              const char *info_file,
417                              bool append,
418                              LEX_CSTRING *suffix);
419 
420 uchar *get_key_master_info(Master_info *mi, size_t *length,
421                            my_bool not_used __attribute__((unused)));
422 void free_key_master_info(Master_info *mi);
423 uint any_slave_sql_running(bool already_locked);
424 bool give_error_if_slave_running(bool already_lock);
425 
426 #endif /* HAVE_REPLICATION */
427 #endif /* RPL_MI_H */
428