Merge 10.0 into 10.1

This commit is contained in:
Marko Mäkelä 2017-03-03 13:27:12 +02:00
commit adc91387e3
68 changed files with 1283 additions and 648 deletions

22
CREDITS
View file

@ -3,16 +3,18 @@ organization registered in the USA.
The current main sponsors of the MariaDB Foundation are:
Booking.com http://www.booking.com (2013 - 2016)
Development Bank of Singapore http://dbs.com (2016)
MariaDB Corporation https://www.mariadb.com (2013 - 2016)
Visma http://visma.com (2015 - 2016)
Acronis http://acronis.com (2016)
Nexedi https://www.nexedi.com (2016)
Automattic https://automattic.com (2014 - 2016)
Tencent Game DBA http://tencentdba.com/about (2016)
Verkkokauppa.com https://www.verkkokauppa.com (2015 - 2016)
Virtuozzo https://virtuozzo.com (2016)
Alibaba Cloud https://intl.aliyun.com (2017)
Booking.com https://www.booking.com (2013 - 2017)
Development Bank of Singapore https://dbs.com (2016 - 2017)
MariaDB Corporation https://www.mariadb.com (2013 - 2017)
Visma https://visma.com (2015 - 2017)
Acronis http://acronis.com (2016 - 2017)
Nexedi https://www.nexedi.com (2016 - 2017)
Automattic https://automattic.com (2014 - 2017)
Tencent Game DBA http://tencentdba.com/about (2016 - 2017)
Tencent TDSQL http://tdsql.org/ (2016 - 2017)
Verkkokauppa.com https://www.verkkokauppa.com (2015 - 2017)
Virtuozzo https://virtuozzo.com (2016 - 2017)
For a full list of sponsors, see
https://mariadb.org/about/supporters/

View file

@ -38,8 +38,8 @@ char ex_var_names[MAX_MYSQL_VAR][FN_REFLEN];
ulonglong last_values[MAX_MYSQL_VAR];
static int interval=0;
static my_bool option_force=0,interrupted=0,new_line=0,
opt_compress=0, opt_relative=0, opt_verbose=0, opt_vertical=0,
tty_password= 0, opt_nobeep;
opt_compress= 0, opt_local= 0, opt_relative= 0, opt_verbose= 0,
opt_vertical= 0, tty_password= 0, opt_nobeep;
static my_bool debug_info_flag= 0, debug_check_flag= 0;
static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations;
static uint opt_count_iterations= 0, my_end_arg;
@ -102,9 +102,12 @@ enum commands {
ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE,
ADMIN_START_ALL_SLAVES, ADMIN_STOP_ALL_SLAVES,
ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD, ADMIN_FLUSH_SLOW_LOG,
ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD, ADMIN_FLUSH_BINARY_LOG,
ADMIN_FLUSH_ENGINE_LOG, ADMIN_FLUSH_ERROR_LOG, ADMIN_FLUSH_GENERAL_LOG,
ADMIN_FLUSH_RELAY_LOG, ADMIN_FLUSH_SLOW_LOG,
ADMIN_FLUSH_TABLE_STATISTICS, ADMIN_FLUSH_INDEX_STATISTICS,
ADMIN_FLUSH_USER_STATISTICS, ADMIN_FLUSH_CLIENT_STATISTICS,
ADMIN_FLUSH_USER_RESOURCES,
ADMIN_FLUSH_ALL_STATUS, ADMIN_FLUSH_ALL_STATISTICS
};
static const char *command_names[]= {
@ -116,9 +119,10 @@ static const char *command_names[]= {
"ping", "extended-status", "flush-status",
"flush-privileges", "start-slave", "stop-slave",
"start-all-slaves", "stop-all-slaves",
"flush-threads", "old-password", "flush-slow-log",
"flush-threads", "old-password", "flush-binary-log", "flush-engine-log",
"flush-error-log", "flush-general-log", "flush-relay-log", "flush-slow-log",
"flush-table-statistics", "flush-index-statistics",
"flush-user-statistics", "flush-client-statistics",
"flush-user-statistics", "flush-client-statistics", "flush-user-resources",
"flush-all-status", "flush-all-statistics",
NullS
};
@ -160,6 +164,9 @@ static struct my_option my_long_options[] =
NO_ARG, 0, 0, 0, 0, 0, 0},
{"host", 'h', "Connect to host.", &host, &host, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"local", 'l', "Local command, don't write to binlog.",
&opt_local, &opt_local, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
{"no-beep", 'b', "Turn off beep on error.", &opt_nobeep,
&opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"password", 'p',
@ -617,6 +624,18 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
*/
struct my_rnd_struct rand_st;
char buff[FN_REFLEN + 20];
if (opt_local)
{
sprintf(buff, "set local sql_log_bin=0");
if (mysql_query(mysql, buff))
{
my_printf_error(0, "SET LOCAL SQL_LOG_BIN=0 failed; error: '%-.200s'",
error_flags, mysql_error(mysql));
return -1;
}
}
for (; argc > 0 ; argv++,argc--)
{
@ -624,7 +643,6 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
switch ((command= find_type(argv[0],&command_typelib,FIND_TYPE_BASIC))) {
case ADMIN_CREATE:
{
char buff[FN_REFLEN+20];
if (argc < 2)
{
my_printf_error(0, "Too few arguments to create", error_flags);
@ -899,6 +917,56 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
break;
}
case ADMIN_FLUSH_BINARY_LOG:
{
if (mysql_query(mysql, "flush binary logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
}
case ADMIN_FLUSH_ENGINE_LOG:
{
if (mysql_query(mysql,"flush engine logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
}
case ADMIN_FLUSH_ERROR_LOG:
{
if (mysql_query(mysql, "flush error logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
}
case ADMIN_FLUSH_GENERAL_LOG:
{
if (mysql_query(mysql, "flush general logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
}
case ADMIN_FLUSH_RELAY_LOG:
{
if (mysql_query(mysql, "flush relay logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
}
case ADMIN_FLUSH_SLOW_LOG:
{
if (mysql_query(mysql,"flush slow logs"))
@ -969,6 +1037,16 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
break;
}
case ADMIN_FLUSH_USER_RESOURCES:
{
if (mysql_query(mysql, "flush user_resources"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
}
case ADMIN_FLUSH_CLIENT_STATISTICS:
{
if (mysql_query(mysql,"flush client_statistics"))
@ -1292,12 +1370,18 @@ static void usage(void)
flush-index-statistics Flush index statistics\n\
flush-logs Flush all logs\n\
flush-privileges Reload grant tables (same as reload)\n\
flush-binary-log Flush binary log\n\
flush-engine-log Flush engine log(s)\n\
flush-error-log Flush error log\n\
flush-general-log Flush general log\n\
flush-relay-log Flush relay log\n\
flush-slow-log Flush slow query log\n\
flush-status Clear status variables\n\
flush-status Clear status variables\n\
flush-table-statistics Clear table statistics\n\
flush-tables Flush all tables\n\
flush-threads Flush the thread cache\n\
flush-user-statistics Flush user statistics\n\
flush-user-resources Flush user resources\n\
kill id,id,... Kill mysql threads");
#if MYSQL_VERSION_ID >= 32200
puts("\

View file

@ -110,7 +110,7 @@ static const char* sock= 0;
static char *opt_plugindir= 0, *opt_default_auth= 0;
#ifdef HAVE_SMEM
static char *shared_memory_base_name= 0;
static const char *shared_memory_base_name= 0;
#endif
static char* user = 0;
static char* pass = 0;

View file

@ -14,7 +14,8 @@
if [ -f `my_print_defaults --mysqld | grep -oP "pid-file=\K[^$]+"` ]; then
# If this fails, check debian.conf!
mysqladmin --defaults-file=/etc/mysql/debian.cnf flush-logs
mysqladmin --defaults-file=/etc/mysql/debian.cnf --local flush-error-log \
flush-engine-log flush-general-log flush-slow-log
fi
endscript
}

View file

@ -774,7 +774,6 @@ int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file,
const char* path)
{
int ret = SSL_FAILURE;
const int HALF_PATH = 128;
if (file) ret = read_file(ctx, file, SSL_FILETYPE_PEM, CA);

View file

@ -1076,10 +1076,9 @@ typedef ulong myf; /* Type of MyFlags in my_funcs */
static inline char *dlerror(void)
{
static char win_errormsg[2048];
if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
0, GetLastError(), 0, win_errormsg, 2048, NULL))
return win_errormsg;
return "";
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
0, GetLastError(), 0, win_errormsg, 2048, NULL);
return win_errormsg;
}
#define HAVE_DLOPEN 1
#define HAVE_DLERROR 1

View file

@ -816,6 +816,18 @@ Connect to the MariaDB server on the given host\&.
.sp -1
.IP \(bu 2.3
.\}
.\" mysqladmin: local option
.\" local option: mysqladmin
\fB\-\-local\fR,
\fB\-l\fR
.sp
Suppress the SQL command(s) from being written to the binary log by enabled sql_log_bin=0 for the session\&.
.RE
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.\" mysqladmin: no-beep option
.\" no-beep option: mysqladmin
\fB\-\-no\-beep\fR,

View file

@ -1170,7 +1170,7 @@ sub command_line_setup {
# Directories
'tmpdir=s' => \$opt_tmpdir,
'vardir=s' => \$opt_vardir,
'mem:s' => \$opt_mem,
'mem' => \$opt_mem,
'clean-vardir' => \$opt_clean_vardir,
'client-bindir=s' => \$path_client_bindir,
'client-libdir=s' => \$path_client_libdir,
@ -1433,9 +1433,6 @@ sub command_line_setup {
# Use $ENV{'MTR_MEM'} as first location to look (if defined)
unshift(@tmpfs_locations, $ENV{'MTR_MEM'}) if defined $ENV{'MTR_MEM'};
# however if the opt_mem was given a value, use this first
unshift(@tmpfs_locations, $opt_mem) if $opt_mem ne '';
foreach my $fs (@tmpfs_locations)
{
if ( -d $fs && ! -l $fs )

View file

@ -2101,6 +2101,27 @@ Note 1061 Duplicate key name 'id1'
DROP TABLE t2;
DROP TABLE t1;
#
# MDEV-6390 CONVERT TO CHARACTER SET utf8 doesn't change DEFAULT CHARSET.
#
CREATE TABLE t1 (id int(11) NOT NULL, a int(11) NOT NULL, b int(11))
ENGINE=InnoDB DEFAULT CHARSET=latin1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL,
`a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
ALTER TABLE t1 CONVERT TO CHARACTER SET utf8;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL,
`a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
DROP TABLE t1;
#
# Start of 10.1 tests
#
#

View file

@ -1,15 +1,17 @@
SHOW CONTRIBUTORS;
Name Location Comment
Booking.com http://www.booking.com Founding member, Platinum Sponsor of the MariaDB Foundation
Booking.com https://www.booking.com Founding member, Platinum Sponsor of the MariaDB Foundation
Alibaba Cloud https://intl.aliyun.com Platinum Sponsor of the MariaDB Foundation
MariaDB Corporation https://mariadb.com Founding member, Gold Sponsor of the MariaDB Foundation
Visma http://visma.com Gold Sponsor of the MariaDB Foundation
DBS http://dbs.com Gold Sponsor of the MariaDB Foundation
Visma https://visma.com Gold Sponsor of the MariaDB Foundation
DBS https://dbs.com Gold Sponsor of the MariaDB Foundation
Nexedi https://www.nexedi.com Silver Sponsor of the MariaDB Foundation
Acronis http://www.acronis.com Silver Sponsor of the MariaDB Foundation
Auttomattic https://automattic.com Bronze Sponsor of the MariaDB Foundation
Verkkokauppa.com https://virtuozzo.com Bronze Sponsor of the MariaDB Foundation
Virtuozzo https://virtuozzo.com/ Bronze Sponsor of the MariaDB Foundation
Tencent Game DBA http://tencentdba.com/about/ Bronze Sponsor of the MariaDB Foundation
Verkkokauppa.com https://www.verkkokauppa.com Bronze Sponsor of the MariaDB Foundation
Virtuozzo https://virtuozzo.com Bronze Sponsor of the MariaDB Foundation
Tencent Game DBA http://tencentdba.com/about Bronze Sponsor of the MariaDB Foundation
Tencent TDSQL http://tdsql.org Bronze Sponsor of the MariaDB Foundation
Google USA Sponsoring encryption, parallel replication and GTID
Facebook USA Sponsoring non-blocking API, LIMIT ROWS EXAMINED etc
Ronald Bradford Brisbane, Australia EFF contribution for UC2006 Auction

View file

@ -7955,6 +7955,44 @@ set global table_open_cache= @tmp_toc;
set global table_definition_cache= @tmp_tdc;
drop procedure p1;
drop table t1,t2,t3,t4,t5,t6;
#
# MDEV-11935: Queries in stored procedures with and
# EXISTS(SELECT * FROM VIEW) crashes and closes hte conneciton.
#
CREATE TABLE ANY_TABLE (
ENTITY_UID BIGINT NOT NULL
);
CREATE TABLE SECURITY_PATH(
origid BIGINT UNSIGNED NOT NULL,
destid BIGINT UNSIGNED NOT NULL,
KEY (destid)
);
CREATE VIEW ENTITY_ACCESS (
ENTITY_UID,
OWNER_UID
) AS
SELECT SP1.origid,
SP2.destid
FROM SECURITY_PATH SP1
JOIN SECURITY_PATH SP2 ON SP1.destid = SP2.origid
;
CREATE PROCEDURE SP_EXAMPLE_SELECT ()
BEGIN
SELECT *
FROM ANY_TABLE AT1
WHERE EXISTS ( SELECT *
FROM ENTITY_ACCESS EA
WHERE AT1.ENTITY_UID = EA.ENTITY_UID
AND EA.OWNER_UID IS NULL );
END
//
CALL SP_EXAMPLE_SELECT ();
ENTITY_UID
CALL SP_EXAMPLE_SELECT ();
ENTITY_UID
drop procedure SP_EXAMPLE_SELECT;
drop view ENTITY_ACCESS;
drop table ANY_TABLE, SECURITY_PATH;
# End of 10.0 test
CREATE FUNCTION f(f1 VARCHAR(64) COLLATE latin1_german2_ci)
RETURNS VARCHAR(64)

View file

@ -0,0 +1,47 @@
set global innodb_file_format=barracuda;
create table t1 (
id1 bigint(20) not null,
id2 bigint(20) not null,
primary key (id1),
unique key id2 (id2)
) engine=innodb row_format=compressed key_block_size=8;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id1` bigint(20) NOT NULL,
`id2` bigint(20) NOT NULL,
PRIMARY KEY (`id1`),
UNIQUE KEY `id2` (`id2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8
alter table t1 row_format=dynamic;
Warnings:
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=8 unless ROW_FORMAT=COMPRESSED.
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id1` bigint(20) NOT NULL,
`id2` bigint(20) NOT NULL,
PRIMARY KEY (`id1`),
UNIQUE KEY `id2` (`id2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8
alter table t1 key_block_size=0;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id1` bigint(20) NOT NULL,
`id2` bigint(20) NOT NULL,
PRIMARY KEY (`id1`) KEY_BLOCK_SIZE=8,
UNIQUE KEY `id2` (`id2`) KEY_BLOCK_SIZE=8
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
alter table t1 drop primary key, add primary key (id1),
drop key id2, add unique (id2);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id1` bigint(20) NOT NULL,
`id2` bigint(20) NOT NULL,
PRIMARY KEY (`id1`),
UNIQUE KEY `id2` (`id2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
drop table t1;
set global innodb_file_format=default;

View file

@ -0,0 +1,23 @@
#
# MDEV-11757 KEY_BLOCK_SIZE strangeness when UNCOMPRESSing COMPRESSed InnoDB tables
#
source include/have_innodb.inc;
set global innodb_file_format=barracuda;
create table t1 (
id1 bigint(20) not null,
id2 bigint(20) not null,
primary key (id1),
unique key id2 (id2)
) engine=innodb row_format=compressed key_block_size=8;
show create table t1;
alter table t1 row_format=dynamic;
show create table t1;
alter table t1 key_block_size=0;
show create table t1;
alter table t1 drop primary key, add primary key (id1),
drop key id2, add unique (id2);
show create table t1;
drop table t1;
set global innodb_file_format=default;

View file

@ -0,0 +1,10 @@
# threads are removed from:
# - information_schema.processlist
# - performance_schema.threads
# at different times, so we may have to wait a little more
# for the event_scheduler to shutdown
#
let $wait_condition=
SELECT COUNT(*) = 0 FROM performance_schema.threads
WHERE name like 'thread/sql/event%';
--source include/wait_condition.inc

View file

@ -0,0 +1,10 @@
# threads are removed from:
# - information_schema.processlist
# - performance_schema.threads
# at different times, so we may have to wait a little more
# for the event_scheduler to shutdown
#
let $wait_condition=
SELECT COUNT(*) = 1 FROM performance_schema.threads
WHERE name like 'thread/sql/event%';
--source include/wait_condition.inc

View file

@ -9,22 +9,10 @@
# Ensure that the event scheduler (started via threads_mysql-master.opt)
# is really running.
--source include/running_event_scheduler.inc
--source include/pfs_running_event_scheduler.inc
SET GLOBAL event_scheduler = OFF;
--source include/no_running_event_scheduler.inc
# threads are removed from:
# - information_schema.processlist
# - performance_schema.threads
# at different times, so we may have to wait a little more
# for the event_scheduler to shutdown
#
let $wait_timeout= 1;
let $wait_condition=
SELECT COUNT(*) = 0 FROM performance_schema.threads
WHERE name like 'thread/sql/event%';
--source include/wait_condition.inc
--source include/pfs_no_running_event_scheduler.inc
--vertical_results
@ -59,7 +47,7 @@ WHERE name LIKE 'thread/sql%';
SET GLOBAL event_scheduler = ON;
--source include/running_event_scheduler.inc
--source include/pfs_running_event_scheduler.inc
# Show entries belonging to the just started event scheduler
SELECT name, type, processlist_user, processlist_host, processlist_db,

View file

@ -1756,6 +1756,17 @@ REFERENCES t1 (id);
DROP TABLE t2;
DROP TABLE t1;
--echo #
--echo # MDEV-6390 CONVERT TO CHARACTER SET utf8 doesn't change DEFAULT CHARSET.
--echo #
CREATE TABLE t1 (id int(11) NOT NULL, a int(11) NOT NULL, b int(11))
ENGINE=InnoDB DEFAULT CHARSET=latin1;
SHOW CREATE TABLE t1;
ALTER TABLE t1 CONVERT TO CHARACTER SET utf8;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # Start of 10.1 tests
--echo #

View file

@ -9418,6 +9418,46 @@ drop procedure p1;
drop table t1,t2,t3,t4,t5,t6;
--echo #
--echo # MDEV-11935: Queries in stored procedures with and
--echo # EXISTS(SELECT * FROM VIEW) crashes and closes hte conneciton.
--echo #
CREATE TABLE ANY_TABLE (
ENTITY_UID BIGINT NOT NULL
);
CREATE TABLE SECURITY_PATH(
origid BIGINT UNSIGNED NOT NULL,
destid BIGINT UNSIGNED NOT NULL,
KEY (destid)
);
CREATE VIEW ENTITY_ACCESS (
ENTITY_UID,
OWNER_UID
) AS
SELECT SP1.origid,
SP2.destid
FROM SECURITY_PATH SP1
JOIN SECURITY_PATH SP2 ON SP1.destid = SP2.origid
;
--delimiter //
CREATE PROCEDURE SP_EXAMPLE_SELECT ()
BEGIN
SELECT *
FROM ANY_TABLE AT1
WHERE EXISTS ( SELECT *
FROM ENTITY_ACCESS EA
WHERE AT1.ENTITY_UID = EA.ENTITY_UID
AND EA.OWNER_UID IS NULL );
END
//
--delimiter ;
CALL SP_EXAMPLE_SELECT ();
CALL SP_EXAMPLE_SELECT ();
drop procedure SP_EXAMPLE_SELECT;
drop view ENTITY_ACCESS;
drop table ANY_TABLE, SECURITY_PATH;
--echo # End of 10.0 test
DELIMITER |;

View file

@ -1074,6 +1074,15 @@
fun:SSL_library_init
}
{
OpenSSL still reachable.
Memcheck:Leak
fun:*alloc
fun:CRYPTO_malloc
fun:sk_new
fun:SSL_COMP_get_compression_methods
fun:SSL_library_init
}
{
OpenSSL still reachable.

View file

@ -114,14 +114,19 @@ my_hash_init2(HASH *hash, uint growth_size, CHARSET_INFO *charset,
static inline void my_hash_free_elements(HASH *hash)
{
uint records= hash->records;
/*
Set records to 0 early to guard against anyone looking at the structure
during the free process
*/
hash->records= 0;
if (hash->free)
{
HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*);
HASH_LINK *end= data + hash->records;
HASH_LINK *end= data + records;
while (data < end)
(*hash->free)((data++)->data);
}
hash->records=0;
}
@ -518,6 +523,9 @@ my_bool my_hash_insert(HASH *info, const uchar *record)
The record with the same record ptr is removed.
If there is a free-function it's called if record was found.
hash->free() is guarantee to be called only after the row has been
deleted from the hash and the hash can be reused by other threads.
@return
@retval 0 ok
@retval 1 Record not found

View file

@ -1876,6 +1876,7 @@ int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
It's currently safe to call this if one has called init_io_cache()
on the 'info' object, even if init_io_cache() failed.
This function is also safe to call twice with the same handle.
Note that info->file is not reset as the caller may still use ut for my_close()
RETURN
0 ok
@ -1905,10 +1906,12 @@ int end_io_cache(IO_CACHE *info)
if (info->type == SEQ_READ_APPEND)
{
/* Destroy allocated mutex */
info->type= TYPE_NOT_SET;
mysql_mutex_destroy(&info->append_buffer_lock);
}
info->share= 0;
info->type= TYPE_NOT_SET; /* Ensure that flush_io_cache() does nothing */
info->write_end= 0; /* Ensure that my_b_write() fails */
info->write_function= 0; /* my_b_write will crash if used */
DBUG_RETURN(error);
} /* end_io_cache */

View file

@ -37,16 +37,18 @@ struct show_table_contributors_st {
struct show_table_contributors_st show_table_contributors[]= {
/* MariaDB foundation sponsors, in contribution, size , time order */
{"Booking.com", "http://www.booking.com", "Founding member, Platinum Sponsor of the MariaDB Foundation"},
{"Booking.com", "https://www.booking.com", "Founding member, Platinum Sponsor of the MariaDB Foundation"},
{"Alibaba Cloud", "https://intl.aliyun.com", "Platinum Sponsor of the MariaDB Foundation"},
{"MariaDB Corporation", "https://mariadb.com", "Founding member, Gold Sponsor of the MariaDB Foundation"},
{"Visma", "http://visma.com", "Gold Sponsor of the MariaDB Foundation"},
{"DBS", "http://dbs.com", "Gold Sponsor of the MariaDB Foundation"},
{"Visma", "https://visma.com", "Gold Sponsor of the MariaDB Foundation"},
{"DBS", "https://dbs.com", "Gold Sponsor of the MariaDB Foundation"},
{"Nexedi", "https://www.nexedi.com", "Silver Sponsor of the MariaDB Foundation"},
{"Acronis", "http://www.acronis.com", "Silver Sponsor of the MariaDB Foundation"},
{"Auttomattic", "https://automattic.com", "Bronze Sponsor of the MariaDB Foundation"},
{"Verkkokauppa.com", "https://virtuozzo.com", "Bronze Sponsor of the MariaDB Foundation"},
{"Virtuozzo", "https://virtuozzo.com/", "Bronze Sponsor of the MariaDB Foundation"},
{"Tencent Game DBA", "http://tencentdba.com/about/", "Bronze Sponsor of the MariaDB Foundation"},
{"Verkkokauppa.com", "https://www.verkkokauppa.com", "Bronze Sponsor of the MariaDB Foundation"},
{"Virtuozzo", "https://virtuozzo.com", "Bronze Sponsor of the MariaDB Foundation"},
{"Tencent Game DBA", "http://tencentdba.com/about", "Bronze Sponsor of the MariaDB Foundation"},
{"Tencent TDSQL", "http://tdsql.org", "Bronze Sponsor of the MariaDB Foundation"},
/* Sponsors of important features */
{"Google", "USA", "Sponsoring encryption, parallel replication and GTID"},

View file

@ -133,12 +133,6 @@ post_init_event_thread(THD *thd)
thd->cleanup();
return TRUE;
}
thread_safe_increment32(&thread_count);
mysql_mutex_lock(&LOCK_thread_count);
threads.append(thd);
mysql_mutex_unlock(&LOCK_thread_count);
inc_thread_running();
return FALSE;
}
@ -157,7 +151,13 @@ deinit_event_thread(THD *thd)
thd->proc_info= "Clearing";
DBUG_PRINT("exit", ("Event thread finishing"));
delete_running_thd(thd);
mysql_mutex_lock(&LOCK_thread_count);
thd->unlink();
mysql_mutex_unlock(&LOCK_thread_count);
delete thd;
thread_safe_decrement32(&thread_count);
signal_thd_deleted();
}
@ -191,8 +191,10 @@ pre_init_event_thread(THD* thd)
thd->net.read_timeout= slave_net_timeout;
thd->variables.option_bits|= OPTION_AUTO_IS_NULL;
thd->client_capabilities|= CLIENT_MULTI_RESULTS;
thread_safe_increment32(&thread_count);
mysql_mutex_lock(&LOCK_thread_count);
thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
threads.append(thd);
mysql_mutex_unlock(&LOCK_thread_count);
/*
@ -240,13 +242,8 @@ event_scheduler_thread(void *arg)
my_free(arg);
if (!res)
scheduler->run(thd);
else
{
thd->proc_info= "Clearing";
net_end(&thd->net);
delete thd;
}
deinit_event_thread(thd);
DBUG_LEAVE; // Against gcc warnings
my_thread_end();
return 0;
@ -310,6 +307,7 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
DBUG_ENTER("Event_worker_thread::run");
DBUG_PRINT("info", ("Time is %ld, THD: 0x%lx", (long) my_time(0), (long) thd));
inc_thread_running();
if (res)
goto end;
@ -338,6 +336,7 @@ end:
event->name.str));
delete event;
dec_thread_running();
deinit_event_thread(thd);
DBUG_VOID_RETURN;
@ -442,13 +441,9 @@ Event_scheduler::start(int *err_no)
" Can not create thread for event scheduler (errno=%d)",
*err_no);
new_thd->proc_info= "Clearing";
DBUG_ASSERT(new_thd->net.buff != 0);
net_end(&new_thd->net);
state= INITIALIZED;
scheduler_thd= NULL;
delete new_thd;
deinit_event_thread(new_thd);
delete scheduler_param_value;
ret= true;
@ -515,7 +510,6 @@ Event_scheduler::run(THD *thd)
}
LOCK_DATA();
deinit_event_thread(thd);
scheduler_thd= NULL;
state= INITIALIZED;
DBUG_PRINT("info", ("Broadcasting COND_state back to the stoppers"));
@ -575,10 +569,7 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name)
sql_print_error("Event_scheduler::execute_top: Can not create event worker"
" thread (errno=%d). Stopping event scheduler", res);
new_thd->proc_info= "Clearing";
DBUG_ASSERT(new_thd->net.buff != 0);
net_end(&new_thd->net);
deinit_event_thread(new_thd);
goto error;
}
@ -590,9 +581,6 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name)
error:
DBUG_PRINT("error", ("Event_scheduler::execute_top() res: %d", res));
if (new_thd)
delete new_thd;
delete event_name;
DBUG_RETURN(TRUE);
}

View file

@ -4200,7 +4200,7 @@ enum_alter_inplace_result
handler::check_if_supported_inplace_alter(TABLE *altered_table,
Alter_inplace_info *ha_alter_info)
{
DBUG_ENTER("check_if_supported_alter");
DBUG_ENTER("handler::check_if_supported_inplace_alter");
HA_CREATE_INFO *create_info= ha_alter_info->create_info;

View file

@ -3932,12 +3932,7 @@ longlong Item_master_pos_wait::val_int()
else
connection_name= thd->variables.default_master_connection;
mysql_mutex_lock(&LOCK_active_mi);
if (master_info_index) // master_info_index is set to NULL on shutdown.
mi= master_info_index->get_master_info(&connection_name,
Sql_condition::WARN_LEVEL_WARN);
mysql_mutex_unlock(&LOCK_active_mi);
if (!mi)
if (!(mi= get_master_info(&connection_name, Sql_condition::WARN_LEVEL_WARN)))
goto err;
if ((event_count = mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
@ -3945,6 +3940,7 @@ longlong Item_master_pos_wait::val_int()
null_value = 1;
event_count=0;
}
mi->release();
#endif
return event_count;

View file

@ -2789,16 +2789,16 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name,
void MYSQL_QUERY_LOG::reopen_file()
{
char *save_name;
DBUG_ENTER("MYSQL_LOG::reopen_file");
mysql_mutex_lock(&LOCK_log);
if (!is_open())
{
DBUG_PRINT("info",("log is closed"));
mysql_mutex_unlock(&LOCK_log);
DBUG_VOID_RETURN;
}
mysql_mutex_lock(&LOCK_log);
save_name= name;
name= 0; // Don't free name
close(LOG_CLOSE_TO_BE_OPENED);
@ -2957,13 +2957,6 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
DBUG_ENTER("MYSQL_QUERY_LOG::write");
mysql_mutex_lock(&LOCK_log);
if (!is_open())
{
mysql_mutex_unlock(&LOCK_log);
DBUG_RETURN(0);
}
if (is_open())
{ // Safety agains reopen
int tmp_errno= 0;
@ -3207,7 +3200,9 @@ void MYSQL_BIN_LOG::cleanup()
}
inited= 0;
mysql_mutex_lock(&LOCK_log);
close(LOG_CLOSE_INDEX|LOG_CLOSE_STOP_EVENT);
mysql_mutex_unlock(&LOCK_log);
delete description_event_for_queue;
delete description_event_for_exec;
@ -3374,6 +3369,8 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
DBUG_ENTER("MYSQL_BIN_LOG::open");
DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg));
mysql_mutex_assert_owner(&LOCK_log);
if (!is_relay_log)
{
if (!binlog_state_recover_done)
@ -4329,7 +4326,7 @@ void MYSQL_BIN_LOG::wait_for_last_checkpoint_event()
int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
{
int error;
int error, errcode;
char *to_purge_if_included= NULL;
inuse_relaylog *ir;
ulonglong log_space_reclaimed= 0;
@ -4397,7 +4394,8 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
}
/* Store where we are in the new file for the execution thread */
flush_relay_log_info(rli);
if (flush_relay_log_info(rli))
error= LOG_INFO_IO;
DBUG_EXECUTE_IF("crash_before_purge_logs", DBUG_SUICIDE(););
@ -4413,10 +4411,10 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
* Need to update the log pos because purge logs has been called
* after fetching initially the log pos at the begining of the method.
*/
if((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)))
if ((errcode= find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)))
{
sql_print_error("next log error: %d offset: %llu log: %s included: %d",
error, rli->linfo.index_file_offset,
errcode, rli->linfo.index_file_offset,
rli->group_relay_log_name, included);
goto err;
}
@ -5040,19 +5038,19 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock)
File UNINIT_VAR(old_file);
DBUG_ENTER("MYSQL_BIN_LOG::new_file_impl");
if (need_lock)
mysql_mutex_lock(&LOCK_log);
mysql_mutex_assert_owner(&LOCK_log);
if (!is_open())
{
DBUG_PRINT("info",("log is closed"));
mysql_mutex_unlock(&LOCK_log);
DBUG_RETURN(error);
}
if (need_lock)
mysql_mutex_lock(&LOCK_log);
mysql_mutex_lock(&LOCK_index);
mysql_mutex_assert_owner(&LOCK_log);
mysql_mutex_assert_owner(&LOCK_index);
/* Reuse old name if not binlog and not update log */
new_name_ptr= name;
@ -5189,9 +5187,9 @@ end:
new_name_ptr, errno);
}
mysql_mutex_unlock(&LOCK_index);
if (need_lock)
mysql_mutex_unlock(&LOCK_log);
mysql_mutex_unlock(&LOCK_index);
DBUG_RETURN(error);
}
@ -8133,9 +8131,11 @@ int MYSQL_BIN_LOG::wait_for_update_binlog_end_pos(THD* thd,
void MYSQL_BIN_LOG::close(uint exiting)
{ // One can't set log_type here!
bool failed_to_save_state= false;
DBUG_ENTER("MYSQL_BIN_LOG::close");
DBUG_PRINT("enter",("exiting: %d", (int) exiting));
mysql_mutex_assert_owner(&LOCK_log);
if (log_state == LOG_OPENED)
{
#ifdef HAVE_REPLICATION

View file

@ -6405,9 +6405,11 @@ bool Rotate_log_event::write()
@retval
0 ok
1 error
*/
int Rotate_log_event::do_update_pos(rpl_group_info *rgi)
{
int error= 0;
Relay_log_info *rli= rgi->rli;
DBUG_ENTER("Rotate_log_event::do_update_pos");
@ -6456,7 +6458,7 @@ int Rotate_log_event::do_update_pos(rpl_group_info *rgi)
(ulong) rli->group_master_log_pos));
mysql_mutex_unlock(&rli->data_lock);
rpl_global_gtid_slave_state->record_and_update_gtid(thd, rgi);
flush_relay_log_info(rli);
error= flush_relay_log_info(rli);
/*
Reset thd->variables.option_bits and sql_mode etc, because this could
@ -6474,8 +6476,7 @@ int Rotate_log_event::do_update_pos(rpl_group_info *rgi)
else
rgi->inc_event_relay_log_pos();
DBUG_RETURN(0);
DBUG_RETURN(error);
}
@ -8235,6 +8236,7 @@ void Stop_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
int Stop_log_event::do_update_pos(rpl_group_info *rgi)
{
int error= 0;
Relay_log_info *rli= rgi->rli;
DBUG_ENTER("Stop_log_event::do_update_pos");
/*
@ -8250,9 +8252,10 @@ int Stop_log_event::do_update_pos(rpl_group_info *rgi)
{
rpl_global_gtid_slave_state->record_and_update_gtid(thd, rgi);
rli->inc_group_relay_log_pos(0, rgi);
flush_relay_log_info(rli);
if (flush_relay_log_info(rli))
error= 1;
}
DBUG_RETURN(0);
DBUG_RETURN(error);
}
#endif /* !MYSQL_CLIENT */
@ -10298,8 +10301,8 @@ int
Rows_log_event::do_update_pos(rpl_group_info *rgi)
{
Relay_log_info *rli= rgi->rli;
DBUG_ENTER("Rows_log_event::do_update_pos");
int error= 0;
DBUG_ENTER("Rows_log_event::do_update_pos");
DBUG_PRINT("info", ("flags: %s",
get_flags(STMT_END_F) ? "STMT_END_F " : ""));
@ -10311,7 +10314,7 @@ Rows_log_event::do_update_pos(rpl_group_info *rgi)
Step the group log position if we are not in a transaction,
otherwise increase the event log position.
*/
rli->stmt_done(log_pos, thd, rgi);
error= rli->stmt_done(log_pos, thd, rgi);
/*
Clear any errors in thd->net.last_err*. It is not known if this is
needed or not. It is believed that any errors that may exist in

View file

@ -1746,8 +1746,8 @@ int
Old_rows_log_event::do_update_pos(rpl_group_info *rgi)
{
Relay_log_info *rli= rgi->rli;
DBUG_ENTER("Old_rows_log_event::do_update_pos");
int error= 0;
DBUG_ENTER("Old_rows_log_event::do_update_pos");
DBUG_PRINT("info", ("flags: %s",
get_flags(STMT_END_F) ? "STMT_END_F " : ""));
@ -1759,7 +1759,7 @@ Old_rows_log_event::do_update_pos(rpl_group_info *rgi)
Step the group log position if we are not in a transaction,
otherwise increase the event log position.
*/
rli->stmt_done(log_pos, thd, rgi);
error= rli->stmt_done(log_pos, thd, rgi);
/*
Clear any errors in thd->net.last_err*. It is not known if this is
needed or not. It is believed that any errors that may exist in

View file

@ -386,8 +386,8 @@ static int register_service()
CloseServiceHandle(sc_manager);
die("CreateService failed (%u)", GetLastError());
}
SERVICE_DESCRIPTION sd= { "MariaDB database server" };
char description[] = "MariaDB database server";
SERVICE_DESCRIPTION sd= { description };
ChangeServiceConfig2(sc_service, SERVICE_CONFIG_DESCRIPTION, &sd);
CloseServiceHandle(sc_service);
CloseServiceHandle(sc_manager);

View file

@ -714,12 +714,15 @@ mysql_mutex_t
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
LOCK_crypt,
LOCK_global_system_variables,
LOCK_user_conn, LOCK_slave_list, LOCK_active_mi,
LOCK_user_conn, LOCK_slave_list,
LOCK_connection_count, LOCK_error_messages, LOCK_slave_background;
mysql_mutex_t LOCK_stats, LOCK_global_user_client_stats,
LOCK_global_table_stats, LOCK_global_index_stats;
/* This protects against changes in master_info_index */
mysql_mutex_t LOCK_active_mi;
/**
The below lock protects access to two global server variables:
max_prepared_stmt_count and prepared_stmt_count. These variables
@ -877,7 +880,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
key_LOCK_system_variables_hash, key_LOCK_thd_data,
key_LOCK_user_conn, key_LOCK_uuid_short_generator, key_LOG_LOCK_log,
key_master_info_data_lock, key_master_info_run_lock,
key_master_info_sleep_lock,
key_master_info_sleep_lock, key_master_info_start_stop_lock,
key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
key_rpl_group_info_sleep_lock,
key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
@ -949,6 +952,7 @@ static PSI_mutex_info all_server_mutexes[]=
{ &key_LOCK_uuid_short_generator, "LOCK_uuid_short_generator", PSI_FLAG_GLOBAL},
{ &key_LOG_LOCK_log, "LOG::LOCK_log", 0},
{ &key_master_info_data_lock, "Master_info::data_lock", 0},
{ &key_master_info_start_stop_lock, "Master_info::start_stop_lock", 0},
{ &key_master_info_run_lock, "Master_info::run_lock", 0},
{ &key_master_info_sleep_lock, "Master_info::sleep_lock", 0},
{ &key_mutex_slave_reporting_capability_err_lock, "Slave_reporting_capability::err_lock", 0},
@ -1434,7 +1438,7 @@ ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
Query_cache query_cache;
#endif
#ifdef HAVE_SMEM
char *shared_memory_base_name= default_shared_memory_base_name;
const char *shared_memory_base_name= default_shared_memory_base_name;
my_bool opt_enable_shared_memory;
HANDLE smem_event_connect_request= 0;
#endif
@ -1675,7 +1679,7 @@ static void close_connections(void)
mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list
Events::deinit();
end_slave();
slave_prepare_for_shutdown();
/*
Give threads time to die.
@ -1752,6 +1756,7 @@ static void close_connections(void)
DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
mysql_mutex_unlock(&LOCK_thread_count);
}
end_slave();
/* All threads has now been aborted */
DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
mysql_mutex_lock(&LOCK_thread_count);
@ -2768,22 +2773,6 @@ void dec_connection_count(THD *thd)
}
/*
Delete THD and decrement thread counters, including thread_running
*/
void delete_running_thd(THD *thd)
{
mysql_mutex_lock(&LOCK_thread_count);
thd->unlink();
mysql_mutex_unlock(&LOCK_thread_count);
delete thd;
dec_thread_running();
thread_safe_decrement32(&thread_count);
signal_thd_deleted();
}
/*
Send a signal to unblock close_conneciton() if there is no more
threads running with a THD attached
@ -5294,15 +5283,13 @@ static int init_server_components()
if (opt_bin_log)
{
/**
* mutex lock is not needed here.
* but to be able to have mysql_mutex_assert_owner() in code,
* we do it anyway */
mysql_mutex_lock(mysql_bin_log.get_log_lock());
int r= mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0, 0,
int error;
mysql_mutex_t *log_lock= mysql_bin_log.get_log_lock();
mysql_mutex_lock(log_lock);
error= mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0, 0,
WRITE_CACHE, max_binlog_size, 0, TRUE);
mysql_mutex_unlock(mysql_bin_log.get_log_lock());
if (r)
mysql_mutex_unlock(log_lock);
if (error)
unireg_abort(1);
}
@ -7652,17 +7639,14 @@ static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff,
var->type= SHOW_MY_BOOL;
var->value= buff;
mysql_mutex_lock(&LOCK_active_mi);
if (master_info_index)
if ((mi= get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_NOTE)))
{
mi= master_info_index->
get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_NOTE);
if (mi)
tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_READING &&
mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN);
tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_READING &&
mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN);
mi->release();
}
mysql_mutex_unlock(&LOCK_active_mi);
if (mi)
*((my_bool *)buff)= tmp;
else
@ -7694,14 +7678,9 @@ static int show_slaves_running(THD *thd, SHOW_VAR *var, char *buff)
{
var->type= SHOW_LONGLONG;
var->value= buff;
mysql_mutex_lock(&LOCK_active_mi);
if (master_info_index)
*((longlong *)buff)= master_info_index->any_slave_sql_running();
else
*((longlong *)buff)= 0;
*((longlong *)buff)= any_slave_sql_running();
mysql_mutex_unlock(&LOCK_active_mi);
return 0;
}
@ -7709,23 +7688,17 @@ static int show_slaves_running(THD *thd, SHOW_VAR *var, char *buff)
static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff,
enum enum_var_type scope)
{
Master_info *mi= NULL;
longlong UNINIT_VAR(tmp);
Master_info *mi;
var->type= SHOW_LONGLONG;
var->value= buff;
mysql_mutex_lock(&LOCK_active_mi);
if (master_info_index)
if ((mi= get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_NOTE)))
{
mi= master_info_index->
get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_NOTE);
if (mi)
tmp= mi->received_heartbeats;
*((longlong *)buff)= mi->received_heartbeats;
mi->release();
}
mysql_mutex_unlock(&LOCK_active_mi);
if (mi)
*((longlong *)buff)= tmp;
else
var->type= SHOW_UNDEF;
return 0;
@ -7735,23 +7708,17 @@ static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff,
static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff,
enum enum_var_type scope)
{
Master_info *mi= NULL;
float UNINIT_VAR(tmp);
Master_info *mi;
var->type= SHOW_CHAR;
var->value= buff;
mysql_mutex_lock(&LOCK_active_mi);
if (master_info_index)
if ((mi= get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_NOTE)))
{
mi= master_info_index->
get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_NOTE);
if (mi)
tmp= mi->heartbeat_period;
sprintf(buff, "%.3f", mi->heartbeat_period);
mi->release();
}
mysql_mutex_unlock(&LOCK_active_mi);
if (mi)
sprintf(buff, "%.3f", tmp);
else
var->type= SHOW_UNDEF;
return 0;

View file

@ -83,7 +83,6 @@ void kill_mysql(void);
void close_connection(THD *thd, uint sql_errno= 0);
void handle_connection_in_main_thread(THD *thd);
void create_thread_to_handle_connection(THD *thd);
void delete_running_thd(THD *thd);
void signal_thd_deleted();
void unlink_thd(THD *thd);
bool one_thread_per_connection_end(THD *thd, bool put_in_cache);
@ -139,7 +138,8 @@ extern my_bool sp_automatic_privileges, opt_noacl;
extern ulong use_stat_tables;
extern my_bool opt_old_style_user_limits, trust_function_creators;
extern uint opt_crash_binlog_innodb;
extern char *shared_memory_base_name, *mysqld_unix_port;
extern const char *shared_memory_base_name;
extern char *mysqld_unix_port;
extern my_bool opt_enable_shared_memory;
extern ulong opt_replicate_events_marked_for_skip;
extern char *default_tz_name;
@ -293,7 +293,7 @@ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
key_LOCK_thd_data,
key_LOCK_user_conn, key_LOG_LOCK_log,
key_master_info_data_lock, key_master_info_run_lock,
key_master_info_sleep_lock,
key_master_info_sleep_lock, key_master_info_start_stop_lock,
key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
key_rpl_group_info_sleep_lock,

View file

@ -508,7 +508,7 @@ BOOL NTService::IsService(LPCSTR ServiceName)
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
BOOL NTService::got_service_option(char **argv, char *service_option)
BOOL NTService::got_service_option(char **argv, const char *service_option)
{
char *option;
for (option= argv[1]; *option; option++)

View file

@ -61,7 +61,7 @@ class NTService
BOOL SeekStatus(LPCSTR szInternName, int OperationType);
BOOL Remove(LPCSTR szInternName);
BOOL IsService(LPCSTR ServiceName);
BOOL got_service_option(char **argv, char *service_option);
BOOL got_service_option(char **argv, const char *service_option);
BOOL is_super_user();
/*

View file

@ -40,7 +40,9 @@ Master_info::Master_info(LEX_STRING *connection_name_arg,
sync_counter(0), heartbeat_period(0), received_heartbeats(0),
master_id(0), prev_master_id(0),
using_gtid(USE_GTID_NO), events_queued_since_last_gtid(0),
gtid_reconnect_event_skip_count(0), gtid_event_seen(false)
gtid_reconnect_event_skip_count(0), gtid_event_seen(false),
in_start_all_slaves(0), in_stop_all_slaves(0),
users(0), killed(0)
{
host[0] = 0; user[0] = 0; password[0] = 0;
ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0;
@ -81,6 +83,8 @@ Master_info::Master_info(LEX_STRING *connection_name_arg,
bzero((char*) &file, sizeof(file));
mysql_mutex_init(key_master_info_run_lock, &run_lock, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_master_info_data_lock, &data_lock, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_master_info_start_stop_lock, &start_stop_lock,
MY_MUTEX_INIT_SLOW);
mysql_mutex_setflags(&run_lock, MYF_NO_DEADLOCK_DETECTION);
mysql_mutex_setflags(&data_lock, MYF_NO_DEADLOCK_DETECTION);
mysql_mutex_init(key_master_info_sleep_lock, &sleep_lock, MY_MUTEX_INIT_FAST);
@ -90,8 +94,27 @@ Master_info::Master_info(LEX_STRING *connection_name_arg,
mysql_cond_init(key_master_info_sleep_cond, &sleep_cond, NULL);
}
/**
Wait until no one is using Master_info
*/
void Master_info::wait_until_free()
{
mysql_mutex_lock(&sleep_lock);
killed= 1;
while (users)
mysql_cond_wait(&sleep_cond, &sleep_lock);
mysql_mutex_unlock(&sleep_lock);
}
/**
Delete master_info
*/
Master_info::~Master_info()
{
wait_until_free();
#ifdef WITH_WSREP
/*
Do not free "wsrep" rpl_filter. It will eventually be freed by
@ -106,6 +129,7 @@ Master_info::~Master_info()
mysql_mutex_destroy(&run_lock);
mysql_mutex_destroy(&data_lock);
mysql_mutex_destroy(&sleep_lock);
mysql_mutex_destroy(&start_stop_lock);
mysql_cond_destroy(&data_cond);
mysql_cond_destroy(&start_cond);
mysql_cond_destroy(&stop_cond);
@ -841,12 +865,28 @@ uchar *get_key_master_info(Master_info *mi, size_t *length,
return (uchar*) mi->cmp_connection_name.str;
}
/*
Delete a master info
Called from my_hash_delete(&master_info_hash)
Stops associated slave threads and frees master_info
*/
void free_key_master_info(Master_info *mi)
{
DBUG_ENTER("free_key_master_info");
mysql_mutex_unlock(&LOCK_active_mi);
/* Ensure that we are not in reset_slave while this is done */
mi->lock_slave_threads();
terminate_slave_threads(mi,SLAVE_FORCE_ALL);
/* We use 2 here instead of 1 just to make it easier when debugging */
mi->killed= 2;
end_master_info(mi);
mi->unlock_slave_threads();
delete mi;
mysql_mutex_lock(&LOCK_active_mi);
DBUG_VOID_RETURN;
}
@ -1002,9 +1042,28 @@ Master_info_index::Master_info_index()
index_file.file= -1;
}
/**
Free all connection threads
This is done during early stages of shutdown
to give connection threads and slave threads time
to die before ~Master_info_index is called
*/
void Master_info_index::free_connections()
{
mysql_mutex_assert_owner(&LOCK_active_mi);
my_hash_reset(&master_info_hash);
}
/**
Free all connection threads and free structures
*/
Master_info_index::~Master_info_index()
{
/* This will close connection for all objects in the cache */
my_hash_free(&master_info_hash);
end_io_cache(&index_file);
if (index_file.file >= 0)
@ -1027,7 +1086,6 @@ bool Master_info_index::init_all_master_info()
File index_file_nr;
DBUG_ENTER("init_all_master_info");
mysql_mutex_assert_owner(&LOCK_active_mi);
DBUG_ASSERT(master_info_index);
if ((index_file_nr= my_open(index_file_name,
@ -1075,7 +1133,6 @@ bool Master_info_index::init_all_master_info()
DBUG_RETURN(1);
}
lock_slave_threads(mi);
init_thread_mask(&thread_mask,mi,0 /*not inverse*/);
create_logfile_name_with_suffix(buf_master_info_file,
@ -1090,6 +1147,7 @@ bool Master_info_index::init_all_master_info()
sql_print_information("Reading Master_info: '%s' Relay_info:'%s'",
buf_master_info_file, buf_relay_log_info_file);
mi->lock_slave_threads();
if (init_master_info(mi, buf_master_info_file, buf_relay_log_info_file,
0, thread_mask))
{
@ -1103,15 +1161,16 @@ bool Master_info_index::init_all_master_info()
if (master_info_index->add_master_info(mi, FALSE))
DBUG_RETURN(1);
succ_num++;
unlock_slave_threads(mi);
mi->unlock_slave_threads();
}
else
{
/* Master_info already in HASH */
sql_print_error(ER_THD_OR_DEFAULT(current_thd,
ER_CONNECTION_ALREADY_EXISTS),
(int) connection_name.length, connection_name.str,
(int) connection_name.length, connection_name.str);
unlock_slave_threads(mi);
mi->unlock_slave_threads();
delete mi;
}
continue;
@ -1128,8 +1187,9 @@ bool Master_info_index::init_all_master_info()
/* Master_info was already registered */
sql_print_error(ER_THD_OR_DEFAULT(current_thd,
ER_CONNECTION_ALREADY_EXISTS),
(int) connection_name.length, connection_name.str,
(int) connection_name.length, connection_name.str);
unlock_slave_threads(mi);
mi->unlock_slave_threads();
delete mi;
continue;
}
@ -1138,7 +1198,6 @@ bool Master_info_index::init_all_master_info()
if (master_info_index->add_master_info(mi, FALSE))
DBUG_RETURN(1);
succ_num++;
unlock_slave_threads(mi);
if (!opt_skip_slave_start)
{
@ -1160,6 +1219,7 @@ bool Master_info_index::init_all_master_info()
(int) connection_name.length,
connection_name.str);
}
mi->unlock_slave_threads();
}
}
@ -1210,6 +1270,71 @@ bool Master_info_index::write_master_name_to_index_file(LEX_STRING *name,
}
/**
Get Master_info for a connection and lock the object from deletion
@param
connection_name Connection name
warning WARN_LEVEL_NOTE -> Don't print anything
WARN_LEVEL_WARN -> Issue warning if not exists
WARN_LEVEL_ERROR-> Issue error if not exists
*/
Master_info *get_master_info(const LEX_STRING *connection_name,
Sql_condition::enum_warning_level warning)
{
Master_info *mi;
DBUG_ENTER("get_master_info");
/* Protect against inserts into hash */
mysql_mutex_lock(&LOCK_active_mi);
/*
The following can only be true during shutdown when slave has been killed
but some other threads are still trying to access slave statistics.
*/
if (unlikely(!master_info_index))
{
if (warning != Sql_condition::WARN_LEVEL_NOTE)
my_error(WARN_NO_MASTER_INFO,
MYF(warning == Sql_condition::WARN_LEVEL_WARN ?
ME_JUST_WARNING : 0),
(int) connection_name->length, connection_name->str);
mysql_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(0);
}
if ((mi= master_info_index->get_master_info(connection_name, warning)))
{
/*
We have to use sleep_lock here. If we would use LOCK_active_mi
then we would take locks in wrong order in Master_info::release()
*/
mysql_mutex_lock(&mi->sleep_lock);
mi->users++;
DBUG_PRINT("info",("users: %d", mi->users));
mysql_mutex_unlock(&mi->sleep_lock);
}
mysql_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(mi);
}
/**
Release master info.
Signals ~Master_info that it's now safe to delete it
*/
void Master_info::release()
{
mysql_mutex_lock(&sleep_lock);
if (!--users && killed)
{
/* Signal ~Master_info that it's ok to now free it */
mysql_cond_signal(&sleep_cond);
}
mysql_mutex_unlock(&sleep_lock);
}
/**
Get Master_info for a connection
@ -1232,8 +1357,6 @@ Master_info_index::get_master_info(const LEX_STRING *connection_name,
("connection_name: '%.*s'", (int) connection_name->length,
connection_name->str));
mysql_mutex_assert_owner(&LOCK_active_mi);
/* Make name lower case for comparison */
res= strmake(buff, connection_name->str, connection_name->length);
my_casedn_str(system_charset_info, buff);
@ -1299,7 +1422,12 @@ bool Master_info_index::check_duplicate_master_info(LEX_STRING *name_arg,
/* Add a Master_info class to Hash Table */
bool Master_info_index::add_master_info(Master_info *mi, bool write_to_file)
{
if (!my_hash_insert(&master_info_hash, (uchar*) mi))
/*
We have to protect against shutdown to ensure we are not calling
my_hash_insert() while my_hash_free() is in progress
*/
if (unlikely(shutdown_in_progress) ||
!my_hash_insert(&master_info_hash, (uchar*) mi))
{
if (global_system_variables.log_warnings > 1)
sql_print_information("Added new Master_info '%.*s' to hash table",
@ -1325,105 +1453,131 @@ bool Master_info_index::add_master_info(Master_info *mi, bool write_to_file)
atomic
*/
bool Master_info_index::remove_master_info(LEX_STRING *name)
bool Master_info_index::remove_master_info(Master_info *mi)
{
Master_info* mi;
DBUG_ENTER("remove_master_info");
mysql_mutex_assert_owner(&LOCK_active_mi);
if ((mi= get_master_info(name, Sql_condition::WARN_LEVEL_WARN)))
// Delete Master_info and rewrite others to file
if (!my_hash_delete(&master_info_hash, (uchar*) mi))
{
// Delete Master_info and rewrite others to file
if (!my_hash_delete(&master_info_hash, (uchar*) mi))
File index_file_nr;
// Close IO_CACHE and FILE handler fisrt
end_io_cache(&index_file);
my_close(index_file.file, MYF(MY_WME));
// Reopen File and truncate it
if ((index_file_nr= my_open(index_file_name,
O_RDWR | O_CREAT | O_TRUNC | O_BINARY ,
MYF(MY_WME))) < 0 ||
init_io_cache(&index_file, index_file_nr,
IO_SIZE, WRITE_CACHE,
my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)),
0, MYF(MY_WME | MY_WAIT_IF_FULL)))
{
File index_file_nr;
int error= my_errno;
if (index_file_nr >= 0)
my_close(index_file_nr,MYF(0));
// Close IO_CACHE and FILE handler fisrt
end_io_cache(&index_file);
my_close(index_file.file, MYF(MY_WME));
// Reopen File and truncate it
if ((index_file_nr= my_open(index_file_name,
O_RDWR | O_CREAT | O_TRUNC | O_BINARY ,
MYF(MY_WME))) < 0 ||
init_io_cache(&index_file, index_file_nr,
IO_SIZE, WRITE_CACHE,
my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)),
0, MYF(MY_WME | MY_WAIT_IF_FULL)))
{
int error= my_errno;
if (index_file_nr >= 0)
my_close(index_file_nr,MYF(0));
sql_print_error("Create of Master Info Index file '%s' failed with "
"error: %M",
index_file_name, error);
DBUG_RETURN(TRUE);
}
// Rewrite Master_info.index
for (uint i= 0; i< master_info_hash.records; ++i)
{
Master_info *tmp_mi;
tmp_mi= (Master_info *) my_hash_element(&master_info_hash, i);
write_master_name_to_index_file(&tmp_mi->connection_name, 0);
}
my_sync(index_file_nr, MYF(MY_WME));
sql_print_error("Create of Master Info Index file '%s' failed with "
"error: %M",
index_file_name, error);
DBUG_RETURN(TRUE);
}
// Rewrite Master_info.index
for (uint i= 0; i< master_info_hash.records; ++i)
{
Master_info *tmp_mi;
tmp_mi= (Master_info *) my_hash_element(&master_info_hash, i);
write_master_name_to_index_file(&tmp_mi->connection_name, 0);
}
if (my_sync(index_file_nr, MYF(MY_WME)))
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE);
}
/**
Master_info_index::give_error_if_slave_running()
give_error_if_slave_running()
@param
already_locked 0 if we need to lock, 1 if we have LOCK_active_mi_locked
@return
TRUE If some slave is running. An error is printed
FALSE No slave is running
*/
bool Master_info_index::give_error_if_slave_running()
bool give_error_if_slave_running(bool already_locked)
{
bool ret= 0;
DBUG_ENTER("give_error_if_slave_running");
mysql_mutex_assert_owner(&LOCK_active_mi);
for (uint i= 0; i< master_info_hash.records; ++i)
if (!already_locked)
mysql_mutex_lock(&LOCK_active_mi);
if (!master_info_index)
{
Master_info *mi;
mi= (Master_info *) my_hash_element(&master_info_hash, i);
if (mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN)
my_error(ER_SERVER_SHUTDOWN, MYF(0));
ret= 1;
}
else
{
HASH *hash= &master_info_index->master_info_hash;
for (uint i= 0; i< hash->records; ++i)
{
my_error(ER_SLAVE_MUST_STOP, MYF(0), (int) mi->connection_name.length,
mi->connection_name.str);
DBUG_RETURN(TRUE);
Master_info *mi;
mi= (Master_info *) my_hash_element(hash, i);
if (mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN)
{
my_error(ER_SLAVE_MUST_STOP, MYF(0), (int) mi->connection_name.length,
mi->connection_name.str);
ret= 1;
break;
}
}
}
DBUG_RETURN(FALSE);
if (!already_locked)
mysql_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(ret);
}
/**
Master_info_index::any_slave_sql_running()
The LOCK_active_mi must be held while calling this function.
any_slave_sql_running()
@return
0 No Slave SQL thread is running
# Number of slave SQL thread running
Note that during shutdown we return 1. This is needed to ensure we
don't try to resize thread pool during shutdown as during shutdown
master_info_hash may be freeing the hash and during that time
hash entries can't be accessed.
*/
uint Master_info_index::any_slave_sql_running()
uint any_slave_sql_running()
{
uint count= 0;
HASH *hash;
DBUG_ENTER("any_slave_sql_running");
mysql_mutex_assert_owner(&LOCK_active_mi);
for (uint i= 0; i< master_info_hash.records; ++i)
mysql_mutex_lock(&LOCK_active_mi);
if (unlikely(shutdown_in_progress || !master_info_index))
{
Master_info *mi= (Master_info *)my_hash_element(&master_info_hash, i);
mysql_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(1);
}
hash= &master_info_index->master_info_hash;
for (uint i= 0; i< hash->records; ++i)
{
Master_info *mi= (Master_info *)my_hash_element(hash, i);
if (mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN)
count++;
}
mysql_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(count);
}
@ -1436,15 +1590,25 @@ uint Master_info_index::any_slave_sql_running()
@return
TRUE Error
FALSE Everything ok.
This code is written so that we don't keep LOCK_active_mi active
while we are starting a slave.
*/
bool Master_info_index::start_all_slaves(THD *thd)
{
bool result= FALSE;
DBUG_ENTER("warn_if_slave_running");
DBUG_ENTER("start_all_slaves");
mysql_mutex_assert_owner(&LOCK_active_mi);
for (uint i= 0; i< master_info_hash.records; ++i)
for (uint i= 0; i< master_info_hash.records; i++)
{
Master_info *mi;
mi= (Master_info *) my_hash_element(&master_info_hash, i);
mi->in_start_all_slaves= 0;
}
for (uint i= 0; i< master_info_hash.records; )
{
int error;
Master_info *mi;
@ -1454,25 +1618,40 @@ bool Master_info_index::start_all_slaves(THD *thd)
Try to start all slaves that are configured (host is defined)
and are not already running
*/
if ((mi->slave_running == MYSQL_SLAVE_NOT_RUN ||
!mi->rli.slave_running) && *mi->host)
if (!((mi->slave_running == MYSQL_SLAVE_NOT_RUN ||
!mi->rli.slave_running) && *mi->host) ||
mi->in_start_all_slaves)
{
if ((error= start_slave(thd, mi, 1)))
{
my_error(ER_CANT_START_STOP_SLAVE, MYF(0),
"START",
(int) mi->connection_name.length,
mi->connection_name.str);
result= 1;
if (error < 0) // fatal error
break;
}
else if (thd)
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SLAVE_STARTED, ER_THD(thd, ER_SLAVE_STARTED),
(int) mi->connection_name.length,
mi->connection_name.str);
i++;
continue;
}
mi->in_start_all_slaves= 1;
mysql_mutex_lock(&mi->sleep_lock);
mi->users++; // Mark used
mysql_mutex_unlock(&mi->sleep_lock);
mysql_mutex_unlock(&LOCK_active_mi);
error= start_slave(thd, mi, 1);
mi->release();
mysql_mutex_lock(&LOCK_active_mi);
if (error)
{
my_error(ER_CANT_START_STOP_SLAVE, MYF(0),
"START",
(int) mi->connection_name.length,
mi->connection_name.str);
result= 1;
if (error < 0) // fatal error
break;
}
else if (thd)
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SLAVE_STARTED, ER_THD(thd, ER_SLAVE_STARTED),
(int) mi->connection_name.length,
mi->connection_name.str);
/* Restart from first element as master_info_hash may have changed */
i= 0;
continue;
}
DBUG_RETURN(result);
}
@ -1488,39 +1667,64 @@ bool Master_info_index::start_all_slaves(THD *thd)
@return
TRUE Error
FALSE Everything ok.
This code is written so that we don't keep LOCK_active_mi active
while we are stopping a slave.
*/
bool Master_info_index::stop_all_slaves(THD *thd)
{
bool result= FALSE;
DBUG_ENTER("warn_if_slave_running");
DBUG_ENTER("stop_all_slaves");
mysql_mutex_assert_owner(&LOCK_active_mi);
DBUG_ASSERT(thd);
for (uint i= 0; i< master_info_hash.records; ++i)
for (uint i= 0; i< master_info_hash.records; i++)
{
Master_info *mi;
mi= (Master_info *) my_hash_element(&master_info_hash, i);
mi->in_stop_all_slaves= 0;
}
for (uint i= 0; i< master_info_hash.records ;)
{
int error;
Master_info *mi;
mi= (Master_info *) my_hash_element(&master_info_hash, i);
if ((mi->slave_running != MYSQL_SLAVE_NOT_RUN ||
mi->rli.slave_running))
if (!(mi->slave_running != MYSQL_SLAVE_NOT_RUN ||
mi->rli.slave_running) ||
mi->in_stop_all_slaves)
{
if ((error= stop_slave(thd, mi, 1)))
{
my_error(ER_CANT_START_STOP_SLAVE, MYF(0),
"STOP",
(int) mi->connection_name.length,
mi->connection_name.str);
result= 1;
if (error < 0) // Fatal error
break;
}
else
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SLAVE_STOPPED, ER_THD(thd, ER_SLAVE_STOPPED),
(int) mi->connection_name.length,
mi->connection_name.str);
i++;
continue;
}
mi->in_stop_all_slaves= 1; // Protection for loops
mysql_mutex_lock(&mi->sleep_lock);
mi->users++; // Mark used
mysql_mutex_unlock(&mi->sleep_lock);
mysql_mutex_unlock(&LOCK_active_mi);
error= stop_slave(thd, mi, 1);
mi->release();
mysql_mutex_lock(&LOCK_active_mi);
if (error)
{
my_error(ER_CANT_START_STOP_SLAVE, MYF(0),
"STOP",
(int) mi->connection_name.length,
mi->connection_name.str);
result= 1;
if (error < 0) // Fatal error
break;
}
else
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SLAVE_STOPPED, ER_THD(thd, ER_SLAVE_STOPPED),
(int) mi->connection_name.length,
mi->connection_name.str);
/* Restart from first element as master_info_hash may have changed */
i= 0;
continue;
}
DBUG_RETURN(result);
}

View file

@ -187,6 +187,10 @@ class Master_info : public Slave_reporting_capability
return opt_slave_parallel_threads > 0 &&
parallel_mode > SLAVE_PARALLEL_NONE;
}
void release();
void wait_until_free();
void lock_slave_threads();
void unlock_slave_threads();
/* the variables below are needed because we can change masters on the fly */
char master_log_name[FN_REFLEN+6]; /* Room for multi-*/
@ -205,7 +209,7 @@ class Master_info : public Slave_reporting_capability
File fd; // we keep the file open, so we need to remember the file pointer
IO_CACHE file;
mysql_mutex_t data_lock, run_lock, sleep_lock;
mysql_mutex_t data_lock, run_lock, sleep_lock, start_stop_lock;
mysql_cond_t data_cond, start_cond, stop_cond, sleep_cond;
THD *io_thd;
MYSQL* mysql;
@ -297,6 +301,9 @@ class Master_info : public Slave_reporting_capability
uint64 gtid_reconnect_event_skip_count;
/* gtid_event_seen is false until we receive first GTID event from master. */
bool gtid_event_seen;
bool in_start_all_slaves, in_stop_all_slaves;
uint users; /* Active user for object */
uint killed;
/* domain-id based filter */
Domain_id_filter domain_id_filter;
@ -341,13 +348,12 @@ public:
bool check_duplicate_master_info(LEX_STRING *connection_name,
const char *host, uint port);
bool add_master_info(Master_info *mi, bool write_to_file);
bool remove_master_info(LEX_STRING *connection_name);
bool remove_master_info(Master_info *mi);
Master_info *get_master_info(const LEX_STRING *connection_name,
Sql_condition::enum_warning_level warning);
bool give_error_if_slave_running();
uint any_slave_sql_running();
bool start_all_slaves(THD *thd);
bool stop_all_slaves(THD *thd);
void free_connections();
};
@ -360,6 +366,8 @@ public:
};
Master_info *get_master_info(const LEX_STRING *connection_name,
Sql_condition::enum_warning_level warning);
bool check_master_connection_name(LEX_STRING *name);
void create_logfile_name_with_suffix(char *res_file_name, size_t length,
const char *info_file,
@ -369,5 +377,8 @@ void create_logfile_name_with_suffix(char *res_file_name, size_t length,
uchar *get_key_master_info(Master_info *mi, size_t *length,
my_bool not_used __attribute__((unused)));
void free_key_master_info(Master_info *mi);
uint any_slave_sql_running();
bool give_error_if_slave_running(bool already_lock);
#endif /* HAVE_REPLICATION */
#endif /* RPL_MI_H */

View file

@ -1313,39 +1313,16 @@ handle_rpl_parallel_thread(void *arg)
*/
rpt->batch_free();
for (;;)
if ((events= rpt->event_queue) != NULL)
{
if ((events= rpt->event_queue) != NULL)
{
/*
Take next group of events from the replication pool.
This is faster than having to wakeup the pool manager thread to give
us a new event.
*/
rpt->dequeue1(events);
mysql_mutex_unlock(&rpt->LOCK_rpl_thread);
goto more_events;
}
if (!rpt->pause_for_ftwrl ||
(in_event_group && !group_rgi->parallel_entry->force_abort))
break;
/*
We are currently in the delicate process of pausing parallel
replication while FLUSH TABLES WITH READ LOCK is starting. We must
not de-allocate the thread (setting rpt->current_owner= NULL) until
rpl_unpause_after_ftwrl() has woken us up.
Take next group of events from the replication pool.
This is faster than having to wakeup the pool manager thread to give
us a new event.
*/
mysql_mutex_lock(&rpt->current_entry->LOCK_parallel_entry);
rpt->dequeue1(events);
mysql_mutex_unlock(&rpt->LOCK_rpl_thread);
if (rpt->pause_for_ftwrl)
mysql_cond_wait(&rpt->current_entry->COND_parallel_entry,
&rpt->current_entry->LOCK_parallel_entry);
mysql_mutex_unlock(&rpt->current_entry->LOCK_parallel_entry);
mysql_mutex_lock(&rpt->LOCK_rpl_thread);
/*
Now loop to check again for more events available, since we released
and re-aquired the LOCK_rpl_thread mutex.
*/
goto more_events;
}
rpt->inuse_relaylog_refcount_update();
@ -1372,11 +1349,36 @@ handle_rpl_parallel_thread(void *arg)
}
if (!in_event_group)
{
/* If we are in a FLUSH TABLES FOR READ LOCK, wait for it */
while (rpt->current_entry && rpt->pause_for_ftwrl)
{
/*
We are currently in the delicate process of pausing parallel
replication while FLUSH TABLES WITH READ LOCK is starting. We must
not de-allocate the thread (setting rpt->current_owner= NULL) until
rpl_unpause_after_ftwrl() has woken us up.
*/
rpl_parallel_entry *e= rpt->current_entry;
/*
Ensure that we will unblock rpl_pause_for_ftrwl()
e->pause_sub_id may be LONGLONG_MAX if rpt->current_entry has changed
*/
DBUG_ASSERT(e->pause_sub_id == (uint64)ULONGLONG_MAX ||
e->last_committed_sub_id >= e->pause_sub_id);
mysql_mutex_lock(&e->LOCK_parallel_entry);
mysql_mutex_unlock(&rpt->LOCK_rpl_thread);
if (rpt->pause_for_ftwrl)
mysql_cond_wait(&e->COND_parallel_entry, &e->LOCK_parallel_entry);
mysql_mutex_unlock(&e->LOCK_parallel_entry);
mysql_mutex_lock(&rpt->LOCK_rpl_thread);
}
rpt->current_owner= NULL;
/* Tell wait_for_done() that we are done, if it is waiting. */
if (likely(rpt->current_entry) &&
unlikely(rpt->current_entry->force_abort))
mysql_cond_broadcast(&rpt->COND_rpl_thread_stop);
rpt->current_entry= NULL;
if (!rpt->stop)
rpt->pool->release_thread(rpt);
@ -1416,10 +1418,24 @@ dealloc_gco(group_commit_orderer *gco)
my_free(gco);
}
/**
Change thread count for global parallel worker threads
@param pool parallel thread pool
@param new_count Number of threads to be in pool. 0 in shutdown
@param force Force thread count to new_count even if slave
threads are running
By default we don't resize pool of there are running threads.
However during shutdown we will always do it.
This is needed as any_slave_sql_running() returns 1 during shutdown
as we don't want to access master_info while
Master_info_index::free_connections are running.
*/
static int
rpl_parallel_change_thread_count(rpl_parallel_thread_pool *pool,
uint32 new_count)
uint32 new_count, bool force)
{
uint32 i;
rpl_parallel_thread **old_list= NULL;
@ -1431,6 +1447,28 @@ rpl_parallel_change_thread_count(rpl_parallel_thread_pool *pool,
if ((res= pool_mark_busy(pool, current_thd)))
return res;
/* Protect against parallel pool resizes */
if (pool->count == new_count)
{
pool_mark_not_busy(pool);
return 0;
}
/*
If we are about to delete pool, do an extra check that there are no new
slave threads running since we marked pool busy
*/
if (!new_count && !force)
{
if (any_slave_sql_running())
{
DBUG_PRINT("warning",
("SQL threads running while trying to reset parallel pool"));
pool_mark_not_busy(pool);
return 0; // Ok to not resize pool
}
}
/*
Allocate the new list of threads up-front.
That way, if we fail half-way, we only need to free whatever we managed
@ -1444,7 +1482,7 @@ rpl_parallel_change_thread_count(rpl_parallel_thread_pool *pool,
{
my_error(ER_OUTOFMEMORY, MYF(0), (int(new_count*sizeof(*new_list) +
new_count*sizeof(*rpt_array))));
goto err;;
goto err;
}
for (i= 0; i < new_count; ++i)
@ -1569,12 +1607,26 @@ err:
return 1;
}
/*
Deactivate the parallel replication thread pool, if there are now no more
SQL threads running.
*/
int rpl_parallel_resize_pool_if_no_slaves(void)
{
/* master_info_index is set to NULL on shutdown */
if (opt_slave_parallel_threads > 0 && !any_slave_sql_running())
return rpl_parallel_inactivate_pool(&global_rpl_thread_pool);
return 0;
}
int
rpl_parallel_activate_pool(rpl_parallel_thread_pool *pool)
{
if (!pool->count)
return rpl_parallel_change_thread_count(pool, opt_slave_parallel_threads);
return rpl_parallel_change_thread_count(pool, opt_slave_parallel_threads,
0);
return 0;
}
@ -1582,7 +1634,7 @@ rpl_parallel_activate_pool(rpl_parallel_thread_pool *pool)
int
rpl_parallel_inactivate_pool(rpl_parallel_thread_pool *pool)
{
return rpl_parallel_change_thread_count(pool, 0);
return rpl_parallel_change_thread_count(pool, 0, 0);
}
@ -1860,7 +1912,7 @@ rpl_parallel_thread_pool::destroy()
{
if (!inited)
return;
rpl_parallel_change_thread_count(this, 0);
rpl_parallel_change_thread_count(this, 0, 1);
mysql_mutex_destroy(&LOCK_rpl_thread_pool);
mysql_cond_destroy(&COND_rpl_thread_pool);
inited= false;
@ -1879,6 +1931,7 @@ rpl_parallel_thread_pool::get_thread(rpl_parallel_thread **owner,
{
rpl_parallel_thread *rpt;
DBUG_ASSERT(count > 0);
mysql_mutex_lock(&LOCK_rpl_thread_pool);
while (unlikely(busy) || !(rpt= free_list))
mysql_cond_wait(&COND_rpl_thread_pool, &LOCK_rpl_thread_pool);
@ -2107,6 +2160,11 @@ rpl_parallel::find(uint32 domain_id)
return e;
}
/**
Wait until all sql worker threads has stopped processing
This is called when sql thread has been killed/stopped
*/
void
rpl_parallel::wait_for_done(THD *thd, Relay_log_info *rli)

View file

@ -365,6 +365,7 @@ struct rpl_parallel {
extern struct rpl_parallel_thread_pool global_rpl_thread_pool;
extern int rpl_parallel_resize_pool_if_no_slaves(void);
extern int rpl_parallel_activate_pool(rpl_parallel_thread_pool *pool);
extern int rpl_parallel_inactivate_pool(rpl_parallel_thread_pool *pool);
extern bool process_gtid_for_restart_pos(Relay_log_info *rli, rpl_gtid *gtid);

View file

@ -208,6 +208,7 @@ a file name for --relay-log-index option", opt_relaylog_index_name);
Master_info* mi= rli->mi;
char buf_relay_logname[FN_REFLEN], buf_relaylog_index_name_buff[FN_REFLEN];
char *buf_relaylog_index_name= opt_relaylog_index_name;
mysql_mutex_t *log_lock;
create_logfile_name_with_suffix(buf_relay_logname,
sizeof(buf_relay_logname),
@ -227,14 +228,18 @@ a file name for --relay-log-index option", opt_relaylog_index_name);
note, that if open() fails, we'll still have index file open
but a destructor will take care of that
*/
log_lock= rli->relay_log.get_log_lock();
mysql_mutex_lock(log_lock);
if (rli->relay_log.open_index_file(buf_relaylog_index_name, ln, TRUE) ||
rli->relay_log.open(ln, LOG_BIN, 0, 0, SEQ_READ_APPEND,
mi->rli.max_relay_log_size, 1, TRUE))
{
mysql_mutex_unlock(log_lock);
mysql_mutex_unlock(&rli->data_lock);
sql_print_error("Failed when trying to open logs for '%s' in init_relay_log_info(). Error: %M", ln, my_errno);
DBUG_RETURN(1);
}
mysql_mutex_unlock(log_lock);
}
/* if file does not exist */
@ -424,7 +429,7 @@ Failed to open the existing relay log info file '%s' (errno %d)",
}
rli->inited= 1;
mysql_mutex_unlock(&rli->data_lock);
DBUG_RETURN(error);
DBUG_RETURN(0);
err:
sql_print_error("%s", msg);
@ -1289,9 +1294,10 @@ bool Relay_log_info::is_until_satisfied(my_off_t master_beg_pos)
}
void Relay_log_info::stmt_done(my_off_t event_master_log_pos, THD *thd,
bool Relay_log_info::stmt_done(my_off_t event_master_log_pos, THD *thd,
rpl_group_info *rgi)
{
int error= 0;
DBUG_ENTER("Relay_log_info::stmt_done");
DBUG_ASSERT(rgi->rli == this);
@ -1343,10 +1349,11 @@ void Relay_log_info::stmt_done(my_off_t event_master_log_pos, THD *thd,
}
DBUG_EXECUTE_IF("inject_crash_before_flush_rli", DBUG_SUICIDE(););
if (mi->using_gtid == Master_info::USE_GTID_NO)
flush_relay_log_info(this);
if (flush_relay_log_info(this))
error= 1;
DBUG_EXECUTE_IF("inject_crash_after_flush_rli", DBUG_SUICIDE(););
}
DBUG_VOID_RETURN;
DBUG_RETURN(error);
}

View file

@ -416,7 +416,7 @@ public:
relay log info and used to produce information for <code>SHOW
SLAVE STATUS</code>.
*/
void stmt_done(my_off_t event_log_pos, THD *thd, rpl_group_info *rgi);
bool stmt_done(my_off_t event_log_pos, THD *thd, rpl_group_info *rgi);
int alloc_inuse_relaylog(const char *name);
void free_inuse_relaylog(inuse_relaylog *ir);
void reset_inuse_relaylog();

View file

@ -232,16 +232,14 @@ void init_thread_mask(int* mask,Master_info* mi,bool inverse)
/*
lock_slave_threads()
lock_slave_threads() against other threads doing STOP, START or RESET SLAVE
*/
void lock_slave_threads(Master_info* mi)
void Master_info::lock_slave_threads()
{
DBUG_ENTER("lock_slave_threads");
//TODO: see if we can do this without dual mutex
mysql_mutex_lock(&mi->run_lock);
mysql_mutex_lock(&mi->rli.run_lock);
mysql_mutex_lock(&start_stop_lock);
DBUG_VOID_RETURN;
}
@ -250,13 +248,10 @@ void lock_slave_threads(Master_info* mi)
unlock_slave_threads()
*/
void unlock_slave_threads(Master_info* mi)
void Master_info::unlock_slave_threads()
{
DBUG_ENTER("unlock_slave_threads");
//TODO: see if we can do this without dual mutex
mysql_mutex_unlock(&mi->rli.run_lock);
mysql_mutex_unlock(&mi->run_lock);
mysql_mutex_unlock(&start_stop_lock);
DBUG_VOID_RETURN;
}
@ -472,7 +467,6 @@ int init_slave()
accepted. However bootstrap may conflict with us if it does START SLAVE.
So it's safer to take the lock.
*/
mysql_mutex_lock(&LOCK_active_mi);
if (pthread_key_create(&RPL_MASTER_INFO, NULL))
goto err;
@ -481,7 +475,6 @@ int init_slave()
if (!master_info_index || master_info_index->init_all_master_info())
{
sql_print_error("Failed to initialize multi master structures");
mysql_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(1);
}
if (!(active_mi= new Master_info(&default_master_connection_name,
@ -540,7 +533,6 @@ int init_slave()
}
end:
mysql_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(error);
err:
@ -713,6 +705,7 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock)
if (!mi->inited)
DBUG_RETURN(0); /* successfully do nothing */
int error,force_all = (thread_mask & SLAVE_FORCE_ALL);
int retval= 0;
mysql_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock;
mysql_mutex_t *log_lock= mi->rli.relay_log.get_log_lock();
@ -732,24 +725,19 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock)
skip_lock)) &&
!force_all)
DBUG_RETURN(error);
retval= error;
mysql_mutex_lock(log_lock);
DBUG_PRINT("info",("Flushing relay-log info file."));
if (current_thd)
THD_STAGE_INFO(current_thd, stage_flushing_relay_log_info_file);
if (flush_relay_log_info(&mi->rli))
DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
if (my_sync(mi->rli.info_fd, MYF(MY_WME)))
DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
if (flush_relay_log_info(&mi->rli) ||
my_sync(mi->rli.info_fd, MYF(MY_WME)))
retval= ER_ERROR_DURING_FLUSH_LOGS;
mysql_mutex_unlock(log_lock);
}
if (opt_slave_parallel_threads > 0 &&
master_info_index &&// master_info_index is set to NULL on server shutdown
!master_info_index->any_slave_sql_running())
rpl_parallel_inactivate_pool(&global_rpl_thread_pool);
if (thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL))
{
DBUG_PRINT("info",("Terminating IO thread"));
@ -760,25 +748,26 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock)
skip_lock)) &&
!force_all)
DBUG_RETURN(error);
if (!retval)
retval= error;
mysql_mutex_lock(log_lock);
DBUG_PRINT("info",("Flushing relay log and master info file."));
if (current_thd)
THD_STAGE_INFO(current_thd, stage_flushing_relay_log_and_master_info_repository);
if (flush_master_info(mi, TRUE, FALSE))
DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
if (likely(mi->fd >= 0))
{
if (flush_master_info(mi, TRUE, FALSE) || my_sync(mi->fd, MYF(MY_WME)))
retval= ER_ERROR_DURING_FLUSH_LOGS;
}
if (mi->rli.relay_log.is_open() &&
my_sync(mi->rli.relay_log.get_log_file()->file, MYF(MY_WME)))
DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
if (my_sync(mi->fd, MYF(MY_WME)))
DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
retval= ER_ERROR_DURING_FLUSH_LOGS;
mysql_mutex_unlock(log_lock);
}
DBUG_RETURN(0);
DBUG_RETURN(retval);
}
@ -941,6 +930,15 @@ int start_slave_thread(
mysql_mutex_unlock(start_lock);
DBUG_RETURN(ER_SLAVE_THREAD);
}
/*
In the following loop we can't check for thd->killed as we have to
wait until THD structures for the slave thread are created
before we can return.
This should be ok as there is no major work done in the slave
threads before they signal that we can stop waiting.
*/
if (start_cond && cond_lock) // caller has cond_lock
{
THD* thd = current_thd;
@ -958,16 +956,9 @@ int start_slave_thread(
registered, we could otherwise go waiting though thd->killed is
set.
*/
if (!thd->killed)
mysql_cond_wait(start_cond, cond_lock);
mysql_cond_wait(start_cond, cond_lock);
thd->EXIT_COND(& saved_stage);
mysql_mutex_lock(cond_lock); // re-acquire it as exit_cond() released
if (thd->killed)
{
if (start_lock)
mysql_mutex_unlock(start_lock);
DBUG_RETURN(thd->killed_errno());
}
}
}
if (start_lock)
@ -1056,10 +1047,7 @@ int start_slave_threads(THD *thd,
mi);
if (!error && (thread_mask & SLAVE_SQL))
{
if (opt_slave_parallel_threads > 0)
error= rpl_parallel_activate_pool(&global_rpl_thread_pool);
if (!error)
error= start_slave_thread(
error= start_slave_thread(
#ifdef HAVE_PSI_INTERFACE
key_thread_slave_sql,
#endif
@ -1075,10 +1063,18 @@ int start_slave_threads(THD *thd,
/*
Release slave threads at time of executing shutdown.
Kill slaves preparing for shutdown
*/
SYNOPSIS
end_slave()
void slave_prepare_for_shutdown()
{
mysql_mutex_lock(&LOCK_active_mi);
master_info_index->free_connections();
mysql_mutex_unlock(&LOCK_active_mi);
}
/*
Release slave threads at time of executing shutdown.
*/
void end_slave()
@ -1096,7 +1092,10 @@ void end_slave()
startup parameter to the server was wrong.
*/
mysql_mutex_lock(&LOCK_active_mi);
/* This will call terminate_slave_threads() on all connections */
/*
master_info_index should not have any threads anymore as they where
killed as part of slave_prepare_for_shutdown()
*/
delete master_info_index;
master_info_index= 0;
active_mi= 0;
@ -2867,7 +2866,9 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full,
mysql_mutex_lock(&mi->data_lock);
mysql_mutex_lock(&mi->rli.data_lock);
/* err_lock is to protect mi->last_error() */
mysql_mutex_lock(&mi->err_lock);
/* err_lock is to protect mi->rli.last_error() */
mysql_mutex_lock(&mi->rli.err_lock);
protocol->store(mi->host, &my_charset_bin);
protocol->store(mi->user, &my_charset_bin);
@ -4715,6 +4716,16 @@ pthread_handler_t handle_slave_sql(void *arg)
rli->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
pthread_detach_this_thread();
if (opt_slave_parallel_threads > 0 &&
rpl_parallel_activate_pool(&global_rpl_thread_pool))
{
mysql_cond_broadcast(&rli->start_cond);
rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, NULL,
"Failed during parallel slave pool activation");
goto err_during_init;
}
if (init_slave_thread(thd, mi, SLAVE_THD_SQL))
{
/*
@ -5016,8 +5027,15 @@ pthread_handler_t handle_slave_sql(void *arg)
if (rli->mi->using_gtid != Master_info::USE_GTID_NO)
{
ulong domain_count;
my_bool save_log_all_errors= thd->log_all_errors;
/*
We don't need to check return value for flush_relay_log_info()
as any errors should be logged to stderr
*/
thd->log_all_errors= 1;
flush_relay_log_info(rli);
thd->log_all_errors= save_log_all_errors;
if (mi->using_parallel())
{
/*
@ -5126,17 +5144,7 @@ err_during_init:
DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5););
mysql_mutex_unlock(&rli->run_lock); // tell the world we are done
/*
Deactivate the parallel replication thread pool, if there are now no more
SQL threads running. Do this here, when we have released all locks, but
while our THD (and current_thd) is still valid.
*/
mysql_mutex_lock(&LOCK_active_mi);
if (opt_slave_parallel_threads > 0 &&
master_info_index &&// master_info_index is set to NULL on server shutdown
!master_info_index->any_slave_sql_running())
rpl_parallel_inactivate_pool(&global_rpl_thread_pool);
mysql_mutex_unlock(&LOCK_active_mi);
rpl_parallel_resize_pool_if_no_slaves();
mysql_mutex_lock(&LOCK_thread_count);
thd->unlink();
@ -6295,6 +6303,7 @@ err:
void end_relay_log_info(Relay_log_info* rli)
{
mysql_mutex_t *log_lock;
DBUG_ENTER("end_relay_log_info");
if (!rli->inited)
@ -6312,8 +6321,11 @@ void end_relay_log_info(Relay_log_info* rli)
rli->cur_log_fd = -1;
}
rli->inited = 0;
log_lock= rli->relay_log.get_log_lock();
mysql_mutex_lock(log_lock);
rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
mysql_mutex_unlock(log_lock);
/*
Delete the slave's temporary tables from memory.
In the future there will be other actions than this, to ensure persistance
@ -6464,7 +6476,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi,
suppress_warnings= 0;
mi->report(ERROR_LEVEL, last_errno, NULL,
"error %s to master '%s@%s:%d'"
" - retry-time: %d retries: %lu message: %s",
" - retry-time: %d maximum-retries: %lu message: %s",
(reconnect ? "reconnecting" : "connecting"),
mi->user, mi->host, mi->port,
mi->connect_retry, master_retry_count,
@ -7026,9 +7038,12 @@ static Log_event* next_event(rpl_group_info *rgi, ulonglong *event_size)
}
rli->event_relay_log_pos = BIN_LOG_HEADER_SIZE;
strmake_buf(rli->event_relay_log_name,rli->linfo.log_file_name);
flush_relay_log_info(rli);
if (flush_relay_log_info(rli))
{
errmsg= "error flushing relay log";
goto err;
}
}
/*
Now we want to open this next log. To know if it's a hot log (the one
being written by the I/O thread now) or a cold log, we can use

View file

@ -220,13 +220,12 @@ bool rpl_master_erroneous_autoinc(THD* thd);
const char *print_slave_db_safe(const char *db);
void skip_load_data_infile(NET* net);
void slave_prepare_for_shutdown();
void end_slave(); /* release slave threads */
void close_active_mi(); /* clean up slave threads data */
void clear_until_condition(Relay_log_info* rli);
void clear_slave_error(Relay_log_info* rli);
void end_relay_log_info(Relay_log_info* rli);
void lock_slave_threads(Master_info* mi);
void unlock_slave_threads(Master_info* mi);
void init_thread_mask(int* mask,Master_info* mi,bool inverse);
Format_description_log_event *
read_relay_log_description_event(IO_CACHE *cur_log, ulonglong start_pos,

View file

@ -70,59 +70,56 @@ public:
// Set for DISABLE KEYS | ENABLE KEYS
static const uint ALTER_KEYS_ONOFF = 1L << 9;
// Set for CONVERT TO CHARACTER SET
static const uint ALTER_CONVERT = 1L << 10;
// Set for FORCE
// Set for ENGINE(same engine)
// Set by mysql_recreate_table()
static const uint ALTER_RECREATE = 1L << 11;
static const uint ALTER_RECREATE = 1L << 10;
// Set for ADD PARTITION
static const uint ALTER_ADD_PARTITION = 1L << 12;
static const uint ALTER_ADD_PARTITION = 1L << 11;
// Set for DROP PARTITION
static const uint ALTER_DROP_PARTITION = 1L << 13;
static const uint ALTER_DROP_PARTITION = 1L << 12;
// Set for COALESCE PARTITION
static const uint ALTER_COALESCE_PARTITION = 1L << 14;
static const uint ALTER_COALESCE_PARTITION = 1L << 13;
// Set for REORGANIZE PARTITION ... INTO
static const uint ALTER_REORGANIZE_PARTITION = 1L << 15;
static const uint ALTER_REORGANIZE_PARTITION = 1L << 14;
// Set for partition_options
static const uint ALTER_PARTITION = 1L << 16;
static const uint ALTER_PARTITION = 1L << 15;
// Set for LOAD INDEX INTO CACHE ... PARTITION
// Set for CACHE INDEX ... PARTITION
static const uint ALTER_ADMIN_PARTITION = 1L << 17;
static const uint ALTER_ADMIN_PARTITION = 1L << 16;
// Set for REORGANIZE PARTITION
static const uint ALTER_TABLE_REORG = 1L << 18;
static const uint ALTER_TABLE_REORG = 1L << 17;
// Set for REBUILD PARTITION
static const uint ALTER_REBUILD_PARTITION = 1L << 19;
static const uint ALTER_REBUILD_PARTITION = 1L << 18;
// Set for partitioning operations specifying ALL keyword
static const uint ALTER_ALL_PARTITION = 1L << 20;
static const uint ALTER_ALL_PARTITION = 1L << 19;
// Set for REMOVE PARTITIONING
static const uint ALTER_REMOVE_PARTITIONING = 1L << 21;
static const uint ALTER_REMOVE_PARTITIONING = 1L << 20;
// Set for ADD FOREIGN KEY
static const uint ADD_FOREIGN_KEY = 1L << 22;
static const uint ADD_FOREIGN_KEY = 1L << 21;
// Set for DROP FOREIGN KEY
static const uint DROP_FOREIGN_KEY = 1L << 23;
static const uint DROP_FOREIGN_KEY = 1L << 22;
// Set for EXCHANGE PARITION
static const uint ALTER_EXCHANGE_PARTITION = 1L << 24;
static const uint ALTER_EXCHANGE_PARTITION = 1L << 23;
// Set by Sql_cmd_alter_table_truncate_partition::execute()
static const uint ALTER_TRUNCATE_PARTITION = 1L << 25;
static const uint ALTER_TRUNCATE_PARTITION = 1L << 24;
// Set for ADD [COLUMN] FIRST | AFTER
static const uint ALTER_COLUMN_ORDER = 1L << 26;
static const uint ALTER_COLUMN_ORDER = 1L << 25;
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };

View file

@ -6674,7 +6674,7 @@ find_field_in_tables(THD *thd, Item_ident *item,
if (!table_ref->belong_to_view &&
!table_ref->belong_to_derived)
{
SELECT_LEX *current_sel= thd->lex->current_select;
SELECT_LEX *current_sel= item->context->select_lex;
SELECT_LEX *last_select= table_ref->select_lex;
bool all_merged= TRUE;
for (SELECT_LEX *sl= current_sel; sl && sl!=last_select;

View file

@ -7066,7 +7066,13 @@ wait_for_commit::reinit()
So in this case, do a re-init of the mutex. In release builds, we want to
avoid the overhead of a re-init though.
To ensure that no one is locking the mutex, we take a lock of it first.
For full explanation, see wait_for_commit::~wait_for_commit()
*/
mysql_mutex_lock(&LOCK_wait_commit);
mysql_mutex_unlock(&LOCK_wait_commit);
mysql_mutex_destroy(&LOCK_wait_commit);
mysql_mutex_init(key_LOCK_wait_commit, &LOCK_wait_commit, MY_MUTEX_INIT_FAST);
#endif

View file

@ -2446,7 +2446,7 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
int
mysql_execute_command(THD *thd)
{
int res= FALSE;
int res= 0;
int up_result= 0;
LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
@ -3119,10 +3119,17 @@ mysql_execute_command(THD *thd)
if (check_global_access(thd, SUPER_ACL))
goto error;
/*
In this code it's ok to use LOCK_active_mi as we are adding new things
into master_info_index
*/
mysql_mutex_lock(&LOCK_active_mi);
if (!master_info_index)
{
mysql_mutex_unlock(&LOCK_active_mi);
my_error(ER_SERVER_SHUTDOWN, MYF(0));
goto error;
}
mi= master_info_index->get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_NOTE);
@ -3151,7 +3158,7 @@ mysql_execute_command(THD *thd)
If new master was not added, we still need to free mi.
*/
if (master_info_added)
master_info_index->remove_master_info(&lex_mi->connection_name);
master_info_index->remove_master_info(mi);
else
delete mi;
}
@ -3169,22 +3176,24 @@ mysql_execute_command(THD *thd)
/* Accept one of two privileges */
if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
mysql_mutex_lock(&LOCK_active_mi);
if (lex->verbose)
{
mysql_mutex_lock(&LOCK_active_mi);
res= show_all_master_info(thd);
mysql_mutex_unlock(&LOCK_active_mi);
}
else
{
LEX_MASTER_INFO *lex_mi= &thd->lex->mi;
Master_info *mi;
mi= master_info_index->get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_ERROR);
if (mi != NULL)
if ((mi= get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_ERROR)))
{
res= show_master_info(thd, mi, 0);
mi->release();
}
}
mysql_mutex_unlock(&LOCK_active_mi);
break;
}
case SQLCOM_SHOW_MASTER_STAT:
@ -3528,22 +3537,23 @@ end_with_restore_list:
load_error= rpl_load_gtid_slave_state(thd);
mysql_mutex_lock(&LOCK_active_mi);
if ((mi= (master_info_index->
get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_ERROR))))
/*
We don't need to ensure that only one user is using master_info
as start_slave is protected against simultaneous usage
*/
if ((mi= get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_ERROR)))
{
if (load_error)
{
/*
We cannot start a slave using GTID if we cannot load the GTID position
from the mysql.gtid_slave_pos table. But we can allow non-GTID
replication (useful eg. during upgrade).
We cannot start a slave using GTID if we cannot load the
GTID position from the mysql.gtid_slave_pos table. But we
can allow non-GTID replication (useful eg. during upgrade).
*/
if (mi->using_gtid != Master_info::USE_GTID_NO)
{
mysql_mutex_unlock(&LOCK_active_mi);
mi->release();
break;
}
else
@ -3551,8 +3561,8 @@ end_with_restore_list:
}
if (!start_slave(thd, mi, 1 /* net report*/))
my_ok(thd);
mi->release();
}
mysql_mutex_unlock(&LOCK_active_mi);
break;
}
case SQLCOM_SLAVE_STOP:
@ -3582,13 +3592,17 @@ end_with_restore_list:
}
lex_mi= &thd->lex->mi;
mysql_mutex_lock(&LOCK_active_mi);
if ((mi= (master_info_index->
get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_ERROR))))
if (!stop_slave(thd, mi, 1/* net report*/))
if ((mi= get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_ERROR)))
{
if (stop_slave(thd, mi, 1/* net report*/))
res= 1;
mi->release();
if (rpl_parallel_resize_pool_if_no_slaves())
res= 1;
if (!res)
my_ok(thd);
mysql_mutex_unlock(&LOCK_active_mi);
}
break;
}
case SQLCOM_SLAVE_ALL_START:
@ -4900,11 +4914,13 @@ end_with_restore_list:
reload_acl_and_cache binlog interactions failed
*/
res= 1;
}
}
if (!res)
my_ok(thd);
}
else
res= 1; // reload_acl_and_cache failed
#ifdef HAVE_REPLICATION
if (lex->type & REFRESH_READ_LOCK)
rpl_unpause_after_ftwrl(thd);

View file

@ -181,24 +181,20 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
slave is not likely to have the same connection names.
*/
tmp_write_to_binlog= 0;
mysql_mutex_lock(&LOCK_active_mi);
if (master_info_index)
if (!(mi= (get_master_info(&connection_name,
Sql_condition::WARN_LEVEL_ERROR))))
{
if (!(mi= (master_info_index->
get_master_info(&connection_name,
Sql_condition::WARN_LEVEL_ERROR))))
{
result= 1;
}
else
{
mysql_mutex_lock(&mi->data_lock);
if (rotate_relay_log(mi))
*write_to_binlog= -1;
mysql_mutex_unlock(&mi->data_lock);
}
result= 1;
}
else
{
mysql_mutex_lock(&mi->data_lock);
if (rotate_relay_log(mi))
*write_to_binlog= -1;
mysql_mutex_unlock(&mi->data_lock);
mi->release();
}
mysql_mutex_unlock(&LOCK_active_mi);
#endif
}
#ifdef HAVE_QUERY_CACHE
@ -375,27 +371,33 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
LEX_MASTER_INFO* lex_mi= &thd->lex->mi;
Master_info *mi;
tmp_write_to_binlog= 0;
mysql_mutex_lock(&LOCK_active_mi);
if (master_info_index)
if (!(mi= get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_ERROR)))
{
if (!(mi= (master_info_index->
get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_ERROR))))
{
result= 1;
}
else if (reset_slave(thd, mi))
result= 1;
}
else
{
/* The following will fail if slave is running */
if (reset_slave(thd, mi))
{
mi->release();
/* NOTE: my_error() has been already called by reset_slave(). */
result= 1;
}
else if (mi->connection_name.length && thd->lex->reset_slave_info.all)
{
/* If not default connection and 'all' is used */
master_info_index->remove_master_info(&mi->connection_name);
mi->release();
mysql_mutex_lock(&LOCK_active_mi);
if (master_info_index->remove_master_info(mi))
result= 1;
mysql_mutex_unlock(&LOCK_active_mi);
}
else
mi->release();
}
mysql_mutex_unlock(&LOCK_active_mi);
}
#endif
if (options & REFRESH_USER_RESOURCES)

View file

@ -3041,7 +3041,16 @@ int start_slave(THD* thd , Master_info* mi, bool net_report)
relay_log_info_file, 0,
&mi->cmp_connection_name);
lock_slave_threads(mi); // this allows us to cleanly read slave_running
mi->lock_slave_threads();
if (mi->killed)
{
/* connection was deleted while we waited for lock_slave_threads */
mi->unlock_slave_threads();
my_error(WARN_NO_MASTER_INFO, mi->connection_name.length,
mi->connection_name.str);
DBUG_RETURN(-1);
}
// Get a mask of _stopped_ threads
init_thread_mask(&thread_mask,mi,1 /* inverse */);
@ -3176,7 +3185,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report)
if (!slave_errno)
slave_errno = start_slave_threads(thd,
0 /*no mutex */,
1,
1 /* wait for start */,
mi,
master_info_file_tmp,
@ -3192,7 +3201,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report)
}
err:
unlock_slave_threads(mi);
mi->unlock_slave_threads();
thd_proc_info(thd, 0);
if (slave_errno)
@ -3233,8 +3242,12 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report )
DBUG_RETURN(-1);
THD_STAGE_INFO(thd, stage_killing_slave);
int thread_mask;
lock_slave_threads(mi);
// Get a mask of _running_ threads
mi->lock_slave_threads();
/*
Get a mask of _running_ threads.
We don't have to test for mi->killed as the thread_mask will take care
of checking if threads exists
*/
init_thread_mask(&thread_mask,mi,0 /* not inverse*/);
/*
Below we will stop all running threads.
@ -3247,8 +3260,7 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report )
if (thread_mask)
{
slave_errno= terminate_slave_threads(mi,thread_mask,
1 /*skip lock */);
slave_errno= terminate_slave_threads(mi,thread_mask, 0 /* get lock */);
}
else
{
@ -3257,7 +3269,8 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report )
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_SLAVE_WAS_NOT_RUNNING,
ER_THD(thd, ER_SLAVE_WAS_NOT_RUNNING));
}
unlock_slave_threads(mi);
mi->unlock_slave_threads();
if (slave_errno)
{
@ -3292,11 +3305,20 @@ int reset_slave(THD *thd, Master_info* mi)
char relay_log_info_file_tmp[FN_REFLEN];
DBUG_ENTER("reset_slave");
lock_slave_threads(mi);
mi->lock_slave_threads();
if (mi->killed)
{
/* connection was deleted while we waited for lock_slave_threads */
mi->unlock_slave_threads();
my_error(WARN_NO_MASTER_INFO, mi->connection_name.length,
mi->connection_name.str);
DBUG_RETURN(-1);
}
init_thread_mask(&thread_mask,mi,0 /* not inverse */);
if (thread_mask) // We refuse if any slave thread is running
{
unlock_slave_threads(mi);
mi->unlock_slave_threads();
my_error(ER_SLAVE_MUST_STOP, MYF(0), (int) mi->connection_name.length,
mi->connection_name.str);
DBUG_RETURN(ER_SLAVE_MUST_STOP);
@ -3359,7 +3381,7 @@ int reset_slave(THD *thd, Master_info* mi)
RUN_HOOK(binlog_relay_io, after_reset_slave, (thd, mi));
err:
unlock_slave_threads(mi);
mi->unlock_slave_threads();
if (error)
my_error(sql_errno, MYF(0), errmsg);
DBUG_RETURN(error);
@ -3474,8 +3496,8 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added)
DBUG_ENTER("change_master");
mysql_mutex_assert_owner(&LOCK_active_mi);
DBUG_ASSERT(master_info_index);
mysql_mutex_assert_owner(&LOCK_active_mi);
*master_info_added= false;
/*
@ -3495,7 +3517,16 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added)
lex_mi->port))
DBUG_RETURN(TRUE);
lock_slave_threads(mi);
mi->lock_slave_threads();
if (mi->killed)
{
/* connection was deleted while we waited for lock_slave_threads */
mi->unlock_slave_threads();
my_error(WARN_NO_MASTER_INFO, mi->connection_name.length,
mi->connection_name.str);
DBUG_RETURN(TRUE);
}
init_thread_mask(&thread_mask,mi,0 /*not inverse*/);
if (thread_mask) // We refuse if any slave thread is running
{
@ -3816,12 +3847,13 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added)
in-memory value at restart (thus causing errors, as the old relay log does
not exist anymore).
*/
flush_relay_log_info(&mi->rli);
if (flush_relay_log_info(&mi->rli))
ret= 1;
mysql_cond_broadcast(&mi->data_cond);
mysql_mutex_unlock(&mi->rli.data_lock);
err:
unlock_slave_threads(mi);
mi->unlock_slave_threads();
if (ret == FALSE)
my_ok(thd);
DBUG_RETURN(ret);
@ -3901,13 +3933,9 @@ bool mysql_show_binlog_events(THD* thd)
{
if (!lex_mi->connection_name.str)
lex_mi->connection_name= thd->variables.default_master_connection;
mysql_mutex_lock(&LOCK_active_mi);
if (!master_info_index ||
!(mi= master_info_index->
get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_ERROR)))
if (!(mi= get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_ERROR)))
{
mysql_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(TRUE);
}
binary_log= &(mi->rli.relay_log);
@ -3926,7 +3954,7 @@ bool mysql_show_binlog_events(THD* thd)
if (mi)
{
/* We can unlock the mutex as we have a lock on the file */
mysql_mutex_unlock(&LOCK_active_mi);
mi->release();
mi= 0;
}
@ -3948,6 +3976,7 @@ bool mysql_show_binlog_events(THD* thd)
goto err;
}
/* These locks is here to enable syncronization with log_in_use() */
mysql_mutex_lock(&LOCK_thread_count);
thd->current_linfo = &linfo;
mysql_mutex_unlock(&LOCK_thread_count);
@ -4061,7 +4090,7 @@ bool mysql_show_binlog_events(THD* thd)
mysql_mutex_unlock(log_lock);
}
else if (mi)
mysql_mutex_unlock(&LOCK_active_mi);
mi->release();
// Check that linfo is still on the function scope.
DEBUG_SYNC(thd, "after_show_binlog_events");
@ -4082,8 +4111,9 @@ err:
else
my_eof(thd);
/* These locks is here to enable syncronization with log_in_use() */
mysql_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0;
thd->current_linfo= 0;
mysql_mutex_unlock(&LOCK_thread_count);
thd->variables.max_allowed_packet= old_max_allowed_packet;
DBUG_RETURN(ret);

View file

@ -6450,6 +6450,9 @@ static bool fill_alter_inplace_info(THD *thd,
new_key->user_defined_key_parts))
goto index_changed;
if (table_key->block_size != new_key->block_size)
goto index_changed;
if (engine_options_differ(table_key->option_struct, new_key->option_struct,
table->file->ht->index_options))
goto index_changed;

View file

@ -7533,7 +7533,7 @@ alter_list_item:
$5->name, $4->csname));
if (Lex->create_info.add_alter_list_item_convert_to_charset($5))
MYSQL_YYABORT;
Lex->alter_info.flags|= Alter_info::ALTER_CONVERT;
Lex->alter_info.flags|= Alter_info::ALTER_OPTIONS;
}
| create_table_options_space_separated
{

View file

@ -1586,7 +1586,6 @@ bool
Sys_var_gtid_slave_pos::do_check(THD *thd, set_var *var)
{
String str, *res;
bool running;
DBUG_ASSERT(var->type == OPT_GLOBAL);
@ -1597,11 +1596,7 @@ Sys_var_gtid_slave_pos::do_check(THD *thd, set_var *var)
return true;
}
mysql_mutex_lock(&LOCK_active_mi);
running= (!master_info_index ||
master_info_index->give_error_if_slave_running());
mysql_mutex_unlock(&LOCK_active_mi);
if (running)
if (give_error_if_slave_running(0))
return true;
if (!(res= var->value->val_str(&str)))
return true;
@ -1639,7 +1634,7 @@ Sys_var_gtid_slave_pos::global_update(THD *thd, set_var *var)
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
if (!master_info_index || master_info_index->give_error_if_slave_running())
if (give_error_if_slave_running(1))
err= true;
else
err= rpl_gtid_pos_update(thd, var->save_result.string_value.str,
@ -1825,16 +1820,7 @@ Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_STRING *base)
static bool
check_slave_parallel_threads(sys_var *self, THD *thd, set_var *var)
{
bool running;
mysql_mutex_lock(&LOCK_active_mi);
running= (!master_info_index ||
master_info_index->give_error_if_slave_running());
mysql_mutex_unlock(&LOCK_active_mi);
if (running)
return true;
return false;
return give_error_if_slave_running(0);
}
static bool
@ -1843,10 +1829,7 @@ fix_slave_parallel_threads(sys_var *self, THD *thd, enum_var_type type)
bool err;
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
err= (!master_info_index ||
master_info_index->give_error_if_slave_running());
mysql_mutex_unlock(&LOCK_active_mi);
err= give_error_if_slave_running(0);
mysql_mutex_lock(&LOCK_global_system_variables);
return err;
@ -1869,16 +1852,7 @@ static Sys_var_ulong Sys_slave_parallel_threads(
static bool
check_slave_domain_parallel_threads(sys_var *self, THD *thd, set_var *var)
{
bool running;
mysql_mutex_lock(&LOCK_active_mi);
running= (!master_info_index ||
master_info_index->give_error_if_slave_running());
mysql_mutex_unlock(&LOCK_active_mi);
if (running)
return true;
return false;
return give_error_if_slave_running(0);
}
static bool
@ -1887,13 +1861,10 @@ fix_slave_domain_parallel_threads(sys_var *self, THD *thd, enum_var_type type)
bool running;
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
running= (!master_info_index ||
master_info_index->give_error_if_slave_running());
mysql_mutex_unlock(&LOCK_active_mi);
running= give_error_if_slave_running(0);
mysql_mutex_lock(&LOCK_global_system_variables);
return running ? true : false;
return running;
}
@ -2036,16 +2007,7 @@ static Sys_var_bit Sys_skip_parallel_replication(
static bool
check_gtid_ignore_duplicates(sys_var *self, THD *thd, set_var *var)
{
bool running;
mysql_mutex_lock(&LOCK_active_mi);
running= (!master_info_index ||
master_info_index->give_error_if_slave_running());
mysql_mutex_unlock(&LOCK_active_mi);
if (running)
return true;
return false;
return give_error_if_slave_running(0);
}
static bool
@ -2054,13 +2016,10 @@ fix_gtid_ignore_duplicates(sys_var *self, THD *thd, enum_var_type type)
bool running;
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
running= (!master_info_index ||
master_info_index->give_error_if_slave_running());
mysql_mutex_unlock(&LOCK_active_mi);
running= give_error_if_slave_running(0);
mysql_mutex_lock(&LOCK_global_system_variables);
return running ? true : false;
return running;
}
@ -2969,10 +2928,8 @@ Sys_var_replicate_events_marked_for_skip::global_update(THD *thd, set_var *var)
DBUG_ENTER("Sys_var_replicate_events_marked_for_skip::global_update");
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
if (master_info_index && !master_info_index->give_error_if_slave_running())
if (!give_error_if_slave_running(0))
result= Sys_var_enum::global_update(thd, var);
mysql_mutex_unlock(&LOCK_active_mi);
mysql_mutex_lock(&LOCK_global_system_variables);
DBUG_RETURN(result);
}
@ -4294,35 +4251,31 @@ static Sys_var_mybool Sys_relay_log_recovery(
bool Sys_var_rpl_filter::global_update(THD *thd, set_var *var)
{
bool result= true; // Assume error
Master_info *mi;
LEX_STRING *base_name= &var->base;
if (!base_name->length)
base_name= &thd->variables.default_master_connection;
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
mi= master_info_index->
get_master_info(base_name, !base_name->length ?
Sql_condition::WARN_LEVEL_ERROR :
Sql_condition::WARN_LEVEL_WARN);
if (mi)
if (Master_info *mi= get_master_info(base_name, !var->base.length ?
Sql_condition::WARN_LEVEL_ERROR :
Sql_condition::WARN_LEVEL_WARN))
{
if (mi->rli.slave_running)
{
my_error(ER_SLAVE_MUST_STOP, MYF(0),
mi->connection_name.length,
mi->connection_name.str);
mi->connection_name.length,
mi->connection_name.str);
result= true;
}
else
{
result= set_filter_value(var->save_result.string_value.str, mi);
}
mi->release();
}
mysql_mutex_unlock(&LOCK_active_mi);
mysql_mutex_lock(&LOCK_global_system_variables);
return result;
}
@ -4332,6 +4285,8 @@ bool Sys_var_rpl_filter::set_filter_value(const char *value, Master_info *mi)
bool status= true;
Rpl_filter* rpl_filter= mi->rpl_filter;
/* Proctect against other threads */
mysql_mutex_lock(&LOCK_active_mi);
switch (opt_id) {
case OPT_REPLICATE_DO_DB:
status= rpl_filter->set_do_db(value);
@ -4352,7 +4307,7 @@ bool Sys_var_rpl_filter::set_filter_value(const char *value, Master_info *mi)
status= rpl_filter->set_wild_ignore_table(value);
break;
}
mysql_mutex_unlock(&LOCK_active_mi);
return status;
}
@ -4366,23 +4321,20 @@ uchar *Sys_var_rpl_filter::global_value_ptr(THD *thd,
Rpl_filter *rpl_filter;
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
mi= master_info_index->
get_master_info(base_name, !base_name->length ?
Sql_condition::WARN_LEVEL_ERROR :
Sql_condition::WARN_LEVEL_WARN);
mysql_mutex_lock(&LOCK_global_system_variables);
mi= get_master_info(base_name, !base_name->length ?
Sql_condition::WARN_LEVEL_ERROR :
Sql_condition::WARN_LEVEL_WARN);
if (!mi)
{
mysql_mutex_unlock(&LOCK_active_mi);
mysql_mutex_lock(&LOCK_global_system_variables);
return 0;
}
rpl_filter= mi->rpl_filter;
tmp.length(0);
mysql_mutex_lock(&LOCK_active_mi);
switch (opt_id) {
case OPT_REPLICATE_DO_DB:
rpl_filter->get_do_db(&tmp);
@ -4403,9 +4355,12 @@ uchar *Sys_var_rpl_filter::global_value_ptr(THD *thd,
rpl_filter->get_wild_ignore_table(&tmp);
break;
}
mysql_mutex_unlock(&LOCK_active_mi);
mysql_mutex_lock(&LOCK_global_system_variables);
mi->release();
ret= (uchar *) thd->strmake(tmp.ptr(), tmp.length());
mysql_mutex_unlock(&LOCK_active_mi);
return ret;
}
@ -4474,17 +4429,12 @@ get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset)
Master_info *mi;
ulonglong res= 0; // Default value
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
mi= master_info_index->
get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_WARN);
if (mi)
if ((mi= get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_WARN)))
{
mysql_mutex_lock(&mi->rli.data_lock);
res= *((ulonglong*) (((uchar*) mi) + master_info_offset));
mysql_mutex_unlock(&mi->rli.data_lock);
mi->release();
}
mysql_mutex_unlock(&LOCK_active_mi);
mysql_mutex_lock(&LOCK_global_system_variables);
return res;
}
@ -4499,19 +4449,16 @@ bool update_multi_source_variable(sys_var *self_var, THD *thd,
if (type == OPT_GLOBAL)
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);
mi= master_info_index->
get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_ERROR);
if (mi)
if ((mi= (get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_ERROR))))
{
mysql_mutex_lock(&mi->rli.run_lock);
mysql_mutex_lock(&mi->rli.data_lock);
result= self->update_variable(thd, mi);
mysql_mutex_unlock(&mi->rli.data_lock);
mysql_mutex_unlock(&mi->rli.run_lock);
mi->release();
}
mysql_mutex_unlock(&LOCK_active_mi);
if (type == OPT_GLOBAL)
mysql_mutex_lock(&LOCK_global_system_variables);
return result;

View file

@ -5173,7 +5173,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
TABLE_SHARE *table_s,
HA_CREATE_INFO *create_info)
{
char v=0, spc= ',', qch= 0;
char v=0;
const char *fncn= "?";
const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src;
const char *col, *ocl, *rnk, *pic, *fcl, *skc, *zfn;
@ -5225,10 +5225,6 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
fncn= topt->catfunc;
fnc= GetFuncID(fncn);
sep= topt->separator;
spc= (!sep) ? ',' : *sep;
qch= topt->qchar ? *topt->qchar : (signed)topt->quoted >= 0 ? '"' : 0;
mul = (int)topt->multiple;
tbl= topt->tablist;
col= topt->colist;
if (topt->oplist) {

View file

@ -27,6 +27,7 @@
#include "ioapi.h"
#include "my_attribute.h"
voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
{
@ -92,7 +93,7 @@ static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPO
static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));
static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));
static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
static voidpf ZCALLBACK fopen_file_func (voidpf opaque __attribute__((unused)), const char* filename, int mode)
{
FILE* file = NULL;
const char* mode_fopen = NULL;
@ -110,7 +111,7 @@ static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, in
return file;
}
static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
static voidpf ZCALLBACK fopen64_file_func (voidpf opaque __attribute__((unused)), const void* filename, int mode)
{
FILE* file = NULL;
const char* mode_fopen = NULL;
@ -129,21 +130,21 @@ static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename,
}
static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
static uLong ZCALLBACK fread_file_func (voidpf opaque __attribute__((unused)), voidpf stream, void* buf, uLong size)
{
uLong ret;
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
static uLong ZCALLBACK fwrite_file_func (voidpf opaque __attribute__((unused)), voidpf stream, const void* buf, uLong size)
{
uLong ret;
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
static long ZCALLBACK ftell_file_func (voidpf opaque __attribute__((unused)), voidpf stream)
{
long ret;
ret = ftell((FILE *)stream);
@ -151,14 +152,14 @@ static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
}
static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque __attribute__((unused)), voidpf stream)
{
ZPOS64_T ret;
ret = FTELLO_FUNC((FILE *)stream);
return ret;
}
static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin)
static long ZCALLBACK fseek_file_func (voidpf opaque __attribute__((unused)), voidpf stream, uLong offset, int origin)
{
int fseek_origin=0;
long ret;
@ -181,7 +182,7 @@ static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offs
return ret;
}
static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)
static long ZCALLBACK fseek64_file_func (voidpf opaque __attribute__((unused)), voidpf stream, ZPOS64_T offset, int origin)
{
int fseek_origin=0;
long ret;
@ -207,14 +208,14 @@ static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T
}
static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
static int ZCALLBACK fclose_file_func (voidpf opaque __attribute__((unused)), voidpf stream)
{
int ret;
ret = fclose((FILE *)stream);
return ret;
}
static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
static int ZCALLBACK ferror_file_func (voidpf opaque __attribute__((unused)), voidpf stream)
{
int ret;
ret = ferror((FILE *)stream);

View file

@ -637,7 +637,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
return relativeOffset;
}
int LoadCentralDirectoryRecord(zip64_internal* pziinit)
static int LoadCentralDirectoryRecord(zip64_internal* pziinit)
{
int err=ZIP_OK;
ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
@ -846,7 +846,7 @@ int LoadCentralDirectoryRecord(zip64_internal* pziinit)
/************************************************************/
extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def)
static zipFile zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def)
{
zip64_internal ziinit;
zip64_internal* zi;
@ -955,7 +955,7 @@ extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append)
return zipOpen3(pathname,append,NULL,NULL);
}
int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local)
static int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local)
{
/* write the local header */
int err;
@ -1752,7 +1752,7 @@ extern int ZEXPORT zipCloseFileInZip (zipFile file)
return zipCloseFileInZipRaw (file,0,0);
}
int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip)
static int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip)
{
int err = ZIP_OK;
ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset;
@ -1774,7 +1774,7 @@ int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eo
return err;
}
int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
static int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
{
int err = ZIP_OK;
@ -1813,7 +1813,7 @@ int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centra
}
return err;
}
int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
static int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
{
int err = ZIP_OK;
@ -1861,7 +1861,7 @@ int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir,
return err;
}
int Write_GlobalComment(zip64_internal* zi, const char* global_comment)
static int Write_GlobalComment(zip64_internal* zi, const char* global_comment)
{
int err = ZIP_OK;
uInt size_global_comment = 0;

View file

@ -1094,7 +1094,12 @@ fil_space_extend_must_retry(
const ulint n_pages = size - start_page_no;
const os_offset_t len = os_offset_t(n_pages) * page_size;
int err = posix_fallocate(node->handle, start_offset, len);
int err;
do {
err = posix_fallocate(node->handle, start_offset, len);
} while (err == EINTR
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
*success = !err;
if (!*success) {
ib_logf(IB_LOG_LEVEL_ERROR, "extending file %s"

View file

@ -1470,17 +1470,7 @@ log_write_up_to(
}
loop:
#ifdef UNIV_DEBUG
loop_count++;
ut_ad(loop_count < 5);
# if 0
if (loop_count > 2) {
fprintf(stderr, "Log loop count %lu\n", loop_count);
}
# endif
#endif
ut_ad(++loop_count < 100);
mutex_enter(&(log_sys->mutex));
ut_ad(!recv_no_log_write);

View file

@ -2394,7 +2394,12 @@ os_file_set_size(
# ifdef HAVE_POSIX_FALLOCATE
if (srv_use_posix_fallocate) {
int err = posix_fallocate(file, 0, size);
int err;
do {
err = posix_fallocate(file, 0, size);
} while (err == EINTR
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
if (err) {
ib_logf(IB_LOG_LEVEL_ERROR,
"preallocating " INT64PF " bytes for"

View file

@ -22,8 +22,14 @@ include_directories(
${ONIGMO_INCLUDE_DIRS}
${MRUBY_INCLUDE_DIRS}
${LIBLZ4_INCLUDE_DIRS})
link_directories(
${LIBLZ4_LIBRARY_DIRS})
if (LIBLZ4_LIBRARY_DIRS)
find_library(LZ4_LIBS
NAMES ${LIBLZ4_LIBRARIES}
PATHS ${LIBLZ4_LIBRARY_DIRS}
NO_DEFAULT_PATH)
else()
set(LZ4_LIBS ${LIBLZ4_LIBRARIES})
endif()
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am LIBGROONGA_SOURCES)
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/dat/sources.am LIBGRNDAT_SOURCES)
@ -60,7 +66,7 @@ set(GRN_ALL_LIBRARIES
${RT_LIBS}
${PTHREAD_LIBS}
${Z_LIBS}
${LIBLZ4_LIBRARIES}
${LZ4_LIBS}
${DL_LIBS}
${M_LIBS}
${WS2_32_LIBS}

View file

@ -2182,6 +2182,74 @@ uint ha_myisam::checksum() const
}
enum_alter_inplace_result
ha_myisam::check_if_supported_inplace_alter(TABLE *new_table,
Alter_inplace_info *alter_info)
{
DBUG_ENTER("ha_myisam::check_if_supported_inplace_alter");
const uint readd_index= Alter_inplace_info::ADD_INDEX |
Alter_inplace_info::DROP_INDEX;
const uint readd_unique= Alter_inplace_info::ADD_UNIQUE_INDEX |
Alter_inplace_info::DROP_UNIQUE_INDEX;
const uint readd_pk= Alter_inplace_info::ADD_PK_INDEX |
Alter_inplace_info::DROP_PK_INDEX;
const uint op= alter_info->handler_flags;
/*
ha_myisam::open() updates table->key_info->block_size to be the actual
MYI index block size, overwriting user-specified value (if any).
So, the server can not reliably detect whether ALTER TABLE changes
key_block_size or not, it might think the block size was changed,
when it wasn't, and in this case the server will recreate (drop+add)
the index unnecessary. Fix it.
*/
if (table->s->keys == new_table->s->keys &&
((op & readd_pk) == readd_pk ||
(op & readd_unique) == readd_unique ||
(op & readd_index) == readd_index))
{
for (uint i=0; i < table->s->keys; i++)
{
KEY *old_key= table->key_info + i;
KEY *new_key= new_table->key_info + i;
if (old_key->block_size == new_key->block_size)
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); // must differ somewhere else
if (new_key->block_size && new_key->block_size != old_key->block_size)
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); // really changed
/* any difference besides the block_size, and we give up */
if (old_key->key_length != new_key->key_length ||
old_key->flags != new_key->flags ||
old_key->user_defined_key_parts != new_key->user_defined_key_parts ||
old_key->algorithm != new_key->algorithm ||
strcmp(old_key->name, new_key->name))
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
for (uint j= 0; j < old_key->user_defined_key_parts; j++)
{
KEY_PART_INFO *old_kp= old_key->key_part + j;
KEY_PART_INFO *new_kp= new_key->key_part + j;
if (old_kp->offset != new_kp->offset ||
old_kp->null_offset != new_kp->null_offset ||
old_kp->length != new_kp->length ||
old_kp->fieldnr != new_kp->fieldnr ||
old_kp->key_part_flag != new_kp->key_part_flag ||
old_kp->type != new_kp->type ||
old_kp->null_bit != new_kp->null_bit)
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
}
alter_info->handler_flags &= ~(readd_pk | readd_unique | readd_index);
}
DBUG_RETURN(handler::check_if_supported_inplace_alter(new_table, alter_info));
}
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *create_info,
uint table_changes)
{

View file

@ -138,6 +138,8 @@ class ha_myisam: public handler
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt);
int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
enum_alter_inplace_result check_if_supported_inplace_alter(TABLE *new_table,
Alter_inplace_info *alter_info);
bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes);
#ifdef HAVE_QUERY_CACHE
my_bool register_query_cache_table(THD *thd, char *table_key,

View file

@ -33,5 +33,5 @@ FROM `version_history` AS `v` INNER JOIN `db_history` AS `db` ON `db`.`nodeID` =
WHERE `latch` = 'breadth_first' AND `origid` = '1' ORDER BY `weight` DESC LIMIT 1;
version nodeID
0.0.3 3
DROP TABLE db_history;
DROP TABLE version_history;
DROP TABLE db_history;

View file

@ -40,8 +40,8 @@
--disconnect con2
--connect (con3,localhost,root,,test)
DROP TABLE db_history;
DROP TABLE version_history;
DROP TABLE db_history;
--disconnect con3

View file

@ -8,5 +8,5 @@ latch origid destid weight seq linkid
breadth_first 1 6 NULL 0 1
breadth_first 1 6 1 1 2
breadth_first 1 6 1 2 6
DROP TABLE IF EXISTS oq_backing;
DROP TABLE IF EXISTS oq_graph;
DROP TABLE IF EXISTS oq_backing;

View file

@ -14,6 +14,6 @@ CREATE TABLE oq_graph (latch VARCHAR(32) NULL, origid BIGINT UNSIGNED NULL, dest
SELECT * FROM oq_graph WHERE latch='breadth_first' AND origid=1 AND destid=6;
DROP TABLE IF EXISTS oq_backing;
DROP TABLE IF EXISTS oq_graph;
DROP TABLE IF EXISTS oq_backing;

View file

@ -1099,7 +1099,12 @@ fil_space_extend_must_retry(
const ulint n_pages = size - start_page_no;
const os_offset_t len = os_offset_t(n_pages) * page_size;
int err = posix_fallocate(node->handle, start_offset, len);
int err;
do {
err = posix_fallocate(node->handle, start_offset, len);
} while (err == EINTR
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
*success = !err;
if (!*success) {
ib_logf(IB_LOG_LEVEL_ERROR, "extending file %s"

View file

@ -1588,17 +1588,7 @@ log_write_up_to(
}
loop:
#ifdef UNIV_DEBUG
loop_count++;
ut_ad(loop_count < 5);
# if 0
if (loop_count > 2) {
fprintf(stderr, "Log loop count %lu\n", loop_count);
}
# endif
#endif
ut_ad(++loop_count < 100);
mutex_enter(&(log_sys->mutex));
ut_ad(!recv_no_log_write);

View file

@ -2576,7 +2576,12 @@ os_file_set_size(
# ifdef HAVE_POSIX_FALLOCATE
if (srv_use_posix_fallocate) {
int err = posix_fallocate(file, 0, size);
int err;
do {
err = posix_fallocate(file, 0, size);
} while (err == EINTR
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
if (err) {
ib_logf(IB_LOG_LEVEL_ERROR,
"preallocating " INT64PF " bytes for"

View file

@ -30,7 +30,8 @@
if test -x @bindir@/mysqladmin && \
@bindir@/mysqladmin ping &>/dev/null
then
@bindir@/mysqladmin flush-logs
@bindir@/mysqladmin --local flush-error-log \
flush-engine-log flush-general-log flush-slow-log
fi
endscript
}

View file

@ -45,6 +45,11 @@ if [ $1 = 1 ] ; then
# The user may already exist, make sure it has the proper group nevertheless (BUG#12823)
usermod --gid %{mysqld_group} %{mysqld_user} 2> /dev/null || true
# Temporary Workaround for MDEV-11386 - will be corrected in Advance Toolchain 10.0-3 and 8.0-8
for ldconfig in /opt/at*/sbin/ldconfig; do
test -x $ldconfig && $ldconfig
done
# Change permissions so that the user that will run the MySQL daemon
# owns all database files.
chown -R %{mysqld_user}:%{mysqld_group} $datadir