diff --git a/mysql-test/main/rpl_info_file_line_count.result b/mysql-test/main/rpl_info_file_line_count.result new file mode 100644 index 0000000000000..0a747059c5558 --- /dev/null +++ b/mysql-test/main/rpl_info_file_line_count.result @@ -0,0 +1,8 @@ +CHANGE MASTER TO master_host='127.0.0.1'; +# restart: --skip-slave-start +Master_SSL_Key = '' +Using_Gtid = 'Current_Pos' +SQL_Delay = '0' +RESET SLAVE ALL; +Warnings: +Note 4190 RESET SLAVE is implicitly changing the value of 'Using_Gtid' from 'Current_Pos' to 'Slave_Pos' diff --git a/mysql-test/main/rpl_info_file_line_count.test b/mysql-test/main/rpl_info_file_line_count.test new file mode 100644 index 0000000000000..aa338f6c37463 --- /dev/null +++ b/mysql-test/main/rpl_info_file_line_count.test @@ -0,0 +1,74 @@ +# Line count / upgrading test for `@@master_info_file` & `@@relay_log_info_file` +# +# This regression test reminds that the line count includes the line count line. +# +# Reference: +# MDEV-39788 CHANGE MASTER savefiles read and write one line to many + +--source include/have_binlog_format_mixed.inc # format-agnostic +CHANGE MASTER TO master_host='127.0.0.1'; # have_info_files + +--let $MYSQLD_DATADIR= `SELECT @@datadir` + + +# `using_gtid` is the key-value section, not the 33rd option. +--remove_file $MYSQLD_DATADIR/master.info +--write_file $MYSQLD_DATADIR/master.info +33 + +4 +127.0.0.1 +root + +3306 +60 +1 + + + + + +1 +60.000 + +0 + +100000 + + + + + + + + + + + + + +using_gtid=1 +EOF + +# This file does not have the 6th option +# (neither does the current `@@relay_log_info_file`). +--remove_file $MYSQLD_DATADIR/relay-log.info +--write_file $MYSQLD_DATADIR/relay-log.info +6 +./mysqld-relay-bin.000001 +4 + +0 +0 +EOF + + +--let $restart_parameters= --skip-slave-start +--source include/restart_mysqld.inc + +--let $status_items= Master_SSL_Key, Using_Gtid, SQL_Delay +--source include/show_slave_status.inc + + +# Reset +RESET SLAVE ALL; diff --git a/sql/rpl_info_file.h b/sql/rpl_info_file.h index 493598f7bf5a8..3d98034dffbc2 100644 --- a/sql/rpl_info_file.h +++ b/sql/rpl_info_file.h @@ -294,9 +294,9 @@ struct Info_file auto &line1= dynamic_cast &>(values[0](this)); if (line1.load_from(&file)) return true; - char *end= str2int(line1.buf, 10, 0, INT32_MAX, &val); + char *end= str2int(line1.buf, 10, 1, INT32_MAX, &val); /** - If this first line was not a number - the line count, + If this first line was not a positive number - the line count, then it was the first value for real, so the for loop should then skip over it, the index 0 of the list. */ @@ -305,7 +305,8 @@ struct Info_file Set the default after parsing: While std::from_chars() does not replace the output if it failed, it does replace if the line is not fully spent. */ - size_t line_count= i ? default_line_count: static_cast(val); + size_t line_count= i ? default_line_count : + static_cast(val - 1); // remove the line count line from the count for (; i < line_count; ++i) { int c; @@ -355,10 +356,11 @@ struct Info_file } /* Pad additional reserved lines: - (1 for the line count line + line count) inclusive -> max line inclusive - = line count exclusive <- max line inclusive + (1 for the line count line + line count) exclusive -> max line inclusive + = line count exclusive -> max line exclusive */ - for (; total_line_count > size; --total_line_count) + // Pad additional reserved lines + while ((++size) < total_line_count) my_b_write_byte(&file, '\n'); }