diff options
Diffstat (limited to 'sql/slave.cc')
-rw-r--r-- | sql/slave.cc | 401 |
1 files changed, 21 insertions, 380 deletions
diff --git a/sql/slave.cc b/sql/slave.cc index 5c8db6f2c56..86180af8aed 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -160,7 +160,6 @@ failed read" typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE; static int process_io_rotate(Master_info* mi, Rotate_log_event* rev); -static int process_io_create_file(Master_info* mi, Create_file_log_event* cev); static bool wait_for_relay_log_space(Relay_log_info* rli); static bool io_slave_killed(Master_info* mi); static bool sql_slave_killed(rpl_group_info *rgi); @@ -1487,20 +1486,6 @@ bool net_request_file(NET* net, const char* fname) (uchar*) "", 0)); } -/* - From other comments and tests in code, it looks like - sometimes Query_log_event and Load_log_event can have db == 0 - (see rewrite_db() above for example) - (cases where this happens are unclear; it may be when the master is 3.23). -*/ - -const char *print_slave_db_safe(const char* db) -{ - DBUG_ENTER("*print_slave_db_safe"); - - DBUG_RETURN((db ? db : "")); -} - #endif /* HAVE_REPLICATION */ bool Sql_cmd_show_slave_status::execute(THD *thd) @@ -1785,6 +1770,8 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) case 0: case 1: case 2: + case 3: + case 4: errmsg= err_buff2; snprintf(err_buff2, sizeof(err_buff2), "Master reported unrecognized MariaDB version: %s", @@ -1792,14 +1779,6 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) err_code= ER_SLAVE_FATAL_ERROR; sprintf(err_buff, ER_DEFAULT(err_code), err_buff2); break; - case 3: - mi->rli.relay_log.description_event_for_queue= new - Format_description_log_event(1, mysql->server_version); - break; - case 4: - mi->rli.relay_log.description_event_for_queue= new - Format_description_log_event(3, mysql->server_version); - break; default: /* Master is MySQL >=5.0. Give a default Format_desc event, so that we can @@ -4877,28 +4856,25 @@ connected: goto connected; } - if (mi->rli.relay_log.description_event_for_queue->binlog_version > 1) + /* + Register ourselves with the master. + */ + THD_STAGE_INFO(thd, stage_registering_slave_on_master); + if (register_slave_on_master(mysql, mi, &suppress_warnings)) { - /* - Register ourselves with the master. - */ - THD_STAGE_INFO(thd, stage_registering_slave_on_master); - if (register_slave_on_master(mysql, mi, &suppress_warnings)) + if (!check_io_slave_killed(mi, "Slave I/O thread killed " + "while registering slave on master")) { - if (!check_io_slave_killed(mi, "Slave I/O thread killed " - "while registering slave on master")) - { - sql_print_error("Slave I/O thread couldn't register on master"); - if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings, - reconnect_messages[SLAVE_RECON_ACT_REG])) - goto err; - } - else + sql_print_error("Slave I/O thread couldn't register on master"); + if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings, + reconnect_messages[SLAVE_RECON_ACT_REG])) goto err; - goto connected; } - DBUG_EXECUTE_IF("fail_com_register_slave", goto err;); + else + goto err; + goto connected; } + DBUG_EXECUTE_IF("fail_com_register_slave", goto err;); DBUG_PRINT("info",("Starting reading binary log from master")); thd->set_command(COM_SLAVE_IO); @@ -5874,115 +5850,6 @@ err_during_init: /* - process_io_create_file() -*/ - -static int process_io_create_file(Master_info* mi, Create_file_log_event* cev) -{ - int error = 1; - ulong num_bytes; - bool cev_not_written; - THD *thd = mi->io_thd; - NET *net = &mi->mysql->net; - DBUG_ENTER("process_io_create_file"); - - if (unlikely(!cev->is_valid())) - DBUG_RETURN(1); - - if (!mi->rpl_filter->db_ok(cev->db)) - { - skip_load_data_infile(net); - DBUG_RETURN(0); - } - DBUG_ASSERT(cev->inited_from_old); - thd->file_id = cev->file_id = mi->file_id++; - thd->variables.server_id = cev->server_id; - cev_not_written = 1; - - if (unlikely(net_request_file(net,cev->fname))) - { - sql_print_error("Slave I/O: failed requesting download of '%s'", - cev->fname); - goto err; - } - - /* - This dummy block is so we could instantiate Append_block_log_event - once and then modify it slightly instead of doing it multiple times - in the loop - */ - { - Append_block_log_event aev(thd,0,0,0,0); - - for (;;) - { - if (unlikely((num_bytes=my_net_read(net)) == packet_error)) - { - sql_print_error("Network read error downloading '%s' from master", - cev->fname); - goto err; - } - if (unlikely(!num_bytes)) /* eof */ - { - /* 3.23 master wants it */ - net_write_command(net, 0, (uchar*) "", 0, (uchar*) "", 0); - /* - If we wrote Create_file_log_event, then we need to write - Execute_load_log_event. If we did not write Create_file_log_event, - then this is an empty file and we can just do as if the LOAD DATA - INFILE had not existed, i.e. write nothing. - */ - if (unlikely(cev_not_written)) - break; - Execute_load_log_event xev(thd,0,0); - xev.log_pos = cev->log_pos; - if (unlikely(mi->rli.relay_log.append(&xev))) - { - mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, NULL, - ER_THD(thd, ER_SLAVE_RELAY_LOG_WRITE_FAILURE), - "error writing Exec_load event to relay log"); - goto err; - } - mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total); - break; - } - if (unlikely(cev_not_written)) - { - cev->block = net->read_pos; - cev->block_len = num_bytes; - if (unlikely(mi->rli.relay_log.append(cev))) - { - mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, NULL, - ER_THD(thd, ER_SLAVE_RELAY_LOG_WRITE_FAILURE), - "error writing Create_file event to relay log"); - goto err; - } - cev_not_written=0; - mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total); - } - else - { - aev.block = net->read_pos; - aev.block_len = num_bytes; - aev.log_pos = cev->log_pos; - if (unlikely(mi->rli.relay_log.append(&aev))) - { - mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, NULL, - ER_THD(thd, ER_SLAVE_RELAY_LOG_WRITE_FAILURE), - "error writing Append_block event to relay log"); - goto err; - } - mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total) ; - } - } - } - error=0; -err: - DBUG_RETURN(error); -} - - -/* Start using a new binary log on the master SYNOPSIS @@ -6026,25 +5893,10 @@ static int process_io_rotate(Master_info *mi, Rotate_log_event *rev) mi->events_till_disconnect++; #endif - /* - If description_event_for_queue is format <4, there is conversion in the - relay log to the slave's format (4). And Rotate can mean upgrade or - nothing. If upgrade, it's to 5.0 or newer, so we will get a Format_desc, so - no need to reset description_event_for_queue now. And if it's nothing (same - master version as before), no need (still using the slave's format). - */ + /* this prevents a redundant FDLE in the relay log */ if (mi->rli.relay_log.description_event_for_queue->binlog_version >= 4) - { - DBUG_ASSERT(mi->rli.relay_log.description_event_for_queue->checksum_alg == - mi->rli.relay_log.relay_log_checksum_alg); - - delete mi->rli.relay_log.description_event_for_queue; - /* start from format 3 (MySQL 4.0) again */ - mi->rli.relay_log.description_event_for_queue= new - Format_description_log_event(3); - mi->rli.relay_log.description_event_for_queue->checksum_alg= - mi->rli.relay_log.relay_log_checksum_alg; - } + mi->rli.relay_log.description_event_for_queue->binlog_version= 3; + /* Rotate the relay log makes binlog format detection easier (at next slave start or mysqlbinlog) @@ -6053,216 +5905,9 @@ static int process_io_rotate(Master_info *mi, Rotate_log_event *rev) } /* - Reads a 3.23 event and converts it to the slave's format. This code was - copied from MySQL 4.0. -*/ -static int queue_binlog_ver_1_event(Master_info *mi, const uchar *buf, - ulong event_len) -{ - const char *errmsg = 0; - ulong inc_pos; - bool ignore_event= 0; - uchar *tmp_buf = 0; - Relay_log_info *rli= &mi->rli; - DBUG_ENTER("queue_binlog_ver_1_event"); - - /* - If we get Load event, we need to pass a non-reusable buffer - to read_log_event, so we do a trick - */ - if ((uchar)buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) - { - if (unlikely(!(tmp_buf= (uchar*) my_malloc(key_memory_binlog_ver_1_event, - event_len+1, MYF(MY_WME))))) - { - mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, NULL, - ER(ER_SLAVE_FATAL_ERROR), "Memory allocation failed"); - DBUG_RETURN(1); - } - memcpy(tmp_buf,buf,event_len); - /* - Create_file constructor wants a 0 as last char of buffer, this 0 will - serve as the string-termination char for the file's name (which is at the - end of the buffer) - We must increment event_len, otherwise the event constructor will not see - this end 0, which leads to segfault. - */ - tmp_buf[event_len++]=0; - int4store(tmp_buf+EVENT_LEN_OFFSET, event_len); - buf= tmp_buf; - } - /* - This will transform LOAD_EVENT into CREATE_FILE_EVENT, ask the master to - send the loaded file, and write it to the relay log in the form of - Append_block/Exec_load (the SQL thread needs the data, as that thread is not - connected to the master). - */ - Log_event *ev= - Log_event::read_log_event(buf, event_len, &errmsg, - mi->rli.relay_log.description_event_for_queue, 0); - if (unlikely(!ev)) - { - sql_print_error("Read invalid event from master: '%s',\ - master could be corrupt but a more likely cause of this is a bug", - errmsg); - my_free(tmp_buf); - DBUG_RETURN(1); - } - - mysql_mutex_lock(&mi->data_lock); - ev->log_pos= mi->master_log_pos; /* 3.23 events don't contain log_pos */ - switch (ev->get_type_code()) { - case STOP_EVENT: - ignore_event= 1; - inc_pos= event_len; - break; - case ROTATE_EVENT: - if (unlikely(process_io_rotate(mi,(Rotate_log_event*)ev))) - { - delete ev; - mysql_mutex_unlock(&mi->data_lock); - DBUG_RETURN(1); - } - inc_pos= 0; - break; - case CREATE_FILE_EVENT: - /* - Yes it's possible to have CREATE_FILE_EVENT here, even if we're in - queue_old_event() which is for 3.23 events which don't comprise - CREATE_FILE_EVENT. This is because read_log_event() above has just - transformed LOAD_EVENT into CREATE_FILE_EVENT. - */ - { - /* We come here when and only when tmp_buf != 0 */ - DBUG_ASSERT(tmp_buf != 0); - inc_pos=event_len; - ev->log_pos+= inc_pos; - int error = process_io_create_file(mi,(Create_file_log_event*)ev); - delete ev; - mi->master_log_pos += inc_pos; - DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); - mysql_mutex_unlock(&mi->data_lock); - my_free(tmp_buf); - DBUG_RETURN(error); - } - default: - inc_pos= event_len; - break; - } - if (likely(!ignore_event)) - { - if (ev->log_pos) - /* - Don't do it for fake Rotate events (see comment in - Log_event::Log_event(const char* buf...) in log_event.cc). - */ - ev->log_pos+= event_len; /* make log_pos be the pos of the end of the event */ - if (unlikely(rli->relay_log.append(ev))) - { - delete ev; - mysql_mutex_unlock(&mi->data_lock); - DBUG_RETURN(1); - } - rli->relay_log.harvest_bytes_written(&rli->log_space_total); - } - delete ev; - mi->master_log_pos+= inc_pos; - DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); - mysql_mutex_unlock(&mi->data_lock); - DBUG_RETURN(0); -} - -/* - Reads a 4.0 event and converts it to the slave's format. This code was copied - from queue_binlog_ver_1_event(), with some affordable simplifications. -*/ -static int queue_binlog_ver_3_event(Master_info *mi, const uchar *buf, - ulong event_len) -{ - const char *errmsg = 0; - ulong inc_pos; - char *tmp_buf = 0; - Relay_log_info *rli= &mi->rli; - DBUG_ENTER("queue_binlog_ver_3_event"); - - /* read_log_event() will adjust log_pos to be end_log_pos */ - Log_event *ev= - Log_event::read_log_event(buf, event_len, &errmsg, - mi->rli.relay_log.description_event_for_queue, 0); - if (unlikely(!ev)) - { - sql_print_error("Read invalid event from master: '%s',\ - master could be corrupt but a more likely cause of this is a bug", - errmsg); - my_free(tmp_buf); - DBUG_RETURN(1); - } - mysql_mutex_lock(&mi->data_lock); - switch (ev->get_type_code()) { - case STOP_EVENT: - goto err; - case ROTATE_EVENT: - if (unlikely(process_io_rotate(mi,(Rotate_log_event*)ev))) - { - delete ev; - mysql_mutex_unlock(&mi->data_lock); - DBUG_RETURN(1); - } - inc_pos= 0; - break; - default: - inc_pos= event_len; - break; - } - - if (unlikely(rli->relay_log.append(ev))) - { - delete ev; - mysql_mutex_unlock(&mi->data_lock); - DBUG_RETURN(1); - } - rli->relay_log.harvest_bytes_written(&rli->log_space_total); - delete ev; - mi->master_log_pos+= inc_pos; -err: - DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); - mysql_mutex_unlock(&mi->data_lock); - DBUG_RETURN(0); -} - -/* - queue_old_event() - - Writes a 3.23 or 4.0 event to the relay log, after converting it to the 5.0 - (exactly, slave's) format. To do the conversion, we create a 5.0 event from - the 3.23/4.0 bytes, then write this event to the relay log. - - TODO: - Test this code before release - it has to be tested on a separate - setup with 3.23 master or 4.0 master -*/ - -static int queue_old_event(Master_info *mi, const uchar *buf, ulong event_len) -{ - DBUG_ENTER("queue_old_event"); - - switch (mi->rli.relay_log.description_event_for_queue->binlog_version) { - case 1: - DBUG_RETURN(queue_binlog_ver_1_event(mi,buf,event_len)); - case 3: - DBUG_RETURN(queue_binlog_ver_3_event(mi,buf,event_len)); - default: /* unsupported format; eg version 2 */ - DBUG_PRINT("info",("unsupported binlog format %d in queue_old_event()", - mi->rli.relay_log.description_event_for_queue->binlog_version)); - DBUG_RETURN(1); - } -} - -/* queue_event() - If the event is 3.23/4.0, passes it to queue_old_event() which will convert - it. Otherwise, writes a 5.0 (or newer) event to the relay log. Then there is + Writes a 5.0 (or newer) event to the relay log. Then there is no format conversion, it's pure read/write of bytes. So a 5.0.0 slave's relay log can contain events in the slave's format or in any >=5.0.0 format. @@ -6350,10 +5995,6 @@ static int queue_event(Master_info* mi, const uchar *buf, ulong event_len) } DBUG_ASSERT(((uchar) buf[FLAGS_OFFSET] & LOG_EVENT_ACCEPT_OWN_F) == 0); - if (mi->rli.relay_log.description_event_for_queue->binlog_version<4 && - buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT /* a way to escape */) - DBUG_RETURN(queue_old_event(mi,buf,event_len)); - #ifdef ENABLED_DEBUG_SYNC /* A (+d,dbug.rows_events_to_delay_relay_logging)-test is supposed to @@ -6617,7 +6258,7 @@ static int queue_event(Master_info* mi, const uchar *buf, ulong event_len) */ inc_pos= uint4korr(buf+LOG_POS_OFFSET) ? event_len : 0; DBUG_PRINT("info",("binlog format is now %d", - mi->rli.relay_log.description_event_for_queue->binlog_version)); + mi->rli.relay_log.description_event_for_queue->binlog_version)); } break; |