From cfd3e686dcbf5f9d8fc9dc63a60188828890ea08 Mon Sep 17 00:00:00 2001 From: Tarun Wadhwa Date: Tue, 16 Jun 2026 18:10:20 +0000 Subject: [PATCH] WIP: MDEV-37605 convert innodb binlog to legacy --- client/mysqlbinlog.cc | 533 +++++++++++++++++- ...lbinlog_convert_engine_binlog_basic.result | 25 + ...sqlbinlog_convert_engine_binlog_basic.test | 61 ++ ...nvert_engine_binlog_gtid_list_event.result | 46 ++ ...convert_engine_binlog_gtid_list_event.test | 129 +++++ sql/log_event.cc | 93 +++ sql/log_event.h | 11 +- sql/log_event_client.cc | 18 + sql/log_event_server.cc | 90 --- sql/rpl_gtid.cc | 9 +- 10 files changed, 900 insertions(+), 115 deletions(-) create mode 100644 mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_basic.result create mode 100644 mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_basic.test create mode 100644 mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_gtid_list_event.result create mode 100644 mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_gtid_list_event.test diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 9ba461c1d9b5e..b81d90e626bc2 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -128,6 +128,7 @@ static my_bool print_row_count_used= 0, print_row_event_positions_used= 0; static my_bool debug_info_flag, debug_check_flag; static my_bool force_if_open_opt= 1; static my_bool opt_raw_mode= 0, opt_stop_never= 0; +static my_bool opt_convert_engine_binlog= 0; my_bool opt_gtid_strict_mode= true; static ulong opt_stop_never_slave_server_id= 0; static my_bool opt_verify_binlog_checksum= 1; @@ -211,6 +212,17 @@ static enum Binlog_format { static handler_binlog_reader *engine_binlog_reader; +static FILE *output_legacy_binlog_file= 0; +static ulonglong convert_engine_output_index= 0; +static char default_output_legacy_binlog_prefix[]= "legacy_log"; + +static char out_file_name[FN_REFLEN + 1]= {0}; + +/* Used to track the position of the log file for computing legacy end_log_pos for converted legacy binlog file */ +static ulonglong log_file_pos= 0; + +static rpl_binlog_state_base *gtid_state= NULL; + /** Pointer to the last read Annotate_rows_log_event. Having read an @@ -1552,6 +1564,438 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, DBUG_RETURN(retval); } +/* + ############################################################################## + Helper functions used for serializing the events to the legacy binlog format. + ############################################################################## +*/ + +static bool write_event_header(FILE *outfile, Log_event_type event_type, + ulong extra_len, time_t timestamp, + my_bool *do_checksum, ha_checksum *crc, + enum_binlog_checksum_alg checksum_alg) +{ + uchar header[LOG_EVENT_HEADER_LEN]; + ulong event_len; + + *do_checksum= checksum_alg != BINLOG_CHECKSUM_ALG_OFF && + checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF; + + int4store(header, timestamp); + header[EVENT_TYPE_OFFSET] = (uchar)event_type; + event_len= LOG_EVENT_HEADER_LEN + extra_len + + (*do_checksum ? BINLOG_CHECKSUM_LEN : 0); + + // TODO: Tarun get this reviewed. what should the server id be? should i get from + // innodb binlog header + int4store(header + SERVER_ID_OFFSET, 0); + int4store(header + EVENT_LEN_OFFSET, event_len); + /* + Notes: For a normal open/current binlog file, the format-description + header flags are typically 0x0001. After clean close, they become + 0x0000. + For GTID_LIST_EVENT and BINLOG_CHECKPOINT_EVENT, the flags are 0x0000 typically. + TODO: Tarun get this reviewed. + */ + int2store(header + FLAGS_OFFSET, 0); + /* Update the log_file_pos */ + log_file_pos+= event_len; + int4store(header + LOG_POS_OFFSET, log_file_pos); + /* Write this header to outfile */ + if (my_fwrite(outfile, (const uchar *)header, LOG_EVENT_HEADER_LEN, MYF(MY_NABP))) { + error("Could not write header into converted binlog file '%s'", + out_file_name); + return true; + } + if (*do_checksum) + { + *crc= my_checksum(0, (uchar*)header, sizeof(header)); + } + return false; +} + + +static bool +write_event_footer(FILE *outfile, my_bool do_checksum, ha_checksum crc) +{ + if (do_checksum) + { + char b[BINLOG_CHECKSUM_LEN]; + int4store(b, crc); + if (my_fwrite(outfile, (const uchar *)b, sizeof(b), MYF(MY_NABP))) + { + error("Could not write footer into converted binlog file '%s'", + out_file_name); + return true; + } + } + return false; +} + +/* + updates the log_file_pos(end_log_pos) to include the raw bytes of the event + It does not update the log_pos variable of ev as it is not + really needed for the conversion. +*/ +static void update_event_end_log_pos(Log_event *ev) +{ + DBUG_ASSERT(ev->temp_buf != NULL && ev->data_written >= LOG_EVENT_HEADER_LEN); + log_file_pos+= ev->data_written; + int4store(&ev->temp_buf[LOG_POS_OFFSET], log_file_pos); +} + +/* + Updates the checksum of the event only in the raw bytes of the event. + Mainly used for FORMAT_DESCRIPTION_EVENT. +*/ +static void update_checksum(Log_event *ev) +{ + DBUG_ASSERT(ev->temp_buf != NULL && + ev->data_written >= LOG_EVENT_HEADER_LEN + BINLOG_CHECKSUM_LEN); + ha_checksum crc= my_checksum(0, (uchar *) ev->temp_buf, + ev->data_written - BINLOG_CHECKSUM_LEN); + int4store(&ev->temp_buf[ev->data_written - BINLOG_CHECKSUM_LEN], crc); +} + +static bool write_format_description_event_to_legacy_binlog( + FILE *outfile, Format_description_log_event *fdev) +{ + // temp_buf stores the raw bytes of the event and data_written is the length of those raw bytes + if(fdev->temp_buf) { + /* Update the log_file_pos */ + update_event_end_log_pos(fdev); + + /* recompute checksum */ + update_checksum(fdev); + + if (my_fwrite(outfile, (const uchar *)fdev->temp_buf, + fdev->data_written, MYF(MY_NABP))) + { + error("Could not write into converted binlog file '%s'", + out_file_name); + return true; + } + + fflush(outfile); + + return false; + } + + /* + fdev->temp_buf is empty, which means fdev was dynamically generated. + Therefore, serialize the FDEV and write it to the output file. + */ + + my_bool do_checksum; + ha_checksum crc; + + char buf[320]; + String str(buf, sizeof(buf), system_charset_info); + + str.length(0); + fdev->dont_set_created= true; + fdev->used_checksum_alg= BINLOG_CHECKSUM_ALG_OFF; + + if (fdev->to_packet(&str)) + { + error("Failed due to out-of-memory writing Format_description event"); + return true; + } + /* Write header of FORMAT_DESCRIPTION_EVENT to output legacy binlog file first */ + if (write_event_header(outfile, FORMAT_DESCRIPTION_EVENT, str.length(), + fdev->created, &do_checksum, &crc, + BINLOG_CHECKSUM_ALG_CRC32)) + { + error("Could not write FORMAT_DESCRIPTION_EVENT header to output legacy " + "binlog file"); + return true; + } + + /* Write body to output legacy binlog file */ + if (my_fwrite(outfile, (const uchar *) str.ptr(), str.length(), + MYF(MY_NABP))) + { + error("Could not write body into converted binlog file '%s'", + out_file_name); + return true; + } + + if (do_checksum) + { + crc= my_checksum(crc, (uchar *) str.ptr(), str.length()); + } + + /* Write footer to output legacy binlog file */ + if (write_event_footer(outfile, do_checksum, crc)) + { + error("Could not write footer into converted binlog file '%s'", + out_file_name); + return true; + } + fflush(outfile); + + return false; +} + +static bool write_gtid_list_event_to_legacy_binlog(FILE *outfile, + Gtid_list_log_event *glev) +{ + my_bool do_checksum; + ha_checksum crc= 0; + char buf[128]; + String str(buf, sizeof(buf), system_charset_info); + str.length(0); + + if (glev->to_packet(&str)) + { + error("Failed due to out-of-memory writing Gtid_list event"); + return true; + } + + /* Write header of GTID_LIST_EVENT to output legacy binlog file first */ + /* TODO: Tarun verify and fix behaviour of timestamp (ts) */ + time_t ts= 0; + if (write_event_header(outfile, GTID_LIST_EVENT, str.length(), ts, + &do_checksum, &crc, BINLOG_CHECKSUM_ALG_OFF)) + { + error( + "Could not write GTID_LIST_EVENT header to output legacy binlog file"); + return true; + } + + /* Write body to output legacy binlog file */ + if (my_fwrite(outfile, (const uchar *)str.ptr(), str.length(), MYF(MY_NABP))) { + error("Could not write body into converted binlog file '%s'", + out_file_name); + return true; + } + + /* + TODO: Tarun get this reviewed. We are disabling/not supporting the checksum in every event. + Should I keep the below code for extensibility? + (do_checksum will always be false here) + */ + if (do_checksum) { + crc= my_checksum(crc, (uchar*)str.ptr(), str.length()); + } + + /* Write footer to output legacy binlog file */ + if (write_event_footer(outfile, do_checksum, crc)) { + error("Could not write footer into converted binlog file '%s'", + out_file_name); + return true; + } + fflush(outfile); + + return false; +} + +static bool write_binlog_checkpoint_event_to_legacy_binlog( + FILE *outfile, Binlog_checkpoint_log_event *bcle) +{ + my_bool do_checksum; + ha_checksum crc= 0; + char buf[128]; + String str(buf, sizeof(buf), system_charset_info); + str.length(0); + + /* Generate BINLOG_CHECKPOINT_EVENT body (This is equivalent to the + to_packet() method used in case of FORMAT_DESCRIPTION_EVENT, + GTID_LIST_EVENT, etc.) */ + uchar header_buf[BINLOG_CHECKPOINT_HEADER_LEN]; + int4store(header_buf, bcle->binlog_file_len); + if (str.append((char *) header_buf, BINLOG_CHECKPOINT_HEADER_LEN)) + { + error("Failed due to out-of-memory writing BINLOG_CHECKPOINT_EVENT body"); + return true; + } + + if (str.append((char *) bcle->binlog_file_name, bcle->binlog_file_len)) + { + error("Failed due to out-of-memory writing BINLOG_CHECKPOINT_EVENT body"); + return true; + } + + /* Write header of BINLOG_CHECKPOINT_EVENT to output legacy binlog file first + */ + /* TODO: Tarun verify and fix behaviour of timestamp (ts) */ + time_t ts= 0; + if (write_event_header(outfile, BINLOG_CHECKPOINT_EVENT, str.length(), ts, + &do_checksum, &crc, BINLOG_CHECKSUM_ALG_OFF)) + { + error("Could not write BINLOG_CHECKPOINT_EVENT header to output legacy " + "binlog file"); + return true; + } + + /* Write body to output legacy binlog file */ + if (my_fwrite(outfile, (const uchar *) str.ptr(), str.length(), + MYF(MY_NABP))) + { + error("Could not write body into converted binlog file '%s'", + out_file_name); + return true; + } + + if (do_checksum) + { + crc= my_checksum(crc, (uchar *) str.ptr(), str.length()); + } + + /* write footer to output legacy binlog file */ + if (write_event_footer(outfile, do_checksum, crc)) + { + error("Could not write footer into converted binlog file '%s'", + out_file_name); + return true; + } + fflush(outfile); + + return false; +} + +static bool init_output_legacy_binlog(FILE **out_file, char *out_name, + size_t out_name_len) +{ + + /* Reset the log_file_pos to 0 for the new output legacy binlog file */ + log_file_pos= 0; + + const char *prefix= result_file_name ? result_file_name + : default_output_legacy_binlog_prefix; + + my_snprintf(out_name, out_name_len, "%s.%06llu", prefix, + ++convert_engine_output_index); + + if (!(*out_file= my_fopen(out_name, O_WRONLY | O_BINARY, MYF(MY_WME)))) + { + error("Could not create converted binlog file: %s", out_name); + return true; + } + + fprintf(stderr, "Generated output file: %s\n", out_name); + + // Write the BINLOG_MAGIC to the output legacy binlog file + if (my_fwrite(*out_file, (const uchar *) BINLOG_MAGIC, BIN_LOG_HEADER_SIZE, + MYF(MY_NABP))) + { + error("Could not write into converted binlog file '%s'", out_name); + return true; + } + log_file_pos+= BIN_LOG_HEADER_SIZE; + + // Write the FORMAT_DESCRIPTION_EVENT to the output legacy binlog file + if (write_format_description_event_to_legacy_binlog(*out_file, + glob_description_event)) + { + error("Could not write FORMAT_DESCRIPTION_EVENT to output legacy binlog " + "file"); + return true; + } + + /* Write the GTID_LIST_EVENT to the output legacy binlog file */ + Gtid_list_log_event gle= Gtid_list_log_event(gtid_state); + if (write_gtid_list_event_to_legacy_binlog(*out_file, &gle)) + { + error("Could not write GTID_LIST_EVENT to output legacy binlog file"); + return true; + } + + /* BINLOG_CHECKPOINT_EVENT only accepts the basename of the binlog file, not + * the full path */ + size_t off= dirname_length(out_name); + uint32 length= (uint32) (strlen(out_name) - off); + + // Write the BINLOG_CHECKPOINT_EVENT to the output legacy binlog file + Binlog_checkpoint_log_event bcle= + Binlog_checkpoint_log_event(out_name + off, length); + if (!bcle.is_valid()) + { + error("Failed to create BINLOG_CHECKPOINT_EVENT"); + return true; + } + if (write_binlog_checkpoint_event_to_legacy_binlog(*out_file, &bcle)) + { + error("Could not write BINLOG_CHECKPOINT_EVENT to output legacy binlog " + "file"); + return true; + } + return false; +} + +/* + Writes the event to the converted legacy binlog file + @param ev: The event to write + @return: OK_CONTINUE if successful, ERROR_STOP if failed +*/ +static Exit_status write_event_to_legacy_binlog(Log_event *ev) +{ + + // if event type is FORMAT_DESCRIPTION_EVENT, store the event in global variable glob_description_event + if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT) { + + delete glob_description_event; + glob_description_event= (Format_description_log_event*) ev; + + // close the output legacy binlog file if it is open + if (output_legacy_binlog_file) { + // TODO: tarun Write the ROTATE_EVENT to the output legacy binlog file + my_fclose(output_legacy_binlog_file, MYF(0)); + output_legacy_binlog_file= NULL; + } + + return OK_CONTINUE; + } + + /* + Open and initialize the output legacy binlog file. + Writes the FORMAT_DESCRIPTION_EVENT, GTID_LIST event, and BINLOG_CHECKPOINT event. + */ + if (!output_legacy_binlog_file) + { + + if (init_output_legacy_binlog(&output_legacy_binlog_file, out_file_name, + sizeof(out_file_name))) + goto err; + } + + /* + if event type is GTID_EVENT, update the gtid_state + which will be used to write the GTID_LIST_EVENT in + the next output legacy binlog file. + */ + if (ev->get_type_code() == GTID_EVENT) { + rpl_gtid ev_gtid; + Gtid_log_event *gle= (Gtid_log_event*) ev; + ev_gtid= {gle->domain_id, gle->server_id, gle->seq_no}; + + if (gtid_state->update_nolock(&ev_gtid)) { + error("Failed to update GTID state"); + goto err; + } + } + + /* Update the log_file_pos */ + update_event_end_log_pos(ev); + + // ev->temp_buf contains the raw event bytes and ev->data_written is the length of the event + if (my_fwrite(output_legacy_binlog_file, (const uchar *)ev->temp_buf, + ev->data_written, MYF(MY_NABP))) + { + error("Could not write into converted binlog file '%s'", + out_file_name); + goto err; + } + fflush(output_legacy_binlog_file); + + delete ev; + return OK_CONTINUE; + +err: + delete ev; + return ERROR_STOP; +} + static struct my_option my_options[] = { @@ -1605,6 +2049,10 @@ static struct my_option my_options[] = "already have. NOTE: you will need a SUPER privilege to use this option.", &disable_log_bin, &disable_log_bin, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"convert-engine-binlog", 0, + "Convert InnoDB based engine binlog files to legacy binlog files.", + &opt_convert_engine_binlog, &opt_convert_engine_binlog, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"flashback", 'B', "Flashback feature can rollback you committed data to a special time point.", #ifdef WHEN_FLASHBACK_REVIEW_READY "before Flashback feature writing a row, original row can insert to review-dbname.review-tablename," @@ -1652,8 +2100,8 @@ static struct my_option my_options[] = "statements. Output files named after server logs.", &opt_raw_mode, &opt_raw_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"result-file", 'r', "Direct output to a given file. With --raw this is a " - "prefix for the file names.", + {"result-file", 'r', "Direct output to a given file. With --raw or " + "--convert-engine-binlog this is a prefix for the output file names.", &result_file_name, &result_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef WHEN_FLASHBACK_REVIEW_READY @@ -1959,6 +2407,8 @@ static void cleanup() delete_dynamic(&binlog_events); delete_dynamic(&events_in_stmt); } + if (gtid_state) + delete gtid_state; delete engine_binlog_reader; DBUG_VOID_RETURN; } @@ -2542,7 +2992,7 @@ static Exit_status dump_log_entries(const char* logname) Set safe delimiter, to dump things like CREATE PROCEDURE safely */ - if (!opt_raw_mode) + if (!opt_raw_mode && !opt_convert_engine_binlog) fprintf(result_file, "DELIMITER /*!*/;\n"); strmov(print_event_info.delimiter, "/*!*/;"); @@ -2563,7 +3013,8 @@ static Exit_status dump_log_entries(const char* logname) print_event_info.short_form= short_form; print_event_info.print_row_count= print_row_count; print_event_info.file= result_file; - fflush(result_file); + if (result_file) + fflush(result_file); rc= (remote_opt ? dump_remote_log_entries(&print_event_info, logname) : dump_local_log_entries(&print_event_info, logname)); @@ -2573,7 +3024,7 @@ static Exit_status dump_log_entries(const char* logname) return rc; /* Set delimiter back to semicolon */ - if (!opt_raw_mode && !opt_flashback) + if (!opt_raw_mode && !opt_flashback && !opt_convert_engine_binlog) fprintf(result_file, "DELIMITER ;\n"); strmov(print_event_info.delimiter, ";"); return rc; @@ -2814,8 +3265,6 @@ static Exit_status handle_event_text_mode(PRINT_EVENT_INFO *print_event_info, } -static char out_file_name[FN_REFLEN + 1]; - static Exit_status handle_event_raw_mode(PRINT_EVENT_INFO *print_event_info, ulong *len, const char* logname, uint logname_len) @@ -3137,6 +3586,12 @@ static Exit_status check_header(IO_CACHE* file, error("File is not a binary log file."); return ERROR_STOP; } + if (opt_convert_engine_binlog) + { + error("The --convert-engine-binlog option requires InnoDB-engine " + "binlog input files"); + return ERROR_STOP; + } /* Imagine we are running with --start-position=1000. We still need @@ -3357,6 +3812,12 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, { if (open_engine_binlog(engine_binlog_reader, start_position, logname, file)) goto err; + /* Initialize the GTID state tracker used to generate GTID_LIST_EVENT while + converting the engine binlog to legacy binlog */ + if (opt_convert_engine_binlog && !gtid_state) { + gtid_state= new rpl_binlog_state_base(); + gtid_state->init(); + } } for (;;) { @@ -3432,9 +3893,16 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, ((ev->get_type_code() == UNKNOWN_EVENT && ((Unknown_log_event *) ev)->what == Unknown_log_event::ENCRYPTED)) || old_off + ev->data_written == my_b_tell(file)); - if ((retval= process_event(print_event_info, ev, old_off, logname)) != - OK_CONTINUE) - goto end; + + if (opt_convert_engine_binlog) { + if ((retval= write_event_to_legacy_binlog(ev)) != OK_CONTINUE) + goto end; + } + else { + if ((retval= process_event(print_event_info, ev, old_off, logname)) != + OK_CONTINUE) + goto end; + } } /* NOTREACHED */ @@ -3443,6 +3911,11 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, retval= ERROR_STOP; end: + if (output_legacy_binlog_file) + { + my_fclose(output_legacy_binlog_file, MYF(0)); + output_legacy_binlog_file= NULL; + } if (fd >= 0) my_close(fd, MYF(MY_WME)); /* @@ -3504,7 +3977,6 @@ int main(int argc, char** argv) error("The --raw mode is not allowed with --flashback mode"); die(1); } - if (opt_flashback) { my_init_dynamic_array(PSI_NOT_INSTRUMENTED, &binlog_events, @@ -3515,7 +3987,28 @@ int main(int argc, char** argv) if (opt_stop_never) to_last_remote_log= TRUE; - if (opt_raw_mode) + if (opt_convert_engine_binlog) + { + if (remote_opt) + { + error("The --convert-engine-binlog option does not support " + "--read-from-remote-server"); + die(1); + } + if (opt_raw_mode) + { + error("The --convert-engine-binlog option cannot be combined with --raw"); + die(1); + } + if (opt_flashback) + { + error("The --convert-engine-binlog option cannot be combined " + "with --flashback"); + die(1); + } + + } + else if (opt_raw_mode) { if (!remote_opt) { @@ -3571,7 +4064,7 @@ int main(int argc, char** argv) else load_processor.init_by_cur_dir(); - if (!opt_raw_mode) + if (!opt_raw_mode && !opt_convert_engine_binlog) { fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;\n"); @@ -3615,14 +4108,16 @@ int main(int argc, char** argv) if we finished processing input before reaching the stop boundaries indicated by --stop-datetime or --stop-position. */ - if (stop_datetime_given && stop_datetime > last_processed_ev.datetime) + if (!opt_convert_engine_binlog && + stop_datetime_given && stop_datetime > last_processed_ev.datetime) warning("Did not reach stop datetime '%s' before end of input", stop_datetime_str); - if ((static_cast(stop_position) != stop_position_default) && + if (!opt_convert_engine_binlog && + (static_cast(stop_position) != stop_position_default) && stop_position > last_processed_ev.position) warning("Did not reach stop position %llu before end of input", stop_position); - if (position_gtid_filter) + if (!opt_convert_engine_binlog && position_gtid_filter) position_gtid_filter->verify_final_state(); /* @@ -3644,7 +4139,7 @@ int main(int argc, char** argv) } /* Set delimiter back to semicolon */ - if (retval != ERROR_STOP) + if (retval != ERROR_STOP && !opt_convert_engine_binlog) { if (!stop_event_string.is_empty() && result_file) fprintf(result_file, "%s", stop_event_string.ptr()); @@ -3652,7 +4147,7 @@ int main(int argc, char** argv) fprintf(result_file, "DELIMITER ;\n"); } - if (retval != ERROR_STOP && !opt_raw_mode) + if (retval != ERROR_STOP && !opt_raw_mode && !opt_convert_engine_binlog) { /* Issue a ROLLBACK in case the last printed binlog was crashed and had half @@ -3697,7 +4192,7 @@ int main(int argc, char** argv) are processed because it immediately errors (i.e. retval will be ERROR_STOP) */ - if (retval != ERROR_STOP && gtid_state_validator && + if (retval != ERROR_STOP && !opt_convert_engine_binlog && gtid_state_validator && gtid_state_validator->report(stderr, opt_gtid_strict_mode)) retval= ERROR_STOP; diff --git a/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_basic.result b/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_basic.result new file mode 100644 index 0000000000000..9156e2df665c1 --- /dev/null +++ b/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_basic.result @@ -0,0 +1,25 @@ +include/reset_master.inc +set TIMESTAMP= UNIX_TIMESTAMP("1970-01-21 15:32:22"); +*** Generate a small workload into binlog-000000.ibb +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0), (2, 0), (3, 0); +UPDATE t1 SET b=1 WHERE a=1; +DELETE FROM t1 WHERE a=2; +REPLACE INTO t1 VALUES (3, 3); +SELECT * FROM t1 ORDER BY a; +a b +1 1 +3 3 +FLUSH BINARY LOGS; +*** Convert binlog-000000.ibb to legacy format +*** Converted file contains the synthesized header events +FOUND 1 /Gtid list/ in conv_listing.txt +FOUND 1 /Binlog checkpoint/ in conv_listing.txt +FOUND 1 /Start: binlog v 4/ in conv_listing.txt +*** Round-trip: replay the converted file and compare data +DROP TABLE t1; +SELECT * FROM t1 ORDER BY a; +a b +1 1 +3 3 +DROP TABLE t1; diff --git a/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_basic.test b/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_basic.test new file mode 100644 index 0000000000000..cfca1082d9ced --- /dev/null +++ b/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_basic.test @@ -0,0 +1,61 @@ +# mysqlbinlog_convert.test +# +# Purpose: +# Basic test for MDEV-37605: mariadb-binlog conversion of InnoDB-format +# binlogs (.ibb) into legacy-format binary log +# + +--source include/have_binlog_format_row.inc +--source include/have_innodb_binlog.inc + +--let $datadir= `SELECT @@datadir` + +--source include/reset_master.inc + +# Fixed timestamp for deterministic event listings (with --timezone=GMT-3 +# from the -master.opt file, matching binlog_in_engine.mysqlbinlog). +set TIMESTAMP= UNIX_TIMESTAMP("1970-01-21 15:32:22"); + +--echo *** Generate a small workload into binlog-000000.ibb +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0), (2, 0), (3, 0); +UPDATE t1 SET b=1 WHERE a=1; +DELETE FROM t1 WHERE a=2; +REPLACE INTO t1 VALUES (3, 3); +SELECT * FROM t1 ORDER BY a; + +# Rotate so binlog-000000.ibb is complete on disk. Waiting for the *next* +# pre-allocated file (binlog-000002.ibb, fully pre-allocated and empty) +# guarantees both 000000 and the new active 000001 exist. +FLUSH BINARY LOGS; +--let $binlog_name= binlog-000002.ibb +--let $binlog_size= 262144 +--source include/wait_for_engine_binlog.inc + +--echo *** Convert binlog-000000.ibb to legacy format +--exec $MYSQL_BINLOG --convert-engine-binlog --result-file=$MYSQL_TMP_DIR/conv $datadir/binlog-000000.ibb + + +--echo *** Converted file contains the synthesized header events +--exec $MYSQL_BINLOG --verbose $MYSQL_TMP_DIR/conv.000001 > $MYSQL_TMP_DIR/conv_listing.txt +--let SEARCH_FILE= $MYSQL_TMP_DIR/conv_listing.txt +--let SEARCH_PATTERN= Gtid list +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= Binlog checkpoint +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= Start: binlog v 4 +--source include/search_pattern_in_file.inc +--remove_file $MYSQL_TMP_DIR/conv_listing.txt + +--echo *** Round-trip: replay the converted file and compare data +# The replayed GTIDs duplicate the originals, so the replay must not use +# GTID strict mode (same as in binlog_in_engine.mysqlbinlog). +--exec $MYSQL_BINLOG --gtid-strict-mode=0 $MYSQL_TMP_DIR/conv.000001 > $MYSQLTEST_VARDIR/tmp/convert_replay.sql +DROP TABLE t1; +--exec $MYSQL --abort-source-on-error -e "source $MYSQLTEST_VARDIR/tmp/convert_replay.sql;" test +--remove_file $MYSQLTEST_VARDIR/tmp/convert_replay.sql +SELECT * FROM t1 ORDER BY a; + +# Cleanup +--remove_file $MYSQL_TMP_DIR/conv.000001 +DROP TABLE t1; diff --git a/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_gtid_list_event.result b/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_gtid_list_event.result new file mode 100644 index 0000000000000..b97edd79aecd1 --- /dev/null +++ b/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_gtid_list_event.result @@ -0,0 +1,46 @@ +SET @@session.sql_log_bin= 0; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB; +SET @@session.sql_log_bin= 1; +include/reset_master.inc +*** Generate GTIDs across several InnoDB binlog files +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +INSERT INTO t1 VALUES (2); +SET @@session.gtid_domain_id= 1; +SET @@session.server_id= 2; +INSERT INTO t2 VALUES (1); +FLUSH BINARY LOGS; +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +INSERT INTO t1 VALUES (1); +SET @@session.gtid_domain_id= 2; +SET @@session.server_id= 3; +INSERT INTO t3 VALUES (1); +FLUSH BINARY LOGS; +SET @@session.gtid_domain_id= 1; +SET @@session.server_id= 1; +INSERT INTO t2 VALUES (2); +SET @@session.gtid_domain_id= 3; +SET @@session.server_id= 4; +INSERT INTO t4 VALUES (1); +# restart +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +INSERT INTO t1 VALUES (3); +FLUSH BINARY LOGS; +*** Convert the generated InnoDB binlogs to legacy format +*** Verify synthesized Gtid_list events in converted legacy binlogs +FOUND 1 /Gtid list \[\]/ in gtid_conv_listing.txt +FOUND 1 /Gtid list \[0-1-1,\n# 1-2-1\]/ in gtid_conv_listing.txt +FOUND 1 /Gtid list \[0-1-2,\n# 1-2-1,\n# 2-3-1\]/ in gtid_conv_listing.txt +FOUND 1 /Gtid list \[0-1-2,\n# 1-2-1,\n# 1-1-2,\n# 2-3-1,\n# 3-4-1\]/ in gtid_conv_listing.txt +*** Convert the generated InnoDB binlog(binlog-000002.ibb) to legacy format in random order +*** Verify synthesized Gtid_list events in converted legacy binlogs +NOT FOUND /Gtid list \[0-1-2,\n# 1-2-1,\n# 1-1-2,\n# 2-3-1,\n# 3-4-1\]/ in gtid_conv_listing.txt +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; diff --git a/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_gtid_list_event.test b/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_gtid_list_event.test new file mode 100644 index 0000000000000..d2d8061a2e50d --- /dev/null +++ b/mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_gtid_list_event.test @@ -0,0 +1,129 @@ +# +# Purpose: +# Verify that mariadb-binlog populates synthesized GTID_LIST_EVENTs correctly +# when converting InnoDB-format binlogs (.ibb) to legacy binlog files. +# +# Methodology: +# Generate several .ibb files with GTIDs across multiple domains and server +# ids, including GTIDs that are not ordered by server id. Restart the server +# in the middle so the converter sees another FORMAT_DESCRIPTION_EVENT and +# rotates the generated legacy output. Convert all completed .ibb files and +# verify each generated legacy binlog contains the expected Gtid_list state. +# Convert the .ibb files again in random order and verify the generated +# legacy binlogs contain the expected Gtid_list state. +# + +--source include/have_binlog_format_row.inc +--source include/have_innodb_binlog.inc + +--let $datadir= `SELECT @@datadir` + +# start of binlog-000000.ibb + +SET @@session.sql_log_bin= 0; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB; +SET @@session.sql_log_bin= 1; + +--source include/reset_master.inc + +--echo *** Generate GTIDs across several InnoDB binlog files +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +INSERT INTO t1 VALUES (2); + +SET @@session.gtid_domain_id= 1; +SET @@session.server_id= 2; +INSERT INTO t2 VALUES (1); + +# end of binlog-000000.ibb + +FLUSH BINARY LOGS; + +# start of binlog-000001.ibb + +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +INSERT INTO t1 VALUES (1); + +SET @@session.gtid_domain_id= 2; +SET @@session.server_id= 3; +INSERT INTO t3 VALUES (1); + +# end of binlog-000001.ibb + +FLUSH BINARY LOGS; + +# start of binlog-000002.ibb + +SET @@session.gtid_domain_id= 1; +SET @@session.server_id= 1; +INSERT INTO t2 VALUES (2); + +SET @@session.gtid_domain_id= 3; +SET @@session.server_id= 4; +INSERT INTO t4 VALUES (1); + +--source include/restart_mysqld.inc + +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +INSERT INTO t1 VALUES (3); + +# end of binlog-000002.ibb + +FLUSH BINARY LOGS; + +--let $binlog_name= binlog-000003.ibb +--let $binlog_size= 262144 +--source include/wait_for_engine_binlog.inc + + +--echo *** Convert the generated InnoDB binlogs to legacy format +--exec $MYSQL_BINLOG --convert-engine-binlog --result-file=$MYSQL_TMP_DIR/gtid_conv $datadir/binlog-000000.ibb $datadir/binlog-000001.ibb $datadir/binlog-000002.ibb + +--echo *** Verify synthesized Gtid_list events in converted legacy binlogs +--exec $MYSQL_BINLOG --verbose $MYSQL_TMP_DIR/gtid_conv.000001 > $MYSQL_TMP_DIR/gtid_conv_listing.txt +--let SEARCH_FILE= $MYSQL_TMP_DIR/gtid_conv_listing.txt +--let SEARCH_PATTERN= Gtid list \[\] +--source include/search_pattern_in_file.inc + +--exec $MYSQL_BINLOG --verbose $MYSQL_TMP_DIR/gtid_conv.000002 > $MYSQL_TMP_DIR/gtid_conv_listing.txt +--let SEARCH_PATTERN= Gtid list \[0-1-1,\n# 1-2-1\] +--source include/search_pattern_in_file.inc + +--exec $MYSQL_BINLOG --verbose $MYSQL_TMP_DIR/gtid_conv.000003 > $MYSQL_TMP_DIR/gtid_conv_listing.txt +--let SEARCH_PATTERN= Gtid list \[0-1-2,\n# 1-2-1,\n# 2-3-1\] +--source include/search_pattern_in_file.inc + +--exec $MYSQL_BINLOG --verbose $MYSQL_TMP_DIR/gtid_conv.000004 > $MYSQL_TMP_DIR/gtid_conv_listing.txt +--let SEARCH_PATTERN= Gtid list \[0-1-2,\n# 1-2-1,\n# 1-1-2,\n# 2-3-1,\n# 3-4-1\] +--source include/search_pattern_in_file.inc + +--remove_file $MYSQL_TMP_DIR/gtid_conv_listing.txt +--remove_file $MYSQL_TMP_DIR/gtid_conv.000001 +--remove_file $MYSQL_TMP_DIR/gtid_conv.000002 +--remove_file $MYSQL_TMP_DIR/gtid_conv.000003 +--remove_file $MYSQL_TMP_DIR/gtid_conv.000004 + + +--echo *** Convert the generated InnoDB binlog(binlog-000002.ibb) to legacy format in random order +--exec $MYSQL_BINLOG --convert-engine-binlog --result-file=$MYSQL_TMP_DIR/gtid_conv $datadir/binlog-000002.ibb + +--echo *** Verify synthesized Gtid_list events in converted legacy binlogs +--exec $MYSQL_BINLOG --verbose $MYSQL_TMP_DIR/gtid_conv.000001 > $MYSQL_TMP_DIR/gtid_conv_listing.txt +--let SEARCH_FILE= $MYSQL_TMP_DIR/gtid_conv_listing.txt +--let SEARCH_PATTERN= Gtid list \[0-1-2,\n# 1-2-1,\n# 1-1-2,\n# 2-3-1,\n# 3-4-1\] +# TODO: Tarun this search will fail now as this functionality is not yet implemented +--source include/search_pattern_in_file.inc + +--remove_file $MYSQL_TMP_DIR/gtid_conv_listing.txt +--remove_file $MYSQL_TMP_DIR/gtid_conv.000001 + + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; diff --git a/sql/log_event.cc b/sql/log_event.cc index 4de91903f04c8..d5e5a3e81af23 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2370,6 +2370,60 @@ Format_description_log_event(const uchar *buf, uint event_len, DBUG_VOID_RETURN; } +bool +Format_description_log_event::to_packet(String *packet) +{ + uchar *p; + uint32 needed_length= + packet->length() + START_V3_HEADER_LEN + 1 + number_of_event_types + 1; + if (packet->reserve(needed_length)) + return true; + p= (uchar *)packet->ptr() + packet->length(); + packet->length(needed_length); + int2store(p, binlog_version); + p += 2; + memcpy(p, server_version, ST_SERVER_VER_LEN); + p+= ST_SERVER_VER_LEN; +/* TODO: Tarun get this reviewed */ +#ifdef MYSQL_SERVER + if (!dont_set_created) + created= get_time(); +#endif + int4store(p, created); + p+= 4; + *p++= common_header_len; + memcpy(p, post_header_len, number_of_event_types); + p+= number_of_event_types; + + /* + if checksum is requested + record the checksum-algorithm descriptor next to + post_header_len vector which will be followed by the checksum value. + Master is supposed to trigger checksum computing by binlog_checksum_options, + slave does it via marking the event according to + FD_queue checksum_alg value. + */ + compile_time_assert(BINLOG_CHECKSUM_ALG_DESC_LEN == 1); + uint8 checksum_byte= (uint8) (used_checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF ? + used_checksum_alg : BINLOG_CHECKSUM_ALG_OFF); + DBUG_ASSERT(used_checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF); + /* + FD of checksum-aware server is always checksum-equipped, (V) is in, + regardless of @@global.binlog_checksum policy. + Thereby a combination of (A) == 0, (V) != 0 means + it's the checksum-aware server's FD event that heads checksum-free binlog + file. + Here 0 stands for checksumming OFF to evaluate (V) as 0 is that case. + A combination of (A) != 0, (V) != 0 denotes FD of the checksum-aware server + heading the checksummed binlog. + (A), (V) presence in FD of the checksum-aware server makes the event + 1 + 4 bytes bigger comparing to the former FD. + */ + *p++= checksum_byte; + + return false; +} + bool Format_description_log_event::start_decryption(Start_encryption_log_event* sele) { DBUG_ASSERT(crypto_data.scheme == 0); @@ -2560,6 +2614,16 @@ Rotate_log_event::Rotate_log_event(const uchar *buf, uint event_len, Binlog_checkpoint_log_event methods **************************************************************************/ +Binlog_checkpoint_log_event::Binlog_checkpoint_log_event( + const char *binlog_file_name_arg, uint binlog_file_len_arg) + : Log_event(), + binlog_file_name(my_strndup(PSI_INSTRUMENT_ME, binlog_file_name_arg, + binlog_file_len_arg, MYF(MY_WME))), + binlog_file_len(binlog_file_len_arg) +{ + cache_type= EVENT_NO_CACHE; +} + Binlog_checkpoint_log_event::Binlog_checkpoint_log_event( const uchar *buf, uint event_len, const Format_description_log_event *description_event) @@ -2771,6 +2835,35 @@ Gtid_list_log_event::Gtid_list_log_event(const uchar *buf, uint event_len, #endif } +bool +Gtid_list_log_event::to_packet(String *packet) +{ + uint32 i; + uchar *p; + uint32 needed_length; + + DBUG_ASSERT(count < 1<<28); + + needed_length= packet->length() + get_data_size(); + if (packet->reserve(needed_length)) + return true; + p= (uchar *)packet->ptr() + packet->length();; + packet->length(needed_length); + int4store(p, (count & ((1<<28)-1)) | gl_flags); + p += 4; + /* Initialise the padding for empty Gtid_list. */ + if (count == 0) + int2store(p, 0); + for (i= 0; i < count; ++i) + { + int4store(p, list[i].domain_id); + int4store(p+4, list[i].server_id); + int8store(p+8, list[i].seq_no); + p += 16; + } + + return false; +} /* Used to record gtid_list event while sending binlog to slave, without having to diff --git a/sql/log_event.h b/sql/log_event.h index 517b2e62fd06e..5c0b82aca8ab0 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -2662,10 +2662,11 @@ class Format_description_log_event: public Log_event #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol) override; #endif /* HAVE_REPLICATION */ - bool to_packet(String *packet); #else bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override; #endif + bool to_packet(String *packet); + bool header_is_valid() const { return common_header_len >= LOG_EVENT_MINIMAL_HEADER_LEN && post_header_len; @@ -3329,14 +3330,15 @@ class Binlog_checkpoint_log_event: public Log_event uint binlog_file_len; #ifdef MYSQL_SERVER - Binlog_checkpoint_log_event(const char *binlog_file_name_arg, - uint binlog_file_len_arg); + #ifdef HAVE_REPLICATION void pack_info(Protocol *protocol) override; #endif #else bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif + Binlog_checkpoint_log_event(const char *binlog_file_name_arg, + uint binlog_file_len_arg); Binlog_checkpoint_log_event(const uchar *buf, uint event_len, const Format_description_log_event *description_event); @@ -3676,6 +3678,7 @@ class Gtid_list_log_event: public Log_event void pack_info(Protocol *protocol) override; #endif #else + Gtid_list_log_event(rpl_binlog_state_base *gtid_set); bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override; #endif Gtid_list_log_event(const uchar *buf, uint event_len, @@ -3691,8 +3694,8 @@ class Gtid_list_log_event: public Log_event GTID_LIST_HEADER_LEN+2 : GTID_LIST_HEADER_LEN+count*element_size); } bool is_valid() const override { return list != NULL; } -#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) bool to_packet(String *packet); +#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) bool write(Log_event_writer *writer) override; int do_apply_event(rpl_group_info *rgi) override; enum_skip_reason do_shall_skip(rpl_group_info *rgi) override; diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc index ab884da52c564..712d359ddc566 100644 --- a/sql/log_event_client.cc +++ b/sql/log_event_client.cc @@ -2353,6 +2353,24 @@ bool Binlog_checkpoint_log_event::print(FILE *file, return cache.flush_data(); } +/* + + Constructor for Gtid_list_log_event. + Used in mysqlbinlog to generate GTID_LIST_EVENT while converting the engine binlog to legacy binlog. + TODO: Tarun get this reviewed. +*/ +Gtid_list_log_event::Gtid_list_log_event(rpl_binlog_state_base *gtid_set) + : count(gtid_set->count_nolock()), gl_flags(0), list(0), sub_id_list(0) +{ + cache_type= EVENT_NO_CACHE; + /* Failure to allocate memory will be caught by is_valid() returning false. */ + if (count < (1<<28) && + (list = (rpl_gtid *)my_malloc(PSI_INSTRUMENT_ME, + count * sizeof(*list) + (count == 0), MYF(MY_WME)))) + { + gtid_set->get_gtid_list_nolock(list, count); + } +} bool Gtid_list_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 3c8d7bea47381..8b48cfd0e1755 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -2454,56 +2454,7 @@ void Format_description_log_event::pack_info(Protocol *protocol) } #endif /* defined(HAVE_REPLICATION) */ -bool -Format_description_log_event::to_packet(String *packet) -{ - uchar *p; - uint32 needed_length= - packet->length() + START_V3_HEADER_LEN + 1 + number_of_event_types + 1; - if (packet->reserve(needed_length)) - return true; - p= (uchar *)packet->ptr() + packet->length();; - packet->length(needed_length); - int2store(p, binlog_version); - p += 2; - memcpy(p, server_version, ST_SERVER_VER_LEN); - p+= ST_SERVER_VER_LEN; - if (!dont_set_created) - created= get_time(); - int4store(p, created); - p+= 4; - *p++= common_header_len; - memcpy(p, post_header_len, number_of_event_types); - p+= number_of_event_types; - - /* - if checksum is requested - record the checksum-algorithm descriptor next to - post_header_len vector which will be followed by the checksum value. - Master is supposed to trigger checksum computing by binlog_checksum_options, - slave does it via marking the event according to - FD_queue checksum_alg value. - */ - compile_time_assert(BINLOG_CHECKSUM_ALG_DESC_LEN == 1); - uint8 checksum_byte= (uint8) (used_checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF ? - used_checksum_alg : BINLOG_CHECKSUM_ALG_OFF); - DBUG_ASSERT(used_checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF); - /* - FD of checksum-aware server is always checksum-equipped, (V) is in, - regardless of @@global.binlog_checksum policy. - Thereby a combination of (A) == 0, (V) != 0 means - it's the checksum-aware server's FD event that heads checksum-free binlog - file. - Here 0 stands for checksumming OFF to evaluate (V) as 0 is that case. - A combination of (A) != 0, (V) != 0 denotes FD of the checksum-aware server - heading the checksummed binlog. - (A), (V) presence in FD of the checksum-aware server makes the event - 1 + 4 bytes bigger comparing to the former FD. - */ - *p++= checksum_byte; - return false; -} bool Format_description_log_event::write(Log_event_writer *writer) { @@ -2879,17 +2830,6 @@ Binlog_checkpoint_log_event::do_shall_skip(rpl_group_info *rgi) #endif -Binlog_checkpoint_log_event::Binlog_checkpoint_log_event( - const char *binlog_file_name_arg, - uint binlog_file_len_arg) - :Log_event(), - binlog_file_name(my_strndup(PSI_INSTRUMENT_ME, binlog_file_name_arg, binlog_file_len_arg, - MYF(MY_WME))), - binlog_file_len(binlog_file_len_arg) -{ - cache_type= EVENT_NO_CACHE; -} - bool Binlog_checkpoint_log_event::write(Log_event_writer *writer) { @@ -3449,36 +3389,6 @@ Gtid_list_log_event::Gtid_list_log_event(slave_connection_state *gtid_set, #if defined(HAVE_REPLICATION) -bool -Gtid_list_log_event::to_packet(String *packet) -{ - uint32 i; - uchar *p; - uint32 needed_length; - - DBUG_ASSERT(count < 1<<28); - - needed_length= packet->length() + get_data_size(); - if (packet->reserve(needed_length)) - return true; - p= (uchar *)packet->ptr() + packet->length();; - packet->length(needed_length); - int4store(p, (count & ((1<<28)-1)) | gl_flags); - p += 4; - /* Initialise the padding for empty Gtid_list. */ - if (count == 0) - int2store(p, 0); - for (i= 0; i < count; ++i) - { - int4store(p, list[i].domain_id); - int4store(p+4, list[i].server_id); - int8store(p+8, list[i].seq_no); - p += 16; - } - - return false; -} - bool Gtid_list_log_event::write(Log_event_writer *writer) diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 430e4a4bfc64a..b40ebeafcbf7a 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -1517,6 +1517,7 @@ rpl_slave_state::alloc_gtid_pos_table(LEX_CSTRING *table_name, void *hton, return p; } +#endif void rpl_binlog_state_base::init() @@ -1694,6 +1695,7 @@ rpl_binlog_state_base::find_nolock(uint32 domain_id, uint32 server_id) sizeof(server_id)); } +#ifndef MYSQL_CLIENT /* Return true if this binlog state is before the position specified by the @@ -1895,10 +1897,12 @@ rpl_binlog_state::update_with_next_gtid(uint32 domain_id, uint32 server_id, return res; } - +#endif // MYSQL_CLIENT +/* TODO: Tarun get this reviewed. changed the base class name from +rpl_gtid_base to rpl_binlog_state_base (also get reviewed the ifndef blocks )*/ /* Helper functions for update. */ int -rpl_binlog_state::element::update_element(const rpl_gtid *gtid) +rpl_binlog_state_base::element::update_element(const rpl_gtid *gtid) { rpl_gtid *lookup_gtid; @@ -1938,6 +1942,7 @@ rpl_binlog_state::element::update_element(const rpl_gtid *gtid) return 0; } +#ifndef MYSQL_CLIENT /* Check that a new GTID can be logged without creating an out-of-order