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;
|
||||
}
|
||||
|
||||
/*
|
||||
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(
|
||||
SPIDER_CONN *conn,
|
||||
SPIDER_CONN_LOOP_CHECK *lcptr
|
||||
) {
|
||||
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;
|
||||
SPIDER_CONN_LOOP_CHECK *lcqptr, *lcrptr;
|
||||
DBUG_ENTER("spider_conn_queue_and_merge_loop_check");
|
||||
DBUG_PRINT("info", ("spider conn=%p", conn));
|
||||
#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,
|
||||
lcptr->hash_value_to,
|
||||
(uchar *) lcptr->to_name.str, lcptr->to_name.length))))
|
||||
(uchar *) lcptr->to_name.str, lcptr->to_name.length)))
|
||||
#else
|
||||
if (unlikely(!(lcqptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_search(
|
||||
&conn->loop_check_queue,
|
||||
(uchar *) lcptr->to_name.str, lcptr->to_name.length))))
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
Construct the right hand side:
|
||||
-<mac>-<pid>-<cur_table>-<from_value>
|
||||
*/
|
||||
DBUG_PRINT("info", ("spider create merged_value and insert"));
|
||||
lcptr->merged_value.length = spider_unique_id.length +
|
||||
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;
|
||||
} else {
|
||||
/* Merge lcptr and lcqptr into a newly created lcrptr. */
|
||||
DBUG_PRINT("info", ("spider append merged_value and replace"));
|
||||
if (unlikely(!spider_bulk_malloc(spider_current_trx, 271, MYF(MY_WME),
|
||||
&lcrptr, (uint) (sizeof(SPIDER_CONN_LOOP_CHECK)),
|
||||
&from_name, (uint) (lcqptr->from_name.length + 1),
|
||||
&cur_name, (uint) (lcqptr->cur_name.length + 1),
|
||||
&to_name, (uint) (lcqptr->to_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;
|
||||
}
|
||||
/*
|
||||
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
|
||||
lcrptr->hash_value_to = lcqptr->hash_value_to;
|
||||
lcrptr->hash_value_full = lcqptr->hash_value_full;
|
||||
#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.length = lcqptr->cur_name.length;
|
||||
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.length = lcqptr->from_value.length;
|
||||
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.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,
|
||||
lcqptr->merged_value.str, 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;
|
||||
}
|
||||
lcptr->flag = SPIDER_LOP_CHK_MERAGED;
|
||||
lcptr->next = NULL;
|
||||
if (!conn->loop_check_meraged_first)
|
||||
conn->loop_check_meraged_first = lcptr;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
||||
@@ -1296,7 +1313,6 @@ error_hash_insert:
|
||||
int spider_conn_reset_queue_loop_check(
|
||||
SPIDER_CONN *conn
|
||||
) {
|
||||
int error_num;
|
||||
SPIDER_CONN_LOOP_CHECK *lcptr;
|
||||
DBUG_ENTER("spider_conn_reset_queue_loop_check");
|
||||
uint l = 0;
|
||||
@@ -1318,30 +1334,8 @@ int spider_conn_reset_queue_loop_check(
|
||||
++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);
|
||||
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(
|
||||
@@ -1352,7 +1346,7 @@ int spider_conn_queue_loop_check(
|
||||
int error_num = HA_ERR_OUT_OF_MEM;
|
||||
uint conn_link_idx = spider->conn_link_idx[link_idx], buf_sz;
|
||||
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;
|
||||
user_var_entry *loop_check;
|
||||
char *loop_check_buf;
|
||||
@@ -1363,6 +1357,17 @@ int spider_conn_queue_loop_check(
|
||||
LEX_CSTRING lex_str, from_str, to_str;
|
||||
DBUG_ENTER("spider_conn_queue_loop_check");
|
||||
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;
|
||||
buf_sz = lex_str.length + 2;
|
||||
loop_check_buf = (char *) my_alloca(buf_sz);
|
||||
@@ -1388,6 +1393,16 @@ int spider_conn_queue_loop_check(
|
||||
} else {
|
||||
lex_str.str = loop_check->value;
|
||||
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));
|
||||
if (unlikely(!(tmp_name = strchr(loop_check->value, '-'))))
|
||||
{
|
||||
@@ -1415,12 +1430,23 @@ int spider_conn_queue_loop_check(
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Validation passed. Put the first component of rhs in from_str
|
||||
*/
|
||||
from_str.str = lex_str.str;
|
||||
from_str.length = tmp_name - lex_str.str + 1;
|
||||
}
|
||||
}
|
||||
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,
|
||||
share->tgt_dbs[conn_link_idx] ? share->tgt_dbs[conn_link_idx] : "",
|
||||
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(
|
||||
&conn->loop_checked, (uchar *) loop_check_buf, buf_sz - 1);
|
||||
#endif
|
||||
if (unlikely(
|
||||
if (
|
||||
!lcptr ||
|
||||
(
|
||||
!lcptr->flag &&
|
||||
@@ -1466,7 +1492,7 @@ int spider_conn_queue_loop_check(
|
||||
memcmp(lcptr->from_value.str, lex_str.str, lex_str.length)
|
||||
)
|
||||
)
|
||||
))
|
||||
)
|
||||
{
|
||||
if (unlikely(lcptr))
|
||||
{
|
||||
@@ -1482,7 +1508,6 @@ int spider_conn_queue_loop_check(
|
||||
DBUG_PRINT("info", ("spider alloc_lcptr"));
|
||||
if (unlikely(!spider_bulk_malloc(spider_current_trx, 272, MYF(MY_WME),
|
||||
&lcptr, (uint) (sizeof(SPIDER_CONN_LOOP_CHECK)),
|
||||
&from_name, (uint) (from_str.length + 1),
|
||||
&cur_name, (uint) (top_share->path.length + 1),
|
||||
&to_name, (uint) (to_str.length + 1),
|
||||
&full_name, (uint) (buf_sz),
|
||||
@@ -1495,9 +1520,6 @@ int spider_conn_queue_loop_check(
|
||||
goto error_alloc_loop_check;
|
||||
}
|
||||
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.length = top_share->path.length;
|
||||
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.length = lex_str.length;
|
||||
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;
|
||||
#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);
|
||||
lcptr->hash_value_full = hash_value;
|
||||
#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
|
||||
if (unlikely(my_hash_insert_with_hash_value(&conn->loop_checked,
|
||||
lcptr->hash_value_full, (uchar *) lcptr)))
|
||||
@@ -1527,19 +1556,11 @@ int spider_conn_queue_loop_check(
|
||||
goto error_hash_insert;
|
||||
}
|
||||
} else {
|
||||
/* Already marked as checked, ignore and return. */
|
||||
if (!lcptr->flag)
|
||||
{
|
||||
DBUG_PRINT("info", ("spider add to ignored list"));
|
||||
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);
|
||||
my_afree(loop_check_buf);
|
||||
|
@@ -26,24 +26,62 @@
|
||||
#define SPIDER_SIMPLE_CHECKSUM_TABLE 4
|
||||
#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)
|
||||
/*
|
||||
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)
|
||||
/*
|
||||
The SPIDER_CONN_LOOP_CHECK has been ignored because it has already
|
||||
been marked as checked
|
||||
*/
|
||||
#define SPIDER_LOP_CHK_IGNORED (1 << 2)
|
||||
|
||||
/* Used for self-reference 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;
|
||||
#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_full;
|
||||
#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;
|
||||
/*
|
||||
The fully qualified data node table name, also used as key in
|
||||
conn->loop_check_queue
|
||||
*/
|
||||
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;
|
||||
/*
|
||||
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;
|
||||
/*
|
||||
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;
|
||||
st_spider_conn_loop_check *next;
|
||||
} SPIDER_CONN_LOOP_CHECK;
|
||||
|
||||
uchar *spider_conn_get_key(
|
||||
|
@@ -66,7 +66,7 @@ spider_db_conn::spider_db_conn(
|
||||
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;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -5283,6 +5283,22 @@ int spider_db_mbase_util::append_time_zone(
|
||||
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(
|
||||
spider_string *str,
|
||||
SPIDER_CONN *conn
|
||||
|
@@ -793,19 +793,24 @@ typedef struct st_spider_conn
|
||||
SPIDER_IP_PORT_CONN *ip_port_conn;
|
||||
|
||||
pthread_mutex_t loop_check_mutex;
|
||||
/*
|
||||
A hash of SPIDER_CONN_LOOP_CHECK, indexed by
|
||||
SPIDER_CONN_LOOP_CHECK::full_name
|
||||
*/
|
||||
HASH loop_checked;
|
||||
uint loop_checked_id;
|
||||
const char *loop_checked_func_name;
|
||||
const char *loop_checked_file_name;
|
||||
ulong loop_checked_line_no;
|
||||
/*
|
||||
A hash of SPIDER_CONN_LOOP_CHECK, indexed by
|
||||
SPIDER_CONN_LOOP_CHECK::to_name
|
||||
*/
|
||||
HASH loop_check_queue;
|
||||
uint loop_check_queue_id;
|
||||
const char *loop_check_queue_func_name;
|
||||
const char *loop_check_queue_file_name;
|
||||
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;
|
||||
|
||||
typedef struct st_spider_lgtm_tblhnd_share
|
||||
|
Reference in New Issue
Block a user