summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Elkin <andrei.elkin@mariadb.com>2018-10-08 21:47:53 +0300
committerAndrei Elkin <andrei.elkin@mariadb.com>2018-10-16 12:42:57 +0300
commitd8974ebd677f97cf80bf0cd1446e60631895a5d7 (patch)
tree4a4bab7b1ef39ffe193aaaa0d6e0ed525c841efa
parent5a5bc21a65eb28f22b2896d96bd5fad0557b5719 (diff)
downloadmariadb-git-d8974ebd677f97cf80bf0cd1446e60631895a5d7.tar.gz
MDEV-14431 binlog.binlog_flush_binlogs_delete_domain failed in buildbot
The test and also rpl_gtid_delete_domain failed on PPC64 platform due to an incorrectly specified actual key for searching in a gtid domain system hash. While the correct size is 32 bits the supplied value was 8 bytes of long int size on the platform. The problem became evident thanks to the big endiness which cut off the *least* significant part of the value field. Fixed with correcting a dynamic array initialization to hold now uint32 values as well as the values extraction for searching in the gtid domain system hash. A new added test ensures no overflowed values are accepted for deletion which prevents inadvertent action. Notice though MariaDB [test]> set @@session.gtid_domain_id=(1 << 32) + 1; MariaDB [test]> show warnings; +---------+------+--------------------------------------------------------+ | Level | Code | Message | +---------+------+--------------------------------------------------------+ | Warning | 1292 | Truncated incorrect gtid_domain_id value: '4294967297' | +---------+------+--------------------------------------------------------+ MariaDB [test]> select @@session.gtid_domain_id; +--------------------------+ | @@session.gtid_domain_id | +--------------------------+ | 4294967295 | +--------------------------+
-rw-r--r--mysql-test/suite/binlog/r/binlog_flush_binlogs_delete_domain.result12
-rw-r--r--mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test19
-rw-r--r--sql/rpl_gtid.cc6
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_yacc.yy13
6 files changed, 47 insertions, 7 deletions
diff --git a/mysql-test/suite/binlog/r/binlog_flush_binlogs_delete_domain.result b/mysql-test/suite/binlog/r/binlog_flush_binlogs_delete_domain.result
index 99f2a57835f..fdcfb4bfa01 100644
--- a/mysql-test/suite/binlog/r/binlog_flush_binlogs_delete_domain.result
+++ b/mysql-test/suite/binlog/r/binlog_flush_binlogs_delete_domain.result
@@ -17,6 +17,12 @@ master-bin.000002 #
SET @@SESSION.gtid_domain_id=1;
SET @@SESSION.server_id=1;
CREATE TABLE t (a int);
+SELECT @@GLOBAL.gtid_binlog_state, @@GLOBAL.gtid_binlog_pos;
+@@GLOBAL.gtid_binlog_state @@GLOBAL.gtid_binlog_pos
+1-1-1 1-1-1
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Rotate # # master-bin.000002;pos=POS
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
ERROR HY000: Could not delete gtid domain. Reason: binlog files may contain gtids from the domain ('1') being deleted. Make sure to first purge those files.
FLUSH BINARY LOGS;
@@ -74,5 +80,11 @@ the following command succeeds with warnings
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
Warnings:
Warning 1076 The current gtid binlog state is incompatible with a former one having a gtid '11-11-1' which is less than the '11-11-11' of the gtid list describing an earlier state. The state may have been affected by manually injecting a lower sequence number gtid or via replication.
+RESET MASTER;
+FLUSH BINARY LOGS DELETE_DOMAIN_ID = (4294967296);
+ERROR HY000: The value of gtid domain being deleted ('4294967296') exceeds its maximum size of 32 bit unsigned integer
+FLUSH BINARY LOGS DELETE_DOMAIN_ID = (4294967295);
+Warnings:
+Warning 1076 The gtid domain being deleted ('4294967295') is not in the current binlog state
DROP TABLE t;
RESET MASTER;
diff --git a/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test b/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test
index 0faafa35a1b..8311f4bd800 100644
--- a/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test
+++ b/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test
@@ -28,6 +28,9 @@ FLUSH BINARY LOGS DELETE_DOMAIN_ID = (99);
SET @@SESSION.gtid_domain_id=1;
SET @@SESSION.server_id=1;
CREATE TABLE t (a int);
+SELECT @@GLOBAL.gtid_binlog_state, @@GLOBAL.gtid_binlog_pos;
+--let $binlog_start=
+--source include/show_binlog_events.inc
--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
@@ -129,6 +132,22 @@ SELECT @gtid_binlog_state_saved "as original state", @@GLOBAL.gtid_binlog_state
--echo the following command succeeds with warnings
--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($del_d_id)
+# cleanup: forget the out-of-order
+RESET MASTER;
+
+#
+# MDEV-14431
+# Check rejection to delete a domain with value exceeding its range's maximum
+#
+--let $d_max_plus_1=`SELECT 1 << 32`
+--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
+--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($d_max_plus_1)
+
+# accepted maximum:
+--let $d_max=`SELECT (1 << 32) - 1`
+--error 0
+--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($d_max)
+
#
# Cleanup
#
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index 955763fe195..2d4acde03fc 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -1846,10 +1846,10 @@ rpl_binlog_state::drop_domain(DYNAMIC_ARRAY *ids,
for (ulong i= 0; i < ids->elements; i++)
{
rpl_binlog_state::element *elem= NULL;
- ulong *ptr_domain_id;
+ uint32 *ptr_domain_id;
bool not_match;
- ptr_domain_id= (ulong*) dynamic_array_ptr(ids, i);
+ ptr_domain_id= (uint32*) dynamic_array_ptr(ids, i);
elem= (rpl_binlog_state::element *)
my_hash_search(&hash, (const uchar *) ptr_domain_id, 0);
if (!elem)
@@ -1870,7 +1870,7 @@ rpl_binlog_state::drop_domain(DYNAMIC_ARRAY *ids,
if (not_match)
{
- sprintf(errbuf, "binlog files may contain gtids from the domain ('%lu') "
+ sprintf(errbuf, "binlog files may contain gtids from the domain ('%u') "
"being deleted. Make sure to first purge those files",
*ptr_domain_id);
errmsg= errbuf;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 085ad1a4b3b..1e6abf74a85 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2882,7 +2882,7 @@ LEX::LEX()
INITIAL_LEX_PLUGIN_LIST_SIZE, 0);
reset_query_tables_list(TRUE);
mi.init();
- init_dynamic_array2(&delete_gtid_domain, sizeof(ulong*),
+ init_dynamic_array2(&delete_gtid_domain, sizeof(uint32),
gtid_domain_static_buffer,
initial_gtid_domain_buffer_size,
initial_gtid_domain_buffer_size, 0);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 05e31c28277..f1edc809579 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -2752,7 +2752,7 @@ public:
*/
DYNAMIC_ARRAY delete_gtid_domain;
static const ulong initial_gtid_domain_buffer_size= 16;
- ulong gtid_domain_static_buffer[initial_gtid_domain_buffer_size];
+ uint32 gtid_domain_static_buffer[initial_gtid_domain_buffer_size];
inline void set_limit_rows_examined()
{
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6ae65e0c50f..af1d67fb2cf 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -12829,9 +12829,18 @@ delete_domain_id_list:
;
delete_domain_id:
- ulong_num
+ ulonglong_num
{
- insert_dynamic(&Lex->delete_gtid_domain, (uchar*) &($1));
+ uint32 value= (uint32) $1;
+ if ($1 > UINT_MAX32)
+ {
+ my_printf_error(ER_BINLOG_CANT_DELETE_GTID_DOMAIN,
+ "The value of gtid domain being deleted ('%llu') "
+ "exceeds its maximum size "
+ "of 32 bit unsigned integer", MYF(0), $1);
+ MYSQL_YYABORT;
+ }
+ insert_dynamic(&Lex->delete_gtid_domain, (uchar*) &value);
}
;