Skip to content

Commit e263e0b

Browse files
Merge pull request #5593 from kamil-holubicki/PS-9777-8.0
PS-9777: binlog_utils_udf plugin should handle binlog.index entries the same as the server code does
2 parents 1a749db + 8b8fe07 commit e263e0b

File tree

3 files changed

+73
-8
lines changed

3 files changed

+73
-8
lines changed

mysql-test/r/percona_binlog_utils_udf.result

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,7 +1655,5 @@ DELETE FROM loaded_ts;
16551655
LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/filtered_binlog_file' INTO TABLE loaded_ts;
16561656
include/assert.inc ['last record timestamp extracted via get_last_record_timestamp_by_binlog() for stage 16 should match the value extracted via mysqlbinlog']
16571657
DROP FUNCTION get_last_record_timestamp_by_binlog;
1658-
DROP TABLE loaded_ts;
16591658
UNINSTALL PLUGIN binlog_utils_udf;
1660-
DROP TABLE captured_gtid;
16611659
DROP TABLE t1;

mysql-test/t/percona_binlog_utils_udf.test

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,11 +338,59 @@ while($stage <= $number_of_stages)
338338
}
339339
DROP FUNCTION get_last_record_timestamp_by_binlog;
340340

341-
# temporary table cleanup
342-
DROP TABLE loaded_ts;
341+
342+
#
343+
# PS-9777 - binlog_utils_udf plugin should handle binlog.index entries the same as the server code does
344+
# Check that binlog_utils_udf plugin handles binlog.index file entries
345+
# that are filenames (no relative or absolute path) correctly.
346+
#
347+
--source include/have_util_sed.inc
348+
349+
# We only expect that the following won't fail at any stage. Actual results don't matter.
350+
--disable_query_log
351+
--disable_result_log
352+
eval CREATE FUNCTION get_gtid_set_by_binlog RETURNS STRING SONAME "$BINLOG_UTILS_UDF_LIB";
353+
eval CREATE FUNCTION get_binlog_by_gtid_set RETURNS STRING SONAME "$BINLOG_UTILS_UDF_LIB";
354+
eval CREATE FUNCTION get_binlog_by_gtid RETURNS STRING SONAME "$BINLOG_UTILS_UDF_LIB";
355+
eval CREATE FUNCTION get_last_gtid_from_binlog RETURNS STRING SONAME "$BINLOG_UTILS_UDF_LIB";
356+
eval CREATE FUNCTION get_first_record_timestamp_by_binlog RETURNS INTEGER SONAME "$BINLOG_UTILS_UDF_LIB";
357+
eval CREATE FUNCTION get_last_record_timestamp_by_binlog RETURNS INTEGER SONAME "$BINLOG_UTILS_UDF_LIB";
358+
359+
# Modify the index file (remove leading ./ leaving only binlog file names)
360+
--let $index_file = `SELECT @@log_bin_index`
361+
--exec $SED -i 's|^\./binlog\.|binlog.|' $index_file
362+
363+
# There will be no temp tables after restart
364+
--let $binlog_file_name = `SELECT binlog_name FROM captured_gtid LIMIT 1`
365+
--let $gtid_value = `SELECT gtid_value FROM captured_gtid LIMIT 1`
366+
367+
# mysqld uses a cache over index file. Restart the server to fetch the new index file content.
368+
--source include/restart_mysqld.inc
369+
370+
# restart re-enables query and resutl logs
371+
--disable_query_log
372+
--disable_result_log
373+
eval SELECT get_gtid_set_by_binlog('$binlog_file_name');
374+
--let $gtidset = `SELECT get_gtid_set_by_binlog('$binlog_file_name')`
375+
eval SELECT get_binlog_by_gtid_set('$gtidset');
376+
eval SELECT get_binlog_by_gtid('$gtid_value');
377+
eval SELECT get_last_gtid_from_binlog('$binlog_file_name');
378+
eval SELECT get_first_record_timestamp_by_binlog('$binlog_file_name');
379+
eval SELECT get_last_record_timestamp_by_binlog('$binlog_file_name');
380+
381+
DROP FUNCTION get_gtid_set_by_binlog;
382+
DROP FUNCTION get_binlog_by_gtid_set;
383+
DROP FUNCTION get_binlog_by_gtid;
384+
DROP FUNCTION get_last_gtid_from_binlog;
385+
DROP FUNCTION get_first_record_timestamp_by_binlog;
386+
DROP FUNCTION get_last_record_timestamp_by_binlog;
387+
--enable_query_log
388+
--enable_result_log
389+
390+
391+
# temporary table cleanup not needed as we restarted the server
343392

344393
--replace_result $BINLOG_UTILS_UDF_LIB BINLOG_UTILS_UDF_LIB
345394
UNINSTALL PLUGIN binlog_utils_udf;
346395

347-
DROP TABLE captured_gtid;
348396
DROP TABLE t1;

plugin/binlog_utils_udf/binlog_utils_udf.cc

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,25 @@ const char *get_short_binlog_name(const std::string &binlog_name) noexcept {
168168
return binlog_name.c_str() + dirname_length(binlog_name.c_str());
169169
}
170170

171+
//
172+
// Retrieves the contents of the index file. Then normalizes its entries (each
173+
// entry is prefixed with relative or absolute path)
174+
//
175+
std::pair<int, std::list<std::string>> get_normalized_log_index() {
176+
auto log_index = mysql_bin_log.get_log_index(true /* need_lock_index */);
177+
178+
auto &binlog_names = log_index.second;
179+
auto bg = std::begin(binlog_names);
180+
auto en = std::end(binlog_names);
181+
std::for_each(bg, en, [](std::string &s) {
182+
fn_reflen_buffer buf;
183+
check_and_normalize_binlog_name(get_short_binlog_name(s), buf);
184+
s.assign(buf);
185+
});
186+
187+
return log_index;
188+
}
189+
171190
log_event_ptr find_first_event(std::string_view binlog_name) {
172191
DBUG_TRACE;
173192

@@ -378,7 +397,7 @@ mysqlpp::udf_result_t<STRING_RESULT> get_binlog_by_gtid_impl::calculate(
378397
throw std::runtime_error("Cannot parse 'gtid_executed'");
379398
}
380399

381-
auto log_index = mysql_bin_log.get_log_index(true /* need_lock_index */);
400+
auto log_index = get_normalized_log_index();
382401
if (log_index.first != LOG_INFO_EOF)
383402
throw std::runtime_error("Cannot read binary log index'");
384403
if (log_index.second.empty())
@@ -480,7 +499,7 @@ mysqlpp::udf_result_t<STRING_RESULT> get_gtid_set_by_binlog_impl::calculate(
480499
const mysqlpp::udf_context &ctx) {
481500
DBUG_TRACE;
482501

483-
auto log_index = mysql_bin_log.get_log_index(true /* need_lock_index */);
502+
auto log_index = get_normalized_log_index();
484503
if (log_index.first != LOG_INFO_EOF)
485504
throw std::runtime_error("Cannot read binary log index");
486505
if (log_index.second.empty())
@@ -584,7 +603,7 @@ mysqlpp::udf_result_t<STRING_RESULT> get_binlog_by_gtid_set_impl::calculate(
584603
throw std::runtime_error("Cannot parse 'gtid_executed'");
585604
}
586605

587-
auto log_index = mysql_bin_log.get_log_index(true /* need_lock_index */);
606+
auto log_index = get_normalized_log_index();
588607
if (log_index.first != LOG_INFO_EOF)
589608
throw std::runtime_error("Cannot read binary log index'");
590609
if (log_index.second.empty())

0 commit comments

Comments
 (0)