| 1 | /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. |
| 2 | Copyright (c) 2009, 2016, MariaDB |
| 3 | |
| 4 | This program is free software; you can redistribute it and/or modify |
| 5 | it under the terms of the GNU General Public License as published by |
| 6 | the Free Software Foundation; version 2 of the License. |
| 7 | |
| 8 | This program is distributed in the hope that it will be useful, |
| 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 | GNU General Public License for more details. |
| 12 | |
| 13 | You should have received a copy of the GNU General Public License |
| 14 | along with this program; if not, write to the Free Software |
| 15 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
| 16 | |
| 17 | #ifndef SLAVE_H |
| 18 | #define SLAVE_H |
| 19 | |
| 20 | /** |
| 21 | MASTER_DELAY can be at most (1 << 31) - 1. |
| 22 | */ |
| 23 | #define MASTER_DELAY_MAX (0x7FFFFFFF) |
| 24 | #if INT_MAX < 0x7FFFFFFF |
| 25 | #error "don't support platforms where INT_MAX < 0x7FFFFFFF" |
| 26 | #endif |
| 27 | |
| 28 | /** |
| 29 | @defgroup Replication Replication |
| 30 | @{ |
| 31 | |
| 32 | @file |
| 33 | */ |
| 34 | |
| 35 | /** |
| 36 | Some of defines are need in parser even though replication is not |
| 37 | compiled in (embedded). |
| 38 | */ |
| 39 | |
| 40 | /** |
| 41 | The maximum is defined as (ULONG_MAX/1000) with 4 bytes ulong |
| 42 | */ |
| 43 | #define SLAVE_MAX_HEARTBEAT_PERIOD 4294967 |
| 44 | |
| 45 | #ifdef HAVE_REPLICATION |
| 46 | |
| 47 | #include "log.h" |
| 48 | #include "my_list.h" |
| 49 | #include "rpl_filter.h" |
| 50 | #include "rpl_tblmap.h" |
| 51 | #include "rpl_gtid.h" |
| 52 | |
| 53 | #define SLAVE_NET_TIMEOUT 60 |
| 54 | |
| 55 | #define MAX_SLAVE_ERROR ER_ERROR_LAST+1 |
| 56 | |
| 57 | #define MAX_REPLICATION_THREAD 64 |
| 58 | |
| 59 | // Forward declarations |
| 60 | class Relay_log_info; |
| 61 | class Master_info; |
| 62 | class Master_info_index; |
| 63 | struct rpl_group_info; |
| 64 | struct rpl_parallel_thread; |
| 65 | |
| 66 | int init_intvar_from_file(int* var, IO_CACHE* f, int default_val); |
| 67 | int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, |
| 68 | const char *default_val); |
| 69 | int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val); |
| 70 | int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f); |
| 71 | |
| 72 | /***************************************************************************** |
| 73 | |
| 74 | MySQL Replication |
| 75 | |
| 76 | Replication is implemented via two types of threads: |
| 77 | |
| 78 | I/O Thread - One of these threads is started for each master server. |
| 79 | They maintain a connection to their master server, read log |
| 80 | events from the master as they arrive, and queues them into |
| 81 | a single, shared relay log file. A Master_info |
| 82 | represents each of these threads. |
| 83 | |
| 84 | SQL Thread - One of these threads is started and reads from the relay log |
| 85 | file, executing each event. A Relay_log_info |
| 86 | represents this thread. |
| 87 | |
| 88 | Buffering in the relay log file makes it unnecessary to reread events from |
| 89 | a master server across a slave restart. It also decouples the slave from |
| 90 | the master where long-running updates and event logging are concerned--ie |
| 91 | it can continue to log new events while a slow query executes on the slave. |
| 92 | |
| 93 | *****************************************************************************/ |
| 94 | |
| 95 | /* |
| 96 | MUTEXES in replication: |
| 97 | |
| 98 | LOCK_active_mi: [note: this was originally meant for multimaster, to switch |
| 99 | from a master to another, to protect active_mi] It is used to SERIALIZE ALL |
| 100 | administrative commands of replication: START SLAVE, STOP SLAVE, CHANGE |
| 101 | MASTER, RESET SLAVE, end_slave() (when mysqld stops) [init_slave() does not |
| 102 | need it it's called early]. Any of these commands holds the mutex from the |
| 103 | start till the end. This thus protects us against a handful of deadlocks |
| 104 | (consider start_slave_thread() which, when starting the I/O thread, releases |
| 105 | mi->run_lock, keeps rli->run_lock, and tries to re-acquire mi->run_lock). |
| 106 | |
| 107 | Currently active_mi never moves (it's created at startup and deleted at |
| 108 | shutdown, and not changed: it always points to the same Master_info struct), |
| 109 | because we don't have multimaster. So for the moment, mi does not move, and |
| 110 | mi->rli does not either. |
| 111 | |
| 112 | In Master_info: run_lock, data_lock |
| 113 | run_lock protects all information about the run state: slave_running, thd |
| 114 | and the existence of the I/O thread (to stop/start it, you need this mutex). |
| 115 | data_lock protects some moving members of the struct: counters (log name, |
| 116 | position) and relay log (MYSQL_BIN_LOG object). |
| 117 | |
| 118 | In Relay_log_info: run_lock, data_lock |
| 119 | see Master_info |
| 120 | However, note that run_lock does not protect |
| 121 | Relay_log_info.run_state; that is protected by data_lock. |
| 122 | |
| 123 | Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you |
| 124 | must acquire LOCK_active_mi first. |
| 125 | |
| 126 | In MYSQL_BIN_LOG: LOCK_log, LOCK_index of the binlog and the relay log |
| 127 | LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog |
| 128 | (so that you have to update the .index file). |
| 129 | */ |
| 130 | |
| 131 | extern ulong master_retry_count; |
| 132 | extern MY_BITMAP slave_error_mask; |
| 133 | extern char slave_skip_error_names[]; |
| 134 | extern bool use_slave_mask; |
| 135 | extern char slave_transaction_retry_error_names[]; |
| 136 | extern uint *slave_transaction_retry_errors; |
| 137 | extern uint slave_transaction_retry_error_length; |
| 138 | extern char *slave_load_tmpdir; |
| 139 | extern char *master_info_file; |
| 140 | extern MYSQL_PLUGIN_IMPORT char *relay_log_info_file; |
| 141 | extern char *opt_relay_logname, *opt_relaylog_index_name; |
| 142 | extern my_bool opt_skip_slave_start, opt_reckless_slave; |
| 143 | extern my_bool opt_log_slave_updates; |
| 144 | extern char *opt_slave_skip_errors; |
| 145 | extern char *opt_slave_transaction_retry_errors; |
| 146 | extern my_bool opt_replicate_annotate_row_events; |
| 147 | extern ulonglong relay_log_space_limit; |
| 148 | extern ulonglong opt_read_binlog_speed_limit; |
| 149 | extern ulonglong slave_skipped_errors; |
| 150 | extern const char *relay_log_index; |
| 151 | extern const char *relay_log_basename; |
| 152 | |
| 153 | /* |
| 154 | 4 possible values for Master_info::slave_running and |
| 155 | Relay_log_info::slave_running. |
| 156 | The values 0,1,2,3 are very important: to keep the diff small, I didn't |
| 157 | substitute places where we use 0/1 with the newly defined symbols. |
| 158 | So don't change these values. |
| 159 | The same way, code is assuming that in Relay_log_info we use only values |
| 160 | 0/1. |
| 161 | I started with using an enum, but |
| 162 | enum_variable=1; is not legal so would have required many line changes. |
| 163 | */ |
| 164 | #define MYSQL_SLAVE_NOT_RUN 0 |
| 165 | #define MYSQL_SLAVE_RUN_NOT_CONNECT 1 |
| 166 | #define MYSQL_SLAVE_RUN_CONNECT 2 |
| 167 | #define MYSQL_SLAVE_RUN_READING 3 |
| 168 | |
| 169 | #define RPL_LOG_NAME (rli->group_master_log_name[0] ? rli->group_master_log_name :\ |
| 170 | "FIRST") |
| 171 | #define IO_RPL_LOG_NAME (mi->master_log_name[0] ? mi->master_log_name :\ |
| 172 | "FIRST") |
| 173 | |
| 174 | /* |
| 175 | If the following is set, if first gives an error, second will be |
| 176 | tried. Otherwise, if first fails, we fail. |
| 177 | */ |
| 178 | #define SLAVE_FORCE_ALL 4 |
| 179 | |
| 180 | /* |
| 181 | Values for the option --replicate-events-marked-for-skip. |
| 182 | Must match the names in replicate_events_marked_for_skip_names in sys_vars.cc |
| 183 | */ |
| 184 | #define RPL_SKIP_REPLICATE 0 |
| 185 | #define RPL_SKIP_FILTER_ON_SLAVE 1 |
| 186 | #define RPL_SKIP_FILTER_ON_MASTER 2 |
| 187 | |
| 188 | |
| 189 | int init_slave(); |
| 190 | int init_recovery(Master_info* mi, const char** errmsg); |
| 191 | bool init_slave_skip_errors(const char* arg); |
| 192 | bool init_slave_transaction_retry_errors(const char* arg); |
| 193 | int register_slave_on_master(MYSQL* mysql); |
| 194 | int terminate_slave_threads(Master_info* mi, int thread_mask, |
| 195 | bool skip_lock = 0); |
| 196 | int start_slave_threads(THD *thd, |
| 197 | bool need_slave_mutex, bool wait_for_start, |
| 198 | Master_info* mi, const char* master_info_fname, |
| 199 | const char* slave_info_fname, int thread_mask); |
| 200 | /* |
| 201 | cond_lock is usually same as start_lock. It is needed for the case when |
| 202 | start_lock is 0 which happens if start_slave_thread() is called already |
| 203 | inside the start_lock section, but at the same time we want a |
| 204 | mysql_cond_wait() on start_cond, start_lock |
| 205 | */ |
| 206 | int start_slave_thread( |
| 207 | #ifdef HAVE_PSI_INTERFACE |
| 208 | PSI_thread_key thread_key, |
| 209 | #endif |
| 210 | pthread_handler h_func, |
| 211 | mysql_mutex_t *start_lock, |
| 212 | mysql_mutex_t *cond_lock, |
| 213 | mysql_cond_t *start_cond, |
| 214 | volatile uint *slave_running, |
| 215 | volatile ulong *slave_run_id, |
| 216 | Master_info *mi); |
| 217 | |
| 218 | /* If fd is -1, dump to NET */ |
| 219 | int mysql_table_dump(THD* thd, const char* db, |
| 220 | const char* tbl_name, int fd = -1); |
| 221 | |
| 222 | /* retrieve table from master and copy to slave*/ |
| 223 | int fetch_master_table(THD* thd, const char* db_name, const char* table_name, |
| 224 | Master_info* mi, MYSQL* mysql, bool overwrite); |
| 225 | |
| 226 | void show_master_info_get_fields(THD *thd, List<Item> *field_list, |
| 227 | bool full, size_t gtid_pos_length); |
| 228 | bool show_master_info(THD* thd, Master_info* mi, bool full); |
| 229 | bool show_all_master_info(THD* thd); |
| 230 | void show_binlog_info_get_fields(THD *thd, List<Item> *field_list); |
| 231 | bool show_binlog_info(THD* thd); |
| 232 | bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report, |
| 233 | bool (*pred)(const void *), const void *param); |
| 234 | bool rpl_master_erroneous_autoinc(THD* thd); |
| 235 | |
| 236 | const char *print_slave_db_safe(const char *db); |
| 237 | void skip_load_data_infile(NET* net); |
| 238 | |
| 239 | void slave_prepare_for_shutdown(); |
| 240 | void end_slave(); /* release slave threads */ |
| 241 | void close_active_mi(); /* clean up slave threads data */ |
| 242 | void clear_until_condition(Relay_log_info* rli); |
| 243 | void clear_slave_error(Relay_log_info* rli); |
| 244 | void end_relay_log_info(Relay_log_info* rli); |
| 245 | void init_thread_mask(int* mask,Master_info* mi,bool inverse); |
| 246 | Format_description_log_event * |
| 247 | read_relay_log_description_event(IO_CACHE *cur_log, ulonglong start_pos, |
| 248 | const char **errmsg); |
| 249 | |
| 250 | int init_relay_log_pos(Relay_log_info* rli,const char* log,ulonglong pos, |
| 251 | bool need_data_lock, const char** errmsg, |
| 252 | bool look_for_description_event); |
| 253 | |
| 254 | int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, |
| 255 | const char** errmsg); |
| 256 | void set_slave_thread_options(THD* thd); |
| 257 | void set_slave_thread_default_charset(THD *thd, rpl_group_info *rgi); |
| 258 | int rotate_relay_log(Master_info* mi); |
| 259 | int has_temporary_error(THD *thd); |
| 260 | int sql_delay_event(Log_event *ev, THD *thd, rpl_group_info *rgi); |
| 261 | int apply_event_and_update_pos(Log_event* ev, THD* thd, |
| 262 | struct rpl_group_info *rgi); |
| 263 | int apply_event_and_update_pos_for_parallel(Log_event* ev, THD* thd, |
| 264 | struct rpl_group_info *rgi); |
| 265 | |
| 266 | int init_intvar_from_file(int* var, IO_CACHE* f, int default_val); |
| 267 | int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val); |
| 268 | int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, |
| 269 | const char *default_val); |
| 270 | int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f); |
| 271 | |
| 272 | pthread_handler_t handle_slave_io(void *arg); |
| 273 | void slave_output_error_info(rpl_group_info *rgi, THD *thd); |
| 274 | pthread_handler_t handle_slave_sql(void *arg); |
| 275 | bool net_request_file(NET* net, const char* fname); |
| 276 | void slave_background_kill_request(THD *to_kill); |
| 277 | void slave_background_gtid_pos_create_request |
| 278 | (rpl_slave_state::gtid_pos_table *table_entry); |
| 279 | |
| 280 | extern bool volatile abort_loop; |
| 281 | extern Master_info *active_mi; /* active_mi for multi-master */ |
| 282 | extern Master_info *default_master_info; /* To replace active_mi */ |
| 283 | extern Master_info_index *master_info_index; |
| 284 | extern LEX_CSTRING default_master_connection_name; |
| 285 | extern my_bool replicate_same_server_id; |
| 286 | |
| 287 | extern int disconnect_slave_event_count, abort_slave_event_count ; |
| 288 | |
| 289 | /* the master variables are defaults read from my.cnf or command line */ |
| 290 | extern uint report_port; |
| 291 | extern char *master_info_file, *report_user; |
| 292 | extern char *report_host, *report_password; |
| 293 | |
| 294 | extern I_List<THD> threads; |
| 295 | |
| 296 | #else |
| 297 | #define close_active_mi() /* no-op */ |
| 298 | #endif /* HAVE_REPLICATION */ |
| 299 | |
| 300 | /* masks for start/stop operations on io and sql slave threads */ |
| 301 | #define SLAVE_IO 1 |
| 302 | #define SLAVE_SQL 2 |
| 303 | |
| 304 | /** |
| 305 | @} (end of group Replication) |
| 306 | */ |
| 307 | |
| 308 | #endif |
| 309 | |