Commit 14c40509 authored by Yuchen Pei's avatar Yuchen Pei

MDEV-32492 Delete and remove trx_ha on spider share mismatch

A SPIDER_TRX_HA associated with a SPIDER_TRX could have longer
lifetime than its associated SPIDER_SHARE. And it is identified with
the associated table name. When the SPIDER_SHARE no longer valid, e.g.
when the associated spider table has been dropped and recreated, the
SPIDER_TRX_HA should be reset too.

Since spider could create a new SPIDER_SHARE with the exact same
address of a freed SPIDER_SHARE, we try to mark all SPIDER_TRX_HAs
associated with a SPIDER_SHARE invalid when the SPIDER_SHARE is about
to be freed.
parent 653050ac
......@@ -584,6 +584,25 @@ int ha_spider::open(
DBUG_RETURN(error_num);
}
/*
Given a SPIDER_SHARE that will be freed, update all SPIDER_TRX_HAs
of spider_current_trx to point to a NULL share, which will cause the
removal of the SPIDER_TRX_HA in spider_check_trx_ha().
*/
static void spider_update_current_trx_ha_with_freed_share(SPIDER_SHARE *share)
{
SPIDER_TRX *trx= spider_current_trx;
if (trx)
{
for (uint i = 0; i < trx->trx_ha_hash.records; i++)
{
SPIDER_TRX_HA *trx_ha = (SPIDER_TRX_HA *) my_hash_element(&trx->trx_ha_hash, i);
if (trx_ha->share == share)
trx_ha->share= NULL;
}
}
}
int ha_spider::close()
{
int error_num = 0, roop_count, error_num2;
......@@ -711,6 +730,7 @@ int ha_spider::close()
result_list.tmp_sqls = NULL;
}
spider_update_current_trx_ha_with_freed_share(share);
spider_free_share(share);
is_clone = FALSE;
pt_clone_source_handler = NULL;
......
#
# MDEV-32492 SIGSEGV in spider_conn_first_link_idx on DELETE
#
for master_1
for child2
for child3
set spider_same_server_link= 1;
CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
CREATE TABLE t (c INT, PRIMARY KEY(c)) ENGINE=Spider;
SHOW CREATE TABLE t;
Table Create Table
t CREATE TABLE `t` (
`c` int(11) NOT NULL,
PRIMARY KEY (`c`)
) ENGINE=SPIDER DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
Warnings:
Error 1429 Unable to connect to foreign data source: localhost
Error 1429 Unable to connect to foreign data source: localhost
DROP TABLE t;
CREATE TABLE t (c INT) ENGINE=Spider COMMENT='port "1 1"';
DELETE FROM t;
ERROR HY000: Unable to connect to foreign data source: localhost
drop table t;
CREATE TABLE t1 (a INT,b VARCHAR(255),PRIMARY KEY(a)) ENGINE=Spider comment="srv 'srv', table 't1', read_only_mode '1'";
INSERT INTO t1 VALUES (1,'aaa'),(2,'bbb'),(3,'ccc'),(4,'ddd');
ERROR HY000: Table 'test.t1' is read only
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` varchar(255) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=SPIDER DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci COMMENT='srv ''srv'', table ''t1'', read_only_mode ''1'''
Warnings:
Error 12719 An infinite loop is detected when opening table test.t1
DROP TABLE t1;
CREATE TABLE t1 (a INT) ENGINE=Spider comment="port '123 456'";
INSERT IGNORE INTO t1 VALUES (42),(42);
ERROR HY000: Unable to connect to foreign data source: localhost
drop table t1;
CREATE TABLE t1 (c INT, KEY(c)) ENGINE=Spider COMMENT='WRAPPER "mysql", SRV "srv",TABLE "t2", PK_NAME "f"';
SET GLOBAL general_log=1;
INSERT INTO t1 VALUES (1, "aaa"),(2, "bbb"),(3, "ccc"),(4, "ddd");
ERROR 21S01: Column count doesn't match value count at row 1
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c` int(11) DEFAULT NULL,
KEY `c` (`c`)
) ENGINE=SPIDER DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci COMMENT='WRAPPER "mysql", SRV "srv",TABLE "t2", PK_NAME "f"'
Warnings:
Error 12702 Remote table 'test.t2' is not found
DROP TABLE t1;
CREATE TABLE t1 (a INT) ENGINE=Spider comment='port "123 456"';
SELECT * FROM t1;
ERROR HY000: Unable to connect to foreign data source: localhost
INSERT IGNORE INTO t1 VALUES (42),(42);
ERROR HY000: Unable to connect to foreign data source: localhost
drop table t1;
drop server srv;
for master_1
for child2
for child3
#
# end of test mdev_32492
#
--echo #
--echo # MDEV-32492 SIGSEGV in spider_conn_first_link_idx on DELETE
--echo #
--disable_query_log
--disable_result_log
--source ../../t/test_init.inc
--enable_result_log
--enable_query_log
set spider_same_server_link= 1;
evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
CREATE TABLE t (c INT, PRIMARY KEY(c)) ENGINE=Spider;
--disable_ps_protocol
SHOW CREATE TABLE t;
--enable_ps_protocol
DROP TABLE t;
CREATE TABLE t (c INT) ENGINE=Spider COMMENT='port "1 1"';
--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
DELETE FROM t;
drop table t;
CREATE TABLE t1 (a INT,b VARCHAR(255),PRIMARY KEY(a)) ENGINE=Spider comment="srv 'srv', table 't1', read_only_mode '1'";
--error 12518
INSERT INTO t1 VALUES (1,'aaa'),(2,'bbb'),(3,'ccc'),(4,'ddd');
--disable_ps_protocol
SHOW CREATE TABLE t1;
--enable_ps_protocol
DROP TABLE t1;
CREATE TABLE t1 (a INT) ENGINE=Spider comment="port '123 456'";
# bug crash site
--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
INSERT IGNORE INTO t1 VALUES (42),(42);
drop table t1;
CREATE TABLE t1 (c INT, KEY(c)) ENGINE=Spider COMMENT='WRAPPER "mysql", SRV "srv",TABLE "t2", PK_NAME "f"';
SET GLOBAL general_log=1;
--error ER_WRONG_VALUE_COUNT_ON_ROW
INSERT INTO t1 VALUES (1, "aaa"),(2, "bbb"),(3, "ccc"),(4, "ddd");
--disable_ps_protocol
SHOW CREATE TABLE t1;
--enable_ps_protocol
DROP TABLE t1;
CREATE TABLE t1 (a INT) ENGINE=Spider comment='port "123 456"';
# bug crash site
--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
SELECT * FROM t1;
--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
INSERT IGNORE INTO t1 VALUES (42),(42);
drop table t1;
drop server srv;
--disable_query_log
--disable_result_log
--source ../../t/test_deinit.inc
--enable_result_log
--enable_query_log
--echo #
--echo # end of test mdev_32492
--echo #
......@@ -1092,6 +1092,7 @@ int spider_free_trx_alloc(
DBUG_RETURN(0);
}
/* Get or create a trx associated with the given THD. */
SPIDER_TRX *spider_get_trx(
THD *thd,
bool regist_allocated_thds,
......@@ -3863,6 +3864,11 @@ SPIDER_TRX_HA *spider_check_trx_ha(
SPIDER_TRX_HA *trx_ha;
SPIDER_SHARE *share = spider->share;
DBUG_ENTER("spider_check_trx_ha");
/*
Check for mismatch in trx_ha->share, link_count and
link_bitmap_size, which is an indication of a share that has been
freed. Delete the trx_ha and return NULL on mismatch.
*/
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
if ((trx_ha = (SPIDER_TRX_HA *) my_hash_search_using_hash_value(
&trx->trx_ha_hash, share->table_name_hash_value,
......@@ -3872,11 +3878,20 @@ SPIDER_TRX_HA *spider_check_trx_ha(
(uchar*) share->table_name, share->table_name_length)))
#endif
{
memcpy(spider->conn_link_idx, trx_ha->conn_link_idx,
sizeof(uint) * share->link_count);
memcpy(spider->conn_can_fo, trx_ha->conn_can_fo,
sizeof(uint) * share->link_bitmap_size);
DBUG_RETURN(trx_ha);
if (trx_ha->share == share && trx_ha->link_count == share->link_count &&
trx_ha->link_bitmap_size == share->link_bitmap_size)
{
memcpy(spider->conn_link_idx, trx_ha->conn_link_idx,
sizeof(uint) * share->link_count);
memcpy(spider->conn_can_fo, trx_ha->conn_can_fo,
sizeof(uint) * share->link_bitmap_size);
DBUG_RETURN(trx_ha);
}
else
{
my_hash_delete(&trx->trx_ha_hash, (uchar*) trx_ha);
spider_free(trx, trx_ha, MYF(0));
}
}
DBUG_RETURN(NULL);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment