mirror of
https://github.com/MariaDB/server.git
synced 2025-04-20 06:05:47 +02:00
Merge 10.5 into 10.6
This commit is contained in:
commit
27834ebc91
41 changed files with 444 additions and 197 deletions
client
include
mysql-test
include
main
suite
mysys
sql
mdl.ccsql_base.ccsql_load.ccsql_parse.ccsql_select.ccsql_servers.ccsql_show.ccsql_test.cctable_cache.ccxa.cc
storage
innobase
perfschema
|
@ -1117,6 +1117,8 @@ inline int get_command_index(char cmd_char)
|
|||
|
||||
static int delimiter_index= -1;
|
||||
static int charset_index= -1;
|
||||
static int sandbox_index= -1;
|
||||
|
||||
static bool real_binary_mode= FALSE;
|
||||
|
||||
|
||||
|
@ -1127,7 +1129,8 @@ int main(int argc,char *argv[])
|
|||
MY_INIT(argv[0]);
|
||||
DBUG_ENTER("main");
|
||||
DBUG_PROCESS(argv[0]);
|
||||
|
||||
|
||||
sandbox_index= get_command_index('-');
|
||||
charset_index= get_command_index('C');
|
||||
delimiter_index= get_command_index('d');
|
||||
delimiter_str= delimiter;
|
||||
|
@ -2261,8 +2264,9 @@ static int read_and_execute(bool interactive)
|
|||
|
||||
/**
|
||||
It checks if the input is a short form command. It returns the command's
|
||||
pointer if a command is found, else return NULL. Note that if binary-mode
|
||||
is set, then only \C is searched for.
|
||||
pointer if a command is found, else return NULL.
|
||||
|
||||
Note that if binary-mode is set, then only \C and \- are searched for.
|
||||
|
||||
@param cmd_char A character of one byte.
|
||||
|
||||
|
@ -2277,13 +2281,23 @@ static COMMANDS *find_command(char cmd_char)
|
|||
int index= -1;
|
||||
|
||||
/*
|
||||
In binary-mode, we disallow all mysql commands except '\C'
|
||||
and DELIMITER.
|
||||
In binary-mode, we disallow all client commands except '\C',
|
||||
DELIMITER (see long comand finding find_command(char *))
|
||||
and '\-' (sandbox, see following comment).
|
||||
*/
|
||||
if (real_binary_mode)
|
||||
{
|
||||
if (cmd_char == 'C')
|
||||
index= charset_index;
|
||||
/*
|
||||
binary-mode enforces stricter controls compared to sandbox mode.
|
||||
Whether sandbox mode is enabled or not is irrelevant when
|
||||
binary-mode is active.
|
||||
The only purpose of processing sandbox mode here is to avoid error
|
||||
messages on files made by mysqldump.
|
||||
*/
|
||||
else if (cmd_char == '-')
|
||||
index= sandbox_index;
|
||||
}
|
||||
else
|
||||
index= get_command_index(cmd_char);
|
||||
|
@ -2339,6 +2353,12 @@ static COMMANDS *find_command(char *name)
|
|||
len= (uint) strlen(name);
|
||||
|
||||
int index= -1;
|
||||
/*
|
||||
In binary-mode, we disallow all client commands except DELIMITER
|
||||
and short commands '\C' and '\-' (see short command finding
|
||||
find_command(char)).
|
||||
*/
|
||||
|
||||
if (real_binary_mode)
|
||||
{
|
||||
if (is_delimiter_command(name, len))
|
||||
|
|
|
@ -686,7 +686,7 @@ static int load_plugin_data(char *plugin_name, char *config_file)
|
|||
if (i == -1) /* if first pass, read this line as so_name */
|
||||
{
|
||||
/* Add proper file extension for soname */
|
||||
if (safe_strcpy(line + line_len - 1, sizeof(line), FN_SOEXT))
|
||||
if (safe_strcpy_truncated(line + line_len - 1, sizeof line, FN_SOEXT))
|
||||
{
|
||||
reason= "Plugin name too long.";
|
||||
fclose(file_ptr);
|
||||
|
@ -749,7 +749,7 @@ static int check_options(int argc, char **argv, char *operation)
|
|||
const char *plugin_dir_prefix = "--plugin_dir=";
|
||||
size_t plugin_dir_len= strlen(plugin_dir_prefix);
|
||||
|
||||
strcpy(plugin_name, "");
|
||||
*plugin_name= '\0';
|
||||
for (i = 0; i < argc && num_found < 5; i++)
|
||||
{
|
||||
|
||||
|
@ -787,8 +787,8 @@ static int check_options(int argc, char **argv, char *operation)
|
|||
/* read the plugin config file and check for match against argument */
|
||||
else
|
||||
{
|
||||
if (safe_strcpy(plugin_name, sizeof(plugin_name), argv[i]) ||
|
||||
safe_strcpy(config_file, sizeof(config_file), argv[i]) ||
|
||||
if (safe_strcpy_truncated(plugin_name, sizeof plugin_name, argv[i]) ||
|
||||
safe_strcpy_truncated(config_file, sizeof config_file, argv[i]) ||
|
||||
safe_strcat(config_file, sizeof(config_file), ".ini"))
|
||||
{
|
||||
fprintf(stderr, "ERROR: argument is too long.\n");
|
||||
|
|
|
@ -6277,7 +6277,7 @@ int do_done(struct st_command *command)
|
|||
if (*cur_block->delim)
|
||||
{
|
||||
/* Restore "old" delimiter after false if block */
|
||||
if (safe_strcpy(delimiter, sizeof(delimiter), cur_block->delim))
|
||||
if (safe_strcpy_truncated(delimiter, sizeof delimiter, cur_block->delim))
|
||||
die("Delimiter too long, truncated");
|
||||
|
||||
delimiter_length= strlen(delimiter);
|
||||
|
@ -6538,7 +6538,8 @@ void do_block(enum block_cmd cmd, struct st_command* command)
|
|||
else
|
||||
{
|
||||
/* Remember "old" delimiter if entering a false if block */
|
||||
if (safe_strcpy(cur_block->delim, sizeof(cur_block->delim), delimiter))
|
||||
if (safe_strcpy_truncated(cur_block->delim, sizeof cur_block->delim,
|
||||
delimiter))
|
||||
die("Delimiter too long, truncated");
|
||||
}
|
||||
|
||||
|
|
|
@ -239,15 +239,14 @@ static inline void lex_string_set3(LEX_CSTRING *lex_str, const char *c_str,
|
|||
lex_str->length= len;
|
||||
}
|
||||
|
||||
/*
|
||||
Copies src into dst and ensures dst is a NULL terminated C string.
|
||||
/**
|
||||
Copies a string.
|
||||
|
||||
Returns 1 if the src string was truncated due to too small size of dst.
|
||||
Returns 0 if src completely fit within dst. Pads the remaining dst with '\0'
|
||||
|
||||
Note: dst_size must be > 0
|
||||
@param dst destination buffer, will be NUL padded.
|
||||
@param dst_size size of dst buffer, must be > 0
|
||||
@param src NUL terminated source string
|
||||
*/
|
||||
static inline int safe_strcpy(char *dst, size_t dst_size, const char *src)
|
||||
static inline void safe_strcpy(char *dst, size_t dst_size, const char *src)
|
||||
{
|
||||
DBUG_ASSERT(dst_size > 0);
|
||||
|
||||
|
@ -256,45 +255,49 @@ static inline int safe_strcpy(char *dst, size_t dst_size, const char *src)
|
|||
*
|
||||
* 2) IF there is no 0 byte in the first dst_size bytes of src, strncpy will
|
||||
* copy dst_size bytes, and the final byte won't be 0.
|
||||
*
|
||||
* In GCC 8+, the `-Wstringop-truncation` warning will object to strncpy()
|
||||
* being used in this way, so we need to disable this warning for this
|
||||
* single statement.
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 8
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-truncation"
|
||||
#endif
|
||||
strncpy(dst, src, dst_size);
|
||||
#if defined(__GNUC__) && __GNUC__ >= 8
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
dst[dst_size - 1]= 0;
|
||||
}
|
||||
|
||||
if (dst[dst_size-1])
|
||||
/**
|
||||
Copies a string, checking for truncation.
|
||||
|
||||
@param dst destination buffer, will be NUL padded.
|
||||
@param dst_size size of dst buffer, must be > 0
|
||||
@param src NUL terminated source string
|
||||
|
||||
@retval 1 if the src string was truncated due to too small size of dst.
|
||||
@retval 0 if src completely fit within dst,
|
||||
*/
|
||||
static inline int safe_strcpy_truncated(char *dst, size_t dst_size,
|
||||
const char *src)
|
||||
{
|
||||
DBUG_ASSERT(dst_size > 0);
|
||||
|
||||
strncpy(dst, src, dst_size);
|
||||
if (dst[dst_size - 1])
|
||||
{
|
||||
/* Only possible in case (2), meaning src was truncated. */
|
||||
dst[dst_size-1]= 0;
|
||||
dst[dst_size - 1]= 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Appends src to dst and ensures dst is a NULL terminated C string.
|
||||
/**
|
||||
Appends src to dst and ensures dst is a NUL terminated C string.
|
||||
|
||||
Returns 1 if the src string was truncated due to too small size of dst.
|
||||
Returns 0 if src completely fit within the remaining dst space. Pads the
|
||||
remaining dst with '\0'.
|
||||
|
||||
Note: dst_size must be > 0
|
||||
@retval 1 if the src string was truncated due to too small size of dst.
|
||||
@retval 0 if src completely fit within the remaining dst space,
|
||||
including NUL termination.
|
||||
*/
|
||||
static inline int safe_strcat(char *dst, size_t dst_size, const char *src)
|
||||
{
|
||||
size_t init_len= strlen(dst);
|
||||
if (init_len >= dst_size - 1)
|
||||
if (init_len > dst_size)
|
||||
return 1;
|
||||
return safe_strcpy(dst + init_len, dst_size - init_len, src);
|
||||
return safe_strcpy_truncated(dst + init_len, dst_size - init_len, src);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
4
mysql-test/include/log_bin.combinations
Normal file
4
mysql-test/include/log_bin.combinations
Normal file
|
@ -0,0 +1,4 @@
|
|||
[binlogoff]
|
||||
|
||||
[binlogon]
|
||||
log-bin
|
3
mysql-test/include/log_bin.inc
Normal file
3
mysql-test/include/log_bin.inc
Normal file
|
@ -0,0 +1,3 @@
|
|||
# include file for test files that can be run with and without log-bin
|
||||
# (see include/log_bin.combinations)
|
||||
|
|
@ -2061,4 +2061,11 @@ DROP TABLE t1;
|
|||
#
|
||||
CREATE TABLE t1 (id1 INT, id2 INT, primary key (id1), unique index (id2) visible);
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-32376 SHOW CREATE DATABASE statement crashes the server when db name contains some unicode characters, ASAN stack-buffer-overflow
|
||||
#
|
||||
SET NAMES utf8mb3;
|
||||
SHOW CREATE DATABASE `#testone#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■`;
|
||||
ERROR 42000: Incorrect database name '#testone#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■...'
|
||||
SET NAMES DEFAULT;
|
||||
# End of 10.5 Test
|
||||
|
|
|
@ -1935,4 +1935,13 @@ DROP TABLE t1;
|
|||
CREATE TABLE t1 (id1 INT, id2 INT, primary key (id1), unique index (id2) visible);
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32376 SHOW CREATE DATABASE statement crashes the server when db name contains some unicode characters, ASAN stack-buffer-overflow
|
||||
--echo #
|
||||
|
||||
SET NAMES utf8mb3;
|
||||
--error ER_WRONG_DB_NAME
|
||||
SHOW CREATE DATABASE `#testone#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■`;
|
||||
SET NAMES DEFAULT;
|
||||
|
||||
--echo # End of 10.5 Test
|
||||
|
|
|
@ -658,4 +658,15 @@ tee
|
|||
source
|
||||
^^^
|
||||
3
|
||||
#
|
||||
# MDEV-34203: Sandbox mode \- is not compatible with --binary-mode
|
||||
#
|
||||
create table t1 (a int);
|
||||
drop table t1;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
drop table t1;
|
||||
# End of 10.5 tests
|
||||
|
|
|
@ -757,4 +757,20 @@ source $MYSQL_TMP_DIR/mysql_in;" $MYSQL_TMP_DIR/mysql_in2;
|
|||
--remove_file $MYSQL_TMP_DIR/mysql_in
|
||||
--remove_file $MYSQL_TMP_DIR/mysql_in2
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-34203: Sandbox mode \- is not compatible with --binary-mode
|
||||
--echo #
|
||||
|
||||
create table t1 (a int);
|
||||
|
||||
--exec $MYSQL_DUMP test t1 > $MYSQLTEST_VARDIR/tmp/MDEV-34203.sql
|
||||
|
||||
drop table t1;
|
||||
|
||||
--exec $MYSQL --binary-mode test 2>&1 < $MYSQLTEST_VARDIR/tmp/MDEV-34203.sql
|
||||
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/MDEV-34203.sql
|
||||
|
||||
--echo # End of 10.5 tests
|
||||
|
|
46
mysql-test/suite/galera/r/galera_partition_key.result
Normal file
46
mysql-test/suite/galera/r/galera_partition_key.result
Normal file
|
@ -0,0 +1,46 @@
|
|||
connection node_2;
|
||||
connection node_1;
|
||||
connection node_1;
|
||||
CREATE TABLE `t1` (
|
||||
`id` int(10) unsigned NOT NULL,
|
||||
`other_id` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`,`other_id`)
|
||||
) ENGINE=InnoDB
|
||||
PARTITION BY LIST (`id` MOD 2)
|
||||
(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB,
|
||||
PARTITION `p1` VALUES IN (1) ENGINE = InnoDB);
|
||||
INSERT INTO t1 VALUES (1, 0);
|
||||
CREATE TABLE t2 LIKE t1;
|
||||
START TRANSACTION;
|
||||
INSERT INTO t2(SELECT * FROM t1 WHERE id = 1);
|
||||
DELETE FROM t1 WHERE id = 1;
|
||||
COMMIT;
|
||||
connection node_2;
|
||||
SELECT * from t1;
|
||||
id other_id
|
||||
SELECT * from t2;
|
||||
id other_id
|
||||
1 0
|
||||
DROP TABLE t1, t2;
|
||||
connection node_1;
|
||||
CREATE TABLE `t1` (
|
||||
`id` int(10) unsigned NOT NULL,
|
||||
`other_id` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB
|
||||
PARTITION BY LIST (`id` MOD 2)
|
||||
(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB,
|
||||
PARTITION `p1` VALUES IN (1) ENGINE = InnoDB);
|
||||
INSERT INTO t1 VALUES (1, 0);
|
||||
CREATE TABLE t2 LIKE t1;
|
||||
START TRANSACTION;
|
||||
INSERT INTO t2(SELECT * FROM t1 WHERE id = 1);
|
||||
DELETE FROM t1 WHERE id = 1;
|
||||
COMMIT;
|
||||
connection node_2;
|
||||
SELECT * from t1;
|
||||
id other_id
|
||||
SELECT * from t2;
|
||||
id other_id
|
||||
1 0
|
||||
DROP TABLE t1, t2;
|
|
@ -1,5 +1,6 @@
|
|||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/log_bin.inc
|
||||
|
||||
#
|
||||
# This tests simple autocommit replication of MyISAM tables.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
--source include/have_partition.inc
|
||||
--source include/big_test.inc
|
||||
--source include/force_restart.inc
|
||||
--source include/log_bin.inc
|
||||
|
||||
--connection node_1
|
||||
|
||||
|
|
55
mysql-test/suite/galera/t/galera_partition_key.test
Normal file
55
mysql-test/suite/galera/t/galera_partition_key.test
Normal file
|
@ -0,0 +1,55 @@
|
|||
--source include/galera_cluster.inc
|
||||
--source include/have_partition.inc
|
||||
--source include/log_bin.inc
|
||||
|
||||
--connection node_1
|
||||
CREATE TABLE `t1` (
|
||||
`id` int(10) unsigned NOT NULL,
|
||||
`other_id` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`,`other_id`)
|
||||
) ENGINE=InnoDB
|
||||
PARTITION BY LIST (`id` MOD 2)
|
||||
(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB,
|
||||
PARTITION `p1` VALUES IN (1) ENGINE = InnoDB);
|
||||
|
||||
INSERT INTO t1 VALUES (1, 0);
|
||||
|
||||
CREATE TABLE t2 LIKE t1;
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
INSERT INTO t2(SELECT * FROM t1 WHERE id = 1);
|
||||
DELETE FROM t1 WHERE id = 1;
|
||||
|
||||
COMMIT;
|
||||
|
||||
--connection node_2
|
||||
SELECT * from t1;
|
||||
SELECT * from t2;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
--connection node_1
|
||||
CREATE TABLE `t1` (
|
||||
`id` int(10) unsigned NOT NULL,
|
||||
`other_id` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB
|
||||
PARTITION BY LIST (`id` MOD 2)
|
||||
(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB,
|
||||
PARTITION `p1` VALUES IN (1) ENGINE = InnoDB);
|
||||
|
||||
INSERT INTO t1 VALUES (1, 0);
|
||||
|
||||
CREATE TABLE t2 LIKE t1;
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
INSERT INTO t2(SELECT * FROM t1 WHERE id = 1);
|
||||
DELETE FROM t1 WHERE id = 1;
|
||||
|
||||
COMMIT;
|
||||
|
||||
--connection node_2
|
||||
SELECT * from t1;
|
||||
SELECT * from t2;
|
||||
DROP TABLE t1, t2;
|
|
@ -1,6 +1,6 @@
|
|||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_log_bin.inc
|
||||
--source include/log_bin.inc
|
||||
--source include/have_sequence.inc
|
||||
--source include/have_aria.inc
|
||||
|
||||
|
|
6
mysql-test/suite/innodb/r/open_files_limit.result
Normal file
6
mysql-test/suite/innodb/r/open_files_limit.result
Normal file
|
@ -0,0 +1,6 @@
|
|||
call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*");
|
||||
call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is exceeded \\(.* files stay open\\)");
|
||||
FOUND 1 /\[Warning\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*/ in mysqld.1.err
|
||||
CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB;
|
||||
DROP TABLE t1;
|
||||
# restart: --innodb_open_files=0
|
3
mysql-test/suite/innodb/t/open_files_limit.opt
Normal file
3
mysql-test/suite/innodb/t/open_files_limit.opt
Normal file
|
@ -0,0 +1,3 @@
|
|||
--innodb_undo_tablespaces=8
|
||||
--innodb_open_files=10
|
||||
--innodb_temp_data_file_path=ibtmp1:32M;ibtmp2:32M:autoextend
|
12
mysql-test/suite/innodb/t/open_files_limit.test
Normal file
12
mysql-test/suite/innodb/t/open_files_limit.test
Normal file
|
@ -0,0 +1,12 @@
|
|||
--source include/have_innodb.inc
|
||||
--source include/not_embedded.inc
|
||||
call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*");
|
||||
call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is exceeded \\(.* files stay open\\)");
|
||||
let SEARCH_PATTERN= \[Warning\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*;
|
||||
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB;
|
||||
DROP TABLE t1;
|
||||
let $restart_parameters=--innodb_open_files=0;
|
||||
--source include/restart_mysqld.inc
|
|
@ -526,7 +526,7 @@ extern "C" const char *my_crc32c_implementation()
|
|||
} // namespace crc32c
|
||||
} // namespace mysys_namespace
|
||||
|
||||
extern "C" unsigned my_crc32c(unsigned int crc, const char *buf, size_t size)
|
||||
extern "C" uint32 my_crc32c(uint32 crc, const void *buf, size_t size)
|
||||
{
|
||||
return mysys_namespace::crc32c::ChosenExtend(crc,buf, size);
|
||||
}
|
||||
|
|
|
@ -184,9 +184,9 @@ static inline uint64_t CombineCRC(
|
|||
// Compute CRC-32C using the Intel hardware instruction.
|
||||
extern "C"
|
||||
USE_PCLMUL
|
||||
uint32_t crc32c_3way(uint32_t crc, const char *buf, size_t len)
|
||||
uint32_t crc32c_3way(uint32_t crc, const void *buf, size_t len)
|
||||
{
|
||||
const unsigned char* next = (const unsigned char*)buf;
|
||||
const unsigned char* next = static_cast<const unsigned char*>(buf);
|
||||
uint64_t count;
|
||||
uint64_t crc0, crc1, crc2;
|
||||
crc0 = crc ^ 0xffffffffu;
|
||||
|
|
|
@ -54,9 +54,9 @@ static uint32_t cpuid_ecx()
|
|||
#endif
|
||||
}
|
||||
|
||||
typedef unsigned (*my_crc32_t)(unsigned, const void *, size_t);
|
||||
extern "C" unsigned int crc32_pclmul(unsigned int, const void *, size_t);
|
||||
extern "C" unsigned int crc32c_3way(unsigned int, const void *, size_t);
|
||||
typedef uint32_t (*my_crc32_t)(uint32_t, const void *, size_t);
|
||||
extern "C" uint32_t crc32_pclmul(uint32_t, const void *, size_t);
|
||||
extern "C" uint32_t crc32c_3way(uint32_t, const void *, size_t);
|
||||
|
||||
#ifdef USE_VPCLMULQDQ
|
||||
# include <immintrin.h>
|
||||
|
|
|
@ -242,8 +242,10 @@ void lf_pinbox_put_pins(LF_PINS *pins)
|
|||
return;
|
||||
}
|
||||
|
||||
static int ptr_cmp(void **a, void **b)
|
||||
static int ptr_cmp(const void *pa, const void *pb)
|
||||
{
|
||||
const void *const*a= pa;
|
||||
const void *const*b= pb;
|
||||
return *a < *b ? -1 : *a == *b ? 0 : 1;
|
||||
}
|
||||
|
||||
|
@ -283,8 +285,10 @@ struct st_harvester {
|
|||
callback forlf_dynarray_iterate:
|
||||
scan all pins of all threads and accumulate all pins
|
||||
*/
|
||||
static int harvest_pins(LF_PINS *el, struct st_harvester *hv)
|
||||
static int harvest_pins(void *e, void *h)
|
||||
{
|
||||
LF_PINS *el= e;
|
||||
struct st_harvester *hv= h;
|
||||
int i;
|
||||
LF_PINS *el_end= el+MY_MIN(hv->npins, LF_DYNARRAY_LEVEL_LENGTH);
|
||||
for (; el < el_end; el++)
|
||||
|
@ -310,8 +314,9 @@ static int harvest_pins(LF_PINS *el, struct st_harvester *hv)
|
|||
callback forlf_dynarray_iterate:
|
||||
scan all pins of all threads and see if addr is present there
|
||||
*/
|
||||
static int match_pins(LF_PINS *el, void *addr)
|
||||
static int match_pins(void *e, void *addr)
|
||||
{
|
||||
LF_PINS *el= e;
|
||||
int i;
|
||||
LF_PINS *el_end= el+LF_DYNARRAY_LEVEL_LENGTH;
|
||||
for (; el < el_end; el++)
|
||||
|
@ -352,13 +357,12 @@ static void lf_pinbox_real_free(LF_PINS *pins)
|
|||
hv.granary= addr;
|
||||
hv.npins= npins;
|
||||
/* scan the dynarray and accumulate all pinned addresses */
|
||||
lf_dynarray_iterate(&pinbox->pinarray,
|
||||
(lf_dynarray_func)harvest_pins, &hv);
|
||||
lf_dynarray_iterate(&pinbox->pinarray, harvest_pins, &hv);
|
||||
|
||||
npins= (int)(hv.granary-addr);
|
||||
/* and sort them */
|
||||
if (npins)
|
||||
qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp);
|
||||
qsort(addr, npins, sizeof(void *), ptr_cmp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -387,8 +391,7 @@ static void lf_pinbox_real_free(LF_PINS *pins)
|
|||
}
|
||||
else /* no alloca - no cookie. linear search here */
|
||||
{
|
||||
if (lf_dynarray_iterate(&pinbox->pinarray,
|
||||
(lf_dynarray_func)match_pins, cur))
|
||||
if (lf_dynarray_iterate(&pinbox->pinarray, match_pins, cur))
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
@ -416,10 +419,11 @@ found:
|
|||
'first' and 'last' are the ends of the linked list of nodes:
|
||||
first->el->el->....->el->last. Use first==last to free only one element.
|
||||
*/
|
||||
static void alloc_free(uchar *first,
|
||||
uchar volatile *last,
|
||||
LF_ALLOCATOR *allocator)
|
||||
static void alloc_free(void *f, void *l, void *alloc)
|
||||
{
|
||||
uchar *first= f;
|
||||
uchar volatile *last= l;
|
||||
LF_ALLOCATOR *allocator= alloc;
|
||||
/*
|
||||
we need a union here to access type-punned pointer reliably.
|
||||
otherwise gcc -fstrict-aliasing will not see 'tmp' changed in the loop
|
||||
|
@ -448,8 +452,7 @@ static void alloc_free(uchar *first,
|
|||
*/
|
||||
void lf_alloc_init(LF_ALLOCATOR *allocator, uint size, uint free_ptr_offset)
|
||||
{
|
||||
lf_pinbox_init(&allocator->pinbox, free_ptr_offset,
|
||||
(lf_pinbox_free_func *)alloc_free, allocator);
|
||||
lf_pinbox_init(&allocator->pinbox, free_ptr_offset, alloc_free, allocator);
|
||||
allocator->top= 0;
|
||||
allocator->mallocs= 0;
|
||||
allocator->element_size= size;
|
||||
|
|
|
@ -62,14 +62,10 @@ my_bool safe_mutex_deadlock_detector= 1; /* On by default */
|
|||
static struct st_safe_mutex_create_info_t *safe_mutex_create_root= NULL;
|
||||
#endif
|
||||
|
||||
static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex,
|
||||
safe_mutex_deadlock_t *locked_mutex);
|
||||
static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex,
|
||||
safe_mutex_t *current_mutex);
|
||||
static my_bool remove_from_locked_mutex(safe_mutex_t *mp,
|
||||
safe_mutex_t *delete_mutex);
|
||||
static my_bool remove_from_used_mutex(safe_mutex_deadlock_t *locked_mutex,
|
||||
safe_mutex_t *mutex);
|
||||
static my_bool add_used_to_locked_mutex(void *used, void *locked);
|
||||
static my_bool add_to_locked_mutex(void *locked, void *current);
|
||||
static my_bool remove_from_locked_mutex(void *m, void* remove);
|
||||
static my_bool remove_from_used_mutex(void *locked, void *m);
|
||||
static void print_deadlock_warning(safe_mutex_t *new_mutex,
|
||||
safe_mutex_t *conflicting_mutex);
|
||||
#endif
|
||||
|
@ -373,8 +369,7 @@ int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file,
|
|||
are now locking (C) in B->C, then we would add C into
|
||||
B->locked_mutex and A->locked_mutex
|
||||
*/
|
||||
my_hash_iterate(mutex_root->used_mutex,
|
||||
(my_hash_walk_action) add_used_to_locked_mutex,
|
||||
my_hash_iterate(mutex_root->used_mutex, add_used_to_locked_mutex,
|
||||
deadlock);
|
||||
|
||||
/*
|
||||
|
@ -654,12 +649,8 @@ void safe_mutex_free_deadlock_data(safe_mutex_t *mp)
|
|||
if (!(mp->create_flags & MYF_NO_DEADLOCK_DETECTION) && mp->used_mutex != NULL)
|
||||
{
|
||||
pthread_mutex_lock(&THR_LOCK_mutex);
|
||||
my_hash_iterate(mp->used_mutex,
|
||||
(my_hash_walk_action) remove_from_locked_mutex,
|
||||
mp);
|
||||
my_hash_iterate(mp->locked_mutex,
|
||||
(my_hash_walk_action) remove_from_used_mutex,
|
||||
mp);
|
||||
my_hash_iterate(mp->used_mutex, remove_from_locked_mutex, mp);
|
||||
my_hash_iterate(mp->locked_mutex, remove_from_used_mutex, mp);
|
||||
pthread_mutex_unlock(&THR_LOCK_mutex);
|
||||
|
||||
my_hash_free(mp->used_mutex);
|
||||
|
@ -710,15 +701,15 @@ void safe_mutex_end(FILE *file __attribute__((unused)))
|
|||
#endif /* SAFE_MUTEX_DETECT_DESTROY */
|
||||
}
|
||||
|
||||
static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex,
|
||||
safe_mutex_deadlock_t *locked_mutex)
|
||||
static my_bool add_used_to_locked_mutex(void *used, void *locked)
|
||||
{
|
||||
safe_mutex_t *used_mutex= used;
|
||||
safe_mutex_deadlock_t *locked_mutex= locked;
|
||||
/* Add mutex to all parent of the current mutex */
|
||||
if (!locked_mutex->warning_only)
|
||||
{
|
||||
(void) my_hash_iterate(locked_mutex->mutex->locked_mutex,
|
||||
(my_hash_walk_action) add_to_locked_mutex,
|
||||
used_mutex);
|
||||
add_to_locked_mutex, used_mutex);
|
||||
/* mark that locked_mutex is locked after used_mutex */
|
||||
(void) add_to_locked_mutex(locked_mutex, used_mutex);
|
||||
}
|
||||
|
@ -730,12 +721,13 @@ static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex,
|
|||
register that locked_mutex was locked after current_mutex
|
||||
*/
|
||||
|
||||
static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex,
|
||||
safe_mutex_t *current_mutex)
|
||||
static my_bool add_to_locked_mutex(void *locked, void *current)
|
||||
{
|
||||
safe_mutex_deadlock_t *locked_mutex= locked;
|
||||
safe_mutex_t *current_mutex= current;
|
||||
DBUG_ENTER("add_to_locked_mutex");
|
||||
DBUG_PRINT("info", ("inserting 0x%lx into 0x%lx (id: %lu -> %lu)",
|
||||
(ulong) locked_mutex, (long) current_mutex,
|
||||
DBUG_PRINT("info", ("inserting %p into %p (id: %lu -> %lu)",
|
||||
locked_mutex, current_mutex,
|
||||
locked_mutex->id, current_mutex->id));
|
||||
if (my_hash_insert(current_mutex->locked_mutex, (uchar*) locked_mutex))
|
||||
{
|
||||
|
@ -763,13 +755,14 @@ static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex,
|
|||
When counter goes to 0, we delete the safe_mutex_deadlock_t entry.
|
||||
*/
|
||||
|
||||
static my_bool remove_from_locked_mutex(safe_mutex_t *mp,
|
||||
safe_mutex_t *delete_mutex)
|
||||
static my_bool remove_from_locked_mutex(void *m, void *remove)
|
||||
{
|
||||
safe_mutex_t *mp= m;
|
||||
safe_mutex_t *delete_mutex= remove;
|
||||
safe_mutex_deadlock_t *found;
|
||||
DBUG_ENTER("remove_from_locked_mutex");
|
||||
DBUG_PRINT("enter", ("delete_mutex: 0x%lx mutex: 0x%lx (id: %lu <- %lu)",
|
||||
(ulong) delete_mutex, (ulong) mp,
|
||||
DBUG_PRINT("enter", ("delete_mutex: %p mutex: %p (id: %lu <- %lu)",
|
||||
delete_mutex, mp,
|
||||
delete_mutex->id, mp->id));
|
||||
|
||||
found= (safe_mutex_deadlock_t *) my_hash_search(mp->locked_mutex,
|
||||
|
@ -787,12 +780,13 @@ static my_bool remove_from_locked_mutex(safe_mutex_t *mp,
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
static my_bool remove_from_used_mutex(safe_mutex_deadlock_t *locked_mutex,
|
||||
safe_mutex_t *mutex)
|
||||
static my_bool remove_from_used_mutex(void *locked, void *m)
|
||||
{
|
||||
safe_mutex_deadlock_t *locked_mutex= locked;
|
||||
safe_mutex_t *mutex= m;
|
||||
DBUG_ENTER("remove_from_used_mutex");
|
||||
DBUG_PRINT("enter", ("delete_mutex: 0x%lx mutex: 0x%lx (id: %lu <- %lu)",
|
||||
(ulong) mutex, (ulong) locked_mutex,
|
||||
DBUG_PRINT("enter", ("delete_mutex: %p mutex: %p (id: %lu <- %lu)",
|
||||
mutex, locked_mutex,
|
||||
mutex->id, locked_mutex->id));
|
||||
if (my_hash_delete(locked_mutex->mutex->used_mutex, (uchar*) mutex))
|
||||
{
|
||||
|
|
|
@ -424,8 +424,10 @@ static void wt_resource_destroy(uchar *arg)
|
|||
It's called from lf_hash when an element is inserted.
|
||||
*/
|
||||
static void wt_resource_init(LF_HASH *hash __attribute__((unused)),
|
||||
WT_RESOURCE *rc, WT_RESOURCE_ID *id)
|
||||
void *resource, const void *ident)
|
||||
{
|
||||
WT_RESOURCE *rc= resource;
|
||||
const WT_RESOURCE_ID *id= ident;
|
||||
DBUG_ENTER("wt_resource_init");
|
||||
rc->id= *id;
|
||||
rc->waiter_count= 0;
|
||||
|
|
15
sql/mdl.cc
15
sql/mdl.cc
|
@ -673,8 +673,10 @@ public:
|
|||
{ ((MDL_lock*)(arg + LF_HASH_OVERHEAD))->~MDL_lock(); }
|
||||
|
||||
static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)),
|
||||
MDL_lock *lock, MDL_key *key_arg)
|
||||
void *_lock, const void *_key_arg)
|
||||
{
|
||||
MDL_lock *lock= static_cast<MDL_lock *>(_lock);
|
||||
const MDL_key *key_arg= static_cast<const MDL_key *>(_key_arg);
|
||||
DBUG_ASSERT(key_arg->mdl_namespace() != MDL_key::BACKUP);
|
||||
new (&lock->key) MDL_key(key_arg);
|
||||
if (key_arg->mdl_namespace() == MDL_key::SCHEMA)
|
||||
|
@ -760,8 +762,10 @@ struct mdl_iterate_arg
|
|||
};
|
||||
|
||||
|
||||
static my_bool mdl_iterate_lock(MDL_lock *lock, mdl_iterate_arg *arg)
|
||||
static my_bool mdl_iterate_lock(void *lk, void *a)
|
||||
{
|
||||
MDL_lock *lock= static_cast<MDL_lock*>(lk);
|
||||
mdl_iterate_arg *arg= static_cast<mdl_iterate_arg*>(a);
|
||||
/*
|
||||
We can skip check for m_strategy here, becase m_granted
|
||||
must be empty for such locks anyway.
|
||||
|
@ -784,14 +788,13 @@ int mdl_iterate(mdl_iterator_callback callback, void *arg)
|
|||
{
|
||||
DBUG_ENTER("mdl_iterate");
|
||||
mdl_iterate_arg argument= { callback, arg };
|
||||
LF_PINS *pins= mdl_locks.get_pins();
|
||||
int res= 1;
|
||||
|
||||
if (pins)
|
||||
if (LF_PINS *pins= mdl_locks.get_pins())
|
||||
{
|
||||
res= mdl_iterate_lock(mdl_locks.m_backup_lock, &argument) ||
|
||||
lf_hash_iterate(&mdl_locks.m_locks, pins,
|
||||
(my_hash_walk_action) mdl_iterate_lock, &argument);
|
||||
lf_hash_iterate(&mdl_locks.m_locks, pins, mdl_iterate_lock,
|
||||
&argument);
|
||||
lf_hash_put_pins(pins);
|
||||
}
|
||||
DBUG_RETURN(res);
|
||||
|
|
|
@ -253,9 +253,10 @@ public:
|
|||
};
|
||||
|
||||
|
||||
static my_bool list_open_tables_callback(TDC_element *element,
|
||||
list_open_tables_arg *arg)
|
||||
static my_bool list_open_tables_callback(void *el, void *a)
|
||||
{
|
||||
TDC_element *element= static_cast<TDC_element*>(el);
|
||||
list_open_tables_arg *arg= static_cast<list_open_tables_arg*>(a);
|
||||
const Lex_ident_db
|
||||
db= Lex_ident_db(Lex_cstring_strlen((const char*) element->m_key));
|
||||
const char *table_name= db.str + db.length + 1;
|
||||
|
@ -303,8 +304,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd,
|
|||
DBUG_ENTER("list_open_tables");
|
||||
list_open_tables_arg argument(thd, db, wild);
|
||||
|
||||
if (tdc_iterate(thd, (my_hash_walk_action) list_open_tables_callback,
|
||||
&argument, true))
|
||||
if (tdc_iterate(thd, list_open_tables_callback, &argument, true))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
DBUG_RETURN(argument.open_list);
|
||||
|
@ -463,9 +463,10 @@ struct tc_collect_arg
|
|||
flush_tables_type flush_type;
|
||||
};
|
||||
|
||||
static my_bool tc_collect_used_shares(TDC_element *element,
|
||||
tc_collect_arg *arg)
|
||||
static my_bool tc_collect_used_shares(void *el, void *a)
|
||||
{
|
||||
TDC_element *element= static_cast<TDC_element*>(el);
|
||||
tc_collect_arg *arg= static_cast<tc_collect_arg*>(a);
|
||||
my_bool result= FALSE;
|
||||
|
||||
DYNAMIC_ARRAY *shares= &arg->shares;
|
||||
|
@ -575,8 +576,7 @@ bool flush_tables(THD *thd, flush_tables_type flag)
|
|||
my_init_dynamic_array(PSI_INSTRUMENT_ME, &collect_arg.shares,
|
||||
sizeof(TABLE_SHARE*), 100, 100, MYF(0));
|
||||
collect_arg.flush_type= flag;
|
||||
if (tdc_iterate(thd, (my_hash_walk_action) tc_collect_used_shares,
|
||||
&collect_arg, true))
|
||||
if (tdc_iterate(thd, tc_collect_used_shares, &collect_arg, true))
|
||||
{
|
||||
/* Release already collected shares */
|
||||
for (uint i= 0 ; i < collect_arg.shares.elements ; i++)
|
||||
|
|
|
@ -119,10 +119,8 @@ public:
|
|||
*/
|
||||
if (WSREP(thd) && wsrep_load_data_splitting)
|
||||
{
|
||||
handlerton *ht= table->s->db_type();
|
||||
// For partitioned tables find underlying hton
|
||||
if (table->file->partition_ht())
|
||||
ht= table->file->partition_ht();
|
||||
handlerton *ht= table->file->partition_ht();
|
||||
if (ht->db_type != DB_TYPE_INNODB)
|
||||
{
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
|
|
|
@ -4705,7 +4705,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
|
|||
#ifdef WITH_WSREP
|
||||
if (wsrep && !first_table->view)
|
||||
{
|
||||
bool is_innodb= (first_table->table->file->ht->db_type == DB_TYPE_INNODB);
|
||||
bool is_innodb= first_table->table->file->partition_ht()->db_type == DB_TYPE_INNODB;
|
||||
|
||||
// For consistency check inserted table needs to be InnoDB
|
||||
if (!is_innodb && thd->wsrep_consistency_check != NO_CONSISTENCY_CHECK)
|
||||
|
@ -6592,6 +6592,23 @@ show_create_db(THD *thd, LEX *lex)
|
|||
DBUG_EXECUTE_IF("4x_server_emul",
|
||||
my_error(ER_UNKNOWN_ERROR, MYF(0)); return 1;);
|
||||
|
||||
#if MYSQL_VERSION_ID<=110301
|
||||
/*
|
||||
This piece of the code was added in 10.5 to fix MDEV-32376.
|
||||
It should not get to 11.3 or higer, as MDEV-32376 was fixed
|
||||
in a different way in 11.3.1 (see MDEV-31948).
|
||||
*/
|
||||
if (lex->name.length > sizeof(db_name_buff) - 1)
|
||||
{
|
||||
my_error(ER_WRONG_DB_NAME, MYF(0),
|
||||
ErrConvString(lex->name.str, lex->name.length,
|
||||
system_charset_info).ptr());
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
#error Remove this preprocessor-conditional code in 11.3.1+
|
||||
#endif
|
||||
|
||||
db_name.str= db_name_buff;
|
||||
db_name.length= lex->name.length;
|
||||
strmov(db_name_buff, lex->name.str);
|
||||
|
|
|
@ -3556,7 +3556,8 @@ bool JOIN::make_aggr_tables_info()
|
|||
{
|
||||
List<Item> *curr_all_fields= &all_fields;
|
||||
List<Item> *curr_fields_list= &fields_list;
|
||||
JOIN_TAB *curr_tab= join_tab + const_tables;
|
||||
// Avoid UB (applying .. offset to nullptr) when join_tab is nullptr
|
||||
JOIN_TAB *curr_tab= join_tab ? join_tab + const_tables : nullptr;
|
||||
TABLE *exec_tmp_table= NULL;
|
||||
bool distinct= false;
|
||||
const bool has_group_by= this->group;
|
||||
|
@ -4117,9 +4118,9 @@ bool JOIN::make_aggr_tables_info()
|
|||
- duplicate value removal
|
||||
Both of these operations are done after window function computation step.
|
||||
*/
|
||||
curr_tab= join_tab + total_join_tab_cnt();
|
||||
if (select_lex->window_funcs.elements)
|
||||
{
|
||||
curr_tab= join_tab + total_join_tab_cnt();
|
||||
if (!(curr_tab->window_funcs_step= new Window_funcs_computation))
|
||||
DBUG_RETURN(true);
|
||||
if (curr_tab->window_funcs_step->setup(thd, &select_lex->window_funcs,
|
||||
|
|
|
@ -133,9 +133,10 @@ struct close_cached_connection_tables_arg
|
|||
};
|
||||
|
||||
|
||||
static my_bool close_cached_connection_tables_callback(
|
||||
TDC_element *element, close_cached_connection_tables_arg *arg)
|
||||
static my_bool close_cached_connection_tables_callback(void *el, void *a)
|
||||
{
|
||||
TDC_element *element= static_cast<TDC_element*>(el);
|
||||
auto arg= static_cast<close_cached_connection_tables_arg*>(a);
|
||||
TABLE_LIST *tmp;
|
||||
|
||||
mysql_mutex_lock(&element->LOCK_table_share);
|
||||
|
@ -188,9 +189,7 @@ static bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection)
|
|||
close_cached_connection_tables_arg argument= { thd, connection, 0 };
|
||||
DBUG_ENTER("close_cached_connections");
|
||||
|
||||
if (tdc_iterate(thd,
|
||||
(my_hash_walk_action) close_cached_connection_tables_callback,
|
||||
&argument))
|
||||
if (tdc_iterate(thd, close_cached_connection_tables_callback, &argument))
|
||||
DBUG_RETURN(true);
|
||||
|
||||
DBUG_RETURN(argument.tables ?
|
||||
|
|
|
@ -3818,7 +3818,7 @@ static bool show_status_array(THD *thd, const char *wild,
|
|||
*/
|
||||
for (var=variables; var->type == SHOW_FUNC ||
|
||||
var->type == SHOW_SIMPLE_FUNC; var= &tmp)
|
||||
((mysql_show_var_func)(var->value))(thd, &tmp, buff,
|
||||
((mysql_show_var_func)(var->value))(thd, &tmp, (void *) buff,
|
||||
status_var, scope);
|
||||
|
||||
SHOW_TYPE show_type=var->type;
|
||||
|
|
|
@ -118,7 +118,7 @@ static void print_cached_tables(void)
|
|||
/* purecov: begin tested */
|
||||
puts("DB Table Version Thread Open Lock");
|
||||
|
||||
tdc_iterate(0, (my_hash_walk_action) print_cached_tables_callback, NULL, true);
|
||||
tdc_iterate(0, print_cached_tables_callback, NULL, true);
|
||||
|
||||
fflush(stdout);
|
||||
/* purecov: end */
|
||||
|
|
|
@ -303,9 +303,11 @@ static void tc_remove_all_unused_tables(TDC_element *element,
|
|||
periodicly flush all not used tables.
|
||||
*/
|
||||
|
||||
static my_bool tc_purge_callback(TDC_element *element,
|
||||
Share_free_tables::List *purge_tables)
|
||||
static my_bool tc_purge_callback(void *_element, void *_purge_tables)
|
||||
{
|
||||
TDC_element *element= static_cast<TDC_element *>(_element);
|
||||
Share_free_tables::List *purge_tables=
|
||||
static_cast<Share_free_tables::List *>(_purge_tables);
|
||||
mysql_mutex_lock(&element->LOCK_table_share);
|
||||
tc_remove_all_unused_tables(element, purge_tables);
|
||||
mysql_mutex_unlock(&element->LOCK_table_share);
|
||||
|
@ -317,7 +319,7 @@ void tc_purge()
|
|||
{
|
||||
Share_free_tables::List purge_tables;
|
||||
|
||||
tdc_iterate(0, (my_hash_walk_action) tc_purge_callback, &purge_tables);
|
||||
tdc_iterate(0, tc_purge_callback, &purge_tables);
|
||||
while (auto table= purge_tables.pop_front())
|
||||
intern_close_table(table);
|
||||
}
|
||||
|
@ -576,17 +578,20 @@ static void lf_alloc_destructor(uchar *arg)
|
|||
|
||||
|
||||
static void tdc_hash_initializer(LF_HASH *,
|
||||
TDC_element *element, LEX_STRING *key)
|
||||
void *_element, const void *_key)
|
||||
{
|
||||
TDC_element *element= static_cast<TDC_element *>(_element);
|
||||
const LEX_STRING *key= static_cast<const LEX_STRING *>(_key);
|
||||
memcpy(element->m_key, key->str, key->length);
|
||||
element->m_key_length= (uint)key->length;
|
||||
tdc_assert_clean_share(element);
|
||||
}
|
||||
|
||||
|
||||
static uchar *tdc_hash_key(const TDC_element *element, size_t *length,
|
||||
static uchar *tdc_hash_key(const unsigned char *_element, size_t *length,
|
||||
my_bool)
|
||||
{
|
||||
const TDC_element *element= (const TDC_element *) _element;
|
||||
*length= element->m_key_length;
|
||||
return (uchar*) element->m_key;
|
||||
}
|
||||
|
@ -1139,7 +1144,7 @@ struct eliminate_duplicates_arg
|
|||
|
||||
|
||||
static uchar *eliminate_duplicates_get_key(const uchar *element, size_t *length,
|
||||
my_bool not_used __attribute__((unused)))
|
||||
my_bool)
|
||||
{
|
||||
LEX_STRING *key= (LEX_STRING *) element;
|
||||
*length= key->length;
|
||||
|
@ -1147,9 +1152,10 @@ static uchar *eliminate_duplicates_get_key(const uchar *element, size_t *length,
|
|||
}
|
||||
|
||||
|
||||
static my_bool eliminate_duplicates(TDC_element *element,
|
||||
eliminate_duplicates_arg *arg)
|
||||
static my_bool eliminate_duplicates(void *el, void *a)
|
||||
{
|
||||
TDC_element *element= static_cast<TDC_element*>(el);
|
||||
eliminate_duplicates_arg *arg= static_cast<eliminate_duplicates_arg*>(a);
|
||||
LEX_STRING *key= (LEX_STRING *) alloc_root(&arg->root, sizeof(LEX_STRING));
|
||||
|
||||
if (!key || !(key->str= (char*) memdup_root(&arg->root, element->m_key,
|
||||
|
@ -1195,7 +1201,7 @@ int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument,
|
|||
hash_flags);
|
||||
no_dups_argument.action= action;
|
||||
no_dups_argument.argument= argument;
|
||||
action= (my_hash_walk_action) eliminate_duplicates;
|
||||
action= eliminate_duplicates;
|
||||
argument= &no_dups_argument;
|
||||
}
|
||||
|
||||
|
|
42
sql/xa.cc
42
sql/xa.cc
|
@ -126,10 +126,11 @@ public:
|
|||
}
|
||||
return true;
|
||||
}
|
||||
static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)),
|
||||
XID_cache_element *element,
|
||||
XID_cache_insert_element *new_element)
|
||||
static void lf_hash_initializer(LF_HASH *, void *el, const void *ie)
|
||||
{
|
||||
XID_cache_element *element= static_cast<XID_cache_element*>(el);
|
||||
XID_cache_insert_element *new_element=
|
||||
static_cast<XID_cache_insert_element*>(const_cast<void*>(ie));
|
||||
DBUG_ASSERT(!element->is_set(ACQUIRED | RECOVERED));
|
||||
element->rm_error= 0;
|
||||
element->xa_state= new_element->xa_state;
|
||||
|
@ -146,11 +147,11 @@ public:
|
|||
DBUG_ASSERT(!reinterpret_cast<XID_cache_element*>(ptr + LF_HASH_OVERHEAD)
|
||||
->is_set(ACQUIRED));
|
||||
}
|
||||
static uchar *key(const XID_cache_element *element, size_t *length,
|
||||
my_bool not_used __attribute__((unused)))
|
||||
static uchar *key(const unsigned char *el, size_t *length, my_bool)
|
||||
{
|
||||
*length= element->xid.key_length();
|
||||
return element->xid.key();
|
||||
const XID &xid= reinterpret_cast<const XID_cache_element*>(el)->xid;
|
||||
*length= xid.key_length();
|
||||
return xid.key();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -221,11 +222,10 @@ void xid_cache_init()
|
|||
{
|
||||
xid_cache_inited= true;
|
||||
lf_hash_init(&xid_cache, sizeof(XID_cache_element), LF_HASH_UNIQUE, 0, 0,
|
||||
(my_hash_get_key) XID_cache_element::key, &my_charset_bin);
|
||||
XID_cache_element::key, &my_charset_bin);
|
||||
xid_cache.alloc.constructor= XID_cache_element::lf_alloc_constructor;
|
||||
xid_cache.alloc.destructor= XID_cache_element::lf_alloc_destructor;
|
||||
xid_cache.initializer=
|
||||
(lf_hash_initializer) XID_cache_element::lf_hash_initializer;
|
||||
xid_cache.initializer= XID_cache_element::lf_hash_initializer;
|
||||
}
|
||||
|
||||
|
||||
|
@ -331,9 +331,10 @@ struct xid_cache_iterate_arg
|
|||
void *argument;
|
||||
};
|
||||
|
||||
static my_bool xid_cache_iterate_callback(XID_cache_element *element,
|
||||
xid_cache_iterate_arg *arg)
|
||||
static my_bool xid_cache_iterate_callback(void *el, void *a)
|
||||
{
|
||||
XID_cache_element *element= static_cast<XID_cache_element*>(el);
|
||||
xid_cache_iterate_arg *arg= static_cast<xid_cache_iterate_arg*>(a);
|
||||
my_bool res= FALSE;
|
||||
if (element->lock())
|
||||
{
|
||||
|
@ -348,8 +349,7 @@ static int xid_cache_iterate(THD *thd, my_hash_walk_action action, void *arg)
|
|||
xid_cache_iterate_arg argument= { action, arg };
|
||||
return thd->fix_xid_hash_pins() ? -1 :
|
||||
lf_hash_iterate(&xid_cache, thd->xid_hash_pins,
|
||||
(my_hash_walk_action) xid_cache_iterate_callback,
|
||||
&argument);
|
||||
xid_cache_iterate_callback, &argument);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1039,17 +1039,19 @@ static my_bool xa_recover_callback(XID_cache_element *xs, Protocol *protocol,
|
|||
}
|
||||
|
||||
|
||||
static my_bool xa_recover_callback_short(XID_cache_element *xs,
|
||||
Protocol *protocol)
|
||||
static my_bool xa_recover_callback_short(void *x, void *p)
|
||||
{
|
||||
XID_cache_element *xs= static_cast<XID_cache_element*>(x);
|
||||
Protocol *protocol= static_cast<Protocol*>(p);
|
||||
return xa_recover_callback(xs, protocol, xs->xid.data,
|
||||
xs->xid.gtrid_length + xs->xid.bqual_length, &my_charset_bin);
|
||||
}
|
||||
|
||||
|
||||
static my_bool xa_recover_callback_verbose(XID_cache_element *xs,
|
||||
Protocol *protocol)
|
||||
static my_bool xa_recover_callback_verbose(void *x, void *p)
|
||||
{
|
||||
XID_cache_element *xs= static_cast<XID_cache_element*>(x);
|
||||
Protocol *protocol= static_cast<Protocol*>(p);
|
||||
char buf[SQL_XIDSIZE];
|
||||
uint len= get_sql_xid(&xs->xid, buf);
|
||||
return xa_recover_callback(xs, protocol, buf, len,
|
||||
|
@ -1089,14 +1091,14 @@ void xa_recover_get_fields(THD *thd, List<Item> *field_list,
|
|||
len= SQL_XIDSIZE;
|
||||
cs= &my_charset_utf8mb3_general_ci;
|
||||
if (action)
|
||||
*action= (my_hash_walk_action) xa_recover_callback_verbose;
|
||||
*action= xa_recover_callback_verbose;
|
||||
}
|
||||
else
|
||||
{
|
||||
len= XIDDATASIZE;
|
||||
cs= &my_charset_bin;
|
||||
if (action)
|
||||
*action= (my_hash_walk_action) xa_recover_callback_short;
|
||||
*action= xa_recover_callback_short;
|
||||
}
|
||||
|
||||
field_list->push_back(new (mem_root)
|
||||
|
|
|
@ -69,13 +69,16 @@ inline bool fil_is_user_tablespace_id(ulint space_id)
|
|||
}
|
||||
|
||||
/** Try to close a file to adhere to the innodb_open_files limit.
|
||||
@param ignore_space Ignore the tablespace which is acquired by caller
|
||||
@param print_info whether to diagnose why a file cannot be closed
|
||||
@return whether a file was closed */
|
||||
bool fil_space_t::try_to_close(bool print_info)
|
||||
bool fil_space_t::try_to_close(fil_space_t *ignore_space, bool print_info)
|
||||
{
|
||||
mysql_mutex_assert_owner(&fil_system.mutex);
|
||||
for (fil_space_t &space : fil_system.space_list)
|
||||
{
|
||||
if (&space == ignore_space)
|
||||
continue;
|
||||
switch (space.purpose) {
|
||||
case FIL_TYPE_TEMPORARY:
|
||||
continue;
|
||||
|
@ -340,7 +343,7 @@ fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle,
|
|||
clear_closing();
|
||||
if (++fil_system.n_open >= srv_max_n_open_files) {
|
||||
reacquire();
|
||||
try_to_close(true);
|
||||
try_to_close(this, true);
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
@ -394,7 +397,7 @@ static bool fil_node_open_file_low(fil_node_t *node)
|
|||
|
||||
/* The following call prints an error message */
|
||||
if (os_file_get_last_error(true) == EMFILE + 100 &&
|
||||
fil_space_t::try_to_close(true))
|
||||
fil_space_t::try_to_close(nullptr, true))
|
||||
continue;
|
||||
|
||||
ib::warn() << "Cannot open '" << node->name << "'.";
|
||||
|
@ -438,7 +441,7 @@ static bool fil_node_open_file(fil_node_t *node)
|
|||
|
||||
for (ulint count= 0; fil_system.n_open >= srv_max_n_open_files; count++)
|
||||
{
|
||||
if (fil_space_t::try_to_close(count > 1))
|
||||
if (fil_space_t::try_to_close(nullptr, count > 1))
|
||||
count= 0;
|
||||
else if (count >= 2)
|
||||
{
|
||||
|
|
|
@ -4091,6 +4091,21 @@ static int innodb_init_params()
|
|||
}
|
||||
}
|
||||
|
||||
ulint min_open_files_limit = srv_undo_tablespaces
|
||||
+ srv_sys_space.m_files.size()
|
||||
+ srv_tmp_space.m_files.size() + 1;
|
||||
if (min_open_files_limit > innobase_open_files) {
|
||||
sql_print_warning(
|
||||
"InnoDB: innodb_open_files=%lu is not greater "
|
||||
"than the number of system tablespace files, "
|
||||
"temporary tablespace files, "
|
||||
"innodb_undo_tablespaces=%lu; adjusting "
|
||||
"to innodb_open_files=%zu",
|
||||
innobase_open_files, srv_undo_tablespaces,
|
||||
min_open_files_limit);
|
||||
innobase_open_files = (ulong) min_open_files_limit;
|
||||
}
|
||||
|
||||
srv_max_n_open_files = innobase_open_files;
|
||||
srv_innodb_status = (ibool) innobase_create_status_file;
|
||||
|
||||
|
|
|
@ -648,9 +648,10 @@ private:
|
|||
|
||||
public:
|
||||
/** Try to close a file to adhere to the innodb_open_files limit.
|
||||
@param ignore_space Ignore the tablespace which is acquired by caller
|
||||
@param print_info whether to diagnose why a file cannot be closed
|
||||
@return whether a file was closed */
|
||||
static bool try_to_close(bool print_info);
|
||||
static bool try_to_close(fil_space_t *ignore_space, bool print_info);
|
||||
|
||||
/** Close all tablespace files at shutdown */
|
||||
static void close_all();
|
||||
|
|
|
@ -437,10 +437,10 @@ class rw_trx_hash_t
|
|||
not accessible by concurrent threads.
|
||||
*/
|
||||
|
||||
static void rw_trx_hash_initializer(LF_HASH *,
|
||||
rw_trx_hash_element_t *element,
|
||||
trx_t *trx)
|
||||
static void rw_trx_hash_initializer(LF_HASH *, void *el, const void *t)
|
||||
{
|
||||
rw_trx_hash_element_t *element= static_cast<rw_trx_hash_element_t*>(el);
|
||||
trx_t *trx= static_cast<trx_t*>(const_cast<void*>(t));
|
||||
ut_ad(element->trx == 0);
|
||||
element->trx= trx;
|
||||
element->id= trx->id;
|
||||
|
@ -454,7 +454,7 @@ class rw_trx_hash_t
|
|||
|
||||
Pins are used to protect object from being destroyed or reused. They are
|
||||
normally stored in trx object for quick access. If caller doesn't have trx
|
||||
available, we try to get it using currnet_trx(). If caller doesn't have trx
|
||||
available, we try to get it using current_trx(). If caller doesn't have trx
|
||||
at all, temporary pins are allocated.
|
||||
*/
|
||||
|
||||
|
@ -480,9 +480,10 @@ class rw_trx_hash_t
|
|||
|
||||
|
||||
template <typename T>
|
||||
static my_bool eliminate_duplicates(rw_trx_hash_element_t *element,
|
||||
eliminate_duplicates_arg<T> *arg)
|
||||
static my_bool eliminate_duplicates(void *el, void *a)
|
||||
{
|
||||
rw_trx_hash_element_t *element= static_cast<rw_trx_hash_element_t*>(el);
|
||||
auto arg= static_cast<eliminate_duplicates_arg<T>*>(a);
|
||||
for (trx_ids_t::iterator it= arg->ids.begin(); it != arg->ids.end(); it++)
|
||||
{
|
||||
if (*it == element->id)
|
||||
|
@ -508,17 +509,17 @@ class rw_trx_hash_t
|
|||
}
|
||||
|
||||
|
||||
template <typename T> struct debug_iterator_arg
|
||||
struct debug_iterator_arg
|
||||
{
|
||||
walk_action<T> *action;
|
||||
T *argument;
|
||||
my_hash_walk_action action;
|
||||
void *argument;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
static my_bool debug_iterator(rw_trx_hash_element_t *element,
|
||||
debug_iterator_arg<T> *arg)
|
||||
static my_bool debug_iterator(void *el, void *a)
|
||||
{
|
||||
rw_trx_hash_element_t *element= static_cast<rw_trx_hash_element_t*>(el);
|
||||
debug_iterator_arg *arg= static_cast<debug_iterator_arg*>(a);
|
||||
element->mutex.wr_lock();
|
||||
if (element->trx)
|
||||
validate_element(element->trx);
|
||||
|
@ -726,7 +727,7 @@ public:
|
|||
|
||||
@param caller_trx used to get/set pins
|
||||
@param action called for every element in hash
|
||||
@param argument opque argument passed to action
|
||||
@param argument opaque argument passed to action
|
||||
|
||||
May return the same element multiple times if hash is under contention.
|
||||
If caller doesn't like to see the same transaction multiple times, it has
|
||||
|
@ -749,28 +750,24 @@ public:
|
|||
@retval 1 iteration was interrupted (action returned 1)
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
int iterate(trx_t *caller_trx, walk_action<T> *action, T *argument= nullptr)
|
||||
int iterate(trx_t *caller_trx, my_hash_walk_action action,
|
||||
void *argument= nullptr)
|
||||
{
|
||||
LF_PINS *pins= caller_trx ? get_pins(caller_trx) : lf_hash_get_pins(&hash);
|
||||
ut_a(pins);
|
||||
#ifdef UNIV_DEBUG
|
||||
debug_iterator_arg<T> debug_arg= { action, argument };
|
||||
action= reinterpret_cast<decltype(action)>(debug_iterator<T>);
|
||||
argument= reinterpret_cast<T*>(&debug_arg);
|
||||
debug_iterator_arg debug_arg= { action, argument };
|
||||
action= debug_iterator;
|
||||
argument= reinterpret_cast<void*>(&debug_arg);
|
||||
#endif
|
||||
int res= lf_hash_iterate(&hash, pins,
|
||||
reinterpret_cast<my_hash_walk_action>(action),
|
||||
const_cast<void*>(static_cast<const void*>
|
||||
(argument)));
|
||||
int res= lf_hash_iterate(&hash, pins, action, argument);
|
||||
if (!caller_trx)
|
||||
lf_hash_put_pins(pins);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
int iterate(walk_action<T> *action, T *argument= nullptr)
|
||||
int iterate(my_hash_walk_action action, void *argument= nullptr)
|
||||
{
|
||||
return iterate(current_trx(), action, argument);
|
||||
}
|
||||
|
@ -1195,9 +1192,10 @@ public:
|
|||
inline void undo_truncate_start(fil_space_t &space);
|
||||
|
||||
private:
|
||||
static my_bool find_same_or_older_callback(rw_trx_hash_element_t *element,
|
||||
trx_id_t *id)
|
||||
static my_bool find_same_or_older_callback(void *el, void *i)
|
||||
{
|
||||
auto element= static_cast<rw_trx_hash_element_t *>(el);
|
||||
auto id= static_cast<trx_id_t*>(i);
|
||||
return element->id <= *id;
|
||||
}
|
||||
|
||||
|
@ -1211,9 +1209,10 @@ private:
|
|||
};
|
||||
|
||||
|
||||
static my_bool copy_one_id(rw_trx_hash_element_t *element,
|
||||
snapshot_ids_arg *arg)
|
||||
static my_bool copy_one_id(void* el, void *a)
|
||||
{
|
||||
auto element= static_cast<const rw_trx_hash_element_t *>(el);
|
||||
auto arg= static_cast<snapshot_ids_arg*>(a);
|
||||
if (element->id < arg->m_id)
|
||||
{
|
||||
trx_id_t no= element->no;
|
||||
|
|
|
@ -5445,8 +5445,10 @@ static void lock_rec_block_validate(const page_id_t page_id)
|
|||
}
|
||||
}
|
||||
|
||||
static my_bool lock_validate_table_locks(rw_trx_hash_element_t *element, void*)
|
||||
|
||||
static my_bool lock_validate_table_locks(void *el, void*)
|
||||
{
|
||||
rw_trx_hash_element_t *element= static_cast<rw_trx_hash_element_t*>(el);
|
||||
lock_sys.assert_locked();
|
||||
element->mutex.wr_lock();
|
||||
if (element->trx)
|
||||
|
@ -5654,10 +5656,10 @@ struct lock_rec_other_trx_holds_expl_arg
|
|||
};
|
||||
|
||||
|
||||
static my_bool lock_rec_other_trx_holds_expl_callback(
|
||||
rw_trx_hash_element_t *element,
|
||||
lock_rec_other_trx_holds_expl_arg *arg)
|
||||
static my_bool lock_rec_other_trx_holds_expl_callback(void *el, void *a)
|
||||
{
|
||||
auto element= static_cast<rw_trx_hash_element_t*>(el);
|
||||
auto arg= static_cast<lock_rec_other_trx_holds_expl_arg*>(a);
|
||||
element->mutex.wr_lock();
|
||||
if (element->trx)
|
||||
{
|
||||
|
@ -6473,13 +6475,14 @@ dberr_t lock_trx_handle_wait(trx_t *trx)
|
|||
/**
|
||||
Do an exhaustive check for any locks (table or rec) against the table.
|
||||
|
||||
@param[in] table check if there are any locks held on records in this table
|
||||
or on the table itself
|
||||
@param t check if there are any locks held on records in this table
|
||||
or on the table itself
|
||||
*/
|
||||
|
||||
static my_bool lock_table_locks_lookup(rw_trx_hash_element_t *element,
|
||||
const dict_table_t *table)
|
||||
static my_bool lock_table_locks_lookup(void *el, void *t)
|
||||
{
|
||||
auto element= static_cast<rw_trx_hash_element_t*>(el);
|
||||
const dict_table_t *table= static_cast<const dict_table_t*>(t);
|
||||
lock_sys.assert_locked();
|
||||
element->mutex.wr_lock();
|
||||
if (element->trx)
|
||||
|
@ -6539,7 +6542,7 @@ bool lock_table_has_locks(dict_table_t *table)
|
|||
{
|
||||
LockMutexGuard g{SRW_LOCK_CALL};
|
||||
trx_sys.rw_trx_hash.iterate(lock_table_locks_lookup,
|
||||
const_cast<const dict_table_t*>(table));
|
||||
static_cast<void*>(table));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
return false;
|
||||
|
|
|
@ -2085,9 +2085,9 @@ static my_bool trx_recover_for_mysql_callback(rw_trx_hash_element_t *element,
|
|||
}
|
||||
|
||||
|
||||
static my_bool trx_recover_reset_callback(rw_trx_hash_element_t *element,
|
||||
void*)
|
||||
static my_bool trx_recover_reset_callback(void *el, void*)
|
||||
{
|
||||
rw_trx_hash_element_t *element= static_cast<rw_trx_hash_element_t*>(el);
|
||||
element->mutex.wr_lock();
|
||||
if (trx_t *trx= element->trx)
|
||||
{
|
||||
|
@ -2139,9 +2139,10 @@ struct trx_get_trx_by_xid_callback_arg
|
|||
};
|
||||
|
||||
|
||||
static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element,
|
||||
trx_get_trx_by_xid_callback_arg *arg)
|
||||
static my_bool trx_get_trx_by_xid_callback(void *el, void *a)
|
||||
{
|
||||
auto element= static_cast<rw_trx_hash_element_t*>(el);
|
||||
auto arg= static_cast<trx_get_trx_by_xid_callback_arg*>(a);
|
||||
my_bool found= 0;
|
||||
element->mutex.wr_lock();
|
||||
if (trx_t *trx= element->trx)
|
||||
|
|
|
@ -133,7 +133,9 @@ static int pfs_done_func(void *p)
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
static int show_func_mutex_instances_lost(THD *thd, SHOW_VAR *var, char *buff)
|
||||
static int show_func_mutex_instances_lost(THD *thd, SHOW_VAR *var, void *buff,
|
||||
struct system_status_var *status_var,
|
||||
enum enum_var_type)
|
||||
{
|
||||
var->type= SHOW_LONG;
|
||||
var->value= buff;
|
||||
|
|
Loading…
Add table
Reference in a new issue