mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-34541 Clean up spider self reference check
SPIDER_CONN::loop_check_meraged_first is useless, because all SPIDER_CONN_LOOP_CHECKs are in SPIDER_CONN::loop_check_queue, which in spider_db_conn::fin_loop_check() is iterated over. This fixes the use-after-free issue when there are three spider tables sharing the same remote, and their corresponding SPIDER_CONN_LOOP_CHECKs getting merged in spider_conn_queue_and_merge_loop_check() This also fixes MDEV-34555
This commit is contained in:
35
storage/spider/mysql-test/spider/bugfix/r/mdev_34541.result
Normal file
35
storage/spider/mysql-test/spider/bugfix/r/mdev_34541.result
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
for master_1
|
||||||
|
for child2
|
||||||
|
for child3
|
||||||
|
SET SESSION spider_same_server_link=1;
|
||||||
|
SET sql_mode='';
|
||||||
|
set @old_table_open_cache=@@global.table_open_cache;
|
||||||
|
set global table_open_cache=10;
|
||||||
|
set spider_same_server_link= 1;
|
||||||
|
CREATE SERVER srv FOREIGN DATA WRAPPER mysql
|
||||||
|
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
|
||||||
|
CREATE TABLE t1 (c INT) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t2 (c INT) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t3 (c INT) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE ta (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
CREATE TABLE t5 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
CREATE TABLE t6 (c INT KEY) ENGINE=InnoDB PARTITION BY RANGE (c) (PARTITION p VALUES LESS THAN (5));
|
||||||
|
CREATE TABLE t7 (a INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
CREATE TABLE t8 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
SELECT * FROM t8;
|
||||||
|
ERROR HY000: Remote table 'test.t' is not found
|
||||||
|
CREATE TEMPORARY TABLE t7 (c INT) ENGINE=InnoDB SELECT * FROM t7;
|
||||||
|
ERROR HY000: Remote table 'test.t' is not found
|
||||||
|
CALL foo;
|
||||||
|
ERROR 42000: PROCEDURE test.foo does not exist
|
||||||
|
CREATE TEMPORARY TABLE t7 (c INT) ENGINE=InnoDB;
|
||||||
|
SELECT * FROM t7 JOIN t6 ON tc=t0.c;
|
||||||
|
ERROR 42S22: Unknown column 'tc' in 'on clause'
|
||||||
|
SHOW TABLE STATUS;
|
||||||
|
drop table ta, t8, t7, t6, t5, t3, t2, t1;
|
||||||
|
drop table t7;
|
||||||
|
drop server srv;
|
||||||
|
set global table_open_cache=@old_table_open_cache;
|
||||||
|
for master_1
|
||||||
|
for child2
|
||||||
|
for child3
|
32
storage/spider/mysql-test/spider/bugfix/r/mdev_34555.result
Normal file
32
storage/spider/mysql-test/spider/bugfix/r/mdev_34555.result
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
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 '',user 'Spider', password 'foo');
|
||||||
|
CREATE TABLE tSpider (a INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
CREATE TABLE t2 (c INT,c2 CHAR(1)) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
XA START 'a';
|
||||||
|
SELECT * FROM information_schema.table_constraints;
|
||||||
|
SELECT SLEEP (1);
|
||||||
|
SLEEP (1)
|
||||||
|
0
|
||||||
|
SELECT * FROM t2;
|
||||||
|
ERROR HY000: Unable to connect to foreign data source: srv
|
||||||
|
SELECT SLEEP (1);
|
||||||
|
SLEEP (1)
|
||||||
|
0
|
||||||
|
SELECT * FROM t2;
|
||||||
|
ERROR HY000: Unable to connect to foreign data source: srv
|
||||||
|
SELECT SLEEP (1);
|
||||||
|
SLEEP (1)
|
||||||
|
0
|
||||||
|
SELECT * FROM t2;
|
||||||
|
ERROR HY000: Unable to connect to foreign data source: srv
|
||||||
|
xa end 'a';
|
||||||
|
xa rollback 'a';
|
||||||
|
drop table tSpider, t2;
|
||||||
|
drop server srv;
|
||||||
|
for master_1
|
||||||
|
for child2
|
||||||
|
for child3
|
48
storage/spider/mysql-test/spider/bugfix/t/mdev_34541.test
Normal file
48
storage/spider/mysql-test/spider/bugfix/t/mdev_34541.test
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
--disable_query_log
|
||||||
|
--disable_result_log
|
||||||
|
--source ../../t/test_init.inc
|
||||||
|
--enable_result_log
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
SET SESSION spider_same_server_link=1;
|
||||||
|
SET sql_mode='';
|
||||||
|
|
||||||
|
set @old_table_open_cache=@@global.table_open_cache;
|
||||||
|
set global table_open_cache=10;
|
||||||
|
|
||||||
|
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 t1 (c INT) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t2 (c INT) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t3 (c INT) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE ta (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
CREATE TABLE t5 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
CREATE TABLE t6 (c INT KEY) ENGINE=InnoDB PARTITION BY RANGE (c) (PARTITION p VALUES LESS THAN (5));
|
||||||
|
CREATE TABLE t7 (a INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
CREATE TABLE t8 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
--error 12702
|
||||||
|
SELECT * FROM t8;
|
||||||
|
--error 12702
|
||||||
|
CREATE TEMPORARY TABLE t7 (c INT) ENGINE=InnoDB SELECT * FROM t7;
|
||||||
|
--error ER_SP_DOES_NOT_EXIST
|
||||||
|
CALL foo;
|
||||||
|
CREATE TEMPORARY TABLE t7 (c INT) ENGINE=InnoDB;
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
SELECT * FROM t7 JOIN t6 ON tc=t0.c;
|
||||||
|
--disable_result_log
|
||||||
|
SHOW TABLE STATUS;
|
||||||
|
--enable_result_log
|
||||||
|
|
||||||
|
# we need to drop t7 twice
|
||||||
|
drop table ta, t8, t7, t6, t5, t3, t2, t1;
|
||||||
|
drop table t7;
|
||||||
|
drop server srv;
|
||||||
|
set global table_open_cache=@old_table_open_cache;
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
--disable_result_log
|
||||||
|
--source ../../t/test_deinit.inc
|
||||||
|
--enable_result_log
|
||||||
|
--enable_query_log
|
33
storage/spider/mysql-test/spider/bugfix/t/mdev_34555.test
Normal file
33
storage/spider/mysql-test/spider/bugfix/t/mdev_34555.test
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
--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 '',user 'Spider', password 'foo');
|
||||||
|
CREATE TABLE tSpider (a INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
CREATE TABLE t2 (c INT,c2 CHAR(1)) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
|
||||||
|
XA START 'a';
|
||||||
|
--disable_result_log
|
||||||
|
--error 0,ER_CONNECT_TO_FOREIGN_DATA_SOURCE
|
||||||
|
SELECT * FROM information_schema.table_constraints;
|
||||||
|
--enable_result_log
|
||||||
|
SELECT SLEEP (1);
|
||||||
|
--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
|
||||||
|
SELECT * FROM t2;
|
||||||
|
SELECT SLEEP (1);
|
||||||
|
--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
|
||||||
|
SELECT * FROM t2;
|
||||||
|
SELECT SLEEP (1);
|
||||||
|
--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
|
||||||
|
SELECT * FROM t2;
|
||||||
|
xa end 'a';
|
||||||
|
xa rollback 'a';
|
||||||
|
drop table tSpider, t2;
|
||||||
|
drop server srv;
|
||||||
|
--disable_query_log
|
||||||
|
--disable_result_log
|
||||||
|
--source ../../t/test_deinit.inc
|
||||||
|
--enable_result_log
|
||||||
|
--enable_query_log
|
@@ -1151,27 +1151,41 @@ void spider_conn_queue_UTC_time_zone(
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Construct merged values and insert into the loop check queue
|
||||||
|
|
||||||
|
Search the loop_check_queue for the data node table, and if one does
|
||||||
|
not exist, construct the merged value in the same format as the
|
||||||
|
right hand side. Otherwise, merge the right hand side of the
|
||||||
|
existing SPIDER_CONN_LOOP_CHECK with the right hand side of lcptr
|
||||||
|
into one right hand side. In either case, add the
|
||||||
|
SPIDER_CONN_LOOP_CHECK to the loop check queue
|
||||||
|
*/
|
||||||
int spider_conn_queue_and_merge_loop_check(
|
int spider_conn_queue_and_merge_loop_check(
|
||||||
SPIDER_CONN *conn,
|
SPIDER_CONN *conn,
|
||||||
SPIDER_CONN_LOOP_CHECK *lcptr
|
SPIDER_CONN_LOOP_CHECK *lcptr
|
||||||
) {
|
) {
|
||||||
int error_num = HA_ERR_OUT_OF_MEM;
|
int error_num = HA_ERR_OUT_OF_MEM;
|
||||||
char *tmp_name, *from_name, *cur_name, *to_name, *full_name, *from_value,
|
char *tmp_name, *cur_name, *to_name, *full_name, *from_value,
|
||||||
*merged_value;
|
*merged_value;
|
||||||
SPIDER_CONN_LOOP_CHECK *lcqptr, *lcrptr;
|
SPIDER_CONN_LOOP_CHECK *lcqptr, *lcrptr;
|
||||||
DBUG_ENTER("spider_conn_queue_and_merge_loop_check");
|
DBUG_ENTER("spider_conn_queue_and_merge_loop_check");
|
||||||
DBUG_PRINT("info", ("spider conn=%p", conn));
|
DBUG_PRINT("info", ("spider conn=%p", conn));
|
||||||
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
|
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
|
||||||
if (unlikely(!(lcqptr = (SPIDER_CONN_LOOP_CHECK *)
|
if (!(lcqptr = (SPIDER_CONN_LOOP_CHECK *)
|
||||||
my_hash_search_using_hash_value(&conn->loop_check_queue,
|
my_hash_search_using_hash_value(&conn->loop_check_queue,
|
||||||
lcptr->hash_value_to,
|
lcptr->hash_value_to,
|
||||||
(uchar *) lcptr->to_name.str, lcptr->to_name.length))))
|
(uchar *) lcptr->to_name.str, lcptr->to_name.length)))
|
||||||
#else
|
#else
|
||||||
if (unlikely(!(lcqptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_search(
|
if (unlikely(!(lcqptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_search(
|
||||||
&conn->loop_check_queue,
|
&conn->loop_check_queue,
|
||||||
(uchar *) lcptr->to_name.str, lcptr->to_name.length))))
|
(uchar *) lcptr->to_name.str, lcptr->to_name.length))))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Construct the right hand side:
|
||||||
|
-<mac>-<pid>-<cur_table>-<from_value>
|
||||||
|
*/
|
||||||
DBUG_PRINT("info", ("spider create merged_value and insert"));
|
DBUG_PRINT("info", ("spider create merged_value and insert"));
|
||||||
lcptr->merged_value.length = spider_unique_id.length +
|
lcptr->merged_value.length = spider_unique_id.length +
|
||||||
lcptr->cur_name.length + lcptr->from_value.length + 1;
|
lcptr->cur_name.length + lcptr->from_value.length + 1;
|
||||||
@@ -1194,10 +1208,10 @@ int spider_conn_queue_and_merge_loop_check(
|
|||||||
}
|
}
|
||||||
lcptr->flag |= SPIDER_LOP_CHK_QUEUED;
|
lcptr->flag |= SPIDER_LOP_CHK_QUEUED;
|
||||||
} else {
|
} else {
|
||||||
|
/* Merge lcptr and lcqptr into a newly created lcrptr. */
|
||||||
DBUG_PRINT("info", ("spider append merged_value and replace"));
|
DBUG_PRINT("info", ("spider append merged_value and replace"));
|
||||||
if (unlikely(!spider_bulk_malloc(spider_current_trx, 271, MYF(MY_WME),
|
if (unlikely(!spider_bulk_malloc(spider_current_trx, 271, MYF(MY_WME),
|
||||||
&lcrptr, (uint) (sizeof(SPIDER_CONN_LOOP_CHECK)),
|
&lcrptr, (uint) (sizeof(SPIDER_CONN_LOOP_CHECK)),
|
||||||
&from_name, (uint) (lcqptr->from_name.length + 1),
|
|
||||||
&cur_name, (uint) (lcqptr->cur_name.length + 1),
|
&cur_name, (uint) (lcqptr->cur_name.length + 1),
|
||||||
&to_name, (uint) (lcqptr->to_name.length + 1),
|
&to_name, (uint) (lcqptr->to_name.length + 1),
|
||||||
&full_name, (uint) (lcqptr->full_name.length + 1),
|
&full_name, (uint) (lcqptr->full_name.length + 1),
|
||||||
@@ -1209,13 +1223,13 @@ int spider_conn_queue_and_merge_loop_check(
|
|||||||
)) {
|
)) {
|
||||||
goto error_alloc_loop_check_replace;
|
goto error_alloc_loop_check_replace;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
TODO: the new lcrptr has the same cur_name, to_name, full_name
|
||||||
|
and from_value as lcqptr, but they do not seem to be relevant.
|
||||||
|
*/
|
||||||
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
|
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
|
||||||
lcrptr->hash_value_to = lcqptr->hash_value_to;
|
lcrptr->hash_value_to = lcqptr->hash_value_to;
|
||||||
lcrptr->hash_value_full = lcqptr->hash_value_full;
|
|
||||||
#endif
|
#endif
|
||||||
lcrptr->from_name.str = from_name;
|
|
||||||
lcrptr->from_name.length = lcqptr->from_name.length;
|
|
||||||
memcpy(from_name, lcqptr->from_name.str, lcqptr->from_name.length + 1);
|
|
||||||
lcrptr->cur_name.str = cur_name;
|
lcrptr->cur_name.str = cur_name;
|
||||||
lcrptr->cur_name.length = lcqptr->cur_name.length;
|
lcrptr->cur_name.length = lcqptr->cur_name.length;
|
||||||
memcpy(cur_name, lcqptr->cur_name.str, lcqptr->cur_name.length + 1);
|
memcpy(cur_name, lcqptr->cur_name.str, lcqptr->cur_name.length + 1);
|
||||||
@@ -1228,8 +1242,14 @@ int spider_conn_queue_and_merge_loop_check(
|
|||||||
lcrptr->from_value.str = from_value;
|
lcrptr->from_value.str = from_value;
|
||||||
lcrptr->from_value.length = lcqptr->from_value.length;
|
lcrptr->from_value.length = lcqptr->from_value.length;
|
||||||
memcpy(from_value, lcqptr->from_value.str, lcqptr->from_value.length + 1);
|
memcpy(from_value, lcqptr->from_value.str, lcqptr->from_value.length + 1);
|
||||||
|
/*
|
||||||
|
The merged_value of lcrptr is a concatenation of that of lcqptr
|
||||||
|
and constructed merged_value from lcptr.
|
||||||
|
*/
|
||||||
lcrptr->merged_value.str = merged_value;
|
lcrptr->merged_value.str = merged_value;
|
||||||
lcrptr->merged_value.length = lcqptr->merged_value.length;
|
lcrptr->merged_value.length =
|
||||||
|
lcqptr->merged_value.length + spider_unique_id.length +
|
||||||
|
lcptr->cur_name.length + 1 + lcptr->from_value.length;
|
||||||
memcpy(merged_value,
|
memcpy(merged_value,
|
||||||
lcqptr->merged_value.str, lcqptr->merged_value.length);
|
lcqptr->merged_value.str, lcqptr->merged_value.length);
|
||||||
merged_value += lcqptr->merged_value.length;
|
merged_value += lcqptr->merged_value.length;
|
||||||
@@ -1273,9 +1293,6 @@ int spider_conn_queue_and_merge_loop_check(
|
|||||||
goto error_hash_insert_queue;
|
goto error_hash_insert_queue;
|
||||||
}
|
}
|
||||||
lcptr->flag = SPIDER_LOP_CHK_MERAGED;
|
lcptr->flag = SPIDER_LOP_CHK_MERAGED;
|
||||||
lcptr->next = NULL;
|
|
||||||
if (!conn->loop_check_meraged_first)
|
|
||||||
conn->loop_check_meraged_first = lcptr;
|
|
||||||
}
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
@@ -1296,7 +1313,6 @@ error_hash_insert:
|
|||||||
int spider_conn_reset_queue_loop_check(
|
int spider_conn_reset_queue_loop_check(
|
||||||
SPIDER_CONN *conn
|
SPIDER_CONN *conn
|
||||||
) {
|
) {
|
||||||
int error_num;
|
|
||||||
SPIDER_CONN_LOOP_CHECK *lcptr;
|
SPIDER_CONN_LOOP_CHECK *lcptr;
|
||||||
DBUG_ENTER("spider_conn_reset_queue_loop_check");
|
DBUG_ENTER("spider_conn_reset_queue_loop_check");
|
||||||
uint l = 0;
|
uint l = 0;
|
||||||
@@ -1318,30 +1334,8 @@ int spider_conn_reset_queue_loop_check(
|
|||||||
++l;
|
++l;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcptr = conn->loop_check_ignored_first;
|
|
||||||
while (lcptr)
|
|
||||||
{
|
|
||||||
lcptr->flag = 0;
|
|
||||||
if ((error_num = spider_conn_queue_and_merge_loop_check(conn, lcptr)))
|
|
||||||
{
|
|
||||||
goto error_queue_and_merge;
|
|
||||||
}
|
|
||||||
lcptr = lcptr->next;
|
|
||||||
}
|
|
||||||
conn->loop_check_meraged_first = NULL;
|
|
||||||
pthread_mutex_unlock(&conn->loop_check_mutex);
|
pthread_mutex_unlock(&conn->loop_check_mutex);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
error_queue_and_merge:
|
|
||||||
lcptr = lcptr->next;
|
|
||||||
while (lcptr)
|
|
||||||
{
|
|
||||||
lcptr->flag = 0;
|
|
||||||
lcptr = lcptr->next;
|
|
||||||
}
|
|
||||||
conn->loop_check_meraged_first = NULL;
|
|
||||||
pthread_mutex_unlock(&conn->loop_check_mutex);
|
|
||||||
DBUG_RETURN(error_num);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int spider_conn_queue_loop_check(
|
int spider_conn_queue_loop_check(
|
||||||
@@ -1352,7 +1346,7 @@ int spider_conn_queue_loop_check(
|
|||||||
int error_num = HA_ERR_OUT_OF_MEM;
|
int error_num = HA_ERR_OUT_OF_MEM;
|
||||||
uint conn_link_idx = spider->conn_link_idx[link_idx], buf_sz;
|
uint conn_link_idx = spider->conn_link_idx[link_idx], buf_sz;
|
||||||
char path[FN_REFLEN + 1];
|
char path[FN_REFLEN + 1];
|
||||||
char *tmp_name, *from_name, *cur_name, *to_name, *full_name, *from_value,
|
char *tmp_name, *cur_name, *to_name, *full_name, *from_value,
|
||||||
*merged_value;
|
*merged_value;
|
||||||
user_var_entry *loop_check;
|
user_var_entry *loop_check;
|
||||||
char *loop_check_buf;
|
char *loop_check_buf;
|
||||||
@@ -1363,6 +1357,17 @@ int spider_conn_queue_loop_check(
|
|||||||
LEX_CSTRING lex_str, from_str, to_str;
|
LEX_CSTRING lex_str, from_str, to_str;
|
||||||
DBUG_ENTER("spider_conn_queue_loop_check");
|
DBUG_ENTER("spider_conn_queue_loop_check");
|
||||||
DBUG_PRINT("info", ("spider conn=%p", conn));
|
DBUG_PRINT("info", ("spider conn=%p", conn));
|
||||||
|
/*
|
||||||
|
construct loop check user var name (left hand side) into
|
||||||
|
lex_str. It is of the format
|
||||||
|
|
||||||
|
spider_lc_<spider_table_name>
|
||||||
|
|
||||||
|
So if the spider table name is ./test/t1, then the constructed
|
||||||
|
user var name is:
|
||||||
|
|
||||||
|
spider_lc_./test/t1
|
||||||
|
*/
|
||||||
lex_str.length = top_share->path.length + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN;
|
lex_str.length = top_share->path.length + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN;
|
||||||
buf_sz = lex_str.length + 2;
|
buf_sz = lex_str.length + 2;
|
||||||
loop_check_buf = (char *) my_alloca(buf_sz);
|
loop_check_buf = (char *) my_alloca(buf_sz);
|
||||||
@@ -1388,6 +1393,16 @@ int spider_conn_queue_loop_check(
|
|||||||
} else {
|
} else {
|
||||||
lex_str.str = loop_check->value;
|
lex_str.str = loop_check->value;
|
||||||
lex_str.length = loop_check->length;
|
lex_str.length = loop_check->length;
|
||||||
|
/*
|
||||||
|
Validate that there are at least four dashes in the user var
|
||||||
|
value: -<mac_addr>-<proc_id>-<table_name>-
|
||||||
|
|
||||||
|
Note: if the value is merged from multiple values, such as
|
||||||
|
|
||||||
|
"-<mac1>-<pid1>-<table_name1>--<mac2>-<pid2>-<table_name2>--<mac3>-<pid3>-<table_name3>-"
|
||||||
|
|
||||||
|
then only the first component is put into from_str
|
||||||
|
*/
|
||||||
DBUG_PRINT("info", ("spider from_str=%s", lex_str.str));
|
DBUG_PRINT("info", ("spider from_str=%s", lex_str.str));
|
||||||
if (unlikely(!(tmp_name = strchr(loop_check->value, '-'))))
|
if (unlikely(!(tmp_name = strchr(loop_check->value, '-'))))
|
||||||
{
|
{
|
||||||
@@ -1415,12 +1430,23 @@ int spider_conn_queue_loop_check(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Validation passed. Put the first component of rhs in from_str
|
||||||
|
*/
|
||||||
from_str.str = lex_str.str;
|
from_str.str = lex_str.str;
|
||||||
from_str.length = tmp_name - lex_str.str + 1;
|
from_str.length = tmp_name - lex_str.str + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
my_afree(loop_check_buf);
|
my_afree(loop_check_buf);
|
||||||
|
/*
|
||||||
|
construct loop_check_buf as <from_str>-<cur>-<to_str> e.g.
|
||||||
|
"-<mac>-<pid>-./test/t0--./test/t1-./test/t2", later used as
|
||||||
|
full_name
|
||||||
|
|
||||||
|
from_str is the first component in the user var value (RHS) or
|
||||||
|
empty if user var value is empty, cur is the spider table, to_str
|
||||||
|
is the remote data node table
|
||||||
|
*/
|
||||||
to_str.length = build_table_filename(path, FN_REFLEN,
|
to_str.length = build_table_filename(path, FN_REFLEN,
|
||||||
share->tgt_dbs[conn_link_idx] ? share->tgt_dbs[conn_link_idx] : "",
|
share->tgt_dbs[conn_link_idx] ? share->tgt_dbs[conn_link_idx] : "",
|
||||||
share->tgt_table_names[conn_link_idx], "", 0);
|
share->tgt_table_names[conn_link_idx], "", 0);
|
||||||
@@ -1457,7 +1483,7 @@ int spider_conn_queue_loop_check(
|
|||||||
lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_search(
|
lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_search(
|
||||||
&conn->loop_checked, (uchar *) loop_check_buf, buf_sz - 1);
|
&conn->loop_checked, (uchar *) loop_check_buf, buf_sz - 1);
|
||||||
#endif
|
#endif
|
||||||
if (unlikely(
|
if (
|
||||||
!lcptr ||
|
!lcptr ||
|
||||||
(
|
(
|
||||||
!lcptr->flag &&
|
!lcptr->flag &&
|
||||||
@@ -1466,7 +1492,7 @@ int spider_conn_queue_loop_check(
|
|||||||
memcmp(lcptr->from_value.str, lex_str.str, lex_str.length)
|
memcmp(lcptr->from_value.str, lex_str.str, lex_str.length)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
))
|
)
|
||||||
{
|
{
|
||||||
if (unlikely(lcptr))
|
if (unlikely(lcptr))
|
||||||
{
|
{
|
||||||
@@ -1482,7 +1508,6 @@ int spider_conn_queue_loop_check(
|
|||||||
DBUG_PRINT("info", ("spider alloc_lcptr"));
|
DBUG_PRINT("info", ("spider alloc_lcptr"));
|
||||||
if (unlikely(!spider_bulk_malloc(spider_current_trx, 272, MYF(MY_WME),
|
if (unlikely(!spider_bulk_malloc(spider_current_trx, 272, MYF(MY_WME),
|
||||||
&lcptr, (uint) (sizeof(SPIDER_CONN_LOOP_CHECK)),
|
&lcptr, (uint) (sizeof(SPIDER_CONN_LOOP_CHECK)),
|
||||||
&from_name, (uint) (from_str.length + 1),
|
|
||||||
&cur_name, (uint) (top_share->path.length + 1),
|
&cur_name, (uint) (top_share->path.length + 1),
|
||||||
&to_name, (uint) (to_str.length + 1),
|
&to_name, (uint) (to_str.length + 1),
|
||||||
&full_name, (uint) (buf_sz),
|
&full_name, (uint) (buf_sz),
|
||||||
@@ -1495,9 +1520,6 @@ int spider_conn_queue_loop_check(
|
|||||||
goto error_alloc_loop_check;
|
goto error_alloc_loop_check;
|
||||||
}
|
}
|
||||||
lcptr->flag = 0;
|
lcptr->flag = 0;
|
||||||
lcptr->from_name.str = from_name;
|
|
||||||
lcptr->from_name.length = from_str.length;
|
|
||||||
memcpy(from_name, from_str.str, from_str.length + 1);
|
|
||||||
lcptr->cur_name.str = cur_name;
|
lcptr->cur_name.str = cur_name;
|
||||||
lcptr->cur_name.length = top_share->path.length;
|
lcptr->cur_name.length = top_share->path.length;
|
||||||
memcpy(cur_name, top_share->path.str, top_share->path.length + 1);
|
memcpy(cur_name, top_share->path.str, top_share->path.length + 1);
|
||||||
@@ -1510,12 +1532,19 @@ int spider_conn_queue_loop_check(
|
|||||||
lcptr->from_value.str = from_value;
|
lcptr->from_value.str = from_value;
|
||||||
lcptr->from_value.length = lex_str.length;
|
lcptr->from_value.length = lex_str.length;
|
||||||
memcpy(from_value, lex_str.str, lex_str.length + 1);
|
memcpy(from_value, lex_str.str, lex_str.length + 1);
|
||||||
|
/*
|
||||||
|
merged_value will only be populated later, in
|
||||||
|
spider_conn_queue_and_merge_loop_check()
|
||||||
|
*/
|
||||||
lcptr->merged_value.str = merged_value;
|
lcptr->merged_value.str = merged_value;
|
||||||
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
|
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
|
||||||
lcptr->hash_value_to = my_calc_hash(&conn->loop_checked,
|
lcptr->hash_value_to = my_calc_hash(&conn->loop_check_queue,
|
||||||
(uchar *) to_str.str, to_str.length);
|
(uchar *) to_str.str, to_str.length);
|
||||||
lcptr->hash_value_full = hash_value;
|
|
||||||
#endif
|
#endif
|
||||||
|
/*
|
||||||
|
Mark as checked. It will be added to loop_check_queue in
|
||||||
|
spider_conn_queue_and_merge_loop_check() below for checking
|
||||||
|
*/
|
||||||
#ifdef HASH_UPDATE_WITH_HASH_VALUE
|
#ifdef HASH_UPDATE_WITH_HASH_VALUE
|
||||||
if (unlikely(my_hash_insert_with_hash_value(&conn->loop_checked,
|
if (unlikely(my_hash_insert_with_hash_value(&conn->loop_checked,
|
||||||
lcptr->hash_value_full, (uchar *) lcptr)))
|
lcptr->hash_value_full, (uchar *) lcptr)))
|
||||||
@@ -1527,19 +1556,11 @@ int spider_conn_queue_loop_check(
|
|||||||
goto error_hash_insert;
|
goto error_hash_insert;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
/* Already marked as checked, ignore and return. */
|
||||||
if (!lcptr->flag)
|
if (!lcptr->flag)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("spider add to ignored list"));
|
DBUG_PRINT("info", ("spider add to ignored list"));
|
||||||
lcptr->flag |= SPIDER_LOP_CHK_IGNORED;
|
lcptr->flag |= SPIDER_LOP_CHK_IGNORED;
|
||||||
lcptr->next = NULL;
|
|
||||||
if (!conn->loop_check_ignored_first)
|
|
||||||
{
|
|
||||||
conn->loop_check_ignored_first = lcptr;
|
|
||||||
conn->loop_check_ignored_last = lcptr;
|
|
||||||
} else {
|
|
||||||
conn->loop_check_ignored_last->next = lcptr;
|
|
||||||
conn->loop_check_ignored_last = lcptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&conn->loop_check_mutex);
|
pthread_mutex_unlock(&conn->loop_check_mutex);
|
||||||
my_afree(loop_check_buf);
|
my_afree(loop_check_buf);
|
||||||
|
@@ -26,24 +26,62 @@
|
|||||||
#define SPIDER_SIMPLE_CHECKSUM_TABLE 4
|
#define SPIDER_SIMPLE_CHECKSUM_TABLE 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
The SPIDER_CONN_LOOP_CHECK has been added to the loop_check queue to
|
||||||
|
check for self-reference.
|
||||||
|
*/
|
||||||
#define SPIDER_LOP_CHK_QUEUED (1 << 0)
|
#define SPIDER_LOP_CHK_QUEUED (1 << 0)
|
||||||
|
/*
|
||||||
|
The SPIDER_CONN_LOOP_CHECK is a merge of multiple
|
||||||
|
SPIDER_CONN_LOOP_CHECKs with the same data node table
|
||||||
|
*/
|
||||||
#define SPIDER_LOP_CHK_MERAGED (1 << 1)
|
#define SPIDER_LOP_CHK_MERAGED (1 << 1)
|
||||||
|
/*
|
||||||
|
The SPIDER_CONN_LOOP_CHECK has been ignored because it has already
|
||||||
|
been marked as checked
|
||||||
|
*/
|
||||||
#define SPIDER_LOP_CHK_IGNORED (1 << 2)
|
#define SPIDER_LOP_CHK_IGNORED (1 << 2)
|
||||||
|
|
||||||
|
/* Used for self-reference check. */
|
||||||
typedef struct st_spider_conn_loop_check
|
typedef struct st_spider_conn_loop_check
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Could be 0, SPIDER_LOP_CHK_QUEUED, SPIDER_LOP_CHK_MERAGED, or
|
||||||
|
SPIDER_LOP_CHK_IGNORED
|
||||||
|
*/
|
||||||
uint flag;
|
uint flag;
|
||||||
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
|
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
|
||||||
|
/* hash value of to_name, used for the hash conn->loop_checked */
|
||||||
my_hash_value_type hash_value_to;
|
my_hash_value_type hash_value_to;
|
||||||
my_hash_value_type hash_value_full;
|
|
||||||
#endif
|
#endif
|
||||||
LEX_CSTRING from_name;
|
/*
|
||||||
|
The fully qualified name of the current spider table, which will
|
||||||
|
also be used to construct the user var name to set in the data
|
||||||
|
node
|
||||||
|
*/
|
||||||
LEX_CSTRING cur_name;
|
LEX_CSTRING cur_name;
|
||||||
|
/*
|
||||||
|
The fully qualified data node table name, also used as key in
|
||||||
|
conn->loop_check_queue
|
||||||
|
*/
|
||||||
LEX_CSTRING to_name;
|
LEX_CSTRING to_name;
|
||||||
|
/*
|
||||||
|
A concatenation of from_value, cur_name and to_name, used as key
|
||||||
|
in hash conn->loop_checked
|
||||||
|
*/
|
||||||
LEX_CSTRING full_name;
|
LEX_CSTRING full_name;
|
||||||
|
/*
|
||||||
|
The first component of the uservar value on the current server,
|
||||||
|
consisting of information of a table that uses the current spider
|
||||||
|
table as a data node
|
||||||
|
*/
|
||||||
LEX_CSTRING from_value;
|
LEX_CSTRING from_value;
|
||||||
|
/*
|
||||||
|
The uservar value to set in the data node, a concatenation of info
|
||||||
|
of tables, mac addresses and process ids of tables that use the
|
||||||
|
current spider table as the data node
|
||||||
|
*/
|
||||||
LEX_CSTRING merged_value;
|
LEX_CSTRING merged_value;
|
||||||
st_spider_conn_loop_check *next;
|
|
||||||
} SPIDER_CONN_LOOP_CHECK;
|
} SPIDER_CONN_LOOP_CHECK;
|
||||||
|
|
||||||
uchar *spider_conn_get_key(
|
uchar *spider_conn_get_key(
|
||||||
|
@@ -66,7 +66,7 @@ spider_db_conn::spider_db_conn(
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
int spider_db_conn::fin_loop_check()
|
int spider_db_conn::fin_loop_check() /* reset flags of all relevant SPIDER_CONN_LOOP_CHECKs */
|
||||||
{
|
{
|
||||||
st_spider_conn_loop_check *lcptr;
|
st_spider_conn_loop_check *lcptr;
|
||||||
DBUG_ENTER("spider_db_conn::fin_loop_check");
|
DBUG_ENTER("spider_db_conn::fin_loop_check");
|
||||||
@@ -82,20 +82,6 @@ int spider_db_conn::fin_loop_check()
|
|||||||
}
|
}
|
||||||
my_hash_reset(&conn->loop_check_queue);
|
my_hash_reset(&conn->loop_check_queue);
|
||||||
}
|
}
|
||||||
lcptr = conn->loop_check_ignored_first;
|
|
||||||
while (lcptr)
|
|
||||||
{
|
|
||||||
lcptr->flag = 0;
|
|
||||||
lcptr = lcptr->next;
|
|
||||||
}
|
|
||||||
conn->loop_check_ignored_first = NULL;
|
|
||||||
lcptr = conn->loop_check_meraged_first;
|
|
||||||
while (lcptr)
|
|
||||||
{
|
|
||||||
lcptr->flag = 0;
|
|
||||||
lcptr = lcptr->next;
|
|
||||||
}
|
|
||||||
conn->loop_check_meraged_first = NULL;
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5283,6 +5283,22 @@ int spider_db_mbase_util::append_time_zone(
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
iterate over loop_check_queue and build queries for loop check
|
||||||
|
|
||||||
|
The query is in the form of
|
||||||
|
|
||||||
|
set @`spider_lc_.<to_table>` =
|
||||||
|
'-<mac1>-<pid1>-<from_table1>--<mac2>-<pid2>-<from_table2>-...'
|
||||||
|
|
||||||
|
where from_table1, from_table2 etc. are spider tables whose direct
|
||||||
|
or indirect remote data nodes contain to_table.
|
||||||
|
|
||||||
|
e.g. if t0->t1->t2, then the query could be:
|
||||||
|
|
||||||
|
set @`spider_lc_./test/t2` =
|
||||||
|
'-234567890abc-def012-./test/t1--1234567890ab-cdef01-./test/t0-'
|
||||||
|
*/
|
||||||
int spider_db_mbase_util::append_loop_check(
|
int spider_db_mbase_util::append_loop_check(
|
||||||
spider_string *str,
|
spider_string *str,
|
||||||
SPIDER_CONN *conn
|
SPIDER_CONN *conn
|
||||||
|
@@ -793,19 +793,24 @@ typedef struct st_spider_conn
|
|||||||
SPIDER_IP_PORT_CONN *ip_port_conn;
|
SPIDER_IP_PORT_CONN *ip_port_conn;
|
||||||
|
|
||||||
pthread_mutex_t loop_check_mutex;
|
pthread_mutex_t loop_check_mutex;
|
||||||
|
/*
|
||||||
|
A hash of SPIDER_CONN_LOOP_CHECK, indexed by
|
||||||
|
SPIDER_CONN_LOOP_CHECK::full_name
|
||||||
|
*/
|
||||||
HASH loop_checked;
|
HASH loop_checked;
|
||||||
uint loop_checked_id;
|
uint loop_checked_id;
|
||||||
const char *loop_checked_func_name;
|
const char *loop_checked_func_name;
|
||||||
const char *loop_checked_file_name;
|
const char *loop_checked_file_name;
|
||||||
ulong loop_checked_line_no;
|
ulong loop_checked_line_no;
|
||||||
|
/*
|
||||||
|
A hash of SPIDER_CONN_LOOP_CHECK, indexed by
|
||||||
|
SPIDER_CONN_LOOP_CHECK::to_name
|
||||||
|
*/
|
||||||
HASH loop_check_queue;
|
HASH loop_check_queue;
|
||||||
uint loop_check_queue_id;
|
uint loop_check_queue_id;
|
||||||
const char *loop_check_queue_func_name;
|
const char *loop_check_queue_func_name;
|
||||||
const char *loop_check_queue_file_name;
|
const char *loop_check_queue_file_name;
|
||||||
ulong loop_check_queue_line_no;
|
ulong loop_check_queue_line_no;
|
||||||
SPIDER_CONN_LOOP_CHECK *loop_check_ignored_first;
|
|
||||||
SPIDER_CONN_LOOP_CHECK *loop_check_ignored_last;
|
|
||||||
SPIDER_CONN_LOOP_CHECK *loop_check_meraged_first;
|
|
||||||
} SPIDER_CONN;
|
} SPIDER_CONN;
|
||||||
|
|
||||||
typedef struct st_spider_lgtm_tblhnd_share
|
typedef struct st_spider_lgtm_tblhnd_share
|
||||||
|
Reference in New Issue
Block a user