diff options
author | Kentoku <kentokushiba@gmail.com> | 2019-05-28 16:40:59 +0900 |
---|---|---|
committer | Kentoku <kentokushiba@gmail.com> | 2019-09-02 07:06:05 +0900 |
commit | 4a8dafe26ec1aa97c153f7dedc7a487b6cedffd9 (patch) | |
tree | 101a557ddf6adbc4d76deac240d6a1dcf52f06c9 | |
parent | 24773bf38024d32c9af4e6bc09e67043318bba6e (diff) | |
download | mariadb-git-bb-10.4-MDEV-6268.tar.gz |
MDEV-6268 SPIDER table with no COMMENT clause causes queries to wait foreverbb-10.4-MDEV-6268
Add loop checks by using user variables
33 files changed, 1488 insertions, 131 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 60371813280..54bf3bf29f2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2040,11 +2040,13 @@ retry_share: if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) goto err_lock; + table_list->intention_table= table; error= open_table_from_share(thd, share, &table_list->alias, HA_OPEN_KEYFILE | HA_TRY_READ_ONLY, EXTRA_RECORD, thd->open_options, table, FALSE, - IF_PARTITIONING(table_list->partition_names,0)); + IF_PARTITIONING(table_list->partition_names,0), + table_list); if (unlikely(error)) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 598f46594e5..f85e598b776 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3123,7 +3123,7 @@ bool JOIN::make_aggr_tables_info() distinct in the engine, so we do this for all queries, not only GROUP BY queries. */ - if (tables_list && !procedure) + if (tables_list && !procedure && join_tab) { /* At the moment we only support push down for queries where diff --git a/sql/table.cc b/sql/table.cc index 699102885c2..ffc00158956 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3543,7 +3543,8 @@ static void print_long_unique_table(TABLE *table) enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, const LEX_CSTRING *alias, uint db_stat, uint prgflag, uint ha_open_flags, TABLE *outparam, - bool is_create_table, List<String> *partitions_to_open) + bool is_create_table, List<String> *partitions_to_open, + TABLE_LIST *table_list) { enum open_frm_error error; uint records, i, bitmap_size, bitmap_count; @@ -3565,6 +3566,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, outparam->s= share; outparam->db_stat= db_stat; outparam->write_row_record= NULL; + outparam->intention_pos_in_table_list= table_list; if (share->incompatible_version && !(ha_open_flags & (HA_OPEN_FOR_ALTER | HA_OPEN_FOR_REPAIR))) diff --git a/sql/table.h b/sql/table.h index 42c017d63af..da7e0b4a99e 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1167,6 +1167,9 @@ public: /* Table's triggers, 0 if there are no of them */ Table_triggers_list *triggers; TABLE_LIST *pos_in_table_list;/* Element referring to this table */ + /* This is same as pos_in_table_list, but it is set as soon as possible when + TABLE is allocated */ + TABLE_LIST *intention_pos_in_table_list; /* Position in thd->locked_table_list under LOCK TABLES */ TABLE_LIST *pos_in_locked_tables; /* Tables used in DEFAULT and CHECK CONSTRAINT (normally sequence tables) */ @@ -2144,6 +2147,9 @@ struct TABLE_LIST /* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */ List<Index_hint> *index_hints; TABLE *table; /* opened table */ + /* This is same as table, but it is set as soon as possible when + TABLE is allocated */ + TABLE *intention_table; ulonglong table_id; /* table id (from binlog) for opened table */ /* select_result for derived table to pass it from table creation to table @@ -2982,7 +2988,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, const LEX_CSTRING *alias, uint db_stat, uint prgflag, uint ha_open_flags, TABLE *outparam, bool is_create_table, - List<String> *partitions_to_open= NULL); + List<String> *partitions_to_open= NULL, + TABLE_LIST *table_list= NULL); bool fix_session_vcol_expr(THD *thd, Virtual_column_info *vcol); bool fix_session_vcol_expr_for_read(THD *thd, Field *field, Virtual_column_info *vcol); diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index fb947ef643f..f279561f4b2 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -1,4 +1,5 @@ -/* Copyright (C) 2008-2018 Kentoku Shiba +/* Copyright (C) 2008-2019 Kentoku Shiba + Copyright (C) 2019 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -356,6 +357,18 @@ int ha_spider::open( dup_key_idx = (uint) -1; conn_kinds = SPIDER_CONN_KIND_MYSQL; + if (table_share->tmp_table == NO_TMP_TABLE) + { + TABLE_LIST *top = spider_get_parent_table_list(this); + if (top->intention_table) + { + top_share = top->intention_table->s; + } else { + top_share = top->table->s; + } + } else { + top_share = NULL; + } if (!spider_get_share(name, table, thd, this, &error_num)) goto error_get_share; thr_lock_data_init(&share->lock,&lock,NULL); diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h index 9ffe49754e8..e6674bc7a50 100644 --- a/storage/spider/ha_spider.h +++ b/storage/spider/ha_spider.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2008-2018 Kentoku Shiba +/* Copyright (C) 2008-2019 Kentoku Shiba + Copyright (C) 2019 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -54,6 +55,7 @@ public: THR_LOCK_DATA lock; SPIDER_SHARE *share; SPIDER_TRX *trx; + TABLE_SHARE *top_share; ulonglong spider_thread_id; ulonglong trx_conn_adjustment; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) diff --git a/storage/spider/mysql-test/spider/bugfix/include/ping_table_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/ping_table_deinit.inc new file mode 100644 index 00000000000..76b7582abfe --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/ping_table_deinit.inc @@ -0,0 +1,11 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/ping_table_init.inc b/storage/spider/mysql-test/spider/bugfix/include/ping_table_init.inc new file mode 100644 index 00000000000..d4757840f0d --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/ping_table_init.inc @@ -0,0 +1,60 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--connection master_1 +if ($VERSION_COMPILE_OS_WIN) +{ + let $PING_COMMAND= + SELECT spider_ping_table('.\\auto_test_local\\tbl_a', 0, 2, 1, + ' where pkey = 1', @@server_id, 1, 0, 0, 0); +} +if (!$VERSION_COMPILE_OS_WIN) +{ + let $PING_COMMAND= + SELECT spider_ping_table('./auto_test_local/tbl_a', 0, 2, 1, + ' where pkey = 1', @@server_id, 1, 0, 0, 0); +} +--disable_query_log +INSERT INTO mysql.spider_link_mon_servers SET + db_name = '%', + table_name = '%', + link_id = '%', + sid = @@server_id, + server = 's_1', + scheme = null, + host = null, + port = null, + socket = null, + username = null, + password = null, + ssl_ca = null, + ssl_capath = null, + ssl_cert = null, + ssl_cipher = null, + ssl_key = null, + ssl_verify_server_cert = 0, + default_file = null, + default_group = null +; +--enable_query_log diff --git a/storage/spider/mysql-test/spider/bugfix/include/self_reference_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/self_reference_deinit.inc new file mode 100644 index 00000000000..34376d50584 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/self_reference_deinit.inc @@ -0,0 +1,10 @@ +--connection master_1 +set spider_same_server_link= @old_spider_same_server_link; +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/self_reference_init.inc b/storage/spider/mysql-test/spider/bugfix/include/self_reference_init.inc new file mode 100644 index 00000000000..b7e2c4d02ca --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/self_reference_init.inc @@ -0,0 +1,13 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", host "127.0.0.1", port "$MASTER_1_MYPORT", user "root"'; +--connection master_1 +set @old_spider_same_server_link= @@spider_same_server_link; +set spider_same_server_link= ON; diff --git a/storage/spider/mysql-test/spider/bugfix/r/self_reference.result b/storage/spider/mysql-test/spider/bugfix/r/self_reference.result new file mode 100644 index 00000000000..1ce9c60a93f --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/self_reference.result @@ -0,0 +1,36 @@ +for master_1 +for child2 +for child3 +connection master_1; +set @old_spider_same_server_link= @@spider_same_server_link; +set spider_same_server_link= ON; + +this test is for MDEV-6268 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; + +create table +connection master_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 + +select test 1 +connection master_1; +SELECT pkey FROM tbl_a; +ERROR HY000: An infinite loop is detected when opening table auto_test_local.tbl_a + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection master_1; +set spider_same_server_link= @old_spider_same_server_link; +for master_1 +for child2 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result b/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result index e93eb78417f..dd492bad006 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result +++ b/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result @@ -48,7 +48,7 @@ SET SESSION sql_log_bin= 0; connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %'; argument -set session time_zone = '+00:00' +set session time_zone = '+00:00';set @`spider_lc_./auto_test_remote/tbl_a` = '-xxxxxxxxxxxx-xxxxx-./auto_test_local/tbl_a-' SET NAMES utf8 set session transaction isolation level read committed;set session autocommit = 1;set session wait_timeout = 604800;start transaction SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %' diff --git a/storage/spider/mysql-test/spider/bugfix/t/ping_table.cnf b/storage/spider/mysql-test/spider/bugfix/t/ping_table.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/ping_table.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/ping_table.test b/storage/spider/mysql-test/spider/bugfix/t/ping_table.test new file mode 100644 index 00000000000..5f33dc2952b --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/ping_table.test @@ -0,0 +1,66 @@ +--source ../include/ping_table_init.inc +--echo +--echo drop and create databases + +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; +--enable_warnings + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +--enable_query_log +INSERT INTO tbl_a VALUES (1),(2); + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +eval $PING_COMMAND; +SELECT pkey FROM tbl_a WHERE NULL; + +--connection child2_1 +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--echo +--echo deinit +--disable_warnings + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/ping_table_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/self_reference.cnf b/storage/spider/mysql-test/spider/bugfix/t/self_reference.cnf new file mode 100644 index 00000000000..b0853e32654 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/self_reference.cnf @@ -0,0 +1,2 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/self_reference.test b/storage/spider/mysql-test/spider/bugfix/t/self_reference.test new file mode 100644 index 00000000000..b93cf8ef715 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/self_reference.test @@ -0,0 +1,45 @@ +--source ../include/self_reference_init.inc +--echo +--echo this test is for MDEV-6268 +--echo +--echo drop and create databases + +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; +--enable_warnings + +--echo +--echo create table + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +--enable_query_log + +--echo +--echo select test 1 + +--connection master_1 +--error 12719 +SELECT pkey FROM tbl_a; + +--echo +--echo deinit +--disable_warnings + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--enable_warnings +--source ../include/self_reference_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test b/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test index 652fbb1c11c..c608ae018ea 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test +++ b/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test @@ -70,6 +70,7 @@ sync_with_master; SET SESSION sql_log_bin= 0; --connection child2_1 +--replace_regex /-[0-9a-f]{12}-[0-9a-f]+-/-xxxxxxxxxxxx-xxxxx-/ eval $CHILD2_1_SELECT_ARGUMENT1; eval $CHILD2_1_SELECT_TABLES; diff --git a/storage/spider/mysql-test/spider/include/deinit_spider.inc b/storage/spider/mysql-test/spider/include/deinit_spider.inc index 3609551e169..523bb31661a 100644 --- a/storage/spider/mysql-test/spider/include/deinit_spider.inc +++ b/storage/spider/mysql-test/spider/include/deinit_spider.inc @@ -3,6 +3,7 @@ DROP FUNCTION spider_bg_direct_sql; DROP FUNCTION spider_ping_table; DROP FUNCTION spider_copy_tables; DROP FUNCTION spider_flush_table_mon_cache; +UNINSTALL PLUGIN spider_alloc_mem; UNINSTALL PLUGIN spider; DROP TABLE IF EXISTS mysql.spider_xa; DROP TABLE IF EXISTS mysql.spider_xa_member; @@ -13,9 +14,65 @@ DROP TABLE IF EXISTS mysql.spider_link_failed_log; DROP TABLE IF EXISTS mysql.spider_table_position_for_recovery; DROP TABLE IF EXISTS mysql.spider_table_sts; DROP TABLE IF EXISTS mysql.spider_table_crd; -DROP SERVER s_2_1; -DROP SERVER s_2_2; -DROP SERVER s_2_3; -DROP SERVER s_3_1; -DROP SERVER s_3_2; -DROP SERVER s_3_3; +if ($VERSION_COMPILE_OS_WIN) +{ + if ($MASTER_1_MYPORT) + { + DROP SERVER s_1; + } + if ($CHILD2_1_MYPORT) + { + DROP SERVER s_2_1; + } + if ($CHILD2_2_MYPORT) + { + DROP SERVER s_2_2; + } + if ($CHILD2_3_MYPORT) + { + DROP SERVER s_2_3; + } + if ($CHILD3_1_MYPORT) + { + DROP SERVER s_3_1; + } + if ($CHILD3_2_MYPORT) + { + DROP SERVER s_3_2; + } + if ($CHILD2_3_MYPORT) + { + DROP SERVER s_3_3; + } +} +if (!$VERSION_COMPILE_OS_WIN) +{ + if ($MASTER_1_MYSOCK) + { + DROP SERVER s_1; + } + if ($CHILD2_1_MYSOCK) + { + DROP SERVER s_2_1; + } + if ($CHILD2_2_MYSOCK) + { + DROP SERVER s_2_2; + } + if ($CHILD2_3_MYSOCK) + { + DROP SERVER s_2_3; + } + if ($CHILD3_1_MYSOCK) + { + DROP SERVER s_3_1; + } + if ($CHILD3_2_MYSOCK) + { + DROP SERVER s_3_2; + } + if ($CHILD3_3_MYSOCK) + { + DROP SERVER s_3_3; + } +} diff --git a/storage/spider/mysql-test/spider/include/init_spider.inc b/storage/spider/mysql-test/spider/include/init_spider.inc index 1da1ec970b5..2ca26f8edd3 100644 --- a/storage/spider/mysql-test/spider/include/init_spider.inc +++ b/storage/spider/mysql-test/spider/include/init_spider.inc @@ -3,104 +3,162 @@ let $VERSION_COMPILE_OS_WIN= if ($VERSION_COMPILE_OS_WIN) { INSTALL PLUGIN spider SONAME 'ha_spider.dll'; + INSTALL PLUGIN spider_alloc_mem SONAME 'ha_spider.dll'; CREATE FUNCTION spider_direct_sql RETURNS INT SONAME 'ha_spider.dll'; CREATE AGGREGATE FUNCTION spider_bg_direct_sql RETURNS INT SONAME 'ha_spider.dll'; CREATE FUNCTION spider_ping_table RETURNS INT SONAME 'ha_spider.dll'; CREATE FUNCTION spider_copy_tables RETURNS INT SONAME 'ha_spider.dll'; CREATE FUNCTION spider_flush_table_mon_cache RETURNS INT SONAME 'ha_spider.dll'; - eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_remote', - USER 'root', - PASSWORD '', - PORT $CHILD2_1_MYPORT - ); - eval CREATE SERVER s_2_2 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_remote2', - USER 'root', - PASSWORD '', - PORT $CHILD2_2_MYPORT - ); - eval CREATE SERVER s_2_3 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_remote3', - USER 'root', - PASSWORD '', - PORT $CHILD2_3_MYPORT - ); - eval CREATE SERVER s_3_1 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_local', - USER 'root', - PASSWORD '', - PORT $CHILD3_1_MYPORT - ); - eval CREATE SERVER s_3_2 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_local', - USER 'root', - PASSWORD '', - PORT $CHILD3_2_MYPORT - ); - eval CREATE SERVER s_3_3 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_local', - USER 'root', - PASSWORD '', - PORT $CHILD2_3_MYPORT - ); + if ($MASTER_1_MYPORT) + { + eval CREATE SERVER s_1 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_local', + USER 'root', + PASSWORD '', + PORT $MASTER_1_MYPORT + ); + } + if ($CHILD2_1_MYPORT) + { + eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_remote', + USER 'root', + PASSWORD '', + PORT $CHILD2_1_MYPORT + ); + } + if ($CHILD2_2_MYPORT) + { + eval CREATE SERVER s_2_2 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_remote2', + USER 'root', + PASSWORD '', + PORT $CHILD2_2_MYPORT + ); + } + if ($CHILD2_3_MYPORT) + { + eval CREATE SERVER s_2_3 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_remote3', + USER 'root', + PASSWORD '', + PORT $CHILD2_3_MYPORT + ); + } + if ($CHILD3_1_MYPORT) + { + eval CREATE SERVER s_3_1 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_local', + USER 'root', + PASSWORD '', + PORT $CHILD3_1_MYPORT + ); + } + if ($CHILD3_2_MYPORT) + { + eval CREATE SERVER s_3_2 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_local', + USER 'root', + PASSWORD '', + PORT $CHILD3_2_MYPORT + ); + } + if ($CHILD2_3_MYPORT) + { + eval CREATE SERVER s_3_3 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_local', + USER 'root', + PASSWORD '', + PORT $CHILD2_3_MYPORT + ); + } } if (!$VERSION_COMPILE_OS_WIN) { INSTALL PLUGIN spider SONAME 'ha_spider.so'; + INSTALL PLUGIN spider_alloc_mem SONAME 'ha_spider.so'; CREATE FUNCTION spider_direct_sql RETURNS INT SONAME 'ha_spider.so'; CREATE AGGREGATE FUNCTION spider_bg_direct_sql RETURNS INT SONAME 'ha_spider.so'; CREATE FUNCTION spider_ping_table RETURNS INT SONAME 'ha_spider.so'; CREATE FUNCTION spider_copy_tables RETURNS INT SONAME 'ha_spider.so'; CREATE FUNCTION spider_flush_table_mon_cache RETURNS INT SONAME 'ha_spider.so'; - eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_remote', - USER 'root', - PASSWORD '', - SOCKET '$CHILD2_1_MYSOCK' - ); - eval CREATE SERVER s_2_2 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_remote2', - USER 'root', - PASSWORD '', - SOCKET '$CHILD2_2_MYSOCK' - ); - eval CREATE SERVER s_2_3 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_remote3', - USER 'root', - PASSWORD '', - SOCKET '$CHILD2_3_MYSOCK' - ); - eval CREATE SERVER s_3_1 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_local', - USER 'root', - PASSWORD '', - SOCKET '$CHILD3_1_MYSOCK' - ); - eval CREATE SERVER s_3_2 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_local', - USER 'root', - PASSWORD '', - SOCKET '$CHILD3_2_MYSOCK' - ); - eval CREATE SERVER s_3_3 FOREIGN DATA WRAPPER mysql OPTIONS ( - HOST 'localhost', - DATABASE 'auto_test_local', - USER 'root', - PASSWORD '', - SOCKET '$CHILD3_3_MYSOCK' - ); + if ($MASTER_1_MYSOCK) + { + eval CREATE SERVER s_1 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_local', + USER 'root', + PASSWORD '', + SOCKET '$MASTER_1_MYSOCK' + ); + } + if ($CHILD2_1_MYSOCK) + { + eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_remote', + USER 'root', + PASSWORD '', + SOCKET '$CHILD2_1_MYSOCK' + ); + } + if ($CHILD2_2_MYSOCK) + { + eval CREATE SERVER s_2_2 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_remote2', + USER 'root', + PASSWORD '', + SOCKET '$CHILD2_2_MYSOCK' + ); + } + if ($CHILD2_3_MYSOCK) + { + eval CREATE SERVER s_2_3 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_remote3', + USER 'root', + PASSWORD '', + SOCKET '$CHILD2_3_MYSOCK' + ); + } + if ($CHILD3_1_MYSOCK) + { + eval CREATE SERVER s_3_1 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_local', + USER 'root', + PASSWORD '', + SOCKET '$CHILD3_1_MYSOCK' + ); + } + if ($CHILD3_2_MYSOCK) + { + eval CREATE SERVER s_3_2 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_local', + USER 'root', + PASSWORD '', + SOCKET '$CHILD3_2_MYSOCK' + ); + } + if ($CHILD3_3_MYSOCK) + { + eval CREATE SERVER s_3_3 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_local', + USER 'root', + PASSWORD '', + SOCKET '$CHILD3_3_MYSOCK' + ); + } } let $SERVER_NAME= diff --git a/storage/spider/mysql-test/spider/r/slave_trx_isolation.result b/storage/spider/mysql-test/spider/r/slave_trx_isolation.result index 4fd2e71d3f2..6ea4e91f631 100644 --- a/storage/spider/mysql-test/spider/r/slave_trx_isolation.result +++ b/storage/spider/mysql-test/spider/r/slave_trx_isolation.result @@ -51,7 +51,7 @@ SET SESSION sql_log_bin= 0; connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %'; argument -set session time_zone = '+00:00' +set session time_zone = '+00:00';set @`spider_lc_./auto_test_remote/tbl_a` = '-xxxxxxxxxxxx-xxxxx-./auto_test_local/tbl_a-' SET NAMES utf8 set session transaction isolation level read committed;set session autocommit = 1;set session wait_timeout = 604800;start transaction SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %' diff --git a/storage/spider/mysql-test/spider/t/slave_trx_isolation.test b/storage/spider/mysql-test/spider/t/slave_trx_isolation.test index 507e5340779..f7f41358f51 100644 --- a/storage/spider/mysql-test/spider/t/slave_trx_isolation.test +++ b/storage/spider/mysql-test/spider/t/slave_trx_isolation.test @@ -108,6 +108,7 @@ if ($USE_CHILD_GROUP2) --connection child2_1 if ($USE_GENERAL_LOG) { + --replace_regex /-[0-9a-f]{12}-[0-9a-f]+-/-xxxxxxxxxxxx-xxxxx-/ eval $CHILD2_1_SELECT_ARGUMENT1; } eval $CHILD2_1_SELECT_TABLES; diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index 9e1dbaf7f28..ac4ab9e8366 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -56,6 +56,8 @@ inline void SPIDER_set_next_thread_id(THD *A) extern handlerton *spider_hton_ptr; extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; +extern struct charset_info_st *spd_charset_utf8_bin; +extern LEX_CSTRING spider_unique_id; pthread_mutex_t spider_conn_id_mutex; pthread_mutex_t spider_ipport_conn_mutex; ulonglong spider_conn_id = 1; @@ -66,6 +68,7 @@ extern pthread_attr_t spider_pt_attr; #ifdef HAVE_PSI_INTERFACE extern PSI_mutex_key spd_key_mutex_mta_conn; extern PSI_mutex_key spd_key_mutex_conn_i; +extern PSI_mutex_key spd_key_mutex_conn_loop_check; extern PSI_cond_key spd_key_cond_conn_i; #ifndef WITHOUT_SPIDER_BG_SEARCH extern PSI_mutex_key spd_key_mutex_bg_conn_chain; @@ -142,6 +145,102 @@ uchar *spider_ipport_conn_get_key( DBUG_RETURN((uchar*) ip_port->key); } +static uchar *spider_loop_check_full_get_key( + SPIDER_CONN_LOOP_CHECK *ptr, + size_t *length, + my_bool not_used __attribute__ ((unused)) +) { + DBUG_ENTER("spider_loop_check_full_get_key"); + *length = ptr->full_name.length; + DBUG_RETURN((uchar*) ptr->full_name.str); +} + +static uchar *spider_loop_check_to_get_key( + SPIDER_CONN_LOOP_CHECK *ptr, + size_t *length, + my_bool not_used __attribute__ ((unused)) +) { + DBUG_ENTER("spider_loop_check_to_get_key"); + *length = ptr->to_name.length; + DBUG_RETURN((uchar*) ptr->to_name.str); +} + +int spider_conn_init( + SPIDER_CONN *conn +) { + int error_num = HA_ERR_OUT_OF_MEM; + DBUG_ENTER("spider_conn_init"); +#if MYSQL_VERSION_ID < 50500 + if (pthread_mutex_init(&conn->loop_check_mutex, MY_MUTEX_INIT_FAST)) +#else + if (mysql_mutex_init(spd_key_mutex_conn_loop_check, &conn->loop_check_mutex, + MY_MUTEX_INIT_FAST)) +#endif + { + goto error_loop_check_mutex_init; + } + if ( + my_hash_init(&conn->loop_checked, spd_charset_utf8_bin, 32, 0, 0, + (my_hash_get_key) spider_loop_check_full_get_key, 0, 0) + ) { + goto error_loop_checked_hash_init; + } + spider_alloc_calc_mem_init(conn->loop_checked, 268); + spider_alloc_calc_mem(spider_current_trx, + conn->loop_checked, + conn->loop_checked.array.max_element * + conn->loop_checked.array.size_of_element); + if ( + my_hash_init(&conn->loop_check_queue, spd_charset_utf8_bin, 32, 0, 0, + (my_hash_get_key) spider_loop_check_to_get_key, 0, 0) + ) { + goto error_loop_check_queue_hash_init; + } + spider_alloc_calc_mem_init(conn->loop_check_queue, 269); + spider_alloc_calc_mem(spider_current_trx, + conn->loop_check_queue, + conn->loop_check_queue.array.max_element * + conn->loop_check_queue.array.size_of_element); + DBUG_RETURN(0); + +error_loop_check_queue_hash_init: + spider_free_mem_calc(spider_current_trx, + conn->loop_checked_id, + conn->loop_checked.array.max_element * + conn->loop_checked.array.size_of_element); + my_hash_free(&conn->loop_checked); +error_loop_checked_hash_init: + pthread_mutex_destroy(&conn->loop_check_mutex); +error_loop_check_mutex_init: + DBUG_RETURN(error_num); +} + +void spider_conn_done( + SPIDER_CONN *conn +) { + SPIDER_CONN_LOOP_CHECK *lcptr; + DBUG_ENTER("spider_conn_done"); + uint l = 0; + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_checked, l))) + { + spider_free(spider_current_trx, lcptr, MYF(0)); + ++l; + } + spider_free_mem_calc(spider_current_trx, + conn->loop_check_queue_id, + conn->loop_check_queue.array.max_element * + conn->loop_check_queue.array.size_of_element); + my_hash_free(&conn->loop_check_queue); + spider_free_mem_calc(spider_current_trx, + conn->loop_checked_id, + conn->loop_checked.array.max_element * + conn->loop_checked.array.size_of_element); + my_hash_free(&conn->loop_checked); + pthread_mutex_destroy(&conn->loop_check_mutex); + DBUG_VOID_RETURN; +} + int spider_reset_conn_setted_parameter( SPIDER_CONN *conn, THD *thd @@ -179,7 +278,7 @@ int spider_reset_conn_setted_parameter( conn->default_database.length(default_database_length); } else conn->default_database.length(0); - DBUG_RETURN(0); + DBUG_RETURN(spider_conn_reset_queue_loop_check(conn)); } int spider_free_conn_alloc( @@ -195,6 +294,7 @@ int spider_free_conn_alloc( delete conn->db_conn; conn->db_conn = NULL; } + spider_conn_done(conn); DBUG_ASSERT(!conn->mta_conn_mutex_file_pos.file_name); pthread_mutex_destroy(&conn->mta_conn_mutex); conn->default_database.free(); @@ -733,6 +833,11 @@ SPIDER_CONN *spider_create_conn( goto error_mta_conn_mutex_init; } + if (unlikely((*error_num = spider_conn_init(conn)))) + { + goto error_conn_init; + } + spider_conn_queue_connect(share, conn, link_idx); conn->ping_time = (time_t) time((time_t*) 0); conn->connect_error_time = conn->ping_time; @@ -784,12 +889,10 @@ SPIDER_CONN *spider_create_conn( DBUG_RETURN(conn); -/* -error_init_lock_table_hash: - DBUG_ASSERT(!conn->mta_conn_mutex_file_pos.file_name); - pthread_mutex_destroy(&conn->mta_conn_mutex); -*/ error_too_many_ipport_count: + spider_conn_done(conn); +error_conn_init: + pthread_mutex_destroy(&conn->mta_conn_mutex); error_mta_conn_mutex_init: error_db_conn_init: delete conn->db_conn; @@ -1224,6 +1327,20 @@ SPIDER_CONN *spider_get_conn( conn->queued_ping = FALSE; } +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + if (conn_kind == SPIDER_CONN_KIND_MYSQL) + { +#endif + if (unlikely(spider && spider->top_share && + (*error_num = spider_conn_queue_loop_check( + conn, spider, base_link_idx)))) + { + goto error; + } +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + } +#endif + DBUG_PRINT("info",("spider conn=%p", conn)); DBUG_RETURN(conn); @@ -1464,6 +1581,423 @@ void spider_conn_queue_UTC_time_zone( DBUG_VOID_RETURN; } +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, + *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 *) + my_hash_search_using_hash_value(&conn->loop_check_queue, + lcptr->hash_value_to, + (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 + { + 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; + tmp_name = (char *) lcptr->merged_value.str; + memcpy(tmp_name, spider_unique_id.str, spider_unique_id.length); + tmp_name += spider_unique_id.length; + memcpy(tmp_name, lcptr->cur_name.str, lcptr->cur_name.length); + tmp_name += lcptr->cur_name.length; + *tmp_name = '-'; + ++tmp_name; + memcpy(tmp_name, lcptr->from_value.str, lcptr->from_value.length + 1); +#ifdef HASH_UPDATE_WITH_HASH_VALUE + if (unlikely(my_hash_insert_with_hash_value(&conn->loop_check_queue, + lcptr->hash_value_to, (uchar *) lcptr))) +#else + if (unlikely(my_hash_insert(&conn->loop_check_queue, (uchar *) lcptr))) +#endif + { + goto error_hash_insert_queue; + } + lcptr->flag |= SPIDER_LOP_CHK_QUEUED; + } else { + 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), + &from_value, (uint) (lcqptr->from_value.length + 1), + &merged_value, (uint) (lcqptr->merged_value.length + + spider_unique_id.length + lcptr->cur_name.length + + lcptr->from_value.length + 2), + NullS) + )) { + goto error_alloc_loop_check_replace; + } +#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); + lcrptr->to_name.str = to_name; + lcrptr->to_name.length = lcqptr->to_name.length; + memcpy(to_name, lcqptr->to_name.str, lcqptr->to_name.length + 1); + lcrptr->full_name.str = full_name; + lcrptr->full_name.length = lcqptr->full_name.length; + memcpy(full_name, lcqptr->full_name.str, lcqptr->full_name.length + 1); + 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); + lcrptr->merged_value.str = merged_value; + lcrptr->merged_value.length = lcqptr->merged_value.length; + memcpy(merged_value, + lcqptr->merged_value.str, lcqptr->merged_value.length); + merged_value += lcqptr->merged_value.length; + memcpy(merged_value, spider_unique_id.str, spider_unique_id.length); + merged_value += spider_unique_id.length; + memcpy(merged_value, lcptr->cur_name.str, lcptr->cur_name.length); + merged_value += lcptr->cur_name.length; + *merged_value = '-'; + ++merged_value; + memcpy(merged_value, lcptr->from_value.str, lcptr->from_value.length + 1); + + DBUG_PRINT("info", ("spider free lcqptr")); +#ifdef HASH_UPDATE_WITH_HASH_VALUE + my_hash_delete_with_hash_value(&conn->loop_checked, + lcqptr->hash_value_full, (uchar *) lcqptr); + my_hash_delete_with_hash_value(&conn->loop_check_queue, + lcqptr->hash_value_to, (uchar *) lcqptr); +#else + my_hash_delete(&conn->loop_checked, (uchar*) lcqptr); + my_hash_delete(&conn->loop_check_queue, (uchar*) lcqptr); +#endif + spider_free(spider_current_trx, lcqptr, MYF(0)); + + lcptr = lcrptr; +#ifdef HASH_UPDATE_WITH_HASH_VALUE + if (unlikely(my_hash_insert_with_hash_value(&conn->loop_checked, + lcptr->hash_value_full, (uchar *) lcptr))) +#else + if (unlikely(my_hash_insert(&conn->loop_checked, (uchar *) lcptr))) +#endif + { + goto error_hash_insert; + } +#ifdef HASH_UPDATE_WITH_HASH_VALUE + if (unlikely(my_hash_insert_with_hash_value(&conn->loop_check_queue, + lcptr->hash_value_to, (uchar *) lcptr))) +#else + if (unlikely(my_hash_insert(&conn->loop_check_queue, (uchar *) lcptr))) +#endif + { + 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; + conn->loop_check_meraged_last = lcptr; + } else { + conn->loop_check_meraged_last->next = lcptr; + conn->loop_check_meraged_last = lcptr; + } + } + DBUG_RETURN(0); + +error_alloc_loop_check_replace: +error_hash_insert_queue: +#ifdef HASH_UPDATE_WITH_HASH_VALUE + my_hash_delete_with_hash_value(&conn->loop_checked, + lcptr->hash_value_full, (uchar *) lcptr); +#else + my_hash_delete(&conn->loop_checked, (uchar*) lcptr); +#endif +error_hash_insert: + spider_free(spider_current_trx, lcptr, MYF(0)); + pthread_mutex_unlock(&conn->loop_check_mutex); + DBUG_RETURN(error_num); +} + +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; + pthread_mutex_lock(&conn->loop_check_mutex); + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_checked, l))) + { + if (!lcptr->flag) + { + DBUG_PRINT("info", ("spider free lcptr")); +#ifdef HASH_UPDATE_WITH_HASH_VALUE + my_hash_delete_with_hash_value(&conn->loop_checked, + lcptr->hash_value_full, (uchar *) lcptr); +#else + my_hash_delete(&conn->loop_checked, (uchar*) lcptr); +#endif + spider_free(spider_current_trx, lcptr, MYF(0)); + } + ++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( + SPIDER_CONN *conn, + ha_spider *spider, + int link_idx +) { + 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, + *merged_value; + user_var_entry *loop_check; + char *loop_check_buf; + THD *thd = spider->trx->thd; + TABLE_SHARE *top_share = spider->top_share; + SPIDER_SHARE *share = spider->share; + SPIDER_CONN_LOOP_CHECK *lcptr; + LEX_CSTRING lex_str, from_str, to_str; + DBUG_ENTER("spider_conn_queue_loop_check"); + DBUG_PRINT("info", ("spider conn=%p", conn)); + 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); + if (unlikely(!loop_check_buf)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + lex_str.str = loop_check_buf; + memcpy(loop_check_buf, + SPIDER_SQL_LOP_CHK_PRM_PRF_STR, SPIDER_SQL_LOP_CHK_PRM_PRF_LEN); + memcpy(loop_check_buf + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN, + top_share->path.str, top_share->path.length); + loop_check_buf[lex_str.length] = '\0'; + DBUG_PRINT("info", ("spider param name=%s", lex_str.str)); + loop_check = get_variable(&thd->user_vars, &lex_str, FALSE); + if (!loop_check || loop_check->type != STRING_RESULT) + { + DBUG_PRINT("info", ("spider client is not Spider")); + lex_str.str = ""; + lex_str.length = 0; + from_str.str = ""; + from_str.length = 0; + } else { + lex_str.str = loop_check->value; + lex_str.length = loop_check->length; + DBUG_PRINT("info", ("spider from_str=%s", lex_str.str)); + if (unlikely(!(tmp_name = strchr(loop_check->value, '-')))) + { + DBUG_PRINT("info", ("spider invalid value for loop checking 1")); + from_str.str = ""; + from_str.length = 0; + } + else if (unlikely(!(tmp_name = strchr(tmp_name + 1, '-')))) + { + DBUG_PRINT("info", ("spider invalid value for loop checking 2")); + from_str.str = ""; + from_str.length = 0; + } + else if (unlikely(!(tmp_name = strchr(tmp_name + 1, '-')))) + { + DBUG_PRINT("info", ("spider invalid value for loop checking 3")); + from_str.str = ""; + from_str.length = 0; + } + else if (unlikely(!(tmp_name = strchr(tmp_name + 1, '-')))) + { + DBUG_PRINT("info", ("spider invalid value for loop checking 4")); + from_str.str = ""; + from_str.length = 0; + } + else + { + from_str.str = lex_str.str; + from_str.length = tmp_name - lex_str.str + 1; + } + } + my_afree(loop_check_buf); + + to_str.length = build_table_filename(path, FN_REFLEN, + share->tgt_dbs[conn_link_idx], share->tgt_table_names[conn_link_idx], + "", 0); + to_str.str = path; + DBUG_PRINT("info", ("spider to=%s", to_str.str)); + buf_sz = from_str.length + top_share->path.length + to_str.length + 3; + loop_check_buf = (char *) my_alloca(buf_sz); + if (unlikely(!loop_check_buf)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + DBUG_PRINT("info", ("spider top_share->path=%s", top_share->path.str)); + memcpy(loop_check_buf, from_str.str, from_str.length); + tmp_name = loop_check_buf + from_str.length; + *tmp_name = '-'; + ++tmp_name; + memcpy(tmp_name, top_share->path.str, top_share->path.length); + tmp_name += top_share->path.length; + *tmp_name = '-'; + ++tmp_name; + memcpy(tmp_name, to_str.str, to_str.length); + tmp_name += to_str.length; + *tmp_name = '\0'; +#ifdef SPIDER_HAS_HASH_VALUE_TYPE + my_hash_value_type hash_value = my_calc_hash(&conn->loop_checked, + (uchar *) loop_check_buf, buf_sz - 1); +#endif + pthread_mutex_lock(&conn->loop_check_mutex); + if (unlikely( +#ifdef SPIDER_HAS_HASH_VALUE_TYPE + !(lcptr = (SPIDER_CONN_LOOP_CHECK *) + my_hash_search_using_hash_value(&conn->loop_checked, hash_value, + (uchar *) loop_check_buf, buf_sz - 1)) || +#else + !(lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_search( + &conn->loop_checked, (uchar *) loop_check_buf, buf_sz - 1)) || +#endif + ( + !lcptr->flag && + ( + lcptr->from_value.length != lex_str.length || + memcmp(lcptr->from_value.str, lex_str.str, lex_str.length) + ) + ) + )) + { + if (unlikely(lcptr)) + { + DBUG_PRINT("info", ("spider free lcptr")); +#ifdef HASH_UPDATE_WITH_HASH_VALUE + my_hash_delete_with_hash_value(&conn->loop_checked, + lcptr->hash_value_full, (uchar *) lcptr); +#else + my_hash_delete(&conn->loop_checked, (uchar*) lcptr); +#endif + spider_free(spider_current_trx, lcptr, MYF(0)); + } + 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), + &from_value, (uint) (lex_str.length + 1), + &merged_value, (uint) (spider_unique_id.length + top_share->path.length + + lex_str.length + 2), + NullS) + )) { + my_afree(loop_check_buf); + 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); + lcptr->to_name.str = to_name; + lcptr->to_name.length = to_str.length; + memcpy(to_name, to_str.str, to_str.length + 1); + lcptr->full_name.str = full_name; + lcptr->full_name.length = buf_sz - 1; + memcpy(full_name, loop_check_buf, buf_sz); + lcptr->from_value.str = from_value; + lcptr->from_value.length = lex_str.length; + memcpy(from_value, lex_str.str, lex_str.length + 1); + lcptr->merged_value.str = merged_value; +#ifdef SPIDER_HAS_HASH_VALUE_TYPE + lcptr->hash_value_to = my_calc_hash(&conn->loop_checked, + (uchar *) to_str.str, to_str.length); + lcptr->hash_value_full = hash_value; +#endif +#ifdef HASH_UPDATE_WITH_HASH_VALUE + if (unlikely(my_hash_insert_with_hash_value(&conn->loop_checked, + lcptr->hash_value_full, (uchar *) lcptr))) +#else + if (unlikely(my_hash_insert(&conn->loop_checked, (uchar *) lcptr))) +#endif + { + my_afree(loop_check_buf); + goto error_hash_insert; + } + } else { + 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); + DBUG_PRINT("info", ("spider be sent or queued already")); + DBUG_RETURN(0); + } + my_afree(loop_check_buf); + + if ((error_num = spider_conn_queue_and_merge_loop_check(conn, lcptr))) + { + goto error_queue_and_merge; + } + pthread_mutex_unlock(&conn->loop_check_mutex); + DBUG_RETURN(0); + +error_hash_insert: + spider_free(spider_current_trx, lcptr, MYF(0)); +error_queue_and_merge: + pthread_mutex_unlock(&conn->loop_check_mutex); +error_alloc_loop_check: + DBUG_RETURN(error_num); +} + void spider_conn_queue_start_transaction( SPIDER_CONN *conn ) { diff --git a/storage/spider/spd_conn.h b/storage/spider/spd_conn.h index ba4db883378..17f1118900a 100644 --- a/storage/spider/spd_conn.h +++ b/storage/spider/spd_conn.h @@ -22,6 +22,26 @@ #define SPIDER_BG_SIMPLE_DISCONNECT 2 #define SPIDER_BG_SIMPLE_RECORDS 3 +#define SPIDER_LOP_CHK_QUEUED (1 << 0) +#define SPIDER_LOP_CHK_MERAGED (1 << 1) +#define SPIDER_LOP_CHK_IGNORED (1 << 2) + +typedef struct st_spider_conn_loop_check +{ + uint flag; +#ifdef SPIDER_HAS_HASH_VALUE_TYPE + my_hash_value_type hash_value_to; + my_hash_value_type hash_value_full; +#endif + LEX_CSTRING from_name; + LEX_CSTRING cur_name; + LEX_CSTRING to_name; + LEX_CSTRING full_name; + LEX_CSTRING from_value; + LEX_CSTRING merged_value; + st_spider_conn_loop_check *next; +} SPIDER_CONN_LOOP_CHECK; + uchar *spider_conn_get_key( SPIDER_CONN *conn, size_t *length, @@ -34,6 +54,14 @@ uchar *spider_ipport_conn_get_key( my_bool not_used __attribute__ ((unused)) ); +int spider_conn_init( + SPIDER_CONN *conn +); + +void spider_conn_done( + SPIDER_CONN *conn +); + int spider_reset_conn_setted_parameter( SPIDER_CONN *conn, THD *thd @@ -146,6 +174,21 @@ void spider_conn_queue_UTC_time_zone( SPIDER_CONN *conn ); +int spider_conn_queue_and_merge_loop_check( + SPIDER_CONN *conn, + SPIDER_CONN_LOOP_CHECK *lcptr +); + +int spider_conn_reset_queue_loop_check( + SPIDER_CONN *conn +); + +int spider_conn_queue_loop_check( + SPIDER_CONN *conn, + ha_spider *spider, + int link_idx +); + void spider_conn_queue_start_transaction( SPIDER_CONN *conn ); diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 97a4d362944..18a85172052 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -396,6 +396,12 @@ int spider_db_conn_queue_action( append_time_zone(&sql_str, conn->queued_time_zone_val)) ) || ( + conn->loop_check_queue.records && + conn->db_conn->set_loop_check_in_bulk_sql() && + (error_num = spider_dbton[conn->dbton_id].db_util-> + append_loop_check(&sql_str, conn)) + ) || + ( conn->queued_trx_start && conn->db_conn->trx_start_in_bulk_sql() && (error_num = spider_dbton[conn->dbton_id].db_util-> @@ -479,6 +485,13 @@ int spider_db_conn_queue_action( DBUG_RETURN(error_num); } if ( + conn->loop_check_queue.records && + !conn->db_conn->set_loop_check_in_bulk_sql() && + (error_num = conn->db_conn->set_loop_check((int *) conn->need_mon)) + ) { + DBUG_RETURN(error_num); + } + if ( conn->queued_trx_isolation && !conn->queued_semi_trx_isolation && conn->queued_trx_isolation_val != conn->trx_isolation && @@ -577,6 +590,11 @@ int spider_db_conn_queue_action( DBUG_PRINT("info", ("spider conn->time_zone=%p", conn->time_zone)); } + + if (conn->loop_check_queue.records) + { + conn->db_conn->fin_loop_check(); + } spider_conn_clear_queue(conn); #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) } else if (conn->server_lost) diff --git a/storage/spider/spd_db_include.cc b/storage/spider/spd_db_include.cc index 2910aa97690..032d2ea067d 100644 --- a/storage/spider/spd_db_include.cc +++ b/storage/spider/spd_db_include.cc @@ -1,4 +1,5 @@ /* Copyright (C) 2018-2019 Kentoku Shiba + Copyright (C) 2018-2019 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +32,7 @@ #include "spd_err.h" #include "spd_db_include.h" #include "spd_include.h" +#include "spd_conn.h" spider_db_result::spider_db_result( SPIDER_DB_CONN *in_db_conn @@ -49,3 +51,62 @@ spider_db_conn::spider_db_conn( DBUG_PRINT("info",("spider this=%p", this)); DBUG_VOID_RETURN; } + +bool spider_db_conn::set_loop_check_in_bulk_sql() +{ + DBUG_ENTER("spider_db_conn::set_loop_check_in_bulk_sql"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(FALSE); +} + +int spider_db_conn::set_loop_check( + int *need_mon +) { + DBUG_ENTER("spider_db_conn::set_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + /* nothing to do */ + DBUG_RETURN(0); +} + +int spider_db_conn::fin_loop_check() +{ + st_spider_conn_loop_check *lcptr; + DBUG_ENTER("spider_db_conn::fin_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + if (conn->loop_check_queue.records) + { + uint l = 0; + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_check_queue, l))) + { + lcptr->flag = 0; + ++l; + } + 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); +} + +int spider_db_util::append_loop_check( + spider_string *str, + SPIDER_CONN *conn +) { + DBUG_ENTER("spider_db_util::append_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + /* nothing to do */ + DBUG_RETURN(0); +} diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 325bf80a1e3..ce95c4132ee 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -94,6 +94,8 @@ typedef st_spider_result SPIDER_RESULT; #define SPIDER_SQL_DOT_STR "." #define SPIDER_SQL_DOT_LEN (sizeof(SPIDER_SQL_DOT_STR) - 1) +#define SPIDER_SQL_HYPHEN_STR "-" +#define SPIDER_SQL_HYPHEN_LEN (sizeof(SPIDER_SQL_HYPHEN_STR) - 1) #define SPIDER_SQL_EQUAL_STR " = " #define SPIDER_SQL_EQUAL_LEN (sizeof(SPIDER_SQL_EQUAL_STR) - 1) @@ -206,6 +208,9 @@ typedef st_spider_result SPIDER_RESULT; #define SPIDER_SQL_LCL_NAME_QUOTE_STR "`" #define SPIDER_SQL_LCL_NAME_QUOTE_LEN (sizeof(SPIDER_SQL_LCL_NAME_QUOTE_STR) - 1) +#define SPIDER_SQL_LOP_CHK_PRM_PRF_STR "spider_lc_" +#define SPIDER_SQL_LOP_CHK_PRM_PRF_LEN (sizeof(SPIDER_SQL_LOP_CHK_PRM_PRF_STR) - 1) + #define SPIDER_CONN_KIND_MYSQL (1 << 0) #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) #define SPIDER_CONN_KIND_HS_READ (1 << 2) @@ -850,6 +855,10 @@ public: spider_string *str, Time_zone *time_zone ) = 0; + virtual int append_loop_check( + spider_string *str, + SPIDER_CONN *conn + ); virtual int append_start_transaction( spider_string *str ) = 0; @@ -1155,6 +1164,11 @@ public: Time_zone *time_zone, int *need_mon ) = 0; + virtual bool set_loop_check_in_bulk_sql(); + virtual int set_loop_check( + int *need_mon + ); + virtual int fin_loop_check(); virtual int show_master_status( SPIDER_TRX *trx, SPIDER_SHARE *share, diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 6a0aef4bafb..b3e223fc981 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2018 Kentoku Shiba +/* Copyright (C) 2012-2019 Kentoku Shiba This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -94,6 +94,9 @@ static const char *name_quote_str = SPIDER_SQL_NAME_QUOTE_STR; #define SPIDER_SQL_TIME_ZONE_STR "set session time_zone = '" #define SPIDER_SQL_TIME_ZONE_LEN sizeof(SPIDER_SQL_TIME_ZONE_STR) - 1 +#define SPIDER_SQL_SET_USER_VAL_STR "set @`" +#define SPIDER_SQL_SET_USER_VAL_LEN sizeof(SPIDER_SQL_SET_USER_VAL_STR) - 1 + #define SPIDER_SQL_COMMIT_STR "commit" #define SPIDER_SQL_COMMIT_LEN sizeof(SPIDER_SQL_COMMIT_STR) - 1 #define SPIDER_SQL_ROLLBACK_STR "rollback" @@ -2175,19 +2178,23 @@ bool spider_db_mbase::is_xa_nota_error( DBUG_RETURN(xa_nota); } -void spider_db_mbase::print_warnings( +int spider_db_mbase::print_warnings( struct tm *l_time ) { + int error_num = 0; DBUG_ENTER("spider_db_mbase::print_warnings"); DBUG_PRINT("info",("spider this=%p", this)); if (db_conn->status == MYSQL_STATUS_READY) { + if ( #if MYSQL_VERSION_ID < 50500 - if (!(db_conn->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS)) + !(db_conn->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) && + db_conn->last_used_con->warning_count #else - if (!(db_conn->server_status & SERVER_MORE_RESULTS_EXISTS)) + !(db_conn->server_status & SERVER_MORE_RESULTS_EXISTS) && + db_conn->warning_count #endif - { + ) { /* pthread_mutex_lock(&conn->mta_conn_mutex); SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos); @@ -2213,7 +2220,7 @@ void spider_db_mbase::print_warnings( SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); */ - DBUG_VOID_RETURN; + DBUG_RETURN(0); } /* no record is ok */ } @@ -2225,17 +2232,32 @@ void spider_db_mbase::print_warnings( if (num_fields != 3) { mysql_free_result(res); - DBUG_VOID_RETURN; + DBUG_RETURN(0); } - while (row) + if (l_time) { - fprintf(stderr, "%04d%02d%02d %02d:%02d:%02d [WARN SPIDER RESULT] " - "from [%s] %ld to %ld: %s %s %s\n", - l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, - l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - conn->tgt_host, (ulong) db_conn->thread_id, - (ulong) current_thd->thread_id, row[0], row[1], row[2]); - row = mysql_fetch_row(res); + while (row) + { + fprintf(stderr, "%04d%02d%02d %02d:%02d:%02d [WARN SPIDER RESULT] " + "from [%s] %ld to %ld: %s %s %s\n", + l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, + l_time->tm_hour, l_time->tm_min, l_time->tm_sec, + conn->tgt_host, (ulong) db_conn->thread_id, + (ulong) current_thd->thread_id, row[0], row[1], row[2]); + row = mysql_fetch_row(res); + } + } else { + while (row) + { + DBUG_PRINT("info",("spider row[0]=%s", row[0])); + DBUG_PRINT("info",("spider row[1]=%s", row[1])); + DBUG_PRINT("info",("spider row[2]=%s", row[2])); + int res_num = + (int) my_strtoll10(row[1], (char**) NULL, &error_num); + my_printf_error(res_num, row[2], MYF(0)); + error_num = res_num; + row = mysql_fetch_row(res); + } } if (res) mysql_free_result(res); @@ -2247,7 +2269,7 @@ void spider_db_mbase::print_warnings( } } } - DBUG_VOID_RETURN; + DBUG_RETURN(error_num); } spider_db_result *spider_db_mbase::store_result( @@ -2819,6 +2841,99 @@ int spider_db_mbase::set_time_zone( DBUG_RETURN(0); } +bool spider_db_mbase::set_loop_check_in_bulk_sql() +{ + DBUG_ENTER("spider_db_mbase::set_loop_check_in_bulk_sql"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(TRUE); +} + +int spider_db_mbase::set_loop_check( + int *need_mon +) { + SPIDER_CONN_LOOP_CHECK *lcptr; + char sql_buf[MAX_FIELD_WIDTH]; + spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); + DBUG_ENTER("spider_db_mbase::set_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + sql_str.init_calc_mem(270); + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_check_queue, 0))) + { + sql_str.length(0); + if (sql_str.reserve(SPIDER_SQL_SET_USER_VAL_LEN + + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN + lcptr->to_name.length + + SPIDER_SQL_NAME_QUOTE_LEN + SPIDER_SQL_EQUAL_LEN + + SPIDER_SQL_VALUE_QUOTE_LEN + + lcptr->merged_value.length + SPIDER_SQL_VALUE_QUOTE_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + sql_str.q_append(SPIDER_SQL_SET_USER_VAL_STR, SPIDER_SQL_SET_USER_VAL_LEN); + sql_str.q_append(SPIDER_SQL_LOP_CHK_PRM_PRF_STR, + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN); + sql_str.q_append(lcptr->to_name.str, lcptr->to_name.length); + sql_str.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); + sql_str.q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN); + sql_str.q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); + sql_str.q_append(lcptr->merged_value.str, lcptr->merged_value.length); + sql_str.q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); + + if (spider_db_query( + conn, + sql_str.ptr(), + sql_str.length(), + -1, + need_mon) + ) { + DBUG_RETURN(spider_db_errorno(conn)); + } + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + +#ifdef HASH_UPDATE_WITH_HASH_VALUE + my_hash_delete_with_hash_value(&conn->loop_check_queue, + lcptr->hash_value, (uchar *) lcptr); +#else + my_hash_delete(&conn->loop_check_queue, (uchar*) lcptr); +#endif + } + DBUG_RETURN(0); +} + +int spider_db_mbase::fin_loop_check() +{ + st_spider_conn_loop_check *lcptr; + DBUG_ENTER("spider_db_mbase::fin_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + if (conn->loop_check_queue.records) + { + uint l = 0; + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_check_queue, l))) + { + lcptr->flag = 0; + ++l; + } + 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); +} + int spider_db_mbase::exec_simple_sql_with_result( SPIDER_TRX *trx, SPIDER_SHARE *share, @@ -3802,6 +3917,47 @@ int spider_db_mbase_util::append_time_zone( DBUG_RETURN(0); } +int spider_db_mbase_util::append_loop_check( + spider_string *str, + SPIDER_CONN *conn +) { + SPIDER_CONN_LOOP_CHECK *lcptr; + DBUG_ENTER("spider_db_mbase_util::append_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_PRINT("info",("spider str=%s", str->c_ptr_safe())); + uint l = 0; + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_check_queue, l))) + { + DBUG_PRINT("info",("spider lcptr=%p", lcptr)); + if (str->reserve(SPIDER_SQL_SEMICOLON_LEN + SPIDER_SQL_SET_USER_VAL_LEN + + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN + lcptr->to_name.length + + SPIDER_SQL_NAME_QUOTE_LEN + SPIDER_SQL_EQUAL_LEN + + SPIDER_SQL_VALUE_QUOTE_LEN + + lcptr->merged_value.length + SPIDER_SQL_VALUE_QUOTE_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + if (str->length()) + { + str->q_append(SPIDER_SQL_SEMICOLON_STR, SPIDER_SQL_SEMICOLON_LEN); + } + str->q_append(SPIDER_SQL_SET_USER_VAL_STR, SPIDER_SQL_SET_USER_VAL_LEN); + str->q_append(SPIDER_SQL_LOP_CHK_PRM_PRF_STR, + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN); + str->q_append(lcptr->to_name.str, lcptr->to_name.length); + str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); + str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN); + str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); + str->q_append(lcptr->merged_value.str, lcptr->merged_value.length); + str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); + + ++l; + DBUG_PRINT("info",("spider str=%s", str->c_ptr_safe())); + } + DBUG_RETURN(0); +} + int spider_db_mbase_util::append_start_transaction( spider_string *str ) { @@ -12430,6 +12586,10 @@ int spider_mbase_handler::show_table_status( DBUG_RETURN(error_num); } } + if ((error_num = ((spider_db_mbase *) conn->db_conn)->print_warnings(NULL))) + { + DBUG_RETURN(error_num); + } if (share->static_records_for_status != -1) { share->records = (ha_rows) share->static_records_for_status; diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index ff7ebc32bd9..ccbb51e2163 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -72,6 +72,10 @@ public: spider_string *str, Time_zone *time_zone ); + int append_loop_check( + spider_string *str, + SPIDER_CONN *conn + ); int append_start_transaction( spider_string *str ); @@ -400,7 +404,7 @@ public: bool is_xa_nota_error( int error_num ); - void print_warnings( + int print_warnings( struct tm *l_time ); spider_db_result *store_result( @@ -480,6 +484,11 @@ public: Time_zone *time_zone, int *need_mon ); + bool set_loop_check_in_bulk_sql(); + int set_loop_check( + int *need_mon + ); + int fin_loop_check(); int exec_simple_sql_with_result( SPIDER_TRX *trx, SPIDER_SHARE *share, diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc index 7237d0877a7..66367effe18 100644 --- a/storage/spider/spd_direct_sql.cc +++ b/storage/spider/spd_direct_sql.cc @@ -593,6 +593,11 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( goto error_mta_conn_mutex_init; } + if (unlikely((*error_num = spider_conn_init(conn)))) + { + goto error_conn_init; + } + if ((*error_num = spider_db_udf_direct_sql_connect(direct_sql, conn))) goto error; conn->ping_time = (time_t) time((time_t*) 0); @@ -646,8 +651,10 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( error: DBUG_ASSERT(!conn->mta_conn_mutex_file_pos.file_name); - pthread_mutex_destroy(&conn->mta_conn_mutex); error_too_many_ipport_count: + spider_conn_done(conn); +error_conn_init: + pthread_mutex_destroy(&conn->mta_conn_mutex); error_mta_conn_mutex_init: error_db_conn_init: delete conn->db_conn; diff --git a/storage/spider/spd_environ.h b/storage/spider/spd_environ.h index 42cbf812bbb..5e7687074b7 100644 --- a/storage/spider/spd_environ.h +++ b/storage/spider/spd_environ.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2008-2018 Kentoku Shiba & 2017 MariaDB corp +/* Copyright (C) 2008-2019 Kentoku Shiba + Copyright (C) 2017-2019 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -51,5 +52,6 @@ #define SPIDER_USE_CONST_ITEM_FOR_STRING_INT_REAL_DECIMAL_DATE_ITEM #define SPIDER_SQL_CACHE_IS_IN_LEX #define SPIDER_LIKE_FUNC_HAS_GET_NEGATED +#define HA_HAS_CHECKSUM_EXTENDED #endif #endif /* SPD_ENVIRON_INCLUDED */ diff --git a/storage/spider/spd_err.h b/storage/spider/spd_err.h index a80d903bd6e..bc13e03649b 100644 --- a/storage/spider/spd_err.h +++ b/storage/spider/spd_err.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2019 Kentoku Shiba + Copyright (C) 2019 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -124,6 +125,21 @@ #define ER_SPIDER_CON_COUNT_ERROR_STR "Too many connections between spider and remote" #define ER_SPIDER_TABLE_OPEN_TIMEOUT_NUM 12714 #define ER_SPIDER_TABLE_OPEN_TIMEOUT_STR "Table %s.%s open timeout" +#define ER_SPIDER_NOT_SUPPORTED_NUM 12715 +#define ER_SPIDER_NOT_SUPPORTED_STR "%s is not supported by %s" +#define ER_SPIDER_INVALID_VALUE_NUM 12716 +#define ER_SPIDER_INVALID_VALUE_STR "Invalid value %s in %s.%s" +#define ER_SPIDER_SYNTAX_NUM 12717 +#define ER_SPIDER_SYNTAX_STR "%s detected a syntax error near '%-.80s' at line %d" +#define ER_SPIDER_TOO_LONG_NUM 12718 +#define ER_SPIDER_TOO_LONG_STR "%s is too long" +#define ER_SPIDER_INFINITE_LOOP_NUM 12719 +#define ER_SPIDER_INFINITE_LOOP_STR "An infinite loop is detected when opening table %s.%s" +#define ER_SPIDER_SAME_SERVER_LINK_NUM 12720 +#define ER_SPIDER_SAME_SERVER_LINK_STR1 "Host:%s and Socket:%s aim self server. Please change spider_same_server_link parameter if this link is required." +#define ER_SPIDER_SAME_SERVER_LINK_STR2 "Host:%s and Port:%ld aim self server. Please change spider_same_server_link parameter if this link is required." +#define ER_SPIDER_CANT_NUM 12721 +#define ER_SPIDER_CANT_STR1 "Can't %s%d" #define ER_SPIDER_COND_SKIP_NUM 12801 #define ER_SPIDER_UNKNOWN_NUM 12500 diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 2886ea02ba4..6b0bb8ef161 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2018 Kentoku Shiba +/* Copyright (C) 2008-2019 Kentoku Shiba This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -260,7 +260,7 @@ const char SPIDER_empty_string = ""; #define SPIDER_TMP_SHARE_LONG_COUNT 19 #define SPIDER_TMP_SHARE_LONGLONG_COUNT 3 -#define SPIDER_MEM_CALC_LIST_NUM 265 +#define SPIDER_MEM_CALC_LIST_NUM 273 #define SPIDER_CONN_META_BUF_LEN 64 #define SPIDER_BACKUP_DASTATUS \ @@ -410,6 +410,8 @@ typedef struct st_spider_alter_table uint tmp_link_statuses_length; } SPIDER_ALTER_TABLE; +typedef struct st_spider_conn_loop_check SPIDER_CONN_LOOP_CHECK; + /* database connection */ typedef struct st_spider_conn { @@ -597,6 +599,22 @@ typedef struct st_spider_conn SPIDER_LINK_IDX_CHAIN *link_idx_chain; #endif SPIDER_IP_PORT_CONN *ip_port_conn; + + pthread_mutex_t loop_check_mutex; + HASH loop_checked; + uint loop_checked_id; + const char *loop_checked_func_name; + const char *loop_checked_file_name; + ulong loop_checked_line_no; + 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_LOOP_CHECK *loop_check_meraged_last; } SPIDER_CONN; typedef struct st_spider_lgtm_tblhnd_share diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 97c42189736..178ef33df3e 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -1,4 +1,5 @@ -/* Copyright (C) 2008-2018 Kentoku Shiba +/* Copyright (C) 2008-2019 Kentoku Shiba + Copyright (C) 2019 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -188,6 +189,7 @@ PSI_mutex_key spd_key_mutex_conn_i; PSI_mutex_key spd_key_mutex_bg_stss; PSI_mutex_key spd_key_mutex_bg_crds; #endif +PSI_mutex_key spd_key_mutex_conn_loop_check; static PSI_mutex_info all_spider_mutexes[]= { @@ -238,6 +240,7 @@ static PSI_mutex_info all_spider_mutexes[]= { &spd_key_mutex_pt_handler, "pt_handler", 0}, #endif { &spd_key_mutex_udf_table, "udf_table", 0}, + { &spd_key_mutex_conn_loop_check, "conn_loop_check", 0}, }; #ifndef WITHOUT_SPIDER_BG_SEARCH @@ -396,6 +399,9 @@ extern ulonglong spider_free_mem_count[SPIDER_MEM_CALC_LIST_NUM]; static char spider_wild_many = '%', spider_wild_one = '_', spider_wild_prefix='\\'; +static char spider_unique_id_buf[1 + 12 + 1 + 16 + 1 + 1]; +LEX_CSTRING spider_unique_id; + // for spider_open_tables uchar *spider_tbl_get_key( SPIDER_SHARE *share, @@ -4583,7 +4589,7 @@ SPIDER_SHARE *spider_get_share( SPIDER_SHARE *share; TABLE_SHARE *table_share = table->s; SPIDER_RESULT_LIST *result_list = &spider->result_list; - uint length, tmp_conn_link_idx = 0; + uint length, tmp_conn_link_idx = 0, buf_sz; char *tmp_name, *tmp_cid; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) char *tmp_hs_r_name, *tmp_hs_w_name; @@ -4618,13 +4624,60 @@ SPIDER_SHARE *spider_get_share( bool same_server_link; int load_sts_at_startup; int load_crd_at_startup; + user_var_entry *loop_check; + char *loop_check_buf; + TABLE_SHARE *top_share; + LEX_CSTRING lex_str; DBUG_ENTER("spider_get_share"); - + top_share = spider->top_share; length = (uint) strlen(table_name); #ifdef SPIDER_HAS_HASH_VALUE_TYPE my_hash_value_type hash_value = my_calc_hash(&spider_open_tables, (uchar*) table_name, length); #endif + if (top_share) + { + lex_str.length = top_share->path.length + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN; + buf_sz = spider_unique_id.length > SPIDER_SQL_LOP_CHK_PRM_PRF_LEN ? + top_share->path.length + spider_unique_id.length + 2 : + lex_str.length + 2; + loop_check_buf = (char *) my_alloca(buf_sz); + if (unlikely(!loop_check_buf)) + { + *error_num = HA_ERR_OUT_OF_MEM; + DBUG_RETURN(NULL); + } + lex_str.str = loop_check_buf + buf_sz - lex_str.length - 2; + memcpy((void *) lex_str.str, + SPIDER_SQL_LOP_CHK_PRM_PRF_STR, SPIDER_SQL_LOP_CHK_PRM_PRF_LEN); + memcpy((void *) (lex_str.str + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN), + top_share->path.str, top_share->path.length); + ((char *) lex_str.str)[lex_str.length] = '\0'; + DBUG_PRINT("info",("spider loop check param name=%s", lex_str.str)); + loop_check = get_variable(&thd->user_vars, &lex_str, FALSE); + if (loop_check && loop_check->type == STRING_RESULT) + { + lex_str.length = top_share->path.length + spider_unique_id.length + 1; + lex_str.str = loop_check_buf + buf_sz - top_share->path.length - + spider_unique_id.length - 2; + memcpy((void *) lex_str.str, spider_unique_id.str, + spider_unique_id.length); + ((char *) lex_str.str)[lex_str.length - 1] = '-'; + ((char *) lex_str.str)[lex_str.length] = '\0'; + DBUG_PRINT("info",("spider loop check key=%s", lex_str.str)); + DBUG_PRINT("info",("spider loop check param value=%s", + loop_check->value)); + if (unlikely(strstr(loop_check->value, lex_str.str))) + { + *error_num = ER_SPIDER_INFINITE_LOOP_NUM; + my_printf_error(*error_num, ER_SPIDER_INFINITE_LOOP_STR, MYF(0), + top_share->db.str, top_share->table_name.str); + my_afree(loop_check_buf); + DBUG_RETURN(NULL); + } + } + my_afree(loop_check_buf); + } pthread_mutex_lock(&spider_tbl_mutex); #ifdef SPIDER_HAS_HASH_VALUE_TYPE if (!(share = (SPIDER_SHARE*) my_hash_search_using_hash_value( @@ -5207,6 +5260,7 @@ SPIDER_SHARE *spider_get_share( my_printf_error(ER_SPIDER_TABLE_OPEN_TIMEOUT_NUM, ER_SPIDER_TABLE_OPEN_TIMEOUT_STR, MYF(0), table_share->db.str, table_share->table_name.str); + spider_free_share(share); goto error_but_no_delete; } my_sleep(10000); // wait 10 ms @@ -5520,6 +5574,7 @@ SPIDER_SHARE *spider_get_share( spider->dbton_handler[dbton_id] = NULL; } } + spider_free_share(share); goto error_but_no_delete; } @@ -6864,8 +6919,9 @@ int spider_panic( int spider_db_init( void *p ) { - int error_num, roop_count; + int error_num = HA_ERR_OUT_OF_MEM, roop_count; uint dbton_id = 0; + char addr[6]; handlerton *spider_hton = (handlerton *)p; DBUG_ENTER("spider_db_init"); spider_hton_ptr = spider_hton; @@ -6908,6 +6964,16 @@ int spider_db_init( spider_hton->create_group_by = spider_create_group_by_handler; #endif + if (my_gethwaddr((uchar *) addr)) + { + my_printf_error(ER_SPIDER_CANT_NUM, ER_SPIDER_CANT_STR1, MYF(0), + "get hardware address with error ", errno); + } + spider_unique_id.str = spider_unique_id_buf; + spider_unique_id.length = my_sprintf(spider_unique_id_buf, + (spider_unique_id_buf, "-%02x%02x%02x%02x%02x%02x-%lx-", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], (ulong) getpid())); + memset(&spider_alloc_func_name, 0, sizeof(spider_alloc_func_name)); memset(&spider_alloc_file_name, 0, sizeof(spider_alloc_file_name)); memset(&spider_alloc_line_no, 0, sizeof(spider_alloc_line_no)); @@ -8474,8 +8540,27 @@ TABLE_LIST *spider_get_parent_table_list( ha_spider *spider ) { TABLE *table = spider->get_top_table(); + TABLE_LIST *current, *parent; DBUG_ENTER("spider_get_parent_table_list"); - DBUG_RETURN(table->pos_in_table_list); + DBUG_PRINT("info",("spider table=%p", table)); + if (table->pos_in_table_list) + { + current = table->pos_in_table_list; + } else { + current = table->intention_pos_in_table_list; + } +#ifdef HANDLER_HAS_TOP_TABLE_FIELDS + if (!spider->set_top_table_fields) + { +#endif + while ((parent = current->parent_l)) + { + current = parent; + } +#ifdef HANDLER_HAS_TOP_TABLE_FIELDS + } +#endif + DBUG_RETURN(current); } List<Index_hint> *spider_get_index_hints( @@ -9761,6 +9846,7 @@ int spider_create_spider_object_for_share( #endif (*spider)->dbton_handler = dbton_hdl; (*spider)->search_link_idx = -1; + (*spider)->top_share = NULL; for (roop_count = 0; roop_count < SPIDER_DBTON_SIZE; roop_count++) { if ( |