From 2fc64d791c46fe50b413e579e07300132b28e77a Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 18 Mar 2024 08:09:02 +0100 Subject: [PATCH] CONC-689: Fix parsing of HEARTBEAT_LOG_EVENT: The heartbeat log event now contains the filename, instead of wrong header information (which was already processed when reading event header). --- include/mariadb_rpl.h | 5 +-- libmariadb/mariadb_rpl.c | 21 ++++----- unittest/libmariadb/rpl_api.c | 82 ++++++++++++++++++++++++++++++++--- 3 files changed, 86 insertions(+), 22 deletions(-) diff --git a/include/mariadb_rpl.h b/include/mariadb_rpl.h index ea0ca4db..f12fdfa1 100644 --- a/include/mariadb_rpl.h +++ b/include/mariadb_rpl.h @@ -501,10 +501,7 @@ struct st_mariadb_rpl_rows_event { }; struct st_mariadb_rpl_heartbeat_event { - uint32_t timestamp; - uint32_t next_position; - uint8_t type; - uint16_t flags; + MARIADB_STRING filename; }; struct st_mariadb_rpl_xa_prepare_log_event { diff --git a/libmariadb/mariadb_rpl.c b/libmariadb/mariadb_rpl.c index 0019f246..163c9723 100644 --- a/libmariadb/mariadb_rpl.c +++ b/libmariadb/mariadb_rpl.c @@ -1165,20 +1165,15 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN switch(rpl_event->event_type) { case UNKNOWN_EVENT: case SLAVE_EVENT: - return rpl_event; - break; + return rpl_event; + break; + case HEARTBEAT_LOG_EVENT: - /* no post header size */ - RPL_CHECK_POS(ev, ev_end, 11); - rpl_event->event.heartbeat.timestamp= uint4korr(ev); - ev+= 4; - rpl_event->event.heartbeat.next_position= uint4korr(ev); - ev+= 4; - rpl_event->event.heartbeat.type= (uint8_t)*ev; - ev+= 1; - rpl_event->event.heartbeat.flags= uint2korr(ev); - ev+= 2; - + len= rpl_event->event_length - (ev - ev_start) - (rpl->use_checksum ? 4 : 0) - (EVENT_HEADER_OFS - 1); + RPL_CHECK_POS(ev, ev_end, len); + rpl_event->event.heartbeat.filename.length= len; + rpl_event->event.heartbeat.filename.str= ev; + ev+= len; break; case BEGIN_LOAD_QUERY_EVENT: diff --git a/unittest/libmariadb/rpl_api.c b/unittest/libmariadb/rpl_api.c index f65a2915..84586a58 100644 --- a/unittest/libmariadb/rpl_api.c +++ b/unittest/libmariadb/rpl_api.c @@ -72,6 +72,7 @@ static int test_rpl_async(MYSQL *my __attribute__((unused))) mysql_query(mysql, "SET @mariadb_slave_capability=4"); mysql_query(mysql, "SET NAMES latin1"); mysql_query(mysql, "SET @slave_gtid_strict_mode=1"); + mysql_query(mysql, "SET @master_heartbeat_period=10"); mysql_query(mysql, "SET @slave_gtid_ignore_duplicates=1"); mysql_query(mysql, "SET NAMES utf8"); mysql_query(mysql, "SET @master_binlog_checksum= @@global.binlog_checksum"); @@ -85,7 +86,7 @@ static int test_rpl_async(MYSQL *my __attribute__((unused))) /* We run rpl_api as very last test, too make sure binary log contains > 10000 events. */ - while((event= mariadb_rpl_fetch(rpl, event)) && events < 10000) + while((event= mariadb_rpl_fetch(rpl, event)) && event->event_type != HEARTBEAT_LOG_EVENT) { events++; } @@ -142,6 +143,7 @@ static int test_rpl_semisync(MYSQL *my __attribute__((unused))) mysql_query(mysql, "SET NAMES latin1"); mysql_query(mysql, "SET @slave_gtid_strict_mode=1"); mysql_query(mysql, "SET @slave_gtid_ignore_duplicates=1"); + mysql_query(mysql, "SET @master_heartbeat_period=10"); mysql_query(mysql, "SET NAMES utf8"); mysql_query(mysql, "SET @master_binlog_checksum= @@global.binlog_checksum"); rpl->server_id= 12; @@ -161,10 +163,7 @@ static int test_rpl_semisync(MYSQL *my __attribute__((unused))) if (mariadb_rpl_open(rpl)) return FAIL; - /* We run rpl_api as very last test, too make sure - binary log contains > 10000 events. - */ - while((event= mariadb_rpl_fetch(rpl, event)) && events < 10000) + while((event= mariadb_rpl_fetch(rpl, event)) && event->event_type != HEARTBEAT_LOG_EVENT) { events++; } @@ -341,7 +340,80 @@ static int test_conc592(MYSQL *my __attribute__((unused))) return OK; } +static int test_conc689(MYSQL *my __attribute__((unused))) +{ + MYSQL *mysql= mysql_init(NULL); + MYSQL_RES *result; + MYSQL_ROW row; + MARIADB_RPL_EVENT *event= NULL; + MARIADB_RPL *rpl; + int events= 0, rc; + + SKIP_SKYSQL; + SKIP_MAXSCALE; + + if (!is_mariadb) + return SKIP; + + if (!my_test_connect(mysql, hostname, username, + password, schema, port, socketname, 0)) + { + diag("Error: %s", mysql_error(mysql)); + mysql_close(mysql); + return FAIL; + } + + rc= mysql_query(mysql, "SELECT @@log_bin"); + check_mysql_rc(rc, mysql); + + result= mysql_store_result(mysql); + row= mysql_fetch_row(result); + if (!atoi(row[0])) + rc= SKIP; + mysql_free_result(result); + + if (rc == SKIP) + { + diag("binary log disabled -> skip"); + mysql_close(mysql); + return SKIP; + } + + rpl = mariadb_rpl_init(mysql); + + mysql_query(mysql, "SET @mariadb_slave_capability=4"); + mysql_query(mysql, "SET NAMES latin1"); + mysql_query(mysql, "SET @slave_gtid_strict_mode=1"); + mysql_query(mysql, "SET @master_heartbeat_period=10"); + mysql_query(mysql, "SET @slave_gtid_ignore_duplicates=1"); + mysql_query(mysql, "SET NAMES utf8"); + mysql_query(mysql, "SET @master_binlog_checksum= @@global.binlog_checksum"); + rpl->server_id= 12; + rpl->start_position= 4; + rpl->flags= MARIADB_RPL_BINLOG_SEND_ANNOTATE_ROWS; + + if (mariadb_rpl_open(rpl)) + return FAIL; + + /* We run rpl_api as very last test, too make sure + binary log contains > 10000 events. + */ + while((event= mariadb_rpl_fetch(rpl, event)) && event->event_type != HEARTBEAT_LOG_EVENT) + { + events++; + } + FAIL_IF(event->event.heartbeat.filename.length == 0, "Invalid filename"); + diag("Filename: %.*s", event->event.heartbeat.filename.length, + event->event.heartbeat.filename.str); + mariadb_free_rpl_event(event); + mariadb_rpl_close(rpl); + mysql_close(mysql); + return OK; +} + + struct my_tests_st my_tests[] = { + {"test_conc689", test_conc689, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_conc592", test_conc592, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_rpl_async", test_rpl_async, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_rpl_semisync", test_rpl_semisync, TEST_CONNECTION_NEW, 0, NULL, NULL},