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