From 96f680aa6589138058a820987e5cf8600f024e81 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Mon, 29 Feb 2016 13:58:41 +0100 Subject: Raise version number after cloning 5.5.49 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ba54e70bc3e..58a6b369de9 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=49 +MYSQL_VERSION_PATCH=50 MYSQL_VERSION_EXTRA= -- cgit v1.2.1 From c7e68606c02b7f87a48c27eb358d4d07480f40f4 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Tue, 1 Mar 2016 10:17:25 +0530 Subject: Bug#21920657: SSL-CA FAILS SILENTLY IF THE PATH CANNOT BE FOUND Description:- Failure during the validation of CA certificate path which is provided as an option for 'ssl-ca' returns two different errors for YaSSL and OPENSSL. Analysis:- 'ssl-ca', option used for specifying the ssl ca certificate path. Failing to validate this certificate with OPENSSL returns an error, "ERROR 2026 (HY000): SSL connection error: SSL_CTX_set_default_verify_paths failed". While YASSL returns "ERROR 2026 (HY000): SSL connection error: ASN: bad other signature confirmation". Error returned by the OPENSSL is correct since "SSL_CTX_load_verify_locations()" returns 0 (in case of OPENSSL) for the failure and sets error as "SSL_INITERR_BAD_PATHS". In case of YASSL, "SSL_CTX_load_verify_locations()" returns an error number which is less than or equal to 0 in case of error. Error numbers for YASSL is mentioned in the file, 'extra/yassl/include/openssl/ssl.h'(line no : 292). Also 'ssl-ca' does not accept tilde home directory path substitution. Fix:- The condition which checks for the error in the "SSL_CTX_load_verify_locations()" is changed in order to accommodate YASSL as well. A logic is written in "mysql_ssl_set()" in order accept the tilde home directory path substitution for all ssl options. --- mysql-test/r/ssl_ca.result | 24 ++++++++++++++++++++++++ mysql-test/t/ssl_ca.test | 35 +++++++++++++++++++++++++++++++++++ sql-common/client.c | 23 +++++++++++++++++++---- vio/viosslfactories.c | 4 ++-- 4 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 mysql-test/r/ssl_ca.result create mode 100644 mysql-test/t/ssl_ca.test diff --git a/mysql-test/r/ssl_ca.result b/mysql-test/r/ssl_ca.result new file mode 100644 index 00000000000..ffc5671f85f --- /dev/null +++ b/mysql-test/r/ssl_ca.result @@ -0,0 +1,24 @@ +# +# Bug#21920657: SSL-CA FAILS SILENTLY IF THE PATH CANNOT BE FOUND +# +# try to connect with wrong '--ssl-ca' path : should fail +ERROR 2026 (HY000): SSL connection error: SSL_CTX_set_default_verify_paths failed +# try to connect with correct '--ssl-ca' path : should connect +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA +# +# Bug#21920678: SSL-CA DOES NOT ACCEPT ~USER TILDE HOME DIRECTORY +# PATH SUBSTITUTION +# +# try to connect with '--ssl-ca' option using tilde home directoy +# path substitution : should connect +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA +# try to connect with '--ssl-key' option using tilde home directoy +# path substitution : should connect +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA +# try to connect with '--ssl-cert' option using tilde home directoy +# path substitution : should connect +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA diff --git a/mysql-test/t/ssl_ca.test b/mysql-test/t/ssl_ca.test new file mode 100644 index 00000000000..92695de4b0d --- /dev/null +++ b/mysql-test/t/ssl_ca.test @@ -0,0 +1,35 @@ +--source include/have_ssl.inc +--source include/not_embedded.inc + +--echo # +--echo # Bug#21920657: SSL-CA FAILS SILENTLY IF THE PATH CANNOT BE FOUND +--echo # + +--echo # try to connect with wrong '--ssl-ca' path : should fail +--error 1 +--exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/wrong-cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" 2>&1 + +--echo # try to connect with correct '--ssl-ca' path : should connect +--exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" + +--echo # +--echo # Bug#21920678: SSL-CA DOES NOT ACCEPT ~USER TILDE HOME DIRECTORY +--echo # PATH SUBSTITUTION +--echo # + +--let $mysql_test_dir_path= `SELECT REPLACE('$MYSQL_TEST_DIR', '$HOME', '~')` + +--echo # try to connect with '--ssl-ca' option using tilde home directoy +--echo # path substitution : should connect +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--exec $MYSQL --ssl-ca=$mysql_test_dir_path/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" + +--echo # try to connect with '--ssl-key' option using tilde home directoy +--echo # path substitution : should connect +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$mysql_test_dir_path/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" + +--echo # try to connect with '--ssl-cert' option using tilde home directoy +--echo # path substitution : should connect +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$mysql_test_dir_path/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" diff --git a/sql-common/client.c b/sql-common/client.c index 0ef70eb7f56..cd9b6a71c53 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1204,6 +1204,21 @@ static int add_init_command(struct st_mysql_options *options, const char *cmd) my_strdup((STR), MYF(MY_WME)) : NULL; \ } while (0) +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) +static char *set_ssl_option_unpack_path(const char *arg) +{ + char *opt_var= NULL; + if (arg) + { + char *buff= (char *)my_malloc(FN_REFLEN + 1, MYF(MY_WME)); + unpack_filename(buff, (char *)arg); + opt_var= my_strdup(buff, MYF(MY_WME)); + my_free(buff); + } + return opt_var; +} +#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ + void mysql_read_default_options(struct st_mysql_options *options, const char *filename,const char *group) { @@ -1798,10 +1813,10 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , { DBUG_ENTER("mysql_ssl_set"); #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) - mysql->options.ssl_key= strdup_if_not_null(key); - mysql->options.ssl_cert= strdup_if_not_null(cert); - mysql->options.ssl_ca= strdup_if_not_null(ca); - mysql->options.ssl_capath= strdup_if_not_null(capath); + mysql->options.ssl_key= set_ssl_option_unpack_path(key); + mysql->options.ssl_cert= set_ssl_option_unpack_path(cert); + mysql->options.ssl_ca= set_ssl_option_unpack_path(ca); + mysql->options.ssl_capath= set_ssl_option_unpack_path(capath); mysql->options.ssl_cipher= strdup_if_not_null(cipher); #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ DBUG_RETURN(0); diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index ea46d9c0302..3aa1c873163 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -250,7 +250,7 @@ new_VioSSLFd(const char *key_file, const char *cert_file, } /* Load certs from the trusted ca */ - if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) == 0) + if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) <= 0) { DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); if (ca_file || ca_path) -- cgit v1.2.1 From bb32ac1d9b6c1333316a8da32ea46105eceefa29 Mon Sep 17 00:00:00 2001 From: Venkatesh Duggirala Date: Tue, 1 Mar 2016 11:58:45 +0530 Subject: BUG#17018343 SLAVE CRASHES WHEN APPLYING ROW-BASED BINLOG ENTRIES IN CASCADING REPLICATION Problem: In RBR mode, merge table updates are not successfully applied on a cascading replication. Analysis & Fix: Every type of row event is preceded by one or more table_map_log_events that gives the information about all the tables that are involved in the row event. Server maintains the list in RPL_TABLE_LIST and it goes through all the tables and checks for the compatibility between master and slave. Before checking for the compatibility, it calls 'open_tables()' which takes the list of all tables that needs to be locked and opened. In RBR, because of the Table_map_log_event , we already have all the tables including base tables in the list. But the open_tables() which is generic call takes care of appending base tables if the list contains merge tables. There is an assumption in the current replication layer logic that these tables (TABLE_LIST type objects) are always added in the end of the list. Replication layer maintains the count of tables(tables_to_lock_count) that needs to be verified for compatibility check and runs through only those many tables from the list and rest of the objects in linked list can be skipped. But this assumption is wrong. open_tables()->..->add_children_to_list() adds base tables to the list immediately after seeing the merge table in the list. For eg: If the list passed to open_tables() is t1->t2->t3 where t3 is merge table (and t1 and t2 are base tables), it adds t1'->t2' to the list after t3. New table list looks like t1->t2->t3->t1'->t2'. It looks like it added at the end of the list but that is not correct. If the list passed to open_tables() is t3->t1->t2 where t3 is merge table (and t1 and t2 are base tables), the new prepared list will be t3->t1'->t2'->t1->t2. Where t1' and t2' are of TABLE_LIST objects which were added by add_children_to_list() call and replication layer should not look into them. Here tables_to_lock_count will not help as the objects are added in between the list. Fix: After investigating add_children_list() logic (which is called from open_tables()), there is no flag/logic in it to skip adding the children to the list even if the children are already included in the table list. Hence to fix the issue, a logic should be added in the replication layer to skip children in the list by checking whether 'parent_l' is non-null or not. If it is children, we will skip 'compatibility' check for that table. Also this patch is not removing 'tables_to_lock_count' logic for the performance issues if there are any children at the end of the list, those can be easily skipped directly by stopping the loop with tables_to_lock_count check. --- sql/log_event.cc | 46 +++++++++++++++++++++++++++++++++++++++------- sql/log_event_old.cc | 52 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 78 insertions(+), 20 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index accb6a28dbd..702cf1d575a 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -7930,9 +7930,6 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) /* When the open and locking succeeded, we check all tables to ensure that they still have the correct type. - - We can use a down cast here since we know that every table added - to the tables_to_lock is a RPL_TABLE_LIST. */ { @@ -7951,10 +7948,37 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) NOTE: The base tables are added here are removed when close_thread_tables is called. */ - RPL_TABLE_LIST *ptr= rli->tables_to_lock; - for (uint i= 0 ; ptr && (i < rli->tables_to_lock_count); - ptr= static_cast(ptr->next_global), i++) + TABLE_LIST *table_list_ptr= rli->tables_to_lock; + for (uint i=0 ; table_list_ptr && (i < rli->tables_to_lock_count); + table_list_ptr= table_list_ptr->next_global, i++) { + /* + Below if condition takes care of skipping base tables that + make up the MERGE table (which are added by open_tables() + call). They are added next to the merge table in the list. + For eg: If RPL_TABLE_LIST is t3->t1->t2 (where t1 and t2 + are base tables for merge table 't3'), open_tables will modify + the list by adding t1 and t2 again immediately after t3 in the + list (*not at the end of the list*). New table_to_lock list will + look like t3->t1'->t2'->t1->t2 (where t1' and t2' are TABLE_LIST + objects added by open_tables() call). There is no flag(or logic) in + open_tables() that can skip adding these base tables to the list. + So the logic here should take care of skipping them. + + tables_to_lock_count logic will take care of skipping base tables + that are added at the end of the list. + For eg: If RPL_TABLE_LIST is t1->t2->t3, open_tables will modify + the list into t1->t2->t3->t1'->t2'. t1' and t2' will be skipped + because tables_to_lock_count logic in this for loop. + */ + if (table_list_ptr->parent_l) + continue; + /* + We can use a down cast here since we know that every table added + to the tables_to_lock is a RPL_TABLE_LIST (or child table which is + skipped above). + */ + RPL_TABLE_LIST *ptr= static_cast(table_list_ptr); DBUG_ASSERT(ptr->m_tabledef_valid); TABLE *conv_table; if (!ptr->m_tabledef.compatible_with(thd, const_cast(rli), @@ -7995,7 +8019,15 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) */ TABLE_LIST *ptr= rli->tables_to_lock; for (uint i=0 ; ptr && (i < rli->tables_to_lock_count); ptr= ptr->next_global, i++) + { + /* + Please see comment in above 'for' loop to know the reason + for this if condition + */ + if (ptr->parent_l) + continue; const_cast(rli)->m_table_map.set_table(ptr->table_id, ptr->table); + } #ifdef HAVE_QUERY_CACHE query_cache.invalidate_locked_for_write(rli->tables_to_lock); diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index ed53aec6006..eb9678ddaa5 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -119,16 +119,25 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info /* When the open and locking succeeded, we check all tables to ensure that they still have the correct type. - - We can use a down cast here since we know that every table added - to the tables_to_lock is a RPL_TABLE_LIST. */ { - RPL_TABLE_LIST *ptr= rli->tables_to_lock; - for (uint i= 0 ; ptr&& (i< rli->tables_to_lock_count); - ptr= static_cast(ptr->next_global), i++) + TABLE_LIST *table_list_ptr= rli->tables_to_lock; + for (uint i=0 ; table_list_ptr&& (i< rli->tables_to_lock_count); + table_list_ptr= table_list_ptr->next_global, i++) { + /* + Please see comment in log_event.cc-Rows_log_event::do_apply_event() + function for the explanation of the below if condition + */ + if (table_list_ptr->parent_l) + continue; + /* + We can use a down cast here since we know that every table added + to the tables_to_lock is a RPL_TABLE_LIST(or child table which is + skipped above). + */ + RPL_TABLE_LIST *ptr=static_cast(table_list_ptr); DBUG_ASSERT(ptr->m_tabledef_valid); TABLE *conv_table; if (!ptr->m_tabledef.compatible_with(thd, const_cast(rli), @@ -162,7 +171,15 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info */ TABLE_LIST *ptr= rli->tables_to_lock; for (uint i=0; ptr && (i < rli->tables_to_lock_count); ptr= ptr->next_global, i++) + { + /* + Please see comment in log_event.cc-Rows_log_event::do_apply_event() + function for the explanation of the below if condition + */ + if (ptr->parent_l) + continue; const_cast(rli)->m_table_map.set_table(ptr->table_id, ptr->table); + } #ifdef HAVE_QUERY_CACHE query_cache.invalidate_locked_for_write(rli->tables_to_lock); #endif @@ -1545,16 +1562,25 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) /* When the open and locking succeeded, we check all tables to ensure that they still have the correct type. - - We can use a down cast here since we know that every table added - to the tables_to_lock is a RPL_TABLE_LIST. */ { - RPL_TABLE_LIST *ptr= rli->tables_to_lock; - for (uint i= 0 ; ptr&& (i< rli->tables_to_lock_count); - ptr= static_cast(ptr->next_global), i++) + TABLE_LIST *table_list_ptr= rli->tables_to_lock; + for (uint i=0; table_list_ptr&& (i< rli->tables_to_lock_count); + table_list_ptr= static_cast(table_list_ptr->next_global), i++) { + /* + Please see comment in log_event.cc-Rows_log_event::do_apply_event() + function for the explanation of the below if condition + */ + if (table_list_ptr->parent_l) + continue; + /* + We can use a down cast here since we know that every table added + to the tables_to_lock is a RPL_TABLE_LIST (or child table which is + skipped above). + */ + RPL_TABLE_LIST *ptr=static_cast(table_list_ptr); TABLE *conv_table; if (ptr->m_tabledef.compatible_with(thd, const_cast(rli), ptr->table, &conv_table)) -- cgit v1.2.1 From 8361151765cc5efd72ad18c5553f80aa440a1d83 Mon Sep 17 00:00:00 2001 From: Sujatha Sivakumar Date: Tue, 1 Mar 2016 12:29:51 +0530 Subject: Bug#20685029: SLAVE IO THREAD SHOULD STOP WHEN DISK IS FULL Bug#21753696: MAKE SHOW SLAVE STATUS NON BLOCKING IF IO THREAD WAITS FOR DISK SPACE Problem: ======== Currently SHOW SLAVE STATUS blocks if IO thread waits for disk space. This makes automation tools verifying server health block on taking relevant action. Finally this will create SHOW SLAVE STATUS piles. Analysis: ========= SHOW SLAVE STATUS hangs on mi->data_lock if relay log write is waiting for free disk space while holding mi->data_lock. mi->data_lock is needed to protect the format description event (mi->format_description_event) which is accessed by the clients running FLUSH LOGS and slave IO thread. Note relay log writes don't need to be protected by mi->data_lock, LOCK_log is used to protect relay log between IO and SQL thread (see MYSQL_BIN_LOG::append_event). The code takes mi->data_lock to protect mi->format_description_event during relay log rotate which might get triggered right after relay log write. Fix: ==== Release the data_lock just for the duration of writing into relay log. Made change to ensure the following lock order is maintained to avoid deadlocks. data_lock, LOCK_log data_lock is held during relay log rotations to protect the description event. --- mysql-test/include/assert_grep.inc | 154 +++++++++++++++++++++ mysql-test/include/rpl_init.inc | 31 ++++- mysql-test/include/rpl_reconnect.inc | 33 +++-- mysql-test/include/start_slave_sql.inc | 39 ++++++ .../rpl/r/rpl_io_thd_wait_for_disk_space.result | 15 ++ .../rpl/t/rpl_io_thd_wait_for_disk_space.test | 71 ++++++++++ mysys/errors.c | 13 +- mysys/my_write.c | 10 +- sql/log.cc | 69 ++++++++- sql/log.h | 7 +- sql/slave.cc | 40 ++++-- sql/slave.h | 4 +- sql/sql_reload.cc | 4 +- 13 files changed, 443 insertions(+), 47 deletions(-) create mode 100644 mysql-test/include/assert_grep.inc create mode 100644 mysql-test/include/start_slave_sql.inc create mode 100644 mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result create mode 100644 mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test diff --git a/mysql-test/include/assert_grep.inc b/mysql-test/include/assert_grep.inc new file mode 100644 index 00000000000..a980a6d73b1 --- /dev/null +++ b/mysql-test/include/assert_grep.inc @@ -0,0 +1,154 @@ +# ==== Purpose ==== +# +# Grep a file for a pattern, produce a single string out of the +# matching lines, and assert that the string matches a given regular +# expression. +# +# ==== Usage ==== +# +# --let $assert_text= TEXT +# --let $assert_file= FILE +# --let $assert_select= REGEX +# [--let $assert_match= REGEX | --let $assert_count= NUMBER] +# [--let $assert_only_after= REGEX] +# --source include/assert_grep.inc +# +# Parameters: +# +# $assert_text +# Text that describes what is being checked. This text is written to +# the query log so it should not contain non-deterministic elements. +# +# $assert_file +# File to search. +# +# $assert_select +# All lines matching this text will be checked. +# +# $assert_match +# The script will find all lines that match $assert_select, +# concatenate them to a long string, and assert that it matches +# $assert_match. +# +# $assert_count +# Instead of asserting that the selected lines match +# $assert_match, assert that there were exactly $assert_count +# matching lines. +# +# $assert_only_after +# Reset all the lines matched and the counter when finding this pattern. +# It is useful for searching things in the mysqld.err log file just +# after the last server restart for example (discarding the log content +# of previous server executions). + + +if (!$assert_text) +{ + --die !!!ERROR IN TEST: you must set $assert_text +} +if (!$assert_file) +{ + --die !!!ERROR IN TEST: you must set $assert_file +} +if (!$assert_select) +{ + --die !!!ERROR IN TEST: you must set $assert_select +} +if ($assert_match == '') +{ + if ($assert_count == '') + { + --die !!!ERROR IN TEST: you must set either $assert_match or $assert_count + } +} +if ($assert_match != '') +{ + if ($assert_count != '') + { + --echo assert_text='$assert_text' assert_count='$assert_count' + --die !!!ERROR IN TEST: you must set only one of $assert_match or $assert_count + } +} + + +--let $include_filename= assert_grep.inc [$assert_text] +--source include/begin_include_file.inc + + +--let _AG_ASSERT_TEXT= $assert_text +--let _AG_ASSERT_FILE= $assert_file +--let _AG_ASSERT_SELECT= $assert_select +--let _AG_ASSERT_MATCH= $assert_match +--let _AG_ASSERT_COUNT= $assert_count +--let _AG_OUT= `SELECT CONCAT('$MYSQLTEST_VARDIR/tmp/_ag_', UUID())` +--let _AG_ASSERT_ONLY_AFTER= $assert_only_after + + +--perl + use strict; + use warnings; + my $file= $ENV{'_AG_ASSERT_FILE'}; + my $assert_select= $ENV{'_AG_ASSERT_SELECT'}; + my $assert_match= $ENV{'_AG_ASSERT_MATCH'}; + my $assert_count= $ENV{'_AG_ASSERT_COUNT'}; + my $assert_only_after= $ENV{'_AG_ASSERT_ONLY_AFTER'}; + my $out= $ENV{'_AG_OUT'}; + + my $result= ''; + my $count= 0; + open(FILE, "$file") or die("Error $? opening $file: $!\n"); + while () { + my $line = $_; + if ($assert_only_after && $line =~ /$assert_only_after/) { + $result = ""; + $count = 0; + } + if ($line =~ /$assert_select/) { + if ($assert_count ne '') { + $count++; + } + else { + $result .= $line; + } + } + } + close(FILE) or die("Error $? closing $file: $!"); + open OUT, "> $out" or die("Error $? opening $out: $!"); + if ($assert_count ne '' && ($count != $assert_count)) { + print OUT ($count) or die("Error $? writing $out: $!"); + } + elsif ($assert_count eq '' && $result !~ /$assert_match/) { + print OUT ($result) or die("Error $? writing $out: $!"); + } + else { + print OUT ("assert_grep.inc ok"); + } + close OUT or die("Error $? closing $out: $!"); +EOF + + +--let $_ag_outcome= `SELECT LOAD_FILE('$_AG_OUT')` +if ($_ag_outcome != 'assert_grep.inc ok') +{ + --source include/show_rpl_debug_info.inc + --echo include/assert_grep.inc failed! + --echo assert_text: '$assert_text' + --echo assert_file: '$assert_file' + --echo assert_select: '$assert_select' + --echo assert_match: '$assert_match' + --echo assert_count: '$assert_count' + --echo assert_only_after: '$assert_only_after' + if ($assert_match != '') + { + --echo matching lines: '$_ag_outcome' + } + if ($assert_count != '') + { + --echo number of matching lines: $_ag_outcome + } + --die assert_grep.inc failed. +} + + +--let $include_filename= include/assert_grep.inc [$assert_text] +--source include/end_include_file.inc diff --git a/mysql-test/include/rpl_init.inc b/mysql-test/include/rpl_init.inc index 2abfd901b03..820bc8e9016 100644 --- a/mysql-test/include/rpl_init.inc +++ b/mysql-test/include/rpl_init.inc @@ -43,6 +43,7 @@ # # [--let $rpl_server_count= 7] # --let $rpl_topology= 1->2->3->1->4, 2->5, 6->7 +# [--let $rpl_extra_connections_per_server= 1] # [--let $rpl_check_server_ids= 1] # [--let $rpl_skip_change_master= 1] # [--let $rpl_skip_start_slave= 1] @@ -65,6 +66,12 @@ # want to specify the empty topology (no server replicates at # all), you have to set $rpl_topology=none. # +# $rpl_extra_connections_per_server +# By default, this script creates connections server_N and +# server_N_1. If you can set this variable to a number, the +# script creates: +# server_N, server_N_1, ..., server_N_$rpl_extra_connections_per_server +# # $rpl_check_server_ids # If $rpl_check_server_ids is set, this script checks that the # @@server_id of all servers are different. This is normally @@ -139,8 +146,17 @@ if (!$SERVER_MYPORT_4) # Check that $rpl_server_count is set if (!$rpl_server_count) { - --let $_compute_rpl_server_count= `SELECT REPLACE('$rpl_topology', '->', ',')` - --let $rpl_server_count= `SELECT GREATEST($_compute_rpl_server_count)` + --let $rpl_server_count= `SELECT REPLACE('$rpl_topology', '->', ',')` + if (`SELECT LOCATE(',', '$rpl_server_count')`) + { + --let $rpl_server_count= `SELECT GREATEST($rpl_server_count)` + } +} + +--let $_rpl_extra_connections_per_server= $rpl_extra_connections_per_server +if ($_rpl_extra_connections_per_server == '') +{ + --let $_rpl_extra_connections_per_server= 1 } @@ -159,15 +175,20 @@ if (!$rpl_debug) # Create two connections to each server; reset master/slave, select # database, set autoinc variables. --let $_rpl_server= $rpl_server_count ---let $_rpl_one= _1 +--let $underscore= _ while ($_rpl_server) { # Connect. --let $rpl_server_number= $_rpl_server --let $rpl_connection_name= server_$_rpl_server --source include/rpl_connect.inc - --let $rpl_connection_name= server_$_rpl_server$_rpl_one - --source include/rpl_connect.inc + --let $_rpl_connection_number= 1 + while ($_rpl_connection_number <= $_rpl_extra_connections_per_server) + { + --let $rpl_connection_name= server_$_rpl_server$underscore$_rpl_connection_number + --source include/rpl_connect.inc + --inc $_rpl_connection_number + } # Configure server. --let $rpl_connection_name= server_$_rpl_server diff --git a/mysql-test/include/rpl_reconnect.inc b/mysql-test/include/rpl_reconnect.inc index cdbbd0a1bf1..673f382bac0 100644 --- a/mysql-test/include/rpl_reconnect.inc +++ b/mysql-test/include/rpl_reconnect.inc @@ -12,6 +12,7 @@ # ==== Usage ==== # # --let $rpl_server_number= N +# [--let $rpl_extra_connections_per_server= 1] # [--let $rpl_debug= 1] # --source include/rpl_reconnect.inc # @@ -21,7 +22,7 @@ # master server, 2 the slave server, 3 the 3rd server, and so on. # Cf. include/rpl_init.inc # -# $rpl_debug +# $rpl_extra_connections_per_server, $rpl_debug # See include/rpl_init.inc --let $include_filename= rpl_reconnect.inc @@ -32,6 +33,11 @@ if (!$rpl_server_number) --die ERROR IN TEST: you must set $rpl_server_number before you source rpl_connect.inc } +if ($_rpl_extra_connections_per_server == '') +{ + --let $_rpl_extra_connections_per_server= 1 +} + if ($rpl_debug) { @@ -72,10 +78,14 @@ if (!$_rpl_server_number) --source include/rpl_connection.inc --enable_reconnect ---let $_rpl_one= _1 ---let $rpl_connection_name= server_$rpl_server_number$_rpl_one ---source include/rpl_connection.inc ---enable_reconnect +--let $_rpl_connection_number= 1 +while ($_rpl_connection_number <= $_rpl_extra_connections_per_server) +{ + --let $rpl_connection_name= server_$rpl_server_number$underscore$_rpl_connection_number + --source include/rpl_connection.inc + --enable_reconnect + --inc $_rpl_connection_number +} if ($rpl_debug) { @@ -122,10 +132,15 @@ if (!$_rpl_server_number) --source include/wait_until_connected_again.inc --disable_reconnect ---let $rpl_connection_name= server_$rpl_server_number$_rpl_one ---source include/rpl_connection.inc ---source include/wait_until_connected_again.inc ---disable_reconnect +--let $_rpl_connection_number= 1 +while ($_rpl_connection_number <= $_rpl_extra_connections_per_server) +{ + --let $rpl_connection_name= server_$rpl_server_number$underscore$_rpl_connection_number + --source include/rpl_connection.inc + --source include/wait_until_connected_again.inc + --disable_reconnect + --inc $_rpl_connection_number +} --let $include_filename= rpl_reconnect.inc diff --git a/mysql-test/include/start_slave_sql.inc b/mysql-test/include/start_slave_sql.inc new file mode 100644 index 00000000000..9cb66a2eb40 --- /dev/null +++ b/mysql-test/include/start_slave_sql.inc @@ -0,0 +1,39 @@ +# ==== Purpose ==== +# +# Issues START SLAVE SQL_THREAD on the current connection. Then waits +# until the SQL thread has started, or until a timeout is reached. +# +# Please use this instead of 'START SLAVE SQL_THREAD', to reduce the +# risk of races in test cases. +# +# +# ==== Usage ==== +# +# [--let $slave_timeout= NUMBER] +# [--let $rpl_debug= 1] +# --source include/start_slave_sql.inc +# +# Parameters: +# $slave_timeout +# See include/wait_for_slave_param.inc +# +# $rpl_debug +# See include/rpl_init.inc + + +--let $include_filename= start_slave_sql.inc +--source include/begin_include_file.inc + + +if (!$rpl_debug) +{ + --disable_query_log +} + + +START SLAVE SQL_THREAD; +--source include/wait_for_slave_sql_to_start.inc + + +--let $include_filename= start_slave_sql.inc +--source include/end_include_file.inc diff --git a/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result b/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result new file mode 100644 index 00000000000..c601c9a4169 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result @@ -0,0 +1,15 @@ +include/master-slave.inc +[connection master] +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); +CALL mtr.add_suppression("Disk is full writing"); +CALL mtr.add_suppression("Retry in 60 secs"); +include/stop_slave_sql.inc +SET @@GLOBAL.DEBUG= 'd,simulate_io_thd_wait_for_disk_space'; +INSERT INTO t1 VALUES(2); +include/wait_for_slave_param.inc [Slave_IO_State] +SET @@GLOBAL.DEBUG= '$debug_saved'; +include/assert_grep.inc [Found the disk full error message on the slave] +include/start_slave_sql.inc +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test b/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test new file mode 100644 index 00000000000..d0c74b94cd1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test @@ -0,0 +1,71 @@ +# ==== Purpose ==== +# +# Check that the execution of SHOW SLAVE STATUS command is not blocked when IO +# thread is blocked waiting for disk space. +# +# ==== Implementation ==== +# +# Simulate a scenario where IO thread is waiting for disk space while writing +# into the relay log. Execute SHOW SLAVE STATUS command after IO thread is +# blocked waiting for space. The command should not be blocked. +# +# ==== References ==== +# +# Bug#21753696: MAKE SHOW SLAVE STATUS NON BLOCKING IF IO THREAD WAITS FOR +# DISK SPACE +# Bug#20685029: SLAVE IO THREAD SHOULD STOP WHEN DISK IS FULL +# +############################################################################### +--source include/have_debug.inc +--source include/master-slave.inc + +# Generate events to be replicated to the slave +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); +--sync_slave_with_master + +# Those errors will only happen in the slave +CALL mtr.add_suppression("Disk is full writing"); +CALL mtr.add_suppression("Retry in 60 secs"); + +# Stop the SQL thread to avoid writing on disk +--source include/stop_slave_sql.inc + +# Set the debug option that will simulate disk full +--let $debug_saved= `SELECT @@GLOBAL.DEBUG` +SET @@GLOBAL.DEBUG= 'd,simulate_io_thd_wait_for_disk_space'; + +# Generate events to be replicated to the slave +--connection master +INSERT INTO t1 VALUES(2); + +--connection slave +# Wait until IO thread is queuing events from master +# Notice that this is performed by querying SHOW SLAVE STATUS +--let $slave_param= Slave_IO_State +--let $slave_param_value= Queueing master event to the relay log +--source include/wait_for_slave_param.inc + +# Get the relay log file name, also using SHOW SLAVE STATUS +--let $relay_log_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) + +# Restore the debug options to "simulate" freed space on disk +SET @@GLOBAL.DEBUG= '$debug_saved'; + +# There should be a message in the error log of the slave stating +# that it was waiting for space to write on the relay log. +--let $assert_file=$MYSQLTEST_VARDIR/log/mysqld.2.err +# Grep only after the message that the I/O thread has started +--let $assert_only_after= Slave I/O .* connected to master .*replication started in log .* at position +--let $assert_count= 1 +--let $assert_select=Disk is full writing .*$relay_log_file.* +--let $assert_text= Found the disk full error message on the slave +--source include/assert_grep.inc + +# Start the SQL thread to let the slave to sync and finish gracefully +--source include/start_slave_sql.inc + +# Cleanup +--connection master +DROP TABLE t1; +--source include/rpl_end.inc diff --git a/mysys/errors.c b/mysys/errors.c index ddd65836b30..942fd3230c0 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -109,6 +109,7 @@ void init_glob_errs() */ void wait_for_free_space(const char *filename, int errors) { + size_t time_to_sleep= MY_WAIT_FOR_USER_TO_FIX_PANIC; if (!(errors % MY_WAIT_GIVE_USER_A_MESSAGE)) { my_printf_warning(EE(EE_DISK_FULL), @@ -119,10 +120,14 @@ void wait_for_free_space(const char *filename, int errors) } DBUG_EXECUTE_IF("simulate_no_free_space_error", { - (void) sleep(1); - return; + time_to_sleep= 1; }); - (void) sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC); + DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", + { + time_to_sleep= 1; + }); + + (void) sleep(time_to_sleep); } const char **get_global_errmsgs() diff --git a/mysys/my_write.c b/mysys/my_write.c index ef15e9a55b6..2e68a4dcff3 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags) { size_t writtenbytes, written; uint errors; + size_t ToWriteCount; DBUG_ENTER("my_write"); DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d", Filedes, Buffer, (ulong) Count, MyFlags)); @@ -37,11 +38,14 @@ size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags) { DBUG_SET("+d,simulate_file_write_error");}); for (;;) { + ToWriteCount= Count; + DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", { ToWriteCount= 1; }); #ifdef _WIN32 - writtenbytes= my_win_write(Filedes, Buffer, Count); + writtenbytes= my_win_write(Filedes, Buffer, ToWriteCount); #else - writtenbytes= write(Filedes, Buffer, Count); + writtenbytes= write(Filedes, Buffer, ToWriteCount); #endif + DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", { errno= ENOSPC; }); DBUG_EXECUTE_IF("simulate_file_write_error", { errno= ENOSPC; diff --git a/sql/log.cc b/sql/log.cc index 9e34532f1ac..eab9a118147 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,6 +37,7 @@ #include "log_event.h" // Query_log_event #include "rpl_filter.h" #include "rpl_rli.h" +#include "rpl_mi.h" #include "sql_audit.h" #include "sql_show.h" @@ -4377,13 +4378,22 @@ end: } -bool MYSQL_BIN_LOG::append(Log_event* ev) +#ifdef HAVE_REPLICATION +bool MYSQL_BIN_LOG::append(Log_event* ev, Master_info *mi) { bool error = 0; + mysql_mutex_assert_owner(&mi->data_lock); mysql_mutex_lock(&LOCK_log); DBUG_ENTER("MYSQL_BIN_LOG::append"); DBUG_ASSERT(log_file.type == SEQ_READ_APPEND); + /* + Release data_lock by holding LOCK_log, while writing into the relay log. + If slave IO thread waits here for free space, we don't want + SHOW SLAVE STATUS to hang on mi->data_lock. Note LOCK_log mutex is + sufficient to block SQL thread when IO thread is updating relay log here. + */ + mysql_mutex_unlock(&mi->data_lock); /* Log_event::write() is smart enough to use my_b_write() or my_b_append() depending on the kind of cache we have. @@ -4398,24 +4408,50 @@ bool MYSQL_BIN_LOG::append(Log_event* ev) if (flush_and_sync(0)) goto err; if ((uint) my_b_append_tell(&log_file) > max_size) + { + /* + If rotation is required we must acquire data_lock to protect + description_event from clients executing FLUSH LOGS in parallel. + In order do that we must release the existing LOCK_log so that we + get it once again in proper locking order to avoid dead locks. + i.e data_lock , LOCK_log. + */ + mysql_mutex_unlock(&LOCK_log); + mysql_mutex_lock(&mi->data_lock); + mysql_mutex_lock(&LOCK_log); error= new_file_without_locking(); + /* + After rotation release data_lock, we need the LOCK_log till we signal + the updation. + */ + mysql_mutex_unlock(&mi->data_lock); + } err: - mysql_mutex_unlock(&LOCK_log); signal_update(); // Safe as we don't call close + mysql_mutex_unlock(&LOCK_log); + mysql_mutex_lock(&mi->data_lock); DBUG_RETURN(error); } -bool MYSQL_BIN_LOG::appendv(const char* buf, uint len,...) +bool MYSQL_BIN_LOG::appendv(Master_info* mi, const char* buf, uint len,...) { bool error= 0; DBUG_ENTER("MYSQL_BIN_LOG::appendv"); va_list(args); va_start(args,len); + mysql_mutex_assert_owner(&mi->data_lock); + mysql_mutex_lock(&LOCK_log); DBUG_ASSERT(log_file.type == SEQ_READ_APPEND); - mysql_mutex_assert_owner(&LOCK_log); + /* + Release data_lock by holding LOCK_log, while writing into the relay log. + If slave IO thread waits here for free space, we don't want + SHOW SLAVE STATUS to hang on mi->data_lock. Note LOCK_log mutex is + sufficient to block SQL thread when IO thread is updating relay log here. + */ + mysql_mutex_unlock(&mi->data_lock); do { if (my_b_append(&log_file,(uchar*) buf,len)) @@ -4428,13 +4464,34 @@ bool MYSQL_BIN_LOG::appendv(const char* buf, uint len,...) DBUG_PRINT("info",("max_size: %lu",max_size)); if (flush_and_sync(0)) goto err; - if ((uint) my_b_append_tell(&log_file) > max_size) + if ((uint) my_b_append_tell(&log_file) > + DBUG_EVALUATE_IF("rotate_slave_debug_group", 500, max_size)) + { + /* + If rotation is required we must acquire data_lock to protect + description_event from clients executing FLUSH LOGS in parallel. + In order do that we must release the existing LOCK_log so that we + get it once again in proper locking order to avoid dead locks. + i.e data_lock , LOCK_log. + */ + mysql_mutex_unlock(&LOCK_log); + mysql_mutex_lock(&mi->data_lock); + mysql_mutex_lock(&LOCK_log); error= new_file_without_locking(); + /* + After rotation release data_lock, we need the LOCK_log till we signal + the updation. + */ + mysql_mutex_unlock(&mi->data_lock); + } err: if (!error) signal_update(); + mysql_mutex_unlock(&LOCK_log); + mysql_mutex_lock(&mi->data_lock); DBUG_RETURN(error); } +#endif bool MYSQL_BIN_LOG::flush_and_sync(bool *synced) { diff --git a/sql/log.h b/sql/log.h index 1fc13afe7d1..7d1c3161ac2 100644 --- a/sql/log.h +++ b/sql/log.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include "handler.h" /* my_xid */ class Relay_log_info; +class Master_info; class Format_description_log_event; @@ -454,8 +455,8 @@ public: v stands for vector invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0) */ - bool appendv(const char* buf,uint len,...); - bool append(Log_event* ev); + bool appendv(Master_info* mi, const char* buf,uint len,...); + bool append(Log_event* ev, Master_info* mi); void make_log_name(char* buf, const char* log_ident); bool is_active(const char* log_file_name); diff --git a/sql/slave.cc b/sql/slave.cc index d97a9cdf6e9..31037c453d3 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1660,7 +1660,7 @@ Waiting for the slave SQL thread to free enough relay log space"); #endif if (rli->sql_force_rotate_relay) { - rotate_relay_log(rli->mi); + rotate_relay_log(rli->mi, true/*need_data_lock=true*/); rli->sql_force_rotate_relay= false; } @@ -1705,7 +1705,7 @@ static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) if (likely((bool)ev)) { ev->server_id= 0; // don't be ignored by slave SQL thread - if (unlikely(rli->relay_log.append(ev))) + if (unlikely(rli->relay_log.append(ev, mi))) mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), "failed to write a Rotate event" @@ -3605,7 +3605,7 @@ static int process_io_create_file(Master_info* mi, Create_file_log_event* cev) break; Execute_load_log_event xev(thd,0,0); xev.log_pos = cev->log_pos; - if (unlikely(mi->rli.relay_log.append(&xev))) + if (unlikely(mi->rli.relay_log.append(&xev, mi))) { mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), @@ -3619,7 +3619,7 @@ static int process_io_create_file(Master_info* mi, Create_file_log_event* cev) { cev->block = net->read_pos; cev->block_len = num_bytes; - if (unlikely(mi->rli.relay_log.append(cev))) + if (unlikely(mi->rli.relay_log.append(cev, mi))) { mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), @@ -3634,7 +3634,7 @@ static int process_io_create_file(Master_info* mi, Create_file_log_event* cev) aev.block = net->read_pos; aev.block_len = num_bytes; aev.log_pos = cev->log_pos; - if (unlikely(mi->rli.relay_log.append(&aev))) + if (unlikely(mi->rli.relay_log.append(&aev, mi))) { mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), @@ -3713,7 +3713,7 @@ static int process_io_rotate(Master_info *mi, Rotate_log_event *rev) Rotate the relay log makes binlog format detection easier (at next slave start or mysqlbinlog) */ - DBUG_RETURN(rotate_relay_log(mi) /* will take the right mutexes */); + DBUG_RETURN(rotate_relay_log(mi, false/*need_data_lock=false*/)); } /* @@ -3819,7 +3819,7 @@ static int queue_binlog_ver_1_event(Master_info *mi, const char *buf, Log_event::Log_event(const char* buf...) in log_event.cc). */ ev->log_pos+= event_len; /* make log_pos be the pos of the end of the event */ - if (unlikely(rli->relay_log.append(ev))) + if (unlikely(rli->relay_log.append(ev, mi))) { delete ev; mysql_mutex_unlock(&mi->data_lock); @@ -3875,7 +3875,7 @@ static int queue_binlog_ver_3_event(Master_info *mi, const char *buf, inc_pos= event_len; break; } - if (unlikely(rli->relay_log.append(ev))) + if (unlikely(rli->relay_log.append(ev, mi))) { delete ev; mysql_mutex_unlock(&mi->data_lock); @@ -4083,7 +4083,6 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) direct master (an unsupported, useless setup!). */ - mysql_mutex_lock(log_lock); s_id= uint4korr(buf + SERVER_ID_OFFSET); if ((s_id == ::server_id && !mi->rli.replicate_same_server_id) || /* @@ -4116,6 +4115,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) IGNORE_SERVER_IDS it increments mi->master_log_pos as well as rli->group_relay_log_pos. */ + mysql_mutex_lock(log_lock); if (!(s_id == ::server_id && !mi->rli.replicate_same_server_id) || (buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT && buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT && @@ -4127,13 +4127,14 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) rli->ign_master_log_pos_end= mi->master_log_pos; } rli->relay_log.signal_update(); // the slave SQL thread needs to re-check + mysql_mutex_unlock(log_lock); DBUG_PRINT("info", ("master_log_pos: %lu, event originating from %u server, ignored", (ulong) mi->master_log_pos, uint4korr(buf + SERVER_ID_OFFSET))); } else { /* write the event to the relay log */ - if (likely(!(rli->relay_log.appendv(buf,event_len,0)))) + if (likely(!(rli->relay_log.appendv(mi, buf,event_len,0)))) { mi->master_log_pos+= inc_pos; DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); @@ -4143,9 +4144,10 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) { error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE; } + mysql_mutex_lock(log_lock); rli->ign_master_log_name_end[0]= 0; // last event is not ignored + mysql_mutex_unlock(log_lock); } - mysql_mutex_unlock(log_lock); skip_relay_logging: @@ -5005,11 +5007,21 @@ err: locks; here we don't, so this function is mainly taking locks). Returns nothing as we cannot catch any error (MYSQL_BIN_LOG::new_file() is void). + + @param mi Master_info for the IO thread. + @param need_data_lock If true, mi->data_lock will be acquired otherwise, + mi->data_lock must be held by the caller. */ -int rotate_relay_log(Master_info* mi) +int rotate_relay_log(Master_info* mi, bool need_data_lock) { DBUG_ENTER("rotate_relay_log"); + if (need_data_lock) + mysql_mutex_lock(&mi->data_lock); + else + { + mysql_mutex_assert_owner(&mi->data_lock); + } Relay_log_info* rli= &mi->rli; int error= 0; @@ -5044,6 +5056,8 @@ int rotate_relay_log(Master_info* mi) */ rli->relay_log.harvest_bytes_written(&rli->log_space_total); end: + if (need_data_lock) + mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(error); } diff --git a/sql/slave.h b/sql/slave.h index 0374a5d27ae..0cf8adb0315 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -205,7 +205,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, const char** errmsg); void set_slave_thread_options(THD* thd); void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli); -int rotate_relay_log(Master_info* mi); +int rotate_relay_log(Master_info* mi, bool need_data_lock); int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli); pthread_handler_t handle_slave_io(void *arg); diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index 40e350c4ddd..f24f31b6399 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -157,7 +157,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long options, { #ifdef HAVE_REPLICATION mysql_mutex_lock(&LOCK_active_mi); - if (rotate_relay_log(active_mi)) + if (rotate_relay_log(active_mi, true/*need_data_lock=true*/)) *write_to_binlog= -1; mysql_mutex_unlock(&LOCK_active_mi); #endif -- cgit v1.2.1 From 32d6db3bfa00e437fbd232b80b73b82a0d30c4ae Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Tue, 1 Mar 2016 13:05:14 +0530 Subject: Bug#19920049 - MYSQLD_MULTI MISLEADING WHEN MY_PRINT_DEFAULTS IS NOT FOUND DESCRIPTION =========== If script mysqld_multi and utility my_print_defaults are in the same folder (not included in $PATH) and the former is made to run, it complaints that the mysqld binary is absent eventhough the binary exists. ANALYSIS ======== We've a subroutine my_which() mimicking the behaviour of POSIX "which" command. Its current behaviour is to check for a given argument as follows: - Step 1: Assume the argument to be a command having full fledged absolute path. If it exists "as-is", return the argument (which will be pathname), else proceed to Step 2. - Step 2: Assume the argument to be a plain command with no aboslute path. Try locating it in all of the paths (mentioned in $PATH) one by one. If found return the pathname. If found nowhere, return NULL. Currently when my_which(my_print_defaults) is called, it returns from Step 1 (since utlity exists in current folder) and doesn't proceed to Step 2. This is wrong since the returned value is same as the argument i.e. 'my_print_default' which defies the purpose of this subroutine whose job is to return a pathname either in Step 1 or Step 2. Later when the utility is executed in subroutine defaults_for_group(), it evaluates to NULL and returns the same. This is because the plain command 'my_print_defaults {options} ...' would execute properly only if my_print_defaults exists in one of the paths (in $PATH). In such a case, in the course of the flow it looks onto the variable $mysqld_found which comes out to be NULL and hence ethe error. In this case, call to my_which should fail resulting in script being aborted and thus avoiding this mess. FIX === This utility my_print_defaults should be tested only in Step 2 since it does not have an absolute path. Thus added a condition in Step 1 so that is gets executed iff not called for my_print_defaults thus bypassing it to proceed to Step 2 where the check is made for various paths (in $PATH) --- scripts/mysqld_multi.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index bb218a9980b..d9ea6a117d2 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public @@ -596,7 +596,11 @@ sub my_which my ($command) = @_; my (@paths, $path); - return $command if (-f $command && -x $command); + # If the argument is not 'my_print_defaults' then it would be of the format + # / + return $command if ($command ne 'my_print_defaults' && -f $command && + -x $command); + @paths = split(':', $ENV{'PATH'}); foreach $path (@paths) { -- cgit v1.2.1 From 767bab4abe7666ee861984bc74ce87200ba23b5d Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Thu, 3 Mar 2016 06:42:12 +0530 Subject: Bug #18740222: CRASH IN GET_INTERVAL_INFO WITH WEIRDO INTERVALS ISSUE: ------ Some string functions return one or a combination of the parameters as their result. Here the resultant string's charset could be incorrectly set to that of the chosen parameter. This results in incorrect behavior when an ascii string is expected. SOLUTION: --------- Since an ascii string is expected, val_str_ascii should explicitly convert the string. Part of the fix is a backport of Bug#22340858 for mysql-5.5 and mysql-5.6. --- sql/item.cc | 17 +++++++++-------- sql/item_geofunc.cc | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index c482f0e1a04..f4917448dda 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -227,9 +227,6 @@ bool Item::val_bool() */ String *Item::val_str_ascii(String *str) { - if (!(collation.collation->state & MY_CS_NONASCII)) - return val_str(str); - DBUG_ASSERT(str != &str_value); uint errors; @@ -237,11 +234,15 @@ String *Item::val_str_ascii(String *str) if (!res) return 0; - if ((null_value= str->copy(res->ptr(), res->length(), - collation.collation, &my_charset_latin1, - &errors))) - return 0; - + if (!(res->charset()->state & MY_CS_NONASCII)) + str= res; + else + { + if ((null_value= str->copy(res->ptr(), res->length(), collation.collation, + &my_charset_latin1, &errors))) + return 0; + } + return str; } diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 621ddcb1a30..983491211c3 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -179,7 +179,7 @@ String *Item_func_geometry_type::val_str_ascii(String *str) /* String will not move */ str->copy(geom->get_class_info()->m_name.str, geom->get_class_info()->m_name.length, - default_charset()); + &my_charset_latin1); return str; } -- cgit v1.2.1 From 5102a7f278460027fc0ff8d47f2d3f4d72deeacd Mon Sep 17 00:00:00 2001 From: Sujatha Sivakumar Date: Mon, 7 Mar 2016 18:19:26 +0530 Subject: Bug#20685029: SLAVE IO THREAD SHOULD STOP WHEN DISK IS FULL Bug#21753696: MAKE SHOW SLAVE STATUS NON BLOCKING IF IO THREAD WAITS FOR DISK SPACE Fixing a post push test issue. --- mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test b/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test index d0c74b94cd1..9eed1089e6d 100644 --- a/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test +++ b/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test @@ -17,6 +17,9 @@ # ############################################################################### --source include/have_debug.inc +# Inorder to grep a specific error pattern in error log a fresh error log +# needs to be generated. +--source include/force_restart.inc --source include/master-slave.inc # Generate events to be replicated to the slave -- cgit v1.2.1 From 6608f84158d3561ef2c2f12a7136aa05cc39d7b4 Mon Sep 17 00:00:00 2001 From: Nisha Gopalakrishnan Date: Mon, 14 Mar 2016 15:20:21 +0530 Subject: BUG#22594514: HANDLE_FATAL_SIGNAL (SIG=11) IN UNIQUE::~UNIQUE | SQL/UNIQUES.CC:355 Analysis ======== Enabling the sort_buffer_size with a large value can cause operations utilizing the sort buffer like DELETE as mentioned in the bug report to fail. 5.5 and 5.6 versions reports OOM error while in 5.7+, the server crashes. While initializing the mem_root for the sort buffer tree, the block size for the mem_root is determined from the 'sort_buffer_size' value. This unsigned long value is typecasted to unsigned int, hence it becomes zero. Further block_size computation while initializing the mem_root results in a very large block_size value. Hence while trying to allocate a block during the DELETE operation, an OOM error is reported. In case of 5.7+, the PFS instrumentation for memory allocation, overshoots the unsigned value and allocates a block of just one byte. While trying to free the block of the mem_root, the original block_size is used. This triggers the crash since the server tries to free unallocated memory. Fix: ==== In order to restrict usage of such unreasonable sort_buffer_size, the typecast of block size to 'unsigned int' is removed and hence reports OOM error across all versions for sizes exceeding unsigned int range. --- include/my_tree.h | 4 ++-- mysys/tree.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/my_tree.h b/include/my_tree.h index 451e2b72b3c..4457bb1bc85 100644 --- a/include/my_tree.h +++ b/include/my_tree.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -62,7 +62,7 @@ typedef struct st_tree { } TREE; /* Functions on whole tree */ -void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit, +void init_tree(TREE *tree, size_t default_alloc_size, ulong memory_limit, int size, qsort_cmp2 compare, my_bool with_delete, tree_element_free free_element, void *custom_arg); void delete_tree(TREE*); diff --git a/mysys/tree.c b/mysys/tree.c index c5bf3681a35..3f7360de40a 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -83,7 +83,7 @@ static void rb_delete_fixup(TREE *tree,TREE_ELEMENT ***parent); static int test_rb_tree(TREE_ELEMENT *element); #endif -void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit, +void init_tree(TREE *tree, size_t default_alloc_size, ulong memory_limit, int size, qsort_cmp2 compare, my_bool with_delete, tree_element_free free_element, void *custom_arg) { @@ -127,7 +127,7 @@ void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit, } if (!(tree->with_delete=with_delete)) { - init_alloc_root(&tree->mem_root, (uint) default_alloc_size, 0); + init_alloc_root(&tree->mem_root, default_alloc_size, 0); tree->mem_root.min_malloc=(sizeof(TREE_ELEMENT)+tree->size_of_element); } DBUG_VOID_RETURN; -- cgit v1.2.1 -- cgit v1.2.1 -- cgit v1.2.1 From b4afc6a7a94a60980eac15dad385cd29ad1dd816 Mon Sep 17 00:00:00 2001 From: "Sreedhar.S" Date: Thu, 14 Apr 2016 14:18:23 +0530 Subject: Fix for Bugs#14583183 and 19949163 --- packaging/WiX/mysql_server.wxs.in | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packaging/WiX/mysql_server.wxs.in b/packaging/WiX/mysql_server.wxs.in index 1802baedf3b..10b6f892a2e 100644 --- a/packaging/WiX/mysql_server.wxs.in +++ b/packaging/WiX/mysql_server.wxs.in @@ -2,7 +2,7 @@ xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"> - + + + + Installed + Date: Mon, 11 Apr 2016 11:41:47 +0530 Subject: Bug#22897202: RPL_IO_THD_WAIT_FOR_DISK_SPACE HAS OCCASIONAL FAILURES Analysis: ========= Test script is not ensuring that "assert_grep.inc" should be called only after 'Disk is full' error is written to the error log. Test checks for "Queueing master event to the relay log" state. But this state is set before invoking 'queue_event'. Actual 'Disk is full' error happens at a very lower level. It can happen that we might even reset the debug point before even the actual disk full simulation occurs and the "Disk is full" message will never appear in the error log. In order to guarentee that we must have some mechanism where in after we write "Disk is full" error messge into the error log we must signal the test to execute SSS and then reset the debug point. So that test is deterministic. Fix: === Added debug sync point to make script deterministic. --- mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result | 2 +- mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test | 11 ++++------- mysys/errors.c | 3 ++- sql/log.cc | 8 ++++++++ 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result b/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result index c601c9a4169..b11ad4f53bd 100644 --- a/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result +++ b/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result @@ -7,7 +7,7 @@ CALL mtr.add_suppression("Retry in 60 secs"); include/stop_slave_sql.inc SET @@GLOBAL.DEBUG= 'd,simulate_io_thd_wait_for_disk_space'; INSERT INTO t1 VALUES(2); -include/wait_for_slave_param.inc [Slave_IO_State] +SET DEBUG_SYNC='now WAIT_FOR parked'; SET @@GLOBAL.DEBUG= '$debug_saved'; include/assert_grep.inc [Found the disk full error message on the slave] include/start_slave_sql.inc diff --git a/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test b/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test index 9eed1089e6d..6076be60ebc 100644 --- a/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test +++ b/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test @@ -42,16 +42,13 @@ SET @@GLOBAL.DEBUG= 'd,simulate_io_thd_wait_for_disk_space'; --connection master INSERT INTO t1 VALUES(2); ---connection slave -# Wait until IO thread is queuing events from master -# Notice that this is performed by querying SHOW SLAVE STATUS ---let $slave_param= Slave_IO_State ---let $slave_param_value= Queueing master event to the relay log ---source include/wait_for_slave_param.inc +--connection slave1 +SET DEBUG_SYNC='now WAIT_FOR parked'; -# Get the relay log file name, also using SHOW SLAVE STATUS +# Get the relay log file name using SHOW SLAVE STATUS --let $relay_log_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--connection slave # Restore the debug options to "simulate" freed space on disk SET @@GLOBAL.DEBUG= '$debug_saved'; diff --git a/mysys/errors.c b/mysys/errors.c index 942fd3230c0..b6064460535 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -15,7 +15,7 @@ #include "mysys_priv.h" #include "mysys_err.h" - +#include "m_string.h" #ifndef SHARED_LIBRARY const char *globerrs[GLOBERRS]= @@ -128,6 +128,7 @@ void wait_for_free_space(const char *filename, int errors) }); (void) sleep(time_to_sleep); + DEBUG_SYNC_C("disk_full_reached"); } const char **get_global_errmsgs() diff --git a/sql/log.cc b/sql/log.cc index eab9a118147..a7f05905514 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4452,6 +4452,14 @@ bool MYSQL_BIN_LOG::appendv(Master_info* mi, const char* buf, uint len,...) sufficient to block SQL thread when IO thread is updating relay log here. */ mysql_mutex_unlock(&mi->data_lock); + DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", + { + const char act[]= "disk_full_reached SIGNAL parked"; + DBUG_ASSERT(opt_debug_sync_timeout > 0); + DBUG_ASSERT(!debug_sync_set_action(current_thd, + STRING_WITH_LEN(act))); + };); + do { if (my_b_append(&log_file,(uchar*) buf,len)) -- cgit v1.2.1 From fbf44eed3c69dc15047ac2d40c09dd0d16993fb0 Mon Sep 17 00:00:00 2001 From: Karthik Kamath Date: Tue, 19 Apr 2016 14:49:27 +0530 Subject: BUG#22286421: NULL POINTER DEREFERENCE ANALYSIS: ========= A LEX_STRING structure pointer is processed during the validation of a stored program name. During this processing, there is a possibility of null pointer dereference. FIX: ==== check_routine_name() is invoked by the parser by supplying a non-empty string as the SP name. To avoid any potential calls to check_routine_name() with NULL value, a debug assert has been added to catch such cases. --- sql/sp_head.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 13d1b310599..992e7415f45 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -490,8 +490,9 @@ sp_name::init_qname(THD *thd) bool check_routine_name(LEX_STRING *ident) { - if (!ident || !ident->str || !ident->str[0] || - ident->str[ident->length-1] == ' ') + DBUG_ASSERT(ident != NULL && ident->str != NULL); + + if (!ident->str[0] || ident->str[ident->length-1] == ' ') { my_error(ER_SP_WRONG_NAME, MYF(0), ident->str); return TRUE; -- cgit v1.2.1 From 3b6f9aac02b126db57fa3e3f1873713438d0a950 Mon Sep 17 00:00:00 2001 From: Nisha Gopalakrishnan Date: Fri, 22 Apr 2016 10:25:16 +0530 Subject: BUG#23135731: INSERT WITH DUPLICATE KEY UPDATE REPORTS INCORRECT ERROR. Analysis ======== INSERT with DUPLICATE KEY UPDATE and REPLACE on a table where foreign key constraint is defined fails with an incorrect 'duplicate entry' error rather than foreign key constraint violation error. As part of the bug fix for BUG#22037930, a new flag 'HA_CHECK_FK_ERROR' was added while checking for non fatal errors to manage FK errors based on the 'IGNORE' flag. For INSERT with DUPLICATE KEY UPDATE and REPLACE queries, the foreign key constraint violation error was marked as non-fatal, even though IGNORE was not set. Hence it continued with the duplicate key processing resulting in an incorrect error. Fix: === Foreign key violation errors are treated as non fatal only when the IGNORE is not set in the above mentioned queries. Hence reports the appropriate foreign key violation error. --- mysql-test/r/insert.result | 15 +++++++++++++++ mysql-test/t/insert.test | 22 ++++++++++++++++++++++ sql/sql_insert.cc | 23 ++++++++++++++++------- 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index 1aa22349593..e840b95f1ba 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -724,3 +724,18 @@ ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (` UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3; ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)) DROP TABLE t2, t1; +# +# BUG#22037930: INSERT IGNORE FAILS TO IGNORE FOREIGN +# KEY CONSTRAINT +CREATE TABLE t1 (fld1 INT PRIMARY KEY) ENGINE= INNODB; +CREATE TABLE t2 (fld1 VARCHAR(10), fld2 INT NOT NULL, +CONSTRAINT fk FOREIGN KEY (fld2) REFERENCES t1(fld1)) ENGINE= INNODB; +# Without patch, reports incorrect error. +INSERT INTO t2 VALUES('abc', 2) ON DUPLICATE KEY UPDATE fld1= 'def'; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)) +REPLACE INTO t2 VALUES('abc', 2); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)) +INSERT IGNORE INTO t2 VALUES('abc', 2) ON DUPLICATE KEY UPDATE fld1= 'def'; +Warnings: +Warning 1452 `test`.`t2`, CONSTRAINT `fk` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`) +DROP TABLE t2, t1; diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index ea89872200c..94cf5d3b475 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -591,3 +591,25 @@ UPDATE t1, t2 SET t2.fld2= t2.fld2 + 3; UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3; DROP TABLE t2, t1; + + +--echo # +--echo # BUG#22037930: INSERT IGNORE FAILS TO IGNORE FOREIGN +--echo # KEY CONSTRAINT + +CREATE TABLE t1 (fld1 INT PRIMARY KEY) ENGINE= INNODB; + +CREATE TABLE t2 (fld1 VARCHAR(10), fld2 INT NOT NULL, +CONSTRAINT fk FOREIGN KEY (fld2) REFERENCES t1(fld1)) ENGINE= INNODB; + +--echo # Without patch, reports incorrect error. +--error ER_NO_REFERENCED_ROW_2 +INSERT INTO t2 VALUES('abc', 2) ON DUPLICATE KEY UPDATE fld1= 'def'; +--error ER_NO_REFERENCED_ROW_2 +REPLACE INTO t2 VALUES('abc', 2); + +--enable_warnings +INSERT IGNORE INTO t2 VALUES('abc', 2) ON DUPLICATE KEY UPDATE fld1= 'def'; +--disable_warnings + +DROP TABLE t2, t1; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a267108c847..dc7cb698476 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1521,16 +1521,25 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) insert_id_for_cur_row= table->file->insert_id_for_cur_row; else table->file->insert_id_for_cur_row= insert_id_for_cur_row; - bool is_duplicate_key_error; - if (table->file->is_fatal_error(error, HA_CHECK_DUP | HA_CHECK_FK_ERROR)) + + /* + If it is a FK constraint violation and 'ignore' flag is set, + report a warning instead of error. + */ + if (info->ignore && !table->file->is_fatal_error(error, + HA_CHECK_FK_ERROR)) + goto ok_or_after_trg_err; + + if (table->file->is_fatal_error(error, HA_CHECK_DUP)) goto err; - is_duplicate_key_error= table->file->is_fatal_error(error, 0); - if (!is_duplicate_key_error) + + if (!table->file->is_fatal_error(error, 0)) { /* - We come here when we had an ignorable error which is not a duplicate - key error. In this we ignore error if ignore flag is set, otherwise - report error as usual. We will not do any duplicate key processing. + We come here when we have an ignorable error which is not a duplicate + key error or FK error(Ex: Partition related errors). In this case we + ignore the error if ignore flag is set, otherwise report error as usual. + We will not do any duplicate key processing. */ if (info->ignore) goto ok_or_after_trg_err; /* Ignoring a not fatal error, return 0 */ -- cgit v1.2.1 From 672bbcd7411b20e87eca7845aceed81f361d6424 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 27 Apr 2016 16:13:14 +0200 Subject: MDEV-9973 : Do not set permissions for serviceaccount user (Win7 and later) This appears to break some installation, and it did not do anything useful anyway. --- win/packaging/extra.wxs.in | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in index 48d15cbf91c..8ee2909511b 100644 --- a/win/packaging/extra.wxs.in +++ b/win/packaging/extra.wxs.in @@ -542,17 +542,6 @@ Value="utf8" /> - - - 600)]]> - - - - - - -- cgit v1.2.1 From 6768f80c0b1f0b82c5addbe47ce712ded14d0d8c Mon Sep 17 00:00:00 2001 From: Harin Vadodaria Date: Fri, 29 Apr 2016 11:06:41 +0530 Subject: Bug#21973610 Post push fix : Fixing i_main.mysqlshow failure. --- client/mysqlshow.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 4d1df00c8fd..f1f8bdaf54b 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -655,7 +655,7 @@ list_table_status(MYSQL *mysql,const char *db,const char *wild) len= sizeof(query); len-= my_snprintf(query, len, "show table status from `%s`", db); if (wild && wild[0] && len) - strxnmov(query + strlen(query), len, " like '", wild, "'", NullS); + strxnmov(query + strlen(query), len - 1, " like '", wild, "'", NullS); if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) { fprintf(stderr,"%s: Cannot get status for db: %s, table: %s: %s\n", @@ -688,7 +688,7 @@ list_fields(MYSQL *mysql,const char *db,const char *table, const char *wild) { char query[NAME_LEN + 100]; - int len; + size_t len; MYSQL_RES *result; MYSQL_ROW row; ulong UNINIT_VAR(rows); @@ -718,7 +718,7 @@ list_fields(MYSQL *mysql,const char *db,const char *table, len-= my_snprintf(query, len, "show /*!32332 FULL */ columns from `%s`", table); if (wild && wild[0] && len) - strxnmov(query + strlen(query), len, " like '", wild, "'", NullS); + strxnmov(query + strlen(query), len - 1, " like '", wild, "'", NullS); if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) { fprintf(stderr,"%s: Cannot list columns in db: %s, table: %s: %s\n", -- cgit v1.2.1 From 964c4f070a7e96bf45979d8755beb10aa6e6617b Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 10 May 2016 19:13:06 +0400 Subject: MDEV-10052 Illegal mix of collations with DAYNAME(date_field)<>varchar_field --- mysql-test/r/locale.result | 28 ++++++++++++++++++++++++++++ mysql-test/t/locale.test | 19 +++++++++++++++++++ sql/item_timefunc.cc | 6 ++---- sql/sql_locale.h | 2 ++ 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/locale.result b/mysql-test/r/locale.result index 195468c4c12..6de1d0708ca 100644 --- a/mysql-test/r/locale.result +++ b/mysql-test/r/locale.result @@ -101,3 +101,31 @@ Februar SELECT monthname('2001-03-01'); monthname('2001-03-01') März +# +# MDEV-10052 Illegal mix of collations with DAYNAME(date_field)<>varchar_field +# +SET NAMES utf8; +CREATE TABLE t1 (c VARCHAR(8) CHARACTER SET latin1, d DATE); +INSERT INTO t1 VALUES ('test',now()); +Warnings: +Note 1265 Data truncated for column 'd' at row 1 +SET lc_time_names=ru_RU; +SELECT c FROM t1 WHERE DAYNAME(d)<>c; +ERROR HY000: Illegal mix of collations (utf8_general_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation '<>' +SELECT c FROM t1 WHERE MONTHNAME(d)<>c; +ERROR HY000: Illegal mix of collations (utf8_general_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation '<>' +SET lc_time_names=en_US; +SELECT c FROM t1 WHERE DAYNAME(d)<>c; +c +test +SELECT c FROM t1 WHERE MONTHNAME(d)<>c; +c +test +SET NAMES latin1; +SELECT c FROM t1 WHERE DAYNAME(d)<>c; +c +test +SELECT c FROM t1 WHERE MONTHNAME(d)<>c; +c +test +DROP TABLE t1; diff --git a/mysql-test/t/locale.test b/mysql-test/t/locale.test index 899d293545d..4944dc7a228 100644 --- a/mysql-test/t/locale.test +++ b/mysql-test/t/locale.test @@ -63,3 +63,22 @@ SET lc_time_names=de_AT; SELECT monthname('2001-01-01'); SELECT monthname('2001-02-01'); SELECT monthname('2001-03-01'); + +--echo # +--echo # MDEV-10052 Illegal mix of collations with DAYNAME(date_field)<>varchar_field +--echo # +SET NAMES utf8; +CREATE TABLE t1 (c VARCHAR(8) CHARACTER SET latin1, d DATE); +INSERT INTO t1 VALUES ('test',now()); +SET lc_time_names=ru_RU; +--error ER_CANT_AGGREGATE_2COLLATIONS +SELECT c FROM t1 WHERE DAYNAME(d)<>c; +--error ER_CANT_AGGREGATE_2COLLATIONS +SELECT c FROM t1 WHERE MONTHNAME(d)<>c; +SET lc_time_names=en_US; +SELECT c FROM t1 WHERE DAYNAME(d)<>c; +SELECT c FROM t1 WHERE MONTHNAME(d)<>c; +SET NAMES latin1; +SELECT c FROM t1 WHERE DAYNAME(d)<>c; +SELECT c FROM t1 WHERE MONTHNAME(d)<>c; +DROP TABLE t1; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 873dcdac4b9..28e93683422 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -935,9 +935,8 @@ void Item_func_monthname::fix_length_and_dec() { THD* thd= current_thd; CHARSET_INFO *cs= thd->variables.collation_connection; - uint32 repertoire= my_charset_repertoire(cs); locale= thd->variables.lc_time_names; - collation.set(cs, DERIVATION_COERCIBLE, repertoire); + collation.set(cs, DERIVATION_COERCIBLE, locale->repertoire()); decimals=0; max_length= locale->max_month_name_length * collation.collation->mbmaxlen; maybe_null=1; @@ -1082,9 +1081,8 @@ void Item_func_dayname::fix_length_and_dec() { THD* thd= current_thd; CHARSET_INFO *cs= thd->variables.collation_connection; - uint32 repertoire= my_charset_repertoire(cs); locale= thd->variables.lc_time_names; - collation.set(cs, DERIVATION_COERCIBLE, repertoire); + collation.set(cs, DERIVATION_COERCIBLE, locale->repertoire()); decimals=0; max_length= locale->max_day_name_length * collation.collation->mbmaxlen; maybe_null=1; diff --git a/sql/sql_locale.h b/sql/sql_locale.h index 8357a9ecba4..8559bb55cd9 100644 --- a/sql/sql_locale.h +++ b/sql/sql_locale.h @@ -61,6 +61,8 @@ public: grouping(grouping_par), errmsgs(errmsgs_par) {} + uint repertoire() const + { return is_ascii ? MY_REPERTOIRE_ASCII : MY_REPERTOIRE_EXTENDED; } }; /* Exported variables */ -- cgit v1.2.1 From 9d72fb4af0d87f6a69a3ccb9202b4029acf2bd56 Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Mon, 16 May 2016 13:46:49 +0530 Subject: Bug#21977380 - POSSIBLE BUFFER OVERFLOW ISSUES DESCRIPTION =========== Buffer overflow is reported in a lot of code sections spanning across server, client programs, Regex libraries etc. If not handled appropriately, they can cause abnormal behaviour. ANALYSIS ======== The reported casea are the ones which are likely to result in SEGFAULT, MEMORY LEAK etc. FIX === - sprintf() has been replaced by my_snprintf() to avoid buffer overflow. - my_free() is done after checking if the pointer isn't NULL already and setting it to NULL thereafter at few places. - Buffer is ensured to be large enough to hold the data. - 'unsigned int' (aka 'uint') is replaced with 'size_t' to avoid wraparound. - Memory is freed (if not done so) after its alloced and used. - Inserted assert() for size check in InnoDb memcached code (from 5.6 onwards) - Other minor changes (cherry picked from commit 3487e20959c940cbd24429afa795ebfc8a01e94f) --- client/mysqlcheck.c | 42 ++++++++++++++++++++++++++---------------- client/mysqldump.c | 49 +++++++++++++++++++++++++++---------------------- client/mysqlshow.c | 36 +++++++++++++++++++----------------- extra/yassl/src/log.cpp | 4 ++-- regex/split.c | 4 ++++ 5 files changed, 78 insertions(+), 57 deletions(-) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index a564e871281..55b941e7f1a 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -213,13 +213,13 @@ static int process_selected_tables(char *db, char **table_names, int tables); static int process_all_tables_in_db(char *database); static int process_one_db(char *database); static int use_db(char *database); -static int handle_request_for_tables(char *tables, uint length); +static int handle_request_for_tables(char *tables, size_t length); static int dbConnect(char *host, char *user,char *passwd); static void dbDisconnect(char *host); static void DBerror(MYSQL *mysql, const char *when); static void safe_exit(int error); static void print_result(); -static uint fixed_name_length(const char *name); +static size_t fixed_name_length(const char *name); static char *fix_table_name(char *dest, char *src); int what_to_do = 0; @@ -486,7 +486,7 @@ static int process_selected_tables(char *db, char **table_names, int tables) *end++= ','; } *--end = 0; - handle_request_for_tables(table_names_comma_sep + 1, (uint) (tot_length - 1)); + handle_request_for_tables(table_names_comma_sep + 1, tot_length - 1); my_free(table_names_comma_sep); } else @@ -496,10 +496,10 @@ static int process_selected_tables(char *db, char **table_names, int tables) } /* process_selected_tables */ -static uint fixed_name_length(const char *name) +static size_t fixed_name_length(const char *name) { const char *p; - uint extra_length= 2; /* count the first/last backticks */ + size_t extra_length= 2; /* count the first/last backticks */ for (p= name; *p; p++) { @@ -508,7 +508,7 @@ static uint fixed_name_length(const char *name) else if (*p == '.') extra_length+= 2; } - return (uint) ((p - name) + extra_length); + return (size_t) ((p - name) + extra_length); } @@ -564,7 +564,7 @@ static int process_all_tables_in_db(char *database) */ char *tables, *end; - uint tot_length = 0; + size_t tot_length = 0; while ((row = mysql_fetch_row(res))) tot_length+= fixed_name_length(row[0]) + 2; @@ -622,7 +622,9 @@ static int fix_table_storage_name(const char *name) int rc= 0; if (strncmp(name, "#mysql50#", 9)) return 1; - sprintf(qbuf, "RENAME TABLE `%s` TO `%s`", name, name + 9); + my_snprintf(qbuf, sizeof(qbuf), "RENAME TABLE `%s` TO `%s`", + name, name + 9); + rc= run_query(qbuf); if (verbose) printf("%-50s %s\n", name, rc ? "FAILED" : "OK"); @@ -635,7 +637,8 @@ static int fix_database_storage_name(const char *name) int rc= 0; if (strncmp(name, "#mysql50#", 9)) return 1; - sprintf(qbuf, "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY NAME", name); + my_snprintf(qbuf, sizeof(qbuf), "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY " + "NAME", name); rc= run_query(qbuf); if (verbose) printf("%-50s %s\n", name, rc ? "FAILED" : "OK"); @@ -653,7 +656,7 @@ static int rebuild_table(char *name) ptr= strmov(query, "ALTER TABLE "); ptr= fix_table_name(ptr, name); ptr= strxmov(ptr, " FORCE", NullS); - if (mysql_real_query(sock, query, (uint)(ptr - query))) + if (mysql_real_query(sock, query, (ulong)(ptr - query))) { fprintf(stderr, "Failed to %s\n", query); fprintf(stderr, "Error: %s\n", mysql_error(sock)); @@ -702,10 +705,10 @@ static int disable_binlog() return run_query(stmt); } -static int handle_request_for_tables(char *tables, uint length) +static int handle_request_for_tables(char *tables, size_t length) { char *query, *end, options[100], message[100]; - uint query_length= 0; + size_t query_length= 0, query_size= sizeof(char)*(length+110); const char *op = 0; options[0] = 0; @@ -736,10 +739,14 @@ static int handle_request_for_tables(char *tables, uint length) return fix_table_storage_name(tables); } - if (!(query =(char *) my_malloc((sizeof(char)*(length+110)), MYF(MY_WME)))) + if (!(query =(char *) my_malloc(query_size, MYF(MY_WME)))) + { return 1; + } if (opt_all_in_1) { + DBUG_ASSERT(strlen(op)+strlen(tables)+strlen(options)+8+1 <= query_size); + /* No backticks here as we added them before */ query_length= sprintf(query, "%s TABLE %s %s", op, tables, options); } @@ -750,7 +757,7 @@ static int handle_request_for_tables(char *tables, uint length) ptr= strmov(strmov(query, op), " TABLE "); ptr= fix_table_name(ptr, tables); ptr= strxmov(ptr, " ", options, NullS); - query_length= (uint) (ptr - query); + query_length= (size_t) (ptr - query); } if (mysql_real_query(sock, query, query_length)) { @@ -834,7 +841,10 @@ static void print_result() prev_alter[0]= 0; } else - strcpy(prev_alter, alter_txt); + { + strncpy(prev_alter, alter_txt, MAX_ALTER_STR_SIZE-1); + prev_alter[MAX_ALTER_STR_SIZE-1]= 0; + } } } } @@ -978,7 +988,7 @@ int main(int argc, char **argv) process_databases(argv); if (opt_auto_repair) { - uint i; + size_t i; if (!opt_silent && (tables4repair.elements || tables4rebuild.elements)) puts("\nRepairing tables"); diff --git a/client/mysqldump.c b/client/mysqldump.c index 6c4fec313c5..00265def489 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -86,7 +86,7 @@ static void add_load_option(DYNAMIC_STRING *str, const char *option, const char *option_value); -static ulong find_set(TYPELIB *lib, const char *x, uint length, +static ulong find_set(TYPELIB *lib, const char *x, size_t length, char **err_pos, uint *err_len); static char *alloc_query_str(ulong size); @@ -852,7 +852,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_set_charset= 0; opt_compatible_mode_str= argument; opt_compatible_mode= find_set(&compatible_mode_typelib, - argument, (uint) strlen(argument), + argument, strlen(argument), &err_ptr, &err_len); if (err_len) { @@ -862,7 +862,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } #if !defined(DBUG_OFF) { - uint size_for_sql_mode= 0; + size_t size_for_sql_mode= 0; const char **ptr; for (ptr= compatible_mode_names; *ptr; ptr++) size_for_sql_mode+= strlen(*ptr); @@ -1138,8 +1138,8 @@ static int fetch_db_collation(const char *db_name, break; } - strncpy(db_cl_name, db_cl_row[0], db_cl_size); - db_cl_name[db_cl_size - 1]= 0; /* just in case. */ + strncpy(db_cl_name, db_cl_row[0], db_cl_size-1); + db_cl_name[db_cl_size - 1]= 0; } while (FALSE); @@ -1150,7 +1150,7 @@ static int fetch_db_collation(const char *db_name, static char *my_case_str(const char *str, - uint str_len, + size_t str_len, const char *token, uint token_len) { @@ -1366,7 +1366,7 @@ static int switch_character_set_results(MYSQL *mysql, const char *cs_name) */ static char *cover_definer_clause(const char *stmt_str, - uint stmt_length, + size_t stmt_length, const char *definer_version_str, uint definer_version_length, const char *stmt_version_str, @@ -1548,14 +1548,14 @@ static void dbDisconnect(char *host) } /* dbDisconnect */ -static void unescape(FILE *file,char *pos,uint length) +static void unescape(FILE *file,char *pos, size_t length) { char *tmp; DBUG_ENTER("unescape"); if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME)))) die(EX_MYSQLERR, "Couldn't allocate memory"); - mysql_real_escape_string(&mysql_connection, tmp, pos, length); + mysql_real_escape_string(&mysql_connection, tmp, pos, (ulong)length); fputc('\'', file); fputs(tmp, file); fputc('\'', file); @@ -1669,7 +1669,7 @@ static char *quote_for_like(const char *name, char *buff) Quote '<' '>' '&' '\"' chars and print a string to the xml_file. */ -static void print_quoted_xml(FILE *xml_file, const char *str, ulong len, +static void print_quoted_xml(FILE *xml_file, const char *str, size_t len, my_bool is_attribute_name) { const char *end; @@ -1928,7 +1928,7 @@ static void print_xml_row(FILE *xml_file, const char *row_name, squeezed to a single hyphen. */ -static void print_xml_comment(FILE *xml_file, ulong len, +static void print_xml_comment(FILE *xml_file, size_t len, const char *comment_string) { const char* end; @@ -2045,7 +2045,7 @@ static uint dump_events_for_db(char *db) DBUG_ENTER("dump_events_for_db"); DBUG_PRINT("enter", ("db: '%s'", db)); - mysql_real_escape_string(mysql, db_name_buff, db, strlen(db)); + mysql_real_escape_string(mysql, db_name_buff, db, (ulong)strlen(db)); /* nice comments */ print_comment(sql_file, 0, @@ -2164,6 +2164,11 @@ static uint dump_events_for_db(char *db) (const char *) (query_str != NULL ? query_str : row[3]), (const char *) delimiter); + if(query_str) + { + my_free(query_str); + query_str= NULL; + } restore_time_zone(sql_file, delimiter); restore_sql_mode(sql_file, delimiter); @@ -2257,7 +2262,7 @@ static uint dump_routines_for_db(char *db) DBUG_ENTER("dump_routines_for_db"); DBUG_PRINT("enter", ("db: '%s'", db)); - mysql_real_escape_string(mysql, db_name_buff, db, strlen(db)); + mysql_real_escape_string(mysql, db_name_buff, db, (ulong)strlen(db)); /* nice comments */ print_comment(sql_file, 0, @@ -2311,9 +2316,9 @@ static uint dump_routines_for_db(char *db) if the user has EXECUTE privilege he see routine names, but NOT the routine body of other routines that are not the creator of! */ - DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d", + DBUG_PRINT("info",("length of body for %s row[2] '%s' is %zu", routine_name, row[2] ? row[2] : "(null)", - row[2] ? (int) strlen(row[2]) : 0)); + row[2] ? strlen(row[2]) : 0)); if (row[2] == NULL) { print_comment(sql_file, 1, "\n-- insufficient privileges to %s\n", @@ -3873,7 +3878,7 @@ static int dump_tablespaces_for_tables(char *db, char **table_names, int tables) int i; char name_buff[NAME_LEN*2+3]; - mysql_real_escape_string(mysql, name_buff, db, strlen(db)); + mysql_real_escape_string(mysql, name_buff, db, (ulong)strlen(db)); init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN (" "SELECT DISTINCT TABLESPACE_NAME FROM" @@ -3886,7 +3891,7 @@ static int dump_tablespaces_for_tables(char *db, char **table_names, int tables) for (i=0 ; imax_length) length=field->max_length; @@ -500,7 +501,8 @@ static int list_tables(MYSQL *mysql,const char *db,const char *table) { const char *header; - uint head_length, counter = 0; + size_t head_length; + uint counter = 0; char query[NAME_LEN + 100], rows[NAME_LEN], fields[16]; MYSQL_FIELD *field; MYSQL_RES *result; @@ -537,7 +539,7 @@ list_tables(MYSQL *mysql,const char *db,const char *table) putchar('\n'); header="Tables"; - head_length=(uint) strlen(header); + head_length= strlen(header); field=mysql_fetch_field(result); if (head_length < field->max_length) head_length=field->max_length; @@ -766,10 +768,10 @@ list_fields(MYSQL *mysql,const char *db,const char *table, *****************************************************************************/ static void -print_header(const char *header,uint head_length,...) +print_header(const char *header,size_t head_length,...) { va_list args; - uint length,i,str_length,pre_space; + size_t length,i,str_length,pre_space; const char *field; va_start(args,head_length); @@ -792,10 +794,10 @@ print_header(const char *header,uint head_length,...) putchar('|'); for (;;) { - str_length=(uint) strlen(field); + str_length= strlen(field); if (str_length > length) str_length=length+1; - pre_space=(uint) (((int) length-(int) str_length)/2)+1; + pre_space= ((length- str_length)/2)+1; for (i=0 ; i < pre_space ; i++) putchar(' '); for (i = 0 ; i < str_length ; i++) @@ -829,11 +831,11 @@ print_header(const char *header,uint head_length,...) static void -print_row(const char *header,uint head_length,...) +print_row(const char *header,size_t head_length,...) { va_list args; const char *field; - uint i,length,field_length; + size_t i,length,field_length; va_start(args,head_length); field=header; length=head_length; @@ -842,7 +844,7 @@ print_row(const char *header,uint head_length,...) putchar('|'); putchar(' '); fputs(field,stdout); - field_length=(uint) strlen(field); + field_length= strlen(field); for (i=field_length ; i <= length ; i++) putchar(' '); if (!(field=va_arg(args,char *))) @@ -856,10 +858,10 @@ print_row(const char *header,uint head_length,...) static void -print_trailer(uint head_length,...) +print_trailer(size_t head_length,...) { va_list args; - uint length,i; + size_t length,i; va_start(args,head_length); length=head_length; @@ -902,7 +904,7 @@ static void print_res_top(MYSQL_RES *result) mysql_field_seek(result,0); while((field = mysql_fetch_field(result))) { - if ((length=(uint) strlen(field->name)) > field->max_length) + if ((length= strlen(field->name)) > field->max_length) field->max_length=length; else length=field->max_length; diff --git a/extra/yassl/src/log.cpp b/extra/yassl/src/log.cpp index 13c68295747..2f112ac35f9 100644 --- a/extra/yassl/src/log.cpp +++ b/extra/yassl/src/log.cpp @@ -1,6 +1,5 @@ /* - Copyright (C) 2000-2007 MySQL AB - Use is subject to license terms + Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -61,6 +60,7 @@ namespace yaSSL { time_t clicks = time(0); char timeStr[32]; + memset(timeStr, 0, sizeof(timeStr)); // get rid of newline strncpy(timeStr, ctime(&clicks), sizeof(timeStr)); unsigned int len = strlen(timeStr); diff --git a/regex/split.c b/regex/split.c index bd2a53c01e3..a3a11f793ed 100644 --- a/regex/split.c +++ b/regex/split.c @@ -163,6 +163,10 @@ char *argv[]; } else if (argc > 3) for (n = atoi(argv[3]); n > 0; n--) { + if(sizeof(buf)-1 < strlen(argv[1])) + { + exit(EXIT_FAILURE); + } (void) strcpy(buf, argv[1]); (void) split(buf, fields, MNF, argv[2]); } -- cgit v1.2.1 From ef3f09f0c9e62ea1bf86b33b5d97e954b3ae34fe Mon Sep 17 00:00:00 2001 From: Sujatha Sivakumar Date: Fri, 13 May 2016 16:42:45 +0530 Subject: Bug#23251517: SEMISYNC REPLICATION HANGING Revert following bug fix: Bug#20685029: SLAVE IO THREAD SHOULD STOP WHEN DISK IS FULL Bug#21753696: MAKE SHOW SLAVE STATUS NON BLOCKING IF IO THREAD WAITS FOR DISK SPACE This fix results in a deadlock between slave IO thread and SQL thread. (cherry picked from commit e3fea6c6dbb36c6ab21c4ab777224560e9608b53) --- mysql-test/include/assert_grep.inc | 154 --------------------- mysql-test/include/rpl_init.inc | 31 +---- mysql-test/include/rpl_reconnect.inc | 33 ++--- mysql-test/include/start_slave_sql.inc | 39 ------ .../rpl/r/rpl_io_thd_wait_for_disk_space.result | 15 -- .../rpl/t/rpl_io_thd_wait_for_disk_space.test | 71 ---------- mysys/errors.c | 14 +- mysys/my_write.c | 8 +- sql/log.cc | 75 +--------- sql/log.h | 5 +- sql/slave.cc | 38 ++--- sql/slave.h | 2 +- sql/sql_reload.cc | 2 +- 13 files changed, 41 insertions(+), 446 deletions(-) delete mode 100644 mysql-test/include/assert_grep.inc delete mode 100644 mysql-test/include/start_slave_sql.inc delete mode 100644 mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result delete mode 100644 mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test diff --git a/mysql-test/include/assert_grep.inc b/mysql-test/include/assert_grep.inc deleted file mode 100644 index a980a6d73b1..00000000000 --- a/mysql-test/include/assert_grep.inc +++ /dev/null @@ -1,154 +0,0 @@ -# ==== Purpose ==== -# -# Grep a file for a pattern, produce a single string out of the -# matching lines, and assert that the string matches a given regular -# expression. -# -# ==== Usage ==== -# -# --let $assert_text= TEXT -# --let $assert_file= FILE -# --let $assert_select= REGEX -# [--let $assert_match= REGEX | --let $assert_count= NUMBER] -# [--let $assert_only_after= REGEX] -# --source include/assert_grep.inc -# -# Parameters: -# -# $assert_text -# Text that describes what is being checked. This text is written to -# the query log so it should not contain non-deterministic elements. -# -# $assert_file -# File to search. -# -# $assert_select -# All lines matching this text will be checked. -# -# $assert_match -# The script will find all lines that match $assert_select, -# concatenate them to a long string, and assert that it matches -# $assert_match. -# -# $assert_count -# Instead of asserting that the selected lines match -# $assert_match, assert that there were exactly $assert_count -# matching lines. -# -# $assert_only_after -# Reset all the lines matched and the counter when finding this pattern. -# It is useful for searching things in the mysqld.err log file just -# after the last server restart for example (discarding the log content -# of previous server executions). - - -if (!$assert_text) -{ - --die !!!ERROR IN TEST: you must set $assert_text -} -if (!$assert_file) -{ - --die !!!ERROR IN TEST: you must set $assert_file -} -if (!$assert_select) -{ - --die !!!ERROR IN TEST: you must set $assert_select -} -if ($assert_match == '') -{ - if ($assert_count == '') - { - --die !!!ERROR IN TEST: you must set either $assert_match or $assert_count - } -} -if ($assert_match != '') -{ - if ($assert_count != '') - { - --echo assert_text='$assert_text' assert_count='$assert_count' - --die !!!ERROR IN TEST: you must set only one of $assert_match or $assert_count - } -} - - ---let $include_filename= assert_grep.inc [$assert_text] ---source include/begin_include_file.inc - - ---let _AG_ASSERT_TEXT= $assert_text ---let _AG_ASSERT_FILE= $assert_file ---let _AG_ASSERT_SELECT= $assert_select ---let _AG_ASSERT_MATCH= $assert_match ---let _AG_ASSERT_COUNT= $assert_count ---let _AG_OUT= `SELECT CONCAT('$MYSQLTEST_VARDIR/tmp/_ag_', UUID())` ---let _AG_ASSERT_ONLY_AFTER= $assert_only_after - - ---perl - use strict; - use warnings; - my $file= $ENV{'_AG_ASSERT_FILE'}; - my $assert_select= $ENV{'_AG_ASSERT_SELECT'}; - my $assert_match= $ENV{'_AG_ASSERT_MATCH'}; - my $assert_count= $ENV{'_AG_ASSERT_COUNT'}; - my $assert_only_after= $ENV{'_AG_ASSERT_ONLY_AFTER'}; - my $out= $ENV{'_AG_OUT'}; - - my $result= ''; - my $count= 0; - open(FILE, "$file") or die("Error $? opening $file: $!\n"); - while () { - my $line = $_; - if ($assert_only_after && $line =~ /$assert_only_after/) { - $result = ""; - $count = 0; - } - if ($line =~ /$assert_select/) { - if ($assert_count ne '') { - $count++; - } - else { - $result .= $line; - } - } - } - close(FILE) or die("Error $? closing $file: $!"); - open OUT, "> $out" or die("Error $? opening $out: $!"); - if ($assert_count ne '' && ($count != $assert_count)) { - print OUT ($count) or die("Error $? writing $out: $!"); - } - elsif ($assert_count eq '' && $result !~ /$assert_match/) { - print OUT ($result) or die("Error $? writing $out: $!"); - } - else { - print OUT ("assert_grep.inc ok"); - } - close OUT or die("Error $? closing $out: $!"); -EOF - - ---let $_ag_outcome= `SELECT LOAD_FILE('$_AG_OUT')` -if ($_ag_outcome != 'assert_grep.inc ok') -{ - --source include/show_rpl_debug_info.inc - --echo include/assert_grep.inc failed! - --echo assert_text: '$assert_text' - --echo assert_file: '$assert_file' - --echo assert_select: '$assert_select' - --echo assert_match: '$assert_match' - --echo assert_count: '$assert_count' - --echo assert_only_after: '$assert_only_after' - if ($assert_match != '') - { - --echo matching lines: '$_ag_outcome' - } - if ($assert_count != '') - { - --echo number of matching lines: $_ag_outcome - } - --die assert_grep.inc failed. -} - - ---let $include_filename= include/assert_grep.inc [$assert_text] ---source include/end_include_file.inc diff --git a/mysql-test/include/rpl_init.inc b/mysql-test/include/rpl_init.inc index 820bc8e9016..2abfd901b03 100644 --- a/mysql-test/include/rpl_init.inc +++ b/mysql-test/include/rpl_init.inc @@ -43,7 +43,6 @@ # # [--let $rpl_server_count= 7] # --let $rpl_topology= 1->2->3->1->4, 2->5, 6->7 -# [--let $rpl_extra_connections_per_server= 1] # [--let $rpl_check_server_ids= 1] # [--let $rpl_skip_change_master= 1] # [--let $rpl_skip_start_slave= 1] @@ -66,12 +65,6 @@ # want to specify the empty topology (no server replicates at # all), you have to set $rpl_topology=none. # -# $rpl_extra_connections_per_server -# By default, this script creates connections server_N and -# server_N_1. If you can set this variable to a number, the -# script creates: -# server_N, server_N_1, ..., server_N_$rpl_extra_connections_per_server -# # $rpl_check_server_ids # If $rpl_check_server_ids is set, this script checks that the # @@server_id of all servers are different. This is normally @@ -146,17 +139,8 @@ if (!$SERVER_MYPORT_4) # Check that $rpl_server_count is set if (!$rpl_server_count) { - --let $rpl_server_count= `SELECT REPLACE('$rpl_topology', '->', ',')` - if (`SELECT LOCATE(',', '$rpl_server_count')`) - { - --let $rpl_server_count= `SELECT GREATEST($rpl_server_count)` - } -} - ---let $_rpl_extra_connections_per_server= $rpl_extra_connections_per_server -if ($_rpl_extra_connections_per_server == '') -{ - --let $_rpl_extra_connections_per_server= 1 + --let $_compute_rpl_server_count= `SELECT REPLACE('$rpl_topology', '->', ',')` + --let $rpl_server_count= `SELECT GREATEST($_compute_rpl_server_count)` } @@ -175,20 +159,15 @@ if (!$rpl_debug) # Create two connections to each server; reset master/slave, select # database, set autoinc variables. --let $_rpl_server= $rpl_server_count ---let $underscore= _ +--let $_rpl_one= _1 while ($_rpl_server) { # Connect. --let $rpl_server_number= $_rpl_server --let $rpl_connection_name= server_$_rpl_server --source include/rpl_connect.inc - --let $_rpl_connection_number= 1 - while ($_rpl_connection_number <= $_rpl_extra_connections_per_server) - { - --let $rpl_connection_name= server_$_rpl_server$underscore$_rpl_connection_number - --source include/rpl_connect.inc - --inc $_rpl_connection_number - } + --let $rpl_connection_name= server_$_rpl_server$_rpl_one + --source include/rpl_connect.inc # Configure server. --let $rpl_connection_name= server_$_rpl_server diff --git a/mysql-test/include/rpl_reconnect.inc b/mysql-test/include/rpl_reconnect.inc index 673f382bac0..cdbbd0a1bf1 100644 --- a/mysql-test/include/rpl_reconnect.inc +++ b/mysql-test/include/rpl_reconnect.inc @@ -12,7 +12,6 @@ # ==== Usage ==== # # --let $rpl_server_number= N -# [--let $rpl_extra_connections_per_server= 1] # [--let $rpl_debug= 1] # --source include/rpl_reconnect.inc # @@ -22,7 +21,7 @@ # master server, 2 the slave server, 3 the 3rd server, and so on. # Cf. include/rpl_init.inc # -# $rpl_extra_connections_per_server, $rpl_debug +# $rpl_debug # See include/rpl_init.inc --let $include_filename= rpl_reconnect.inc @@ -33,11 +32,6 @@ if (!$rpl_server_number) --die ERROR IN TEST: you must set $rpl_server_number before you source rpl_connect.inc } -if ($_rpl_extra_connections_per_server == '') -{ - --let $_rpl_extra_connections_per_server= 1 -} - if ($rpl_debug) { @@ -78,14 +72,10 @@ if (!$_rpl_server_number) --source include/rpl_connection.inc --enable_reconnect ---let $_rpl_connection_number= 1 -while ($_rpl_connection_number <= $_rpl_extra_connections_per_server) -{ - --let $rpl_connection_name= server_$rpl_server_number$underscore$_rpl_connection_number - --source include/rpl_connection.inc - --enable_reconnect - --inc $_rpl_connection_number -} +--let $_rpl_one= _1 +--let $rpl_connection_name= server_$rpl_server_number$_rpl_one +--source include/rpl_connection.inc +--enable_reconnect if ($rpl_debug) { @@ -132,15 +122,10 @@ if (!$_rpl_server_number) --source include/wait_until_connected_again.inc --disable_reconnect ---let $_rpl_connection_number= 1 -while ($_rpl_connection_number <= $_rpl_extra_connections_per_server) -{ - --let $rpl_connection_name= server_$rpl_server_number$underscore$_rpl_connection_number - --source include/rpl_connection.inc - --source include/wait_until_connected_again.inc - --disable_reconnect - --inc $_rpl_connection_number -} +--let $rpl_connection_name= server_$rpl_server_number$_rpl_one +--source include/rpl_connection.inc +--source include/wait_until_connected_again.inc +--disable_reconnect --let $include_filename= rpl_reconnect.inc diff --git a/mysql-test/include/start_slave_sql.inc b/mysql-test/include/start_slave_sql.inc deleted file mode 100644 index 9cb66a2eb40..00000000000 --- a/mysql-test/include/start_slave_sql.inc +++ /dev/null @@ -1,39 +0,0 @@ -# ==== Purpose ==== -# -# Issues START SLAVE SQL_THREAD on the current connection. Then waits -# until the SQL thread has started, or until a timeout is reached. -# -# Please use this instead of 'START SLAVE SQL_THREAD', to reduce the -# risk of races in test cases. -# -# -# ==== Usage ==== -# -# [--let $slave_timeout= NUMBER] -# [--let $rpl_debug= 1] -# --source include/start_slave_sql.inc -# -# Parameters: -# $slave_timeout -# See include/wait_for_slave_param.inc -# -# $rpl_debug -# See include/rpl_init.inc - - ---let $include_filename= start_slave_sql.inc ---source include/begin_include_file.inc - - -if (!$rpl_debug) -{ - --disable_query_log -} - - -START SLAVE SQL_THREAD; ---source include/wait_for_slave_sql_to_start.inc - - ---let $include_filename= start_slave_sql.inc ---source include/end_include_file.inc diff --git a/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result b/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result deleted file mode 100644 index b11ad4f53bd..00000000000 --- a/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result +++ /dev/null @@ -1,15 +0,0 @@ -include/master-slave.inc -[connection master] -CREATE TABLE t1(a INT); -INSERT INTO t1 VALUES(1); -CALL mtr.add_suppression("Disk is full writing"); -CALL mtr.add_suppression("Retry in 60 secs"); -include/stop_slave_sql.inc -SET @@GLOBAL.DEBUG= 'd,simulate_io_thd_wait_for_disk_space'; -INSERT INTO t1 VALUES(2); -SET DEBUG_SYNC='now WAIT_FOR parked'; -SET @@GLOBAL.DEBUG= '$debug_saved'; -include/assert_grep.inc [Found the disk full error message on the slave] -include/start_slave_sql.inc -DROP TABLE t1; -include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test b/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test deleted file mode 100644 index 6076be60ebc..00000000000 --- a/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test +++ /dev/null @@ -1,71 +0,0 @@ -# ==== Purpose ==== -# -# Check that the execution of SHOW SLAVE STATUS command is not blocked when IO -# thread is blocked waiting for disk space. -# -# ==== Implementation ==== -# -# Simulate a scenario where IO thread is waiting for disk space while writing -# into the relay log. Execute SHOW SLAVE STATUS command after IO thread is -# blocked waiting for space. The command should not be blocked. -# -# ==== References ==== -# -# Bug#21753696: MAKE SHOW SLAVE STATUS NON BLOCKING IF IO THREAD WAITS FOR -# DISK SPACE -# Bug#20685029: SLAVE IO THREAD SHOULD STOP WHEN DISK IS FULL -# -############################################################################### ---source include/have_debug.inc -# Inorder to grep a specific error pattern in error log a fresh error log -# needs to be generated. ---source include/force_restart.inc ---source include/master-slave.inc - -# Generate events to be replicated to the slave -CREATE TABLE t1(a INT); -INSERT INTO t1 VALUES(1); ---sync_slave_with_master - -# Those errors will only happen in the slave -CALL mtr.add_suppression("Disk is full writing"); -CALL mtr.add_suppression("Retry in 60 secs"); - -# Stop the SQL thread to avoid writing on disk ---source include/stop_slave_sql.inc - -# Set the debug option that will simulate disk full ---let $debug_saved= `SELECT @@GLOBAL.DEBUG` -SET @@GLOBAL.DEBUG= 'd,simulate_io_thd_wait_for_disk_space'; - -# Generate events to be replicated to the slave ---connection master -INSERT INTO t1 VALUES(2); - ---connection slave1 -SET DEBUG_SYNC='now WAIT_FOR parked'; - -# Get the relay log file name using SHOW SLAVE STATUS ---let $relay_log_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) - ---connection slave -# Restore the debug options to "simulate" freed space on disk -SET @@GLOBAL.DEBUG= '$debug_saved'; - -# There should be a message in the error log of the slave stating -# that it was waiting for space to write on the relay log. ---let $assert_file=$MYSQLTEST_VARDIR/log/mysqld.2.err -# Grep only after the message that the I/O thread has started ---let $assert_only_after= Slave I/O .* connected to master .*replication started in log .* at position ---let $assert_count= 1 ---let $assert_select=Disk is full writing .*$relay_log_file.* ---let $assert_text= Found the disk full error message on the slave ---source include/assert_grep.inc - -# Start the SQL thread to let the slave to sync and finish gracefully ---source include/start_slave_sql.inc - -# Cleanup ---connection master -DROP TABLE t1; ---source include/rpl_end.inc diff --git a/mysys/errors.c b/mysys/errors.c index b6064460535..a6e2e300a1f 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -15,7 +15,7 @@ #include "mysys_priv.h" #include "mysys_err.h" -#include "m_string.h" + #ifndef SHARED_LIBRARY const char *globerrs[GLOBERRS]= @@ -109,7 +109,6 @@ void init_glob_errs() */ void wait_for_free_space(const char *filename, int errors) { - size_t time_to_sleep= MY_WAIT_FOR_USER_TO_FIX_PANIC; if (!(errors % MY_WAIT_GIVE_USER_A_MESSAGE)) { my_printf_warning(EE(EE_DISK_FULL), @@ -120,15 +119,10 @@ void wait_for_free_space(const char *filename, int errors) } DBUG_EXECUTE_IF("simulate_no_free_space_error", { - time_to_sleep= 1; - }); - DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", - { - time_to_sleep= 1; + (void) sleep(1); + return; }); - - (void) sleep(time_to_sleep); - DEBUG_SYNC_C("disk_full_reached"); + (void) sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC); } const char **get_global_errmsgs() diff --git a/mysys/my_write.c b/mysys/my_write.c index 2e68a4dcff3..f092420756e 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -24,7 +24,6 @@ size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags) { size_t writtenbytes, written; uint errors; - size_t ToWriteCount; DBUG_ENTER("my_write"); DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d", Filedes, Buffer, (ulong) Count, MyFlags)); @@ -38,14 +37,11 @@ size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags) { DBUG_SET("+d,simulate_file_write_error");}); for (;;) { - ToWriteCount= Count; - DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", { ToWriteCount= 1; }); #ifdef _WIN32 - writtenbytes= my_win_write(Filedes, Buffer, ToWriteCount); + writtenbytes= my_win_write(Filedes, Buffer, Count); #else - writtenbytes= write(Filedes, Buffer, ToWriteCount); + writtenbytes= write(Filedes, Buffer, Count); #endif - DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", { errno= ENOSPC; }); DBUG_EXECUTE_IF("simulate_file_write_error", { errno= ENOSPC; diff --git a/sql/log.cc b/sql/log.cc index a7f05905514..42937ec1682 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -37,7 +37,6 @@ #include "log_event.h" // Query_log_event #include "rpl_filter.h" #include "rpl_rli.h" -#include "rpl_mi.h" #include "sql_audit.h" #include "sql_show.h" @@ -4378,22 +4377,13 @@ end: } -#ifdef HAVE_REPLICATION -bool MYSQL_BIN_LOG::append(Log_event* ev, Master_info *mi) +bool MYSQL_BIN_LOG::append(Log_event* ev) { bool error = 0; - mysql_mutex_assert_owner(&mi->data_lock); mysql_mutex_lock(&LOCK_log); DBUG_ENTER("MYSQL_BIN_LOG::append"); DBUG_ASSERT(log_file.type == SEQ_READ_APPEND); - /* - Release data_lock by holding LOCK_log, while writing into the relay log. - If slave IO thread waits here for free space, we don't want - SHOW SLAVE STATUS to hang on mi->data_lock. Note LOCK_log mutex is - sufficient to block SQL thread when IO thread is updating relay log here. - */ - mysql_mutex_unlock(&mi->data_lock); /* Log_event::write() is smart enough to use my_b_write() or my_b_append() depending on the kind of cache we have. @@ -4408,58 +4398,24 @@ bool MYSQL_BIN_LOG::append(Log_event* ev, Master_info *mi) if (flush_and_sync(0)) goto err; if ((uint) my_b_append_tell(&log_file) > max_size) - { - /* - If rotation is required we must acquire data_lock to protect - description_event from clients executing FLUSH LOGS in parallel. - In order do that we must release the existing LOCK_log so that we - get it once again in proper locking order to avoid dead locks. - i.e data_lock , LOCK_log. - */ - mysql_mutex_unlock(&LOCK_log); - mysql_mutex_lock(&mi->data_lock); - mysql_mutex_lock(&LOCK_log); error= new_file_without_locking(); - /* - After rotation release data_lock, we need the LOCK_log till we signal - the updation. - */ - mysql_mutex_unlock(&mi->data_lock); - } err: - signal_update(); // Safe as we don't call close mysql_mutex_unlock(&LOCK_log); - mysql_mutex_lock(&mi->data_lock); + signal_update(); // Safe as we don't call close DBUG_RETURN(error); } -bool MYSQL_BIN_LOG::appendv(Master_info* mi, const char* buf, uint len,...) +bool MYSQL_BIN_LOG::appendv(const char* buf, uint len,...) { bool error= 0; DBUG_ENTER("MYSQL_BIN_LOG::appendv"); va_list(args); va_start(args,len); - mysql_mutex_assert_owner(&mi->data_lock); - mysql_mutex_lock(&LOCK_log); DBUG_ASSERT(log_file.type == SEQ_READ_APPEND); - /* - Release data_lock by holding LOCK_log, while writing into the relay log. - If slave IO thread waits here for free space, we don't want - SHOW SLAVE STATUS to hang on mi->data_lock. Note LOCK_log mutex is - sufficient to block SQL thread when IO thread is updating relay log here. - */ - mysql_mutex_unlock(&mi->data_lock); - DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", - { - const char act[]= "disk_full_reached SIGNAL parked"; - DBUG_ASSERT(opt_debug_sync_timeout > 0); - DBUG_ASSERT(!debug_sync_set_action(current_thd, - STRING_WITH_LEN(act))); - };); - + mysql_mutex_assert_owner(&LOCK_log); do { if (my_b_append(&log_file,(uchar*) buf,len)) @@ -4472,34 +4428,13 @@ bool MYSQL_BIN_LOG::appendv(Master_info* mi, const char* buf, uint len,...) DBUG_PRINT("info",("max_size: %lu",max_size)); if (flush_and_sync(0)) goto err; - if ((uint) my_b_append_tell(&log_file) > - DBUG_EVALUATE_IF("rotate_slave_debug_group", 500, max_size)) - { - /* - If rotation is required we must acquire data_lock to protect - description_event from clients executing FLUSH LOGS in parallel. - In order do that we must release the existing LOCK_log so that we - get it once again in proper locking order to avoid dead locks. - i.e data_lock , LOCK_log. - */ - mysql_mutex_unlock(&LOCK_log); - mysql_mutex_lock(&mi->data_lock); - mysql_mutex_lock(&LOCK_log); + if ((uint) my_b_append_tell(&log_file) > max_size) error= new_file_without_locking(); - /* - After rotation release data_lock, we need the LOCK_log till we signal - the updation. - */ - mysql_mutex_unlock(&mi->data_lock); - } err: if (!error) signal_update(); - mysql_mutex_unlock(&LOCK_log); - mysql_mutex_lock(&mi->data_lock); DBUG_RETURN(error); } -#endif bool MYSQL_BIN_LOG::flush_and_sync(bool *synced) { diff --git a/sql/log.h b/sql/log.h index 7d1c3161ac2..4d13e4d0720 100644 --- a/sql/log.h +++ b/sql/log.h @@ -20,7 +20,6 @@ #include "handler.h" /* my_xid */ class Relay_log_info; -class Master_info; class Format_description_log_event; @@ -455,8 +454,8 @@ public: v stands for vector invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0) */ - bool appendv(Master_info* mi, const char* buf,uint len,...); - bool append(Log_event* ev, Master_info* mi); + bool appendv(const char* buf,uint len,...); + bool append(Log_event* ev); void make_log_name(char* buf, const char* log_ident); bool is_active(const char* log_file_name); diff --git a/sql/slave.cc b/sql/slave.cc index 31037c453d3..acf68e231f3 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1660,7 +1660,7 @@ Waiting for the slave SQL thread to free enough relay log space"); #endif if (rli->sql_force_rotate_relay) { - rotate_relay_log(rli->mi, true/*need_data_lock=true*/); + rotate_relay_log(rli->mi); rli->sql_force_rotate_relay= false; } @@ -1705,7 +1705,7 @@ static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) if (likely((bool)ev)) { ev->server_id= 0; // don't be ignored by slave SQL thread - if (unlikely(rli->relay_log.append(ev, mi))) + if (unlikely(rli->relay_log.append(ev))) mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), "failed to write a Rotate event" @@ -3605,7 +3605,7 @@ static int process_io_create_file(Master_info* mi, Create_file_log_event* cev) break; Execute_load_log_event xev(thd,0,0); xev.log_pos = cev->log_pos; - if (unlikely(mi->rli.relay_log.append(&xev, mi))) + if (unlikely(mi->rli.relay_log.append(&xev))) { mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), @@ -3619,7 +3619,7 @@ static int process_io_create_file(Master_info* mi, Create_file_log_event* cev) { cev->block = net->read_pos; cev->block_len = num_bytes; - if (unlikely(mi->rli.relay_log.append(cev, mi))) + if (unlikely(mi->rli.relay_log.append(cev))) { mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), @@ -3634,7 +3634,7 @@ static int process_io_create_file(Master_info* mi, Create_file_log_event* cev) aev.block = net->read_pos; aev.block_len = num_bytes; aev.log_pos = cev->log_pos; - if (unlikely(mi->rli.relay_log.append(&aev, mi))) + if (unlikely(mi->rli.relay_log.append(&aev))) { mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), @@ -3713,7 +3713,7 @@ static int process_io_rotate(Master_info *mi, Rotate_log_event *rev) Rotate the relay log makes binlog format detection easier (at next slave start or mysqlbinlog) */ - DBUG_RETURN(rotate_relay_log(mi, false/*need_data_lock=false*/)); + DBUG_RETURN(rotate_relay_log(mi) /* will take the right mutexes */); } /* @@ -3819,7 +3819,7 @@ static int queue_binlog_ver_1_event(Master_info *mi, const char *buf, Log_event::Log_event(const char* buf...) in log_event.cc). */ ev->log_pos+= event_len; /* make log_pos be the pos of the end of the event */ - if (unlikely(rli->relay_log.append(ev, mi))) + if (unlikely(rli->relay_log.append(ev))) { delete ev; mysql_mutex_unlock(&mi->data_lock); @@ -3875,7 +3875,7 @@ static int queue_binlog_ver_3_event(Master_info *mi, const char *buf, inc_pos= event_len; break; } - if (unlikely(rli->relay_log.append(ev, mi))) + if (unlikely(rli->relay_log.append(ev))) { delete ev; mysql_mutex_unlock(&mi->data_lock); @@ -4083,6 +4083,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) direct master (an unsupported, useless setup!). */ + mysql_mutex_lock(log_lock); s_id= uint4korr(buf + SERVER_ID_OFFSET); if ((s_id == ::server_id && !mi->rli.replicate_same_server_id) || /* @@ -4115,7 +4116,6 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) IGNORE_SERVER_IDS it increments mi->master_log_pos as well as rli->group_relay_log_pos. */ - mysql_mutex_lock(log_lock); if (!(s_id == ::server_id && !mi->rli.replicate_same_server_id) || (buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT && buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT && @@ -4127,14 +4127,13 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) rli->ign_master_log_pos_end= mi->master_log_pos; } rli->relay_log.signal_update(); // the slave SQL thread needs to re-check - mysql_mutex_unlock(log_lock); DBUG_PRINT("info", ("master_log_pos: %lu, event originating from %u server, ignored", (ulong) mi->master_log_pos, uint4korr(buf + SERVER_ID_OFFSET))); } else { /* write the event to the relay log */ - if (likely(!(rli->relay_log.appendv(mi, buf,event_len,0)))) + if (likely(!(rli->relay_log.appendv(buf,event_len,0)))) { mi->master_log_pos+= inc_pos; DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); @@ -4144,10 +4143,9 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) { error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE; } - mysql_mutex_lock(log_lock); rli->ign_master_log_name_end[0]= 0; // last event is not ignored - mysql_mutex_unlock(log_lock); } + mysql_mutex_unlock(log_lock); skip_relay_logging: @@ -5007,21 +5005,11 @@ err: locks; here we don't, so this function is mainly taking locks). Returns nothing as we cannot catch any error (MYSQL_BIN_LOG::new_file() is void). - - @param mi Master_info for the IO thread. - @param need_data_lock If true, mi->data_lock will be acquired otherwise, - mi->data_lock must be held by the caller. */ -int rotate_relay_log(Master_info* mi, bool need_data_lock) +int rotate_relay_log(Master_info* mi) { DBUG_ENTER("rotate_relay_log"); - if (need_data_lock) - mysql_mutex_lock(&mi->data_lock); - else - { - mysql_mutex_assert_owner(&mi->data_lock); - } Relay_log_info* rli= &mi->rli; int error= 0; @@ -5056,8 +5044,6 @@ int rotate_relay_log(Master_info* mi, bool need_data_lock) */ rli->relay_log.harvest_bytes_written(&rli->log_space_total); end: - if (need_data_lock) - mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(error); } diff --git a/sql/slave.h b/sql/slave.h index 0cf8adb0315..7bf136694cc 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -205,7 +205,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, const char** errmsg); void set_slave_thread_options(THD* thd); void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli); -int rotate_relay_log(Master_info* mi, bool need_data_lock); +int rotate_relay_log(Master_info* mi); int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli); pthread_handler_t handle_slave_io(void *arg); diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index f24f31b6399..b29cc9a9433 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -157,7 +157,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long options, { #ifdef HAVE_REPLICATION mysql_mutex_lock(&LOCK_active_mi); - if (rotate_relay_log(active_mi, true/*need_data_lock=true*/)) + if (rotate_relay_log(active_mi)) *write_to_binlog= -1; mysql_mutex_unlock(&LOCK_active_mi); #endif -- cgit v1.2.1 From 18487ed60ecf8d8e8416a45e1f45c3a012662ce7 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 24 May 2016 14:18:55 +0200 Subject: MDEV-10108 Fix errors in installations by domain user --- win/packaging/extra.wxs.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in index 8ee2909511b..6e5d1bf0fb2 100644 --- a/win/packaging/extra.wxs.in +++ b/win/packaging/extra.wxs.in @@ -66,6 +66,7 @@ + @@ -463,7 +464,7 @@ Key='SOFTWARE\@MANUFACTURER@\@CPACK_WIX_PACKAGE_NAME@' Name='DATADIR' Value='[DATADIR]' Type='string' KeyPath='yes'/> - + @@ -851,6 +852,7 @@ + Date: Tue, 24 May 2016 14:20:53 +0200 Subject: MDEV-10071 Block installation on XP/Windows 2003 Server(they are no more supported) --- win/packaging/extra.wxs.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in index 6e5d1bf0fb2..b716bbf7e88 100644 --- a/win/packaging/extra.wxs.in +++ b/win/packaging/extra.wxs.in @@ -899,6 +899,9 @@ + + + = 600)]]> -- cgit v1.2.1 From 535160b170b3d0b0489193b9863042578cddd826 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 24 May 2016 16:57:03 +0200 Subject: MDEV-10117 - update HeidiSQL to current version --- win/packaging/heidisql.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/packaging/heidisql.cmake b/win/packaging/heidisql.cmake index 5b0cd07cea4..e2636eb4af8 100644 --- a/win/packaging/heidisql.cmake +++ b/win/packaging/heidisql.cmake @@ -1,4 +1,4 @@ -SET(HEIDISQL_BASE_NAME "HeidiSQL_9.1_Portable") +SET(HEIDISQL_BASE_NAME "HeidiSQL_9.3_Portable") SET(HEIDISQL_ZIP "${HEIDISQL_BASE_NAME}.zip") SET(HEIDISQL_URL "http://www.heidisql.com/downloads/releases/${HEIDISQL_ZIP}") SET(HEIDISQL_DOWNLOAD_DIR ${THIRD_PARTY_DOWNLOAD_LOCATION}/${HEIDISQL_BASE_NAME}) -- cgit v1.2.1 From 221adbc6feadb51d44b2a16a666f3c78d297c705 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 24 May 2016 17:01:08 +0200 Subject: Fix warnings on Windows, compiler option -ggdb3 option is nonexistent --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1ce1c55978..9ab8870ffb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -254,8 +254,10 @@ IF (ENABLE_GCOV AND NOT WIN32 AND NOT APPLE) ENDIF() MY_CHECK_C_COMPILER_FLAG(-ggdb3 HAVE_GGDB3) -SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb3") -SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3") +IF(HAVE_GGDB3) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb3") + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3") +ENDIF() OPTION(ENABLED_LOCAL_INFILE "If we should should enable LOAD DATA LOCAL by default" ${IF_WIN}) -- cgit v1.2.1 From ff832e0d16f83fa0db64ca76ba756f8e714c7e43 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 24 May 2016 17:37:23 +0200 Subject: Restore COMPONENT Embedded for Windows embedded libs. --- libmysqld/CMakeLists.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index ee5c8875686..bd7631c1d6b 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -108,8 +108,12 @@ ADD_DEPENDENCIES(sql_embedded GenError GenServerSource) # On Unix, it is libmysqld.a IF(WIN32) SET(MYSQLSERVER_OUTPUT_NAME mysqlserver) + SET(COMPONENT_MYSQLSERVER "Embedded") + SET(COMPONENT_LIBMYSQLD "Embedded") ELSE() SET(MYSQLSERVER_OUTPUT_NAME mysqld) + SET(COMPONENT_MYSQLSERVER "Development") + SET(COMPONENT_LIBMYSQLD "Server") ENDIF() @@ -134,9 +138,9 @@ FOREACH(LIB ${LIBS}) ENDFOREACH() MERGE_LIBRARIES(mysqlserver STATIC ${EMBEDDED_LIBS} - OUTPUT_NAME ${MYSQLSERVER_OUTPUT_NAME} COMPONENT Development) + OUTPUT_NAME ${MYSQLSERVER_OUTPUT_NAME} COMPONENT ${COMPONENT_MYSQLSERVER}) -INSTALL(FILES embedded_priv.h DESTINATION ${INSTALL_INCLUDEDIR}/private COMPONENT Development) +INSTALL(FILES embedded_priv.h DESTINATION ${INSTALL_INCLUDEDIR}/private COMPONENT ${COMPONENT_MYSQLSERVER}) # Visual Studio users need debug static library IF(MSVC) @@ -163,7 +167,7 @@ ENDFOREACH() IF(NOT DISABLE_SHARED) MERGE_LIBRARIES(libmysqld SHARED mysqlserver EXPORTS ${EMBEDDED_API} - COMPONENT Server) + COMPONENT ${COMPONENT_LIBMYSQLD}) IF(UNIX) # Name the shared library, handle versioning (provides same api as client # library hence the same version) -- cgit v1.2.1 From 0f252702b15dfb5d90446fd49c9e28aa93424eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 8 Jun 2016 08:40:10 +0300 Subject: MDEV-7139: Sporadic failure in innodb.innodb_corrupt_bit on P8 Use direct persistent index corruption set on InnoDB dictionary for this test. Do not allow creating new indexes if one of the existing indexes is already marked as corrupted. --- .../suite/innodb/r/innodb_corrupt_bit.result | 90 +++++++--------------- mysql-test/suite/innodb/t/innodb_corrupt_bit.test | 84 +++++++------------- storage/innobase/handler/ha_innodb.cc | 40 +++++++++- storage/innobase/handler/handler0alter.cc | 35 +++++++++ storage/xtradb/handler/ha_innodb.cc | 40 +++++++++- storage/xtradb/handler/handler0alter.cc | 35 +++++++++ 6 files changed, 204 insertions(+), 120 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb_corrupt_bit.result b/mysql-test/suite/innodb/r/innodb_corrupt_bit.result index 2ba79ced75f..bc4334bd219 100644 --- a/mysql-test/suite/innodb/r/innodb_corrupt_bit.result +++ b/mysql-test/suite/innodb/r/innodb_corrupt_bit.result @@ -1,83 +1,49 @@ -set names utf8; -CREATE TABLE corrupt_bit_test_ā( -a INT AUTO_INCREMENT PRIMARY KEY, -b CHAR(100), -c INT, -z INT, -INDEX(b)) -ENGINE=InnoDB; -INSERT INTO corrupt_bit_test_ā VALUES(0,'x',1, 1); -CREATE UNIQUE INDEX idxā ON corrupt_bit_test_ā(c, b); -CREATE UNIQUE INDEX idxē ON corrupt_bit_test_ā(z, b); -SELECT * FROM corrupt_bit_test_ā; a b c z 1 x 1 1 -select @@unique_checks; -@@unique_checks -0 -select @@innodb_change_buffering_debug; -@@innodb_change_buffering_debug -1 -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1,z+1 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+10,z+10 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+20,z+20 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+50,z+50 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+100,z+100 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+200,z+200 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+400,z+400 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+800,z+800 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1600,z+1600 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+4000,z+4000 FROM corrupt_bit_test_ā; -select count(*) from corrupt_bit_test_ā; count(*) -1024 -CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c); -INSERT INTO corrupt_bit_test_ā VALUES(13000,'x',1,1); -CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z); -check table corrupt_bit_test_ā; +2 Table Op Msg_type Msg_text -test.corrupt_bit_test_ā check Warning InnoDB: The B-tree of index "idxā" is corrupted. -test.corrupt_bit_test_ā check Warning InnoDB: The B-tree of index "idxē" is corrupted. +test.corrupt_bit_test_ā check Warning InnoDB: Index "idx" is marked as corrupted +test.corrupt_bit_test_ā check Warning InnoDB: Index "idxā" is marked as corrupted +test.corrupt_bit_test_ā check Warning InnoDB: Index "idxē" is marked as corrupted test.corrupt_bit_test_ā check error Corrupt -select c from corrupt_bit_test_ā; ERROR HY000: Index corrupt_bit_test_ā is corrupted -select z from corrupt_bit_test_ā; ERROR HY000: Index corrupt_bit_test_ā is corrupted -show warnings; +ERROR HY000: Index corrupt_bit_test_ā is corrupted +ERROR HY000: Index corrupt_bit_test_ā is corrupted Level Code Message Warning 179 InnoDB: Index "idxē" for table "test"."corrupt_bit_test_ā" is marked as corrupted Warning 179 Got error 179 when reading table `test`.`corrupt_bit_test_ā` Error 1712 Index corrupt_bit_test_ā is corrupted -insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001); -select * from corrupt_bit_test_ā use index(primary) where a = 10001; a b c z 10001 a 20001 20001 -begin; -insert into corrupt_bit_test_ā values (10002, "a", 20002, 20002); -delete from corrupt_bit_test_ā where a = 10001; -insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001); -rollback; -drop index idxā on corrupt_bit_test_ā; -check table corrupt_bit_test_ā; Table Op Msg_type Msg_text +test.corrupt_bit_test_ā check Warning InnoDB: Index "idx" is marked as corrupted test.corrupt_bit_test_ā check Warning InnoDB: Index "idxē" is marked as corrupted test.corrupt_bit_test_ā check error Corrupt -set names utf8; -select z from corrupt_bit_test_ā; ERROR HY000: Index corrupt_bit_test_ā is corrupted -drop index idxē on corrupt_bit_test_ā; -select z from corrupt_bit_test_ā limit 10; +Table Create Table +corrupt_bit_test_ā CREATE TABLE `corrupt_bit_test_ā` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` char(100) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `z` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `idxē` (`z`,`b`), + KEY `idx` (`b`) +) ENGINE=InnoDB AUTO_INCREMENT=10003 DEFAULT CHARSET=latin1 +ERROR HY000: Index corrupt_bit_test_ā is corrupted +ERROR HY000: Index corrupt_bit_test_ā is corrupted +Table Create Table +corrupt_bit_test_ā CREATE TABLE `corrupt_bit_test_ā` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` char(100) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `z` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx` (`b`) +) ENGINE=InnoDB AUTO_INCREMENT=10003 DEFAULT CHARSET=latin1 z 20001 1 -1 2 -11 -12 -21 -22 -31 -32 -drop table corrupt_bit_test_ā; -DROP DATABASE pad; -SET GLOBAL innodb_change_buffering_debug = 0; diff --git a/mysql-test/suite/innodb/t/innodb_corrupt_bit.test b/mysql-test/suite/innodb/t/innodb_corrupt_bit.test index 88da919bfaa..f67e2e7e047 100644 --- a/mysql-test/suite/innodb/t/innodb_corrupt_bit.test +++ b/mysql-test/suite/innodb/t/innodb_corrupt_bit.test @@ -2,45 +2,23 @@ # Test for persistent corrupt bit for corrupted index and table # -- source include/have_innodb.inc - -# Issues with innodb_change_buffering_debug on Windows, so the test scenario -# cannot be created on windows ---source include/not_windows.inc - +-- source include/not_embedded.inc # This test needs debug server ---source include/have_debug.inc +-- source include/have_debug.inc -- disable_query_log call mtr.add_suppression("Flagged corruption of idx.*in CHECK TABLE"); -# This test setup is extracted from bug56680.test: -# The flag innodb_change_buffering_debug is only available in debug builds. -# It instructs InnoDB to try to evict pages from the buffer pool when -# change buffering is possible, so that the change buffer will be used -# whenever possible. -SET @innodb_change_buffering_debug_orig = @@innodb_change_buffering_debug; -SET GLOBAL innodb_change_buffering_debug = 1; - -# Turn off Unique Check to create corrupted index with dup key -SET UNIQUE_CHECKS=0; - -CREATE DATABASE pad; -let $i=338; -while ($i) -{ ---eval CREATE TABLE pad.t$i(a INT PRIMARY KEY)ENGINE=InnoDB; - dec $i; -} - --- enable_query_log set names utf8; +SET UNIQUE_CHECKS=0; + CREATE TABLE corrupt_bit_test_ā( a INT AUTO_INCREMENT PRIMARY KEY, b CHAR(100), c INT, z INT, - INDEX(b)) + INDEX idx(b)) ENGINE=InnoDB; INSERT INTO corrupt_bit_test_ā VALUES(0,'x',1, 1); @@ -53,38 +31,21 @@ CREATE UNIQUE INDEX idxē ON corrupt_bit_test_ā(z, b); SELECT * FROM corrupt_bit_test_ā; -select @@unique_checks; -select @@innodb_change_buffering_debug; - -# Create enough rows for the table, so that the insert buffer will be -# used for modifying the secondary index page. There must be multiple -# index pages, because changes to the root page are never buffered. - INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1,z+1 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+10,z+10 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+20,z+20 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+50,z+50 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+100,z+100 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+200,z+200 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+400,z+400 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+800,z+800 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1600,z+1600 FROM corrupt_bit_test_ā; -INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+4000,z+4000 FROM corrupt_bit_test_ā; select count(*) from corrupt_bit_test_ā; -CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c); - -# Create a dup key error on index "idxē" and "idxā" by inserting a dup value -INSERT INTO corrupt_bit_test_ā VALUES(13000,'x',1,1); +# This will flag all secondary indexes corrupted +SET SESSION debug_dbug="+d,dict_set_index_corrupted"; +check table corrupt_bit_test_ā; +SET SESSION debug_dbug="-d,dict_set_index_corrupted"; -# creating an index should succeed even if other secondary indexes are corrupted +# Cannot create new indexes while corrupted indexes exist +--error ER_INDEX_CORRUPT +CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c); +--error ER_INDEX_CORRUPT CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z); -# Check table will find the unique indexes corrupted -# with dup key -check table corrupt_bit_test_ā; - # This selection intend to use the corrupted index. Expect to fail -- error ER_INDEX_CORRUPT select c from corrupt_bit_test_ā; @@ -108,7 +69,6 @@ delete from corrupt_bit_test_ā where a = 10001; insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001); rollback; -# Drop one corrupted index before reboot drop index idxā on corrupt_bit_test_ā; check table corrupt_bit_test_ā; @@ -118,14 +78,26 @@ set names utf8; -- error ER_INDEX_CORRUPT select z from corrupt_bit_test_ā; +show create table corrupt_bit_test_ā; + # Drop the corrupted index drop index idxē on corrupt_bit_test_ā; +# Cannot create new indexes while a corrupt index exists. +--error ER_INDEX_CORRUPT +CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c); +--error ER_INDEX_CORRUPT +CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z); + +show create table corrupt_bit_test_ā; +drop index idx on corrupt_bit_test_ā; + +# Now that there exist no corrupted indexes, we can create new indexes. +CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c); +CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z); + # Now select back to normal select z from corrupt_bit_test_ā limit 10; # Drop table drop table corrupt_bit_test_ā; -DROP DATABASE pad; - -SET GLOBAL innodb_change_buffering_debug = 0; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b3e6b3c7310..734dbe1cafd 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2106,7 +2106,6 @@ no_db_name: A wrapper function of innobase_convert_name(), convert a table or index name to the MySQL system_charset_info (UTF-8) and quote it if needed. @return pointer to the end of buf */ -static inline void innobase_format_name( /*==================*/ @@ -8685,6 +8684,36 @@ ha_innobase::check( DBUG_RETURN(HA_ADMIN_CORRUPT); } + if (prebuilt->table->corrupted) { + char index_name[MAX_FULL_NAME_LEN + 1]; + /* If some previous operation has marked the table as + corrupted in memory, and has not propagated such to + clustered index, we will do so here */ + index = dict_table_get_first_index(prebuilt->table); + + if (!dict_index_is_corrupted(index)) { + row_mysql_lock_data_dictionary(prebuilt->trx); + dict_set_corrupted(index); + row_mysql_unlock_data_dictionary(prebuilt->trx); + } + + innobase_format_name(index_name, sizeof index_name, + index->name, TRUE); + + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_INDEX_CORRUPT, + "InnoDB: Index %s is marked as" + " corrupted", + index_name); + + /* Now that the table is already marked as corrupted, + there is no need to check any index of this table */ + prebuilt->trx->op_info = ""; + + DBUG_RETURN(HA_ADMIN_CORRUPT); + } + prebuilt->trx->op_info = "checking table"; old_isolation_level = prebuilt->trx->isolation_level; @@ -8761,6 +8790,15 @@ ha_innobase::check( prebuilt->index_usable = row_merge_is_index_usable( prebuilt->trx, prebuilt->index); + DBUG_EXECUTE_IF( + "dict_set_index_corrupted", + if (!dict_index_is_clust(index)) { + prebuilt->index_usable = FALSE; + row_mysql_lock_data_dictionary(prebuilt->trx); + dict_set_corrupted(index); + row_mysql_unlock_data_dictionary(prebuilt->trx); + }); + if (UNIV_UNLIKELY(!prebuilt->index_usable)) { innobase_format_name( index_name, sizeof index_name, diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 735d9fb95d0..ecfda6d6264 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -654,6 +654,19 @@ public: ~ha_innobase_add_index() {} }; + +/*****************************************************************//** +A wrapper function of innobase_convert_name(), convert a table or +index name to the MySQL system_charset_info (UTF-8) and quote it if needed. +@return pointer to the end of buf */ +void +innobase_format_name( +/*==================*/ + char* buf, /*!< out: buffer for converted identifier */ + ulint buflen, /*!< in: length of buf, in bytes */ + const char* name, /*!< in: index or table name to format */ + ibool is_index_name); /*!< in: index name */ + /*******************************************************************//** Create indexes. @return 0 or error number */ @@ -715,6 +728,28 @@ ha_innobase::add_index( DBUG_RETURN(-1); } + /* Check if any of the existing indexes are marked as corruption, + and if they are, refuse adding more indexes. */ + for (dict_index_t* check_index = dict_table_get_first_index(indexed_table); + check_index != NULL; + check_index = dict_table_get_next_index(check_index)) { + + if (dict_index_is_corrupted(check_index)) { + char index_name[MAX_FULL_NAME_LEN + 1]; + + innobase_format_name(index_name, sizeof index_name, + check_index->name, TRUE); + + push_warning_printf(user_thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_INDEX_CORRUPT, + "InnoDB: Index %s is marked as" + " corrupted", + index_name); + DBUG_RETURN(HA_ERR_INDEX_CORRUPT); + } + } + /* Check that index keys are sensible */ error = innobase_check_index_keys(key_info, num_of_keys, prebuilt->table); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index fcf387bd892..8148c3e1dd5 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -2409,7 +2409,6 @@ no_db_name: A wrapper function of innobase_convert_name(), convert a table or index name to the MySQL system_charset_info (UTF-8) and quote it if needed. @return pointer to the end of buf */ -static inline void innobase_format_name( /*==================*/ @@ -9859,6 +9858,36 @@ ha_innobase::check( DBUG_RETURN(HA_ADMIN_CORRUPT); } + if (prebuilt->table->corrupted) { + char index_name[MAX_FULL_NAME_LEN + 1]; + /* If some previous operation has marked the table as + corrupted in memory, and has not propagated such to + clustered index, we will do so here */ + index = dict_table_get_first_index(prebuilt->table); + + if (!dict_index_is_corrupted(index)) { + row_mysql_lock_data_dictionary(prebuilt->trx); + dict_set_corrupted(index); + row_mysql_unlock_data_dictionary(prebuilt->trx); + } + + innobase_format_name(index_name, sizeof index_name, + index->name, TRUE); + + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_INDEX_CORRUPT, + "InnoDB: Index %s is marked as" + " corrupted", + index_name); + + /* Now that the table is already marked as corrupted, + there is no need to check any index of this table */ + prebuilt->trx->op_info = ""; + + DBUG_RETURN(HA_ADMIN_CORRUPT); + } + prebuilt->trx->op_info = "checking table"; old_isolation_level = prebuilt->trx->isolation_level; @@ -9935,6 +9964,15 @@ ha_innobase::check( prebuilt->index_usable = row_merge_is_index_usable( prebuilt->trx, prebuilt->index); + DBUG_EXECUTE_IF( + "dict_set_index_corrupted", + if (!dict_index_is_clust(index)) { + prebuilt->index_usable = FALSE; + row_mysql_lock_data_dictionary(prebuilt->trx); + dict_set_corrupted(index); + row_mysql_unlock_data_dictionary(prebuilt->trx); + }); + if (UNIV_UNLIKELY(!prebuilt->index_usable)) { innobase_format_name( index_name, sizeof index_name, diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 65b2c2f58df..82902db8412 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -655,6 +655,19 @@ public: ~ha_innobase_add_index() {} }; + +/*****************************************************************//** +A wrapper function of innobase_convert_name(), convert a table or +index name to the MySQL system_charset_info (UTF-8) and quote it if needed. +@return pointer to the end of buf */ +void +innobase_format_name( +/*==================*/ + char* buf, /*!< out: buffer for converted identifier */ + ulint buflen, /*!< in: length of buf, in bytes */ + const char* name, /*!< in: index or table name to format */ + ibool is_index_name); /*!< in: index name */ + /*******************************************************************//** Create indexes. @return 0 or error number */ @@ -720,6 +733,28 @@ ha_innobase::add_index( DBUG_RETURN(-1); } + /* Check if any of the existing indexes are marked as corruption, + and if they are, refuse adding more indexes. */ + for (dict_index_t* check_index = dict_table_get_first_index(indexed_table); + check_index != NULL; + check_index = dict_table_get_next_index(check_index)) { + + if (dict_index_is_corrupted(check_index)) { + char index_name[MAX_FULL_NAME_LEN + 1]; + + innobase_format_name(index_name, sizeof index_name, + check_index->name, TRUE); + + push_warning_printf(user_thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_INDEX_CORRUPT, + "InnoDB: Index %s is marked as" + " corrupted", + index_name); + DBUG_RETURN(HA_ERR_INDEX_CORRUPT); + } + } + /* Check that index keys are sensible */ error = innobase_check_index_keys(key_info, num_of_keys, prebuilt->table); -- cgit v1.2.1 From a4848e975d2fe359ff354e767427c01dbe908037 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 8 Jun 2016 19:04:12 +0400 Subject: MDEV-9972 Least function retuns date in date time format --- mysql-test/r/type_date.result | 7 ++++--- mysql-test/t/type_date.test | 1 + sql/item_func.cc | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index 7678f038862..ecbda1d13e6 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -442,6 +442,7 @@ select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1; drop table t1; # # MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null +# MDEV-9972 Least function retuns date in date time format # CREATE TABLE t1 ( id BIGINT NOT NULL, @@ -465,9 +466,9 @@ LEAST(IFNULL(t2.date_fin, IFNULL(t1.date_fin, NULL)), IFNULL(t1.date_fin, IFNULL(t2.date_fin, NULL))) AS date_fin FROM t1 LEFT JOIN t2 ON (t1.id=t2.id); id date_debut date_fin -1 2016-01-01 2016-01-31 00:00:00 -2 2016-02-01 2016-01-28 00:00:00 -3 2016-03-01 2016-03-31 00:00:00 +1 2016-01-01 2016-01-31 +2 2016-02-01 2016-01-28 +3 2016-03-01 2016-03-31 4 2016-04-01 NULL DROP TABLE t1,t2; SELECT diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 4b058171ad2..8b0c5dcf330 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -388,6 +388,7 @@ drop table t1; --echo # --echo # MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null +--echo # MDEV-9972 Least function retuns date in date time format --echo # CREATE TABLE t1 ( id BIGINT NOT NULL, diff --git a/sql/item_func.cc b/sql/item_func.cc index cabba7a666c..4b5f96cd3e7 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2939,12 +2939,13 @@ bool Item_func_min_max::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) } unpack_time(min_max, ltime); - if (compare_as_dates->field_type() == MYSQL_TYPE_DATE) + enum_field_types ftype= compare_as_dates->field_type(); + if (ftype == MYSQL_TYPE_DATE || ftype == MYSQL_TYPE_NEWDATE) { ltime->time_type= MYSQL_TIMESTAMP_DATE; ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0; } - else if (compare_as_dates->field_type() == MYSQL_TYPE_TIME) + else if (ftype == MYSQL_TYPE_TIME) { ltime->time_type= MYSQL_TIMESTAMP_TIME; ltime->hour+= (ltime->month * 32 + ltime->day) * 24; -- cgit v1.2.1 From 7adf04e237c41d323b5181c108e7babed3c015fa Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 5 Jan 2016 22:48:50 +0100 Subject: MDEV-9366 : do_shutdown_server fails to detect server shutdown on Windows. Fix test whether process is alive in mysqltest. Also fix SHUT_RD definition on Windows to be SD_RECEIVE. SD_BOTH was used instead prior to this patch, and this would occasionally make mysql_shutdown() fail - when the socket for the current connection is not able send the COM_SHUTDOWN response anymore. --- client/mysqltest.cc | 5 +++-- include/violite.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 9a1dfaa18ef..3652d1a40e2 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -5086,12 +5086,13 @@ static int my_kill(int pid, int sig) { #ifdef __WIN__ HANDLE proc; - if ((proc= OpenProcess(PROCESS_TERMINATE, FALSE, pid)) == NULL) + if ((proc= OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid)) == NULL) return -1; if (sig == 0) { + DWORD wait_result= WaitForSingleObject(proc, 0); CloseHandle(proc); - return 0; + return wait_result == WAIT_OBJECT_0?-1:0; } (void)TerminateProcess(proc, 201); CloseHandle(proc); diff --git a/include/violite.h b/include/violite.h index ea7e3d7897c..da58de4373c 100644 --- a/include/violite.h +++ b/include/violite.h @@ -184,7 +184,7 @@ void vio_end(void); /* shutdown(2) flags */ #ifndef SHUT_RD -#define SHUT_RD SD_BOTH +#define SHUT_RD SD_RECEIVE #endif /* -- cgit v1.2.1 From df1448801ceba4d8d8a02db83ba022fea9e6755d Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 10 Jun 2016 15:50:19 +0400 Subject: MDEV-10181 Illegal mix of collation for a field and an ASCII string as a view field --- mysql-test/r/ctype_recoding.result | 33 ++++++++++++++++++++++++++++++++- mysql-test/t/ctype_recoding.test | 28 +++++++++++++++++++++++++++- sql/field.cc | 1 + sql/field.h | 21 ++++++++++++--------- sql/sql_select.cc | 6 ++++-- 5 files changed, 76 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index c84da0d7496..2555749fa8c 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -277,9 +277,40 @@ CREATE TABLE t1 ( a VARCHAR(1) ); INSERT INTO t1 VALUES ('m'),('n'); CREATE VIEW v1 AS SELECT 'w' ; SELECT * FROM t1 WHERE a < ALL ( SELECT * FROM v1 ); -ERROR HY000: Illegal mix of collations (utf8_general_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation '<=' +a +m +n drop view v1; drop table t1; SET character_set_connection = default; SET optimizer_switch= default; #End of 5.3 tests +# +# Start of 5.5 tests +# +# +# MDEV-10181 Illegal mix of collation for a field and an ASCII string as a view field +# +SET NAMES utf8; +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1); +INSERT INTO t1 VALUES ('A'),('a'),('B'),('b'); +CREATE VIEW v1 AS SELECT 'a'; +SELECT * FROM v1,t1 where t1.a=v1.a; +a a +a A +a a +DROP VIEW v1; +DROP TABLE t1; +SET NAMES utf8; +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1); +INSERT INTO t1 VALUES ('a'),('b'),('c'); +CREATE VIEW v1 AS SELECT 'a' AS a UNION SELECT 'b'; +SELECT * FROM v1,t1 WHERE t1.a=v1.a; +a a +a a +b b +DROP VIEW v1; +DROP TABLE t1; +# +# End of 5.5 tests +# diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test index ee07ef24def..81c04fc9c30 100644 --- a/mysql-test/t/ctype_recoding.test +++ b/mysql-test/t/ctype_recoding.test @@ -220,7 +220,6 @@ SET character_set_connection = utf8; CREATE TABLE t1 ( a VARCHAR(1) ); INSERT INTO t1 VALUES ('m'),('n'); CREATE VIEW v1 AS SELECT 'w' ; ---error ER_CANT_AGGREGATE_2COLLATIONS SELECT * FROM t1 WHERE a < ALL ( SELECT * FROM v1 ); drop view v1; drop table t1; @@ -228,3 +227,30 @@ SET character_set_connection = default; SET optimizer_switch= default; --echo #End of 5.3 tests + +--echo # +--echo # Start of 5.5 tests +--echo # + +--echo # +--echo # MDEV-10181 Illegal mix of collation for a field and an ASCII string as a view field +--echo # +SET NAMES utf8; +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1); +INSERT INTO t1 VALUES ('A'),('a'),('B'),('b'); +CREATE VIEW v1 AS SELECT 'a'; +SELECT * FROM v1,t1 where t1.a=v1.a; +DROP VIEW v1; +DROP TABLE t1; + +SET NAMES utf8; +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1); +INSERT INTO t1 VALUES ('a'),('b'),('c'); +CREATE VIEW v1 AS SELECT 'a' AS a UNION SELECT 'b'; +SELECT * FROM v1,t1 WHERE t1.a=v1.a; +DROP VIEW v1; +DROP TABLE t1; + +--echo # +--echo # End of 5.5 tests +--echo # diff --git a/sql/field.cc b/sql/field.cc index ceea0893a3f..a0686fb2f19 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1701,6 +1701,7 @@ Field_str::Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, if (charset_arg->state & MY_CS_BINSORT) flags|=BINARY_FLAG; field_derivation= DERIVATION_IMPLICIT; + field_repertoire= my_charset_repertoire(charset_arg); } diff --git a/sql/field.h b/sql/field.h index f761aa8d3ea..fdf229edfbb 100644 --- a/sql/field.h +++ b/sql/field.h @@ -580,11 +580,12 @@ public: { return binary() ? &my_charset_bin : charset(); } virtual CHARSET_INFO *sort_charset(void) const { return charset(); } virtual bool has_charset(void) const { return FALSE; } - virtual void set_charset(CHARSET_INFO *charset_arg) { } virtual enum Derivation derivation(void) const { return DERIVATION_IMPLICIT; } virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; } - virtual void set_derivation(enum Derivation derivation_arg) { } + virtual void set_derivation(enum Derivation derivation_arg, + uint repertoire_arg) + { } virtual int set_time() { return 1; } void set_warning(MYSQL_ERROR::enum_warning_level, unsigned int code, int cuted_increment); @@ -775,8 +776,10 @@ public: class Field_str :public Field { protected: + // TODO-10.2: Reuse DTCollation instead of these three members CHARSET_INFO *field_charset; enum Derivation field_derivation; + uint field_repertoire; public: Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, @@ -799,15 +802,15 @@ public: int store_decimal(const my_decimal *); int store(const char *to,uint length,CHARSET_INFO *cs)=0; uint size_of() const { return sizeof(*this); } - uint repertoire(void) const - { - return my_charset_repertoire(field_charset); - } + uint repertoire(void) const { return field_repertoire; } CHARSET_INFO *charset(void) const { return field_charset; } - void set_charset(CHARSET_INFO *charset_arg) { field_charset= charset_arg; } enum Derivation derivation(void) const { return field_derivation; } - virtual void set_derivation(enum Derivation derivation_arg) - { field_derivation= derivation_arg; } + void set_derivation(enum Derivation derivation_arg, + uint repertoire_arg) + { + field_derivation= derivation_arg; + field_repertoire= repertoire_arg; + } bool binary() const { return field_charset == &my_charset_bin; } uint32 max_display_length() { return field_length; } friend class Create_field; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 91aecadfd0a..613cbb2e086 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -14586,7 +14586,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, item->collation.collation); else new_field= item->make_string_field(table); - new_field->set_derivation(item->collation.derivation); + new_field->set_derivation(item->collation.derivation, + item->collation.repertoire); break; case DECIMAL_RESULT: new_field= Field_new_decimal::create_from_item(item); @@ -14825,7 +14826,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, modify_item, convert_blob_length); case Item::TYPE_HOLDER: result= ((Item_type_holder *)item)->make_field_by_type(table); - result->set_derivation(item->collation.derivation); + result->set_derivation(item->collation.derivation, + item->collation.repertoire); return result; default: // Dosen't have to be stored return 0; -- cgit v1.2.1 From 4155d0937b98e57a93adbe5b5dc20d06ceda59e7 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 10 Jun 2016 17:06:38 +0400 Subject: MDEV-8402 Bug #77473 Truncated data with subquery & UTF8 --- mysql-test/r/ctype_utf8.result | 39 +++++++++++++++++++++++++++++++++++++++ mysql-test/r/ctype_utf8mb4.result | 34 ++++++++++++++++++++++++++++++++++ mysql-test/t/ctype_utf8.test | 23 +++++++++++++++++++++++ mysql-test/t/ctype_utf8mb4.test | 20 ++++++++++++++++++++ sql/field.h | 7 +++---- 5 files changed, 119 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 217d3ca26d8..121168c2a2a 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -5830,5 +5830,44 @@ OCTET_LENGTH(a) a 255 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA DROP TABLE t1; # +# MDEV-8402 Bug#77473 Bug#21317406 TRUNCATED DATA WITH SUBQUERY & UTF8 +# +# +SET NAMES utf8; +SELECT length(rpad(_utf8 0xD0B1, 65536, _utf8 0xD0B2)) AS data; +data +131072 +SELECT length(data) AS len FROM ( +SELECT rpad(_utf8 0xD0B1, 65536, _utf8 0xD0B2) AS data +) AS sub; +len +131072 +SELECT length(rpad(_utf8 0xD0B1, 65535, _utf8 0xD0B2)) AS data; +data +131070 +SELECT length(data) AS len FROM ( +SELECT rpad(_utf8 0xD0B1, 65535, _utf8 0xD0B2) AS data +) AS sub; +len +131070 +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 36766) AS data) AS sub; +len +73532 +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 36767) AS data) AS sub; +len +73534 +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 36778) AS data) AS sub; +len +73556 +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 65535) AS data) AS sub; +len +131070 +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 65536) AS data) AS sub; +len +131072 +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 65537) AS data) AS sub; +len +131074 +# # End of 5.5 tests # diff --git a/mysql-test/r/ctype_utf8mb4.result b/mysql-test/r/ctype_utf8mb4.result index 448645ebbae..17a1a2f787e 100644 --- a/mysql-test/r/ctype_utf8mb4.result +++ b/mysql-test/r/ctype_utf8mb4.result @@ -2622,6 +2622,40 @@ OCTET_LENGTH(a) a 252 😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎 DROP TABLE t1; # +# MDEV-8402 Bug#77473 Bug#21317406 TRUNCATED DATA WITH SUBQUERY & UTF8 +# +# +SET NAMES utf8mb4; +SELECT length(repeat(_utf8mb4 0xE29883, 21844)) AS data; +data +65532 +SELECT length(data) AS len +FROM ( SELECT repeat(_utf8mb4 0xE29883, 21844) AS data ) AS sub; +len +65532 +SELECT length(repeat(_utf8mb4 0xE29883, 21846)) AS data; +data +65538 +SELECT length(data) AS len +FROM ( SELECT repeat(_utf8mb4 0xE29883, 21846) AS data ) AS sub; +len +65538 +SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 21844) AS data ) AS sub; +len +65532 +SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 21845) AS data ) AS sub; +len +65535 +SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 21846) AS data ) AS sub; +len +65538 +SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 65535) AS data ) AS sub; +len +196605 +SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 65536) AS data ) AS sub; +len +196608 +# # End of 5.5 tests # # diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index a9b5cee11ce..d6fdc6c6a2c 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1658,6 +1658,29 @@ ALTER TABLE t1 MODIFY a TINYTEXT CHARACTER SET utf8; SELECT OCTET_LENGTH(a),a FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-8402 Bug#77473 Bug#21317406 TRUNCATED DATA WITH SUBQUERY & UTF8 +--echo # +--echo # + +SET NAMES utf8; +SELECT length(rpad(_utf8 0xD0B1, 65536, _utf8 0xD0B2)) AS data; +SELECT length(data) AS len FROM ( + SELECT rpad(_utf8 0xD0B1, 65536, _utf8 0xD0B2) AS data +) AS sub; + +SELECT length(rpad(_utf8 0xD0B1, 65535, _utf8 0xD0B2)) AS data; +SELECT length(data) AS len FROM ( + SELECT rpad(_utf8 0xD0B1, 65535, _utf8 0xD0B2) AS data +) AS sub; + +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 36766) AS data) AS sub; +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 36767) AS data) AS sub; +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 36778) AS data) AS sub; +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 65535) AS data) AS sub; +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 65536) AS data) AS sub; +SELECT length(data) AS len FROM (SELECT REPEAT('ä', 65537) AS data) AS sub; + --echo # --echo # End of 5.5 tests --echo # diff --git a/mysql-test/t/ctype_utf8mb4.test b/mysql-test/t/ctype_utf8mb4.test index 66f5a3ba5ac..c240f261af4 100644 --- a/mysql-test/t/ctype_utf8mb4.test +++ b/mysql-test/t/ctype_utf8mb4.test @@ -1838,6 +1838,26 @@ SELECT OCTET_LENGTH(a),a FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-8402 Bug#77473 Bug#21317406 TRUNCATED DATA WITH SUBQUERY & UTF8 +--echo # +--echo # + +SET NAMES utf8mb4; +SELECT length(repeat(_utf8mb4 0xE29883, 21844)) AS data; +SELECT length(data) AS len +FROM ( SELECT repeat(_utf8mb4 0xE29883, 21844) AS data ) AS sub; + +SELECT length(repeat(_utf8mb4 0xE29883, 21846)) AS data; +SELECT length(data) AS len +FROM ( SELECT repeat(_utf8mb4 0xE29883, 21846) AS data ) AS sub; + +SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 21844) AS data ) AS sub; +SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 21845) AS data ) AS sub; +SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 21846) AS data ) AS sub; +SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 65535) AS data ) AS sub; +SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 65536) AS data ) AS sub; + --echo # --echo # End of 5.5 tests --echo # diff --git a/sql/field.h b/sql/field.h index fdf229edfbb..f8fc7427618 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1854,10 +1854,9 @@ public: packlength= 4; if (set_packlength) { - uint32 l_char_length= len_arg/cs->mbmaxlen; - packlength= l_char_length <= 255 ? 1 : - l_char_length <= 65535 ? 2 : - l_char_length <= 16777215 ? 3 : 4; + packlength= len_arg <= 255 ? 1 : + len_arg <= 65535 ? 2 : + len_arg <= 16777215 ? 3 : 4; } } Field_blob(uint32 packlength_arg) -- cgit v1.2.1 From 87007dc2f71634cc460271eb277ad851ec69c04b Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 8 Jun 2016 15:03:18 +0400 Subject: MDEV-9994 - Aria service threads are not "joined" Aria service threads are created "joinable", but they're not "joined" on completion. This causes memory leaks around thread local storage. Fixed by joining service thread. Simplified relevant code and cleaned up relevant valgrind suppressions. --- mysql-test/valgrind.supp | 70 ---------------------------------------- storage/maria/ma_checkpoint.c | 18 +++++------ storage/maria/ma_loghandler.c | 11 +++---- storage/maria/ma_servicethread.c | 51 +++++++---------------------- storage/maria/ma_servicethread.h | 7 ++-- 5 files changed, 26 insertions(+), 131 deletions(-) diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 29897e4bd6c..16b59b8a06f 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -19,36 +19,6 @@ # Suppress some common (not fatal) errors in system libraries found by valgrind # -# -# Pthread doesn't free all thread specific memory before program exists -# -{ - pthread allocate_tls memory loss - Memcheck:Leak - fun:calloc - fun:_dl_allocate_tls - fun:allocate_stack - fun:pthread_create* -} - -{ - pthread allocate_tls memory loss - Memcheck:Leak - fun:calloc - fun:_dl_allocate_tls - fun:pthread_create* - -} - -{ - pthread allocate_tls memory loss - Memcheck:Leak - fun:calloc - obj:/lib*/ld*.so - fun:_dl_allocate_tls - fun:pthread_create* -} - { pthead_exit memory loss 1 Memcheck:Leak @@ -89,34 +59,6 @@ fun:_dl_map_object_from_fd } -{ - pthread allocate_dtv memory loss - Memcheck:Leak - fun:calloc - fun:allocate_dtv - fun:_dl_allocate_tls_storage - fun:__GI__dl_allocate_tls - fun:pthread_create -} - -{ - pthread allocate_dtv memory loss second - Memcheck:Leak - fun:calloc - fun:allocate_dtv - fun:_dl_allocate_tls - fun:pthread_create* -} - -{ - pthread memalign memory loss - Memcheck:Leak - fun:memalign - fun:_dl_allocate_tls_storage - fun:__GI__dl_allocate_tls - fun:pthread_create -} - { pthread pthread_key_create Memcheck:Leak @@ -972,18 +914,6 @@ fun:nptl_pthread_exit_hack_handler } -# -# Pthread doesn't free all thread specific memory before program exists -# -{ - pthread allocate_tls memory loss in 2.6.1. - Memcheck:Leak - fun:calloc - obj:*/ld-*.so - fun:_dl_allocate_tls - fun:pthread_create* -} - { memory "leak" in backtrace() of glibc 2.9 (not present in 2.13) Memcheck:Leak diff --git a/storage/maria/ma_checkpoint.c b/storage/maria/ma_checkpoint.c index 1e8adb64981..f01af164aa6 100644 --- a/storage/maria/ma_checkpoint.c +++ b/storage/maria/ma_checkpoint.c @@ -46,7 +46,7 @@ static mysql_mutex_t LOCK_checkpoint; static mysql_cond_t COND_checkpoint; /** @brief control structure for checkpoint background thread */ static MA_SERVICE_THREAD_CONTROL checkpoint_control= - {THREAD_DEAD, FALSE, &LOCK_checkpoint, &COND_checkpoint}; + {0, FALSE, FALSE, &LOCK_checkpoint, &COND_checkpoint}; /* is ulong like pagecache->blocks_changed */ static ulong pages_to_flush_before_next_checkpoint; static PAGECACHE_FILE *dfiles, /**< data files to flush in background */ @@ -326,7 +326,6 @@ end: int ma_checkpoint_init(ulong interval) { - pthread_t th; int res= 0; DBUG_ENTER("ma_checkpoint_init"); if (ma_service_thread_control_init(&checkpoint_control)) @@ -334,14 +333,14 @@ int ma_checkpoint_init(ulong interval) else if (interval > 0) { compile_time_assert(sizeof(void *) >= sizeof(ulong)); - if (!(res= mysql_thread_create(key_thread_checkpoint, - &th, NULL, ma_checkpoint_background, - (void *)interval))) - { - /* thread lives, will have to be killed */ - checkpoint_control.status= THREAD_RUNNING; - } + if ((res= mysql_thread_create(key_thread_checkpoint, + &checkpoint_control.thread, NULL, + ma_checkpoint_background, + (void*) interval))) + checkpoint_control.killed= TRUE; } + else + checkpoint_control.killed= TRUE; DBUG_RETURN(res); } @@ -717,7 +716,6 @@ pthread_handler_t ma_checkpoint_background(void *arg) DBUG_EXECUTE_IF("maria_checkpoint_indirect", level= CHECKPOINT_INDIRECT;); ma_checkpoint_execute(level, FALSE); } - my_service_thread_signal_end(&checkpoint_control); my_thread_end(); return 0; } diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 54f67eb1ab3..bf2205f5a4c 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -54,7 +54,7 @@ static mysql_mutex_t LOCK_soft_sync; static mysql_cond_t COND_soft_sync; /** @brief control structure for checkpoint background thread */ static MA_SERVICE_THREAD_CONTROL soft_sync_control= - {THREAD_DEAD, FALSE, &LOCK_soft_sync, &COND_soft_sync}; + {0, FALSE, FALSE, &LOCK_soft_sync, &COND_soft_sync}; /* transaction log file descriptor */ @@ -8819,7 +8819,6 @@ ma_soft_sync_background( void *arg __attribute__((unused))) if (my_service_thread_sleep(&soft_sync_control, sleep)) break; } - my_service_thread_signal_end(&soft_sync_control); my_thread_end(); DBUG_RETURN(0); } @@ -8832,7 +8831,6 @@ ma_soft_sync_background( void *arg __attribute__((unused))) int translog_soft_sync_start(void) { - pthread_t th; int res= 0; uint32 min, max; DBUG_ENTER("translog_soft_sync_start"); @@ -8847,9 +8845,10 @@ int translog_soft_sync_start(void) soft_need_sync= 1; if (!(res= ma_service_thread_control_init(&soft_sync_control))) - if (!(res= mysql_thread_create(key_thread_soft_sync, - &th, NULL, ma_soft_sync_background, NULL))) - soft_sync_control.status= THREAD_RUNNING; + if ((res= mysql_thread_create(key_thread_soft_sync, + &soft_sync_control.thread, NULL, + ma_soft_sync_background, NULL))) + soft_sync_control.killed= TRUE; DBUG_RETURN(res); } diff --git a/storage/maria/ma_servicethread.c b/storage/maria/ma_servicethread.c index e5c949a7571..d92c5315933 100644 --- a/storage/maria/ma_servicethread.c +++ b/storage/maria/ma_servicethread.c @@ -33,7 +33,7 @@ int ma_service_thread_control_init(MA_SERVICE_THREAD_CONTROL *control) DBUG_ENTER("ma_service_thread_control_init"); DBUG_PRINT("init", ("control 0x%lx", (ulong) control)); control->inited= TRUE; - control->status= THREAD_DEAD; /* not yet born == dead */ + control->killed= FALSE; res= (mysql_mutex_init(key_SERVICE_THREAD_CONTROL_lock, control->LOCK_control, MY_MUTEX_INIT_SLOW) || mysql_cond_init(key_SERVICE_THREAD_CONTROL_cond, @@ -60,20 +60,17 @@ void ma_service_thread_control_end(MA_SERVICE_THREAD_CONTROL *control) DBUG_PRINT("init", ("control 0x%lx", (ulong) control)); DBUG_ASSERT(control->inited); mysql_mutex_lock(control->LOCK_control); - if (control->status != THREAD_DEAD) /* thread was started OK */ + if (!control->killed) { DBUG_PRINT("info",("killing Maria background thread")); - control->status= THREAD_DYING; /* kill it */ - do /* and wait for it to be dead */ - { - /* wake it up if it was in a sleep */ - mysql_cond_broadcast(control->COND_control); - DBUG_PRINT("info",("waiting for Maria background thread to die")); - mysql_cond_wait(control->COND_control, control->LOCK_control); - } - while (control->status != THREAD_DEAD); + control->killed= TRUE; /* kill it */ + mysql_cond_broadcast(control->COND_control); + mysql_mutex_unlock(control->LOCK_control); + DBUG_PRINT("info", ("waiting for Maria background thread to die")); + pthread_join(control->thread, NULL); } - mysql_mutex_unlock(control->LOCK_control); + else + mysql_mutex_unlock(control->LOCK_control); mysql_mutex_destroy(control->LOCK_control); mysql_cond_destroy(control->COND_control); control->inited= FALSE; @@ -100,7 +97,7 @@ my_bool my_service_thread_sleep(MA_SERVICE_THREAD_CONTROL *control, DBUG_ENTER("my_service_thread_sleep"); DBUG_PRINT("init", ("control 0x%lx", (ulong) control)); mysql_mutex_lock(control->LOCK_control); - if (control->status == THREAD_DYING) + if (control->killed) { mysql_mutex_unlock(control->LOCK_control); DBUG_RETURN(TRUE); @@ -119,34 +116,8 @@ my_bool my_service_thread_sleep(MA_SERVICE_THREAD_CONTROL *control, control->LOCK_control, &abstime); } #endif - if (control->status == THREAD_DYING) + if (control->killed) res= TRUE; mysql_mutex_unlock(control->LOCK_control); DBUG_RETURN(res); } - - -/** - inform about thread exiting - - @param control control block -*/ - -void my_service_thread_signal_end(MA_SERVICE_THREAD_CONTROL *control) -{ - DBUG_ENTER("my_service_thread_signal_end"); - DBUG_PRINT("init", ("control 0x%lx", (ulong) control)); - mysql_mutex_lock(control->LOCK_control); - control->status = THREAD_DEAD; /* indicate that we are dead */ - /* - wake up ma_service_thread_control_end which may be waiting for - our death - */ - mysql_cond_broadcast(control->COND_control); - /* - broadcast was inside unlock because ma_service_thread_control_end - destroys mutex - */ - mysql_mutex_unlock(control->LOCK_control); - DBUG_VOID_RETURN; -} diff --git a/storage/maria/ma_servicethread.h b/storage/maria/ma_servicethread.h index ed578d93c24..254225bd608 100644 --- a/storage/maria/ma_servicethread.h +++ b/storage/maria/ma_servicethread.h @@ -16,12 +16,10 @@ #include -enum ma_service_thread_state {THREAD_RUNNING, THREAD_DYING, THREAD_DEAD}; - typedef struct st_ma_service_thread_control { - /** 'kill' flag for the background thread */ - enum ma_service_thread_state status; + pthread_t thread; + my_bool killed; /** if thread module was inited or not */ my_bool inited; /** for killing the background thread */ @@ -35,4 +33,3 @@ int ma_service_thread_control_init(MA_SERVICE_THREAD_CONTROL *control); void ma_service_thread_control_end(MA_SERVICE_THREAD_CONTROL *control); my_bool my_service_thread_sleep(MA_SERVICE_THREAD_CONTROL *control, ulonglong sleep_time); -void my_service_thread_signal_end(MA_SERVICE_THREAD_CONTROL *control); -- cgit v1.2.1 From 67b4a6f576db102d652b401c3d0150556826f641 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sun, 12 Jun 2016 20:14:51 +0300 Subject: MDEV-8859 rpl.rpl_mdev382 sporadically fails to finish due to disappeared expect file The combination of --remove_file and --write_file on .expect file creates a race condition which can be hit by MTR which reads the file in a loop. Instead, .expect file should be changed with --append_file. It was fixed in 10.x, but in 5.5 the sporadic failure still affected buildbot. Fixed 3 test files which use the problematic combination --- mysql-test/suite/binlog/t/binlog_mdev342.test | 3 +-- mysql-test/suite/rpl/t/rpl_mdev382.test | 3 +-- mysql-test/suite/storage_engine/alter_tablespace.test | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/binlog/t/binlog_mdev342.test b/mysql-test/suite/binlog/t/binlog_mdev342.test index 02310b87a76..024fa884f91 100644 --- a/mysql-test/suite/binlog/t/binlog_mdev342.test +++ b/mysql-test/suite/binlog/t/binlog_mdev342.test @@ -44,8 +44,7 @@ connection con1; --error 2006,2013 reap; ---remove_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect restart-binlog_mdev342.test EOF diff --git a/mysql-test/suite/rpl/t/rpl_mdev382.test b/mysql-test/suite/rpl/t/rpl_mdev382.test index 21925e0e130..784617bd198 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev382.test +++ b/mysql-test/suite/rpl/t/rpl_mdev382.test @@ -209,8 +209,7 @@ EOF --shutdown_server 30 ---remove_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect restart-rpl_mdev382.test EOF diff --git a/mysql-test/suite/storage_engine/alter_tablespace.test b/mysql-test/suite/storage_engine/alter_tablespace.test index dec16e5a3ac..6318b410e6e 100644 --- a/mysql-test/suite/storage_engine/alter_tablespace.test +++ b/mysql-test/suite/storage_engine/alter_tablespace.test @@ -53,8 +53,7 @@ EOF --replace_result $datadir --copy_file $datadir/test/t1.ibd $datadir/test/t1.ibd.save - --remove_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect - --write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect restart EOF -- cgit v1.2.1 From 416006a3d8164684a1bfffa2e20a1f9894baf372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Sun, 12 Jun 2016 22:45:15 +0300 Subject: MDEV-8012: Wrong exit code when asking for help Make mysql_waitpid return exit code 0 when -V flag is supplied. --- extra/mysql_waitpid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/mysql_waitpid.c b/extra/mysql_waitpid.c index 7777da25aa1..aa004e57308 100644 --- a/extra/mysql_waitpid.c +++ b/extra/mysql_waitpid.c @@ -50,7 +50,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), switch(optid) { case 'V': printf("%s version %s by Jani Tolonen\n", progname, VER); - exit(-1); + exit(0); case 'I': case '?': usage(); -- cgit v1.2.1 From 3c77a00d55efe901db9cb52ec000cc93d909a3c9 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Tue, 8 Mar 2016 13:27:18 +0200 Subject: MDEV-8012: Wrong exit code when asking for help MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `--help` is a perfectly valid parameter and both `mysqladmin` and `mysql_waitpid` should exit with success (zero errror code). Signed-off-by: Vicențiu Ciorbaru --- client/mysqladmin.cc | 11 ++--------- extra/mysql_waitpid.c | 5 ++++- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 9fd8a9b36fc..e7c6410978d 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -232,8 +232,6 @@ my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) { - int error = 0; - switch(optid) { case 'c': opt_count_iterations= 1; @@ -281,8 +279,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; case '?': case 'I': /* Info */ - error++; - break; + usage(); + exit(0); case OPT_CHARSETS_DIR: #if MYSQL_VERSION_ID > 32300 charsets_dir = argument; @@ -293,11 +291,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt->name); break; } - if (error) - { - usage(); - exit(1); - } return 0; } diff --git a/extra/mysql_waitpid.c b/extra/mysql_waitpid.c index aa004e57308..5cdf1dedc27 100644 --- a/extra/mysql_waitpid.c +++ b/extra/mysql_waitpid.c @@ -54,6 +54,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case 'I': case '?': usage(); + exit(0); } return 0; } @@ -69,7 +70,10 @@ int main(int argc, char *argv[]) exit(-1); if (!argv[0] || !argv[1] || (pid= atoi(argv[0])) <= 0 || (t= atoi(argv[1])) <= 0) + { usage(); + exit(-1); + } for (; t > 0; t--) { if (kill((pid_t) pid, sig)) @@ -100,5 +104,4 @@ void usage(void) printf("integer arguments.\n\n"); printf("Options:\n"); my_print_help(my_long_options); - exit(-1); } -- cgit v1.2.1 From 2db724c8d2f3771c1a20b8cf9aaaf913b94aee68 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Mon, 13 Jun 2016 15:54:12 +0400 Subject: MDEV-10218 - rpl.rpl_binlog_errors fails in buildbot with valgrind warnings - bytes are possibly lost Timer thread of threadpool is created "joinable", but they're not "joined" on completion. This causes memory leaks around thread local storage. Fixed by joining timer thread. --- sql/threadpool_unix.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sql/threadpool_unix.cc b/sql/threadpool_unix.cc index df1a05b3ebf..6075c758e40 100644 --- a/sql/threadpool_unix.cc +++ b/sql/threadpool_unix.cc @@ -166,6 +166,7 @@ struct pool_timer_t volatile uint64 next_timeout_check; int tick_interval; bool shutdown; + pthread_t timer_thread_id; }; static pool_timer_t pool_timer; @@ -603,12 +604,12 @@ void check_stall(thread_group_t *thread_group) static void start_timer(pool_timer_t* timer) { - pthread_t thread_id; DBUG_ENTER("start_timer"); mysql_mutex_init(key_timer_mutex,&timer->mutex, NULL); mysql_cond_init(key_timer_cond, &timer->cond, NULL); timer->shutdown = false; - mysql_thread_create(key_timer_thread,&thread_id, NULL, timer_thread, timer); + mysql_thread_create(key_timer_thread, &timer->timer_thread_id, NULL, + timer_thread, timer); DBUG_VOID_RETURN; } @@ -620,6 +621,7 @@ static void stop_timer(pool_timer_t *timer) timer->shutdown = true; mysql_cond_signal(&timer->cond); mysql_mutex_unlock(&timer->mutex); + pthread_join(timer->timer_thread_id, NULL); DBUG_VOID_RETURN; } -- cgit v1.2.1 From d6a1bae57f369d6d1781b94696b87e81e39be4ca Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Mon, 13 Jun 2016 17:10:31 +0400 Subject: MDEV-10218 - rpl.rpl_binlog_errors fails in buildbot with valgrind warnings - bytes are possibly lost Restored suppressions removed by MDEV-9994: they're needed for detached threads. --- mysql-test/valgrind.supp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 16b59b8a06f..b86cbd23408 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -1047,3 +1047,22 @@ fun:_nss_dns_gethostbyaddr_r fun:gethostbyaddr_r } + + +# +# Detached threads may not complete deiniitialization by the time shutdown +# thread calls exit. This is unfortunate property of detached threads, which +# we currently can only ignore. Unfortunately there is no way to distinguish +# between false positives generated by detached threads and real memory leaks +# generated by not joined joinable threads. So we hide both cases. +# +# To avoid enumeration of the whole variety of possible traces we ignore all +# "possibly lost" blocks allocated by pthread_create (and it's callees). +# +{ + Detached threads memory loss + Memcheck:Leak + match-leak-kinds:possible + ... + fun:pthread_create* +} -- cgit v1.2.1 From f54dcf1e8742e19d13ab7fb8b92ae6a179e67fe3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 14 Jun 2016 12:38:47 +0200 Subject: 5.5.49-37.9 --- storage/xtradb/dict/dict0crea.c | 4 ++-- storage/xtradb/handler/ha_innodb.cc | 2 +- storage/xtradb/include/os0sync.h | 47 ++++++++++++++++++------------------ storage/xtradb/include/univ.i | 2 +- storage/xtradb/log/log0recv.c | 4 ++-- storage/xtradb/os/os0file.c | 48 ++++++++++++++++++++++++++++++++++++- 6 files changed, 76 insertions(+), 31 deletions(-) diff --git a/storage/xtradb/dict/dict0crea.c b/storage/xtradb/dict/dict0crea.c index 44ebca83373..b950c2d9b3f 100644 --- a/storage/xtradb/dict/dict0crea.c +++ b/storage/xtradb/dict/dict0crea.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1255,7 +1255,7 @@ dict_create_index_step( >= DICT_TF_FORMAT_ZIP); node->index = dict_index_get_if_in_cache_low(index_id); - ut_a((node->index == 0) == (err != DB_SUCCESS)); + ut_a((node->index == NULL) == (err != DB_SUCCESS)); if (err != DB_SUCCESS) { diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index effff7cf0c4..896b27a2047 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -12605,7 +12605,7 @@ innodb_buffer_pool_evict_update( mutex_enter(&block->mutex); buf_LRU_free_block(&block->page, - FALSE, FALSE); + FALSE, TRUE); mutex_exit(&block->mutex); block = prev_block; } diff --git a/storage/xtradb/include/os0sync.h b/storage/xtradb/include/os0sync.h index 83647fe3367..d7dee5e0567 100644 --- a/storage/xtradb/include/os0sync.h +++ b/storage/xtradb/include/os0sync.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -41,7 +41,6 @@ Created 9/6/1995 Heikki Tuuri || defined _M_X64 || defined __WIN__ #define IB_STRONG_MEMORY_MODEL -#undef HAVE_IB_GCC_ATOMIC_TEST_AND_SET // Quick-and-dirty fix for bug 1519094 #endif /* __i386__ || __x86_64__ || _M_IX86 || M_X64 || __WIN__ */ @@ -332,28 +331,7 @@ Returns the old value of *ptr, atomically sets *ptr to new_val */ # define os_atomic_test_and_set_byte(ptr, new_val) \ __sync_lock_test_and_set(ptr, (byte) new_val) -# if defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) - -/** Do an atomic test-and-set. -@param[in,out] ptr Memory location to set to non-zero -@return the previous value */ -static inline -lock_word_t -os_atomic_test_and_set(volatile lock_word_t* ptr) -{ - return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE)); -} - -/** Do an atomic clear. -@param[in,out] ptr Memory location to set to zero */ -static inline -void -os_atomic_clear(volatile lock_word_t* ptr) -{ - __atomic_clear(ptr, __ATOMIC_RELEASE); -} - -# elif defined(IB_STRONG_MEMORY_MODEL) +# if defined(IB_STRONG_MEMORY_MODEL) /** Do an atomic test and set. @param[in,out] ptr Memory location to set to non-zero @@ -382,6 +360,27 @@ os_atomic_clear(volatile lock_word_t* ptr) return(__sync_lock_test_and_set(ptr, 0)); } +# elif defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) + +/** Do an atomic test-and-set. +@param[in,out] ptr Memory location to set to non-zero +@return the previous value */ +static inline +lock_word_t +os_atomic_test_and_set(volatile lock_word_t* ptr) +{ + return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE)); +} + +/** Do an atomic clear. +@param[in,out] ptr Memory location to set to zero */ +static inline +void +os_atomic_clear(volatile lock_word_t* ptr) +{ + __atomic_clear(ptr, __ATOMIC_RELEASE); +} + # else # error "Unsupported platform" diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 4814a07d3a4..d5ec85ce995 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -64,7 +64,7 @@ component, i.e. we show M.N.P as M.N */ (INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR) #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 37.8 +#define PERCONA_INNODB_VERSION 37.9 #endif #define INNODB_VERSION_STR MYSQL_SERVER_VERSION diff --git a/storage/xtradb/log/log0recv.c b/storage/xtradb/log/log0recv.c index f9eddec4b4a..3429361c74c 100644 --- a/storage/xtradb/log/log0recv.c +++ b/storage/xtradb/log/log0recv.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1837,7 +1837,7 @@ loop: goto loop; } - ut_ad((allow_ibuf == 0) == (mutex_own(&log_sys->mutex) != 0)); + ut_ad((!allow_ibuf) == mutex_own(&log_sys->mutex)); if (!allow_ibuf) { recv_no_ibuf_operations = TRUE; diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c index 6e1b59aba12..21f8c3eed11 100644 --- a/storage/xtradb/os/os0file.c +++ b/storage/xtradb/os/os0file.c @@ -386,6 +386,43 @@ os_get_os_version(void) } #endif /* __WIN__ */ +/***********************************************************************//** +For an EINVAL I/O error, prints a diagnostic message if innodb_flush_method +== ALL_O_DIRECT. +@return TRUE if the diagnostic message was printed +@return FALSE if the diagnostic message does not apply */ +static +ibool +os_diagnose_all_o_direct_einval( +/*============================*/ + ulint err) /*!< in: C error code */ +{ + if ((err == EINVAL) + && (srv_unix_file_flush_method == SRV_UNIX_ALL_O_DIRECT)) { + fprintf(stderr, + "InnoDB: The error might be caused by redo log I/O " + "not satisfying innodb_flush_method=ALL_O_DIRECT " + "requirements by the underlying file system.\n"); + if (srv_log_block_size != 512) + fprintf(stderr, + "InnoDB: This might be caused by an " + "incompatible non-default " + "innodb_log_block_size value %lu.\n", + srv_log_block_size); + fprintf(stderr, + "InnoDB: Please file a bug at " + "https://bugs.percona.com and include this error " + "message, my.cnf settings, and information about the " + "file system where the redo log resides.\n"); + fprintf(stderr, + "InnoDB: A possible workaround is to change " + "innodb_flush_method value to something else " + "than ALL_O_DIRECT.\n"); + return(TRUE); + } + return(FALSE); +} + /***********************************************************************//** Retrieves the last error number if an error occurs in a file io function. The number should be retrieved before any other OS calls (because they may @@ -511,7 +548,7 @@ os_file_get_last_error( "InnoDB: The error means mysqld does not have" " the access rights to\n" "InnoDB: the directory.\n"); - } else { + } else if (!os_diagnose_all_o_direct_einval(err)) { if (strerror((int)err) != NULL) { fprintf(stderr, "InnoDB: Error number %lu" @@ -2513,6 +2550,9 @@ os_file_pwrite( /* Handle partial writes and signal interruptions correctly */ for (ret = 0; ret < (ssize_t) n; ) { n_written = pwrite(file, buf, (ssize_t)n - ret, offs); + DBUG_EXECUTE_IF("xb_simulate_all_o_direct_write_failure", + n_written = -1; + errno = EINVAL;); if (n_written >= 0) { ret += n_written; offs += n_written; @@ -2702,6 +2742,10 @@ try_again: try_again: ret = os_file_pread(file, buf, n, offset, offset_high, trx); + DBUG_EXECUTE_IF("xb_simulate_all_o_direct_read_failure", + ret = -1; + errno = EINVAL;); + if ((ulint)ret == n) { return(TRUE); @@ -3066,6 +3110,8 @@ retry: "InnoDB: " REFMAN "operating-system-error-codes.html\n"); + os_diagnose_all_o_direct_einval(errno); + os_has_said_disk_full = TRUE; } -- cgit v1.2.1 From 1b50d599606244677215fbe7b05be1a891fecf18 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Tue, 14 Jun 2016 14:44:09 +0400 Subject: MDEV-9945 - main.kill_processlist-6619 fails sporadically SHOW PROCESSLIST output can be affected by not completed concurrent KILL QUERY. Filter out more column values to make output stable. --- mysql-test/r/kill_processlist-6619.result | 4 ++-- mysql-test/t/kill_processlist-6619.test | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/kill_processlist-6619.result b/mysql-test/r/kill_processlist-6619.result index a3d971e2115..f14727f1696 100644 --- a/mysql-test/r/kill_processlist-6619.result +++ b/mysql-test/r/kill_processlist-6619.result @@ -6,5 +6,5 @@ SHOW PROCESSLIST; ERROR 70100: Query execution was interrupted SHOW PROCESSLIST; Id User Host db Command Time State Info Progress -# root # test Sleep # # NULL 0.000 -# root # test Query # # SHOW PROCESSLIST 0.000 +# root # test # # # # 0.000 +# root # test # # # # 0.000 diff --git a/mysql-test/t/kill_processlist-6619.test b/mysql-test/t/kill_processlist-6619.test index d73859ce8cd..28f98bcbb24 100644 --- a/mysql-test/t/kill_processlist-6619.test +++ b/mysql-test/t/kill_processlist-6619.test @@ -11,5 +11,5 @@ eval KILL QUERY $con_id; --connection con1 --error ER_QUERY_INTERRUPTED SHOW PROCESSLIST; ---replace_column 1 # 3 # 6 # 7 # +--replace_column 1 # 3 # 5 # 6 # 7 # 8 # SHOW PROCESSLIST; -- cgit v1.2.1 From 90eb30266bd88f9b101054ceb67d30ed4eee76e6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 14 Jun 2016 13:57:49 +0200 Subject: fix main.ssl_ca from mysql-5.5.50 1. to work for OpenSSL 2. to work when $HOME can match in the middle of $MYSQL_TEST_DIR --- mysql-test/t/ssl_ca.test | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mysql-test/t/ssl_ca.test b/mysql-test/t/ssl_ca.test index 92695de4b0d..e0a5fa9ad07 100644 --- a/mysql-test/t/ssl_ca.test +++ b/mysql-test/t/ssl_ca.test @@ -10,6 +10,7 @@ --exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/wrong-cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" 2>&1 --echo # try to connect with correct '--ssl-ca' path : should connect +--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA --exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" --echo # @@ -17,19 +18,19 @@ --echo # PATH SUBSTITUTION --echo # ---let $mysql_test_dir_path= `SELECT REPLACE('$MYSQL_TEST_DIR', '$HOME', '~')` +--let $mysql_test_dir_path= `SELECT REPLACE('=$MYSQL_TEST_DIR', '=$HOME', '=~')` --echo # try to connect with '--ssl-ca' option using tilde home directoy --echo # path substitution : should connect ---replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL --ssl-ca=$mysql_test_dir_path/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" +--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA +--exec $MYSQL --ssl-ca$mysql_test_dir_path/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" --echo # try to connect with '--ssl-key' option using tilde home directoy --echo # path substitution : should connect ---replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$mysql_test_dir_path/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" +--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA +--exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key$mysql_test_dir_path/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" --echo # try to connect with '--ssl-cert' option using tilde home directoy --echo # path substitution : should connect ---replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$mysql_test_dir_path/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" +--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA +--exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert$mysql_test_dir_path/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_cipher'" -- cgit v1.2.1 From c3c272cca45205b8ffc5c44b2cce136576649967 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 10 Jun 2016 13:47:00 +0200 Subject: MDEV-10166 probes_mysql_nodtrace.h is not provided anymore by mariadb-10.0.25 backport of commit bba3d42 Author: Sergei Golubchik Date: Sat Apr 30 10:27:42 2016 +0200 MDEV-9926 probes_mysql.h includes nonexisting files install private generated files --- include/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 33eaa28ae1e..219a2917917 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -69,3 +69,9 @@ INSTALL(DIRECTORY . DESTINATION ${INSTALL_INCLUDEDIR}/private COMPONENT Developm PATTERN CMakeFiles EXCLUDE PATTERN mysql EXCLUDE REGEX "\\./(${EXCL_RE}$)" EXCLUDE) + +INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/. DESTINATION ${INSTALL_INCLUDEDIR}/private COMPONENT Development + FILES_MATCHING PATTERN "*.h" + PATTERN CMakeFiles EXCLUDE + PATTERN mysql EXCLUDE + REGEX "\\./(${EXCL_RE}$)" EXCLUDE) -- cgit v1.2.1 From c73b987e73343d49c0b98666552d7aeb1a9799da Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 14 Jun 2016 13:18:05 +0200 Subject: MDEV-8328 Evaluation of two "!" operators depends on space in beetween fix the lexer to backtrack when parsing "<=", "<>", "!=", ">=", "<<", ">>", "<=>". --- mysql-test/r/parser.result | 20 ++++++ mysql-test/suite/plugins/r/server_audit.result | 2 +- .../plugins/r/thread_pool_server_audit.result | 2 +- mysql-test/t/parser.test | 12 ++++ sql/lex.h | 3 - sql/sql_lex.cc | 29 ++++---- sql/sql_yacc.yy | 77 +++++++++++----------- 7 files changed, 87 insertions(+), 58 deletions(-) diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index 915ace0c1b4..25143f97d9a 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -643,3 +643,23 @@ CREATE TRIGGER trigger1 BEFORE INSERT ON t1 FOR EACH ROW SET default_storage_engine = NEW.INNODB; ERROR 42S22: Unknown column 'INNODB' in 'NEW' DROP TABLE t1; +select 0==0; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '=0' at line 1 +select 1=!0, 1 = ! 0; +1=!0 1 = ! 0 +1 1 +select !!0, ! ! 0; +!!0 ! ! 0 +0 0 +select 2>!0, 2 > ! 0; +2>!0 2 > ! 0 +1 1 +select 0<=!0, 0 <= !0; +0<=!0 0 <= !0 +1 1 +select 1<; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '=' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 CREATE USER u3 IDENTIFIED BY ''; drop user u1, u2, u3; select 2; diff --git a/mysql-test/suite/plugins/r/thread_pool_server_audit.result b/mysql-test/suite/plugins/r/thread_pool_server_audit.result index 67338506001..2dcfa107103 100644 --- a/mysql-test/suite/plugins/r/thread_pool_server_audit.result +++ b/mysql-test/suite/plugins/r/thread_pool_server_audit.result @@ -165,7 +165,7 @@ CREATE USER u1 IDENTIFIED BY 'pwd-123'; GRANT ALL ON sa_db TO u2 IDENTIFIED BY "pwd-321"; SET PASSWORD FOR u1 = PASSWORD('pwd 098'); SET PASSWORD FOR u1=; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '=' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 CREATE USER u3 IDENTIFIED BY ''; drop user u1, u2, u3; select 2; diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index 6899e2876a6..c6aa8927848 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -758,3 +758,15 @@ CREATE TABLE t1 (s VARCHAR(100)); CREATE TRIGGER trigger1 BEFORE INSERT ON t1 FOR EACH ROW SET default_storage_engine = NEW.INNODB; DROP TABLE t1; + +# +# MDEV-8328 Evaluation of two "!" operators depends on space in beetween +# +--error ER_PARSE_ERROR +select 0==0; +select 1=!0, 1 = ! 0; +select !!0, ! ! 0; +select 2>!0, 2 > ! 0; +select 0<=!0, 0 <= !0; +select 1<", SYM(NE)}, { "!=", SYM(NE)}, - { "=", SYM(EQ)}, - { ">", SYM(GT_SYM)}, { ">=", SYM(GE)}, { "<<", SYM(SHIFT_LEFT)}, { ">>", SYM(SHIFT_RIGHT)}, diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 7b8b37f61fd..ee0e09acbf9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1452,32 +1452,35 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) return (BIN_NUM); case MY_LEX_CMP_OP: // Incomplete comparison operator + lip->next_state= MY_LEX_START; // Allow signed numbers if (state_map[(uchar) lip->yyPeek()] == MY_LEX_CMP_OP || state_map[(uchar) lip->yyPeek()] == MY_LEX_LONG_CMP_OP) - lip->yySkip(); - if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0))) { - lip->next_state= MY_LEX_START; // Allow signed numbers - return(tokval); + lip->yySkip(); + if ((tokval= find_keyword(lip, 2, 0))) + return(tokval); + lip->yyUnget(); } - state = MY_LEX_CHAR; // Something fishy found - break; + return(c); case MY_LEX_LONG_CMP_OP: // Incomplete comparison operator + lip->next_state= MY_LEX_START; if (state_map[(uchar) lip->yyPeek()] == MY_LEX_CMP_OP || state_map[(uchar) lip->yyPeek()] == MY_LEX_LONG_CMP_OP) { lip->yySkip(); if (state_map[(uchar) lip->yyPeek()] == MY_LEX_CMP_OP) + { lip->yySkip(); + if ((tokval= find_keyword(lip, 3, 0))) + return(tokval); + lip->yyUnget(); + } + if ((tokval= find_keyword(lip, 2, 0))) + return(tokval); + lip->yyUnget(); } - if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0))) - { - lip->next_state= MY_LEX_START; // Found long op - return(tokval); - } - state = MY_LEX_CHAR; // Something fishy found - break; + return(c); case MY_LEX_BOOL: if (c != lip->yyPeek()) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2cb02059ba4..50484e08b3f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -970,7 +970,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token ENGINES_SYM %token ENGINE_SYM %token ENUM -%token EQ /* OPERATOR */ %token EQUAL_SYM /* OPERATOR */ %token ERROR_SYM %token ERRORS @@ -1016,7 +1015,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token GRANTS %token GROUP_SYM /* SQL-2003-R */ %token GROUP_CONCAT_SYM -%token GT_SYM /* OPERATOR */ %token HANDLER_SYM %token HARD_SYM %token HASH_SYM @@ -1095,7 +1093,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token LONG_SYM %token LOOP_SYM %token LOW_PRIORITY -%token LT /* OPERATOR */ %token MASTER_CONNECT_RETRY_SYM %token MASTER_HOST_SYM %token MASTER_LOG_FILE_SYM @@ -1439,7 +1436,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %left XOR %left AND_SYM AND_AND_SYM %left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE -%left EQ EQUAL_SYM GE GT_SYM LE LT NE IS LIKE REGEXP IN_SYM +%left '=' EQUAL_SYM GE '>' LE '<' NE IS LIKE REGEXP IN_SYM %left '|' %left '&' %left SHIFT_LEFT SHIFT_RIGHT @@ -1922,58 +1919,58 @@ master_defs: ; master_def: - MASTER_HOST_SYM EQ TEXT_STRING_sys + MASTER_HOST_SYM '=' TEXT_STRING_sys { Lex->mi.host = $3.str; } - | MASTER_USER_SYM EQ TEXT_STRING_sys + | MASTER_USER_SYM '=' TEXT_STRING_sys { Lex->mi.user = $3.str; } - | MASTER_PASSWORD_SYM EQ TEXT_STRING_sys + | MASTER_PASSWORD_SYM '=' TEXT_STRING_sys { Lex->mi.password = $3.str; } - | MASTER_PORT_SYM EQ ulong_num + | MASTER_PORT_SYM '=' ulong_num { Lex->mi.port = $3; } - | MASTER_CONNECT_RETRY_SYM EQ ulong_num + | MASTER_CONNECT_RETRY_SYM '=' ulong_num { Lex->mi.connect_retry = $3; } - | MASTER_SSL_SYM EQ ulong_num + | MASTER_SSL_SYM '=' ulong_num { Lex->mi.ssl= $3 ? LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE; } - | MASTER_SSL_CA_SYM EQ TEXT_STRING_sys + | MASTER_SSL_CA_SYM '=' TEXT_STRING_sys { Lex->mi.ssl_ca= $3.str; } - | MASTER_SSL_CAPATH_SYM EQ TEXT_STRING_sys + | MASTER_SSL_CAPATH_SYM '=' TEXT_STRING_sys { Lex->mi.ssl_capath= $3.str; } - | MASTER_SSL_CERT_SYM EQ TEXT_STRING_sys + | MASTER_SSL_CERT_SYM '=' TEXT_STRING_sys { Lex->mi.ssl_cert= $3.str; } - | MASTER_SSL_CIPHER_SYM EQ TEXT_STRING_sys + | MASTER_SSL_CIPHER_SYM '=' TEXT_STRING_sys { Lex->mi.ssl_cipher= $3.str; } - | MASTER_SSL_KEY_SYM EQ TEXT_STRING_sys + | MASTER_SSL_KEY_SYM '=' TEXT_STRING_sys { Lex->mi.ssl_key= $3.str; } - | MASTER_SSL_VERIFY_SERVER_CERT_SYM EQ ulong_num + | MASTER_SSL_VERIFY_SERVER_CERT_SYM '=' ulong_num { Lex->mi.ssl_verify_server_cert= $3 ? LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE; } - | MASTER_HEARTBEAT_PERIOD_SYM EQ NUM_literal + | MASTER_HEARTBEAT_PERIOD_SYM '=' NUM_literal { Lex->mi.heartbeat_period= (float) $3->val_real(); if (Lex->mi.heartbeat_period > SLAVE_MAX_HEARTBEAT_PERIOD || @@ -2004,7 +2001,7 @@ master_def: } Lex->mi.heartbeat_opt= LEX_MASTER_INFO::LEX_MI_ENABLE; } - | IGNORE_SERVER_IDS_SYM EQ '(' ignore_server_id_list ')' + | IGNORE_SERVER_IDS_SYM '=' '(' ignore_server_id_list ')' { Lex->mi.repl_ignore_server_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE; } @@ -2025,11 +2022,11 @@ ignore_server_id: } master_file_def: - MASTER_LOG_FILE_SYM EQ TEXT_STRING_sys + MASTER_LOG_FILE_SYM '=' TEXT_STRING_sys { Lex->mi.log_file_name = $3.str; } - | MASTER_LOG_POS_SYM EQ ulonglong_num + | MASTER_LOG_POS_SYM '=' ulonglong_num { Lex->mi.pos = $3; /* @@ -2045,11 +2042,11 @@ master_file_def: */ Lex->mi.pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.pos); } - | RELAY_LOG_FILE_SYM EQ TEXT_STRING_sys + | RELAY_LOG_FILE_SYM '=' TEXT_STRING_sys { Lex->mi.relay_log_name = $3.str; } - | RELAY_LOG_POS_SYM EQ ulong_num + | RELAY_LOG_POS_SYM '=' ulong_num { Lex->mi.relay_log_pos = $3; /* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */ @@ -3032,7 +3029,7 @@ opt_set_signal_information: ; signal_information_item_list: - signal_condition_information_item_name EQ signal_allowed_expr + signal_condition_information_item_name '=' signal_allowed_expr { Set_signal_information *info; info= &thd->m_parser_state->m_yacc.m_set_signal_info; @@ -3041,7 +3038,7 @@ signal_information_item_list: info->m_item[index]= $3; } | signal_information_item_list ',' - signal_condition_information_item_name EQ signal_allowed_expr + signal_condition_information_item_name '=' signal_allowed_expr { Set_signal_information *info; info= &thd->m_parser_state->m_yacc.m_set_signal_info; @@ -4439,7 +4436,7 @@ opt_linear: opt_key_algo: /* empty */ { Lex->part_info->key_algorithm= partition_info::KEY_ALGORITHM_NONE;} - | ALGORITHM_SYM EQ real_ulong_num + | ALGORITHM_SYM '=' real_ulong_num { switch ($3) { case 1: @@ -7076,7 +7073,7 @@ opt_place: opt_to: /* empty */ {} | TO_SYM {} - | EQ {} + | '=' {} | AS {} ; @@ -7943,13 +7940,13 @@ bool_pri: if ($$ == NULL) MYSQL_YYABORT; } - | bool_pri comp_op predicate %prec EQ + | bool_pri comp_op predicate %prec '=' { $$= (*$2)(0)->create($1,$3); if ($$ == NULL) MYSQL_YYABORT; } - | bool_pri comp_op all_or_any '(' subselect ')' %prec EQ + | bool_pri comp_op all_or_any '(' subselect ')' %prec '=' { $$= all_any_subquery_creator($1, $2, $3, $5); if ($$ == NULL) @@ -8172,11 +8169,11 @@ not2: ; comp_op: - EQ { $$ = &comp_eq_creator; } + '=' { $$ = &comp_eq_creator; } | GE { $$ = &comp_ge_creator; } - | GT_SYM { $$ = &comp_gt_creator; } + | '>' { $$ = &comp_gt_creator; } | LE { $$ = &comp_le_creator; } - | LT { $$ = &comp_lt_creator; } + | '<' { $$ = &comp_lt_creator; } | NE { $$ = &comp_ne_creator; } ; @@ -10197,7 +10194,7 @@ date_time_type: table_alias: /* empty */ | AS - | EQ + | '=' ; opt_table_alias: @@ -11100,7 +11097,7 @@ ident_eq_value: ; equal: - EQ {} + '=' {} | SET_VAR {} ; @@ -13968,11 +13965,11 @@ handler_rkey_function: ; handler_rkey_mode: - EQ { $$=HA_READ_KEY_EXACT; } + '=' { $$=HA_READ_KEY_EXACT; } | GE { $$=HA_READ_KEY_OR_NEXT; } | LE { $$=HA_READ_KEY_OR_PREV; } - | GT_SYM { $$=HA_READ_AFTER_KEY; } - | LT { $$=HA_READ_BEFORE_KEY; } + | '>' { $$=HA_READ_AFTER_KEY; } + | '<' { $$=HA_READ_BEFORE_KEY; } ; /* GRANT / REVOKE */ @@ -14744,7 +14741,7 @@ no_definer: ; definer: - DEFINER_SYM EQ user + DEFINER_SYM '=' user { thd->lex->definer= get_current_user(thd, $3); } @@ -14771,11 +14768,11 @@ view_replace: ; view_algorithm: - ALGORITHM_SYM EQ UNDEFINED_SYM + ALGORITHM_SYM '=' UNDEFINED_SYM { Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED; } - | ALGORITHM_SYM EQ MERGE_SYM + | ALGORITHM_SYM '=' MERGE_SYM { Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; } - | ALGORITHM_SYM EQ TEMPTABLE_SYM + | ALGORITHM_SYM '=' TEMPTABLE_SYM { Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; } ; -- cgit v1.2.1 From a4cfd32125a76a3818f1ad1e2b0ed455329ec26f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 14 Jun 2016 14:52:43 +0200 Subject: main.openssl_1 failure don't test a cipher that was removed from recent openssl versions --- mysql-test/r/openssl_1.result | 2 -- mysql-test/t/openssl_1.test | 1 - 2 files changed, 3 deletions(-) diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result index 44ea5795a95..a49a12c230d 100644 --- a/mysql-test/r/openssl_1.result +++ b/mysql-test/r/openssl_1.result @@ -198,8 +198,6 @@ Ssl_cipher DHE-RSA-AES256-SHA Variable_name Value Ssl_cipher EDH-RSA-DES-CBC3-SHA Variable_name Value -Ssl_cipher EDH-RSA-DES-CBC-SHA -Variable_name Value Ssl_cipher RC4-SHA select 'is still running; no cipher request crashed the server' as result from dual; result diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test index 1b28c40c0bf..62b5c9c10e0 100644 --- a/mysql-test/t/openssl_1.test +++ b/mysql-test/t/openssl_1.test @@ -222,7 +222,6 @@ DROP TABLE t1; # Common ciphers to openssl and yassl --exec $MYSQL --host=localhost -e "SHOW STATUS LIKE 'Ssl_cipher';" --ssl-cipher=DHE-RSA-AES256-SHA --exec $MYSQL --host=localhost -e "SHOW STATUS LIKE 'Ssl_cipher';" --ssl-cipher=EDH-RSA-DES-CBC3-SHA ---exec $MYSQL --host=localhost -e "SHOW STATUS LIKE 'Ssl_cipher';" --ssl-cipher=EDH-RSA-DES-CBC-SHA --exec $MYSQL --host=localhost -e "SHOW STATUS LIKE 'Ssl_cipher';" --ssl-cipher=RC4-SHA --disable_query_log --disable_result_log -- cgit v1.2.1 From 05bb3b9f85d68cc0e99a7b43c8b40cc07d272d76 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 14 Jun 2016 16:28:07 +0200 Subject: fix main.ssl_ca test for windows where $HOME is the empty string --- mysql-test/t/ssl_ca.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/ssl_ca.test b/mysql-test/t/ssl_ca.test index e0a5fa9ad07..3652040dd0b 100644 --- a/mysql-test/t/ssl_ca.test +++ b/mysql-test/t/ssl_ca.test @@ -18,7 +18,7 @@ --echo # PATH SUBSTITUTION --echo # ---let $mysql_test_dir_path= `SELECT REPLACE('=$MYSQL_TEST_DIR', '=$HOME', '=~')` +--let $mysql_test_dir_path= `SELECT IF(LENGTH('$HOME'), REPLACE('=$MYSQL_TEST_DIR', '=$HOME', '=~'), '=$MYSQL_TEST_DIR')` --echo # try to connect with '--ssl-ca' option using tilde home directoy --echo # path substitution : should connect -- cgit v1.2.1 From cf721d23cc90e7848b0611180b9777d080a1faf6 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 10 Dec 2015 17:00:14 +1100 Subject: MDEV-9257: Increase limit on parallel workers in mysql-test-run Signed-off-by: Daniel Black --- mysql-test/mysql-test-run.pl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 26b31d34d3c..63b18c6bebd 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1801,9 +1801,12 @@ sub set_build_thread_ports($) { if ( lc($opt_build_thread) eq 'auto' ) { my $found_free = 0; $build_thread = 300; # Start attempts from here + my $build_thread_upper = $build_thread + ($opt_parallel > 1500 + ? 3000 + : 2 * $opt_parallel); while (! $found_free) { - $build_thread= mtr_get_unique_id($build_thread, 349); + $build_thread= mtr_get_unique_id($build_thread, $build_thread_upper); if ( !defined $build_thread ) { mtr_error("Could not get a unique build thread id"); } -- cgit v1.2.1 From 0089af8e1c767ed34ff8d92428beacf50fa97e79 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Mon, 13 Jun 2016 18:11:31 +0300 Subject: MDEV-9433: [PATCH] cppcheck reported a number of minor coding errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a bug in testhash.c that caused an out of bounds memory access when command line parameters specified 0 records to be inserted in the hashtable. Signed-off-by: Vicențiu Ciorbaru --- mysys/testhash.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mysys/testhash.c b/mysys/testhash.c index ffdaaece770..aa78a2d8c40 100644 --- a/mysys/testhash.c +++ b/mysys/testhash.c @@ -169,7 +169,9 @@ static int do_test() for (j=0 ; j < 1000 ; j++) if (key1[j] > 1) break; - if (key1[j] > 1) + // j will be 1000 only if we have no keys in the hash. This only happens + // when the parameter recant is set to 0 via command line argument. + if (j < 1000 && key1[j] > 1) { HASH_SEARCH_STATE state; printf("- Testing identical read\n"); -- cgit v1.2.1 From bfef17bec193d8c965604ad29d4b4b9f800bccac Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Mon, 13 Jun 2016 18:30:02 +0300 Subject: MDEV-9433: [PATCH} cppcheck reported a number of minor coding errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix cppwarning of va_args being opened but not closed. Signed-off-by: Vicențiu Ciorbaru --- mysys/mf_iocache.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 02e5c5373ae..31a09e214d2 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -1874,6 +1874,7 @@ void die(const char* fmt, ...) fprintf(stderr,"Error:"); vfprintf(stderr, fmt,va_args); fprintf(stderr,", errno=%d\n", errno); + va_end(va_args); exit(1); } -- cgit v1.2.1 From 6a34ba313005ab861bc9c38b6f9d0624ff17a026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 16 Feb 2016 16:15:22 +0200 Subject: [Code cleanup] Refactor duplicate code within myisam and maria sort.cc --- storage/maria/ma_sort.c | 62 ++++++++++++++++++++--------------------------- storage/myisam/sort.c | 64 +++++++++++++++++++++---------------------------- 2 files changed, 53 insertions(+), 73 deletions(-) diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index 95454d88308..ce17446eea7 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -86,6 +86,27 @@ static int write_merge_key_varlen(MARIA_SORT_PARAM *info, static inline int my_var_write(MARIA_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs); +/* + Sets the appropriate read and write methods for the MARIA_SORT_PARAM + based on the variable length key flag. +*/ +static void set_sort_param_read_write(MARIA_SORT_PARAM *sort_param) +{ + if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY) + { + sort_param->write_keys= write_keys_varlen; + sort_param->read_to_buffer= read_to_buffer_varlen; + sort_param->write_key= write_merge_key_varlen; + } + else + { + sort_param->write_keys= write_keys; + sort_param->read_to_buffer= read_to_buffer; + sort_param->write_key= write_merge_key; + } +} + + /* Creates a index of sorted keys @@ -115,18 +136,7 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, (ulong) sortbuff_size, info->key_length, (ulong) info->sort_info->max_records)); - if (info->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - info->write_keys= write_keys_varlen; - info->read_to_buffer=read_to_buffer_varlen; - info->write_key=write_merge_key_varlen; - } - else - { - info->write_keys= write_keys; - info->read_to_buffer=read_to_buffer; - info->write_key=write_merge_key; - } + set_sort_param_read_write(info); my_b_clear(&tempfile); my_b_clear(&tempfile_for_exceptions); @@ -347,18 +357,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) if (sort_param->sort_info->got_error) goto err; - if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - sort_param->write_keys= write_keys_varlen; - sort_param->read_to_buffer= read_to_buffer_varlen; - sort_param->write_key= write_merge_key_varlen; - } - else - { - sort_param->write_keys= write_keys; - sort_param->read_to_buffer= read_to_buffer; - sort_param->write_key= write_merge_key; - } + set_sort_param_read_write(sort_param); my_b_clear(&sort_param->tempfile); my_b_clear(&sort_param->tempfile_for_exceptions); @@ -564,18 +563,9 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) { if (got_error) continue; - if (sinfo->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - sinfo->write_keys=write_keys_varlen; - sinfo->read_to_buffer=read_to_buffer_varlen; - sinfo->write_key=write_merge_key_varlen; - } - else - { - sinfo->write_keys=write_keys; - sinfo->read_to_buffer=read_to_buffer; - sinfo->write_key=write_merge_key; - } + + set_sort_param_read_write(sinfo); + if (sinfo->buffpek.elements) { uint maxbuffer=sinfo->buffpek.elements-1; diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index 2c4639b3143..69c0bfc3edc 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -84,6 +84,28 @@ static int write_merge_key_varlen(MI_SORT_PARAM *info, static inline int my_var_write(MI_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs); + +/* + Sets the appropriate read and write methods for the MI_SORT_PARAM + based on the variable length key flag. +*/ +static void set_sort_param_read_write(MI_SORT_PARAM *sort_param) +{ + if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY) + { + sort_param->write_keys= write_keys_varlen; + sort_param->read_to_buffer= read_to_buffer_varlen; + sort_param->write_key= write_merge_key_varlen; + } + else + { + sort_param->write_keys= write_keys; + sort_param->read_to_buffer= read_to_buffer; + sort_param->write_key= write_merge_key; + } +} + + /* Creates a index of sorted keys @@ -111,18 +133,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, DBUG_ENTER("_create_index_by_sort"); DBUG_PRINT("enter",("sort_length: %d", info->key_length)); - if (info->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - info->write_keys=write_keys_varlen; - info->read_to_buffer=read_to_buffer_varlen; - info->write_key= write_merge_key_varlen; - } - else - { - info->write_keys=write_keys; - info->read_to_buffer=read_to_buffer; - info->write_key=write_merge_key; - } + set_sort_param_read_write(info); my_b_clear(&tempfile); my_b_clear(&tempfile_for_exceptions); @@ -307,7 +318,6 @@ static ha_rows find_all_keys(MI_SORT_PARAM *info, uint keys, DBUG_RETURN((*maxbuffer)*(keys-1)+idx); } /* find_all_keys */ - /* Search after all keys and place them in a temp. file */ pthread_handler_t thr_find_all_keys(void *arg) @@ -332,18 +342,7 @@ pthread_handler_t thr_find_all_keys(void *arg) if (sort_param->sort_info->got_error) goto err; - if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - sort_param->write_keys= write_keys_varlen; - sort_param->read_to_buffer= read_to_buffer_varlen; - sort_param->write_key= write_merge_key_varlen; - } - else - { - sort_param->write_keys= write_keys; - sort_param->read_to_buffer= read_to_buffer; - sort_param->write_key= write_merge_key; - } + set_sort_param_read_write(sort_param); my_b_clear(&sort_param->tempfile); my_b_clear(&sort_param->tempfile_for_exceptions); @@ -550,18 +549,9 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) { if (got_error) continue; - if (sinfo->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - sinfo->write_keys=write_keys_varlen; - sinfo->read_to_buffer=read_to_buffer_varlen; - sinfo->write_key=write_merge_key_varlen; - } - else - { - sinfo->write_keys=write_keys; - sinfo->read_to_buffer=read_to_buffer; - sinfo->write_key=write_merge_key; - } + + set_sort_param_read_write(sinfo); + if (sinfo->buffpek.elements) { uint maxbuffer=sinfo->buffpek.elements-1; -- cgit v1.2.1 From 2b47832a2d261dbaf735b26e796aa126bccafb20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Thu, 10 Dec 2015 03:56:31 +0200 Subject: Fixed compilation failure using clang Both aria and myisam storage engines feature a logic path in thr_find_all_keys that leads to undefined behaviour by bypassing the initialization code of variables after my_thread_init(). By refactoring the nested logic into a separate function, this problem is resolved. --- include/myisam.h | 3 +- storage/maria/ma_sort.c | 289 ++++++++++++++++++++++-------------------- storage/maria/maria_def.h | 3 +- storage/myisam/sort.c | 311 ++++++++++++++++++++++++---------------------- 4 files changed, 321 insertions(+), 285 deletions(-) diff --git a/include/myisam.h b/include/myisam.h index d50b1dc360e..186b049b32e 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -330,7 +330,8 @@ typedef struct st_sort_info my_off_t filelength, dupp, buff_length; ha_rows max_records; uint current_key, total_keys; - uint got_error, threads_running; + volatile uint got_error; + uint threads_running; myf myf_rw; enum data_file_type new_data_file_type; } MI_SORT_INFO; diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index ce17446eea7..ea2b61b358a 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -333,170 +333,187 @@ err: } /* find_all_keys */ -/* Search after all keys and place them in a temp. file */ - -pthread_handler_t _ma_thr_find_all_keys(void *arg) +static my_bool _ma_thr_find_all_keys_exec(MARIA_SORT_PARAM* sort_param) { - MARIA_SORT_PARAM *sort_param= (MARIA_SORT_PARAM*) arg; - int error; - size_t memavl,old_memavl; - uint sort_length; - ulong idx, maxbuffer, keys; - uchar **sort_keys=0; - - LINT_INIT(keys); + DBUG_ENTER("_ma_thr_find_all_keys"); + DBUG_PRINT("enter", ("master: %d", sort_param->master)); - error=1; + my_bool error= FALSE; + ulonglong memavl, old_memavl; + uint UNINIT_VAR(keys), idx; + uint sort_length; + uint maxbuffer; + uchar **sort_keys= NULL; - if (my_thread_init()) - goto err; + if (sort_param->sort_info->got_error) + DBUG_RETURN(TRUE); - { /* Add extra block since DBUG_ENTER declare variables */ - DBUG_ENTER("_ma_thr_find_all_keys"); - DBUG_PRINT("enter", ("master: %d", sort_param->master)); - if (sort_param->sort_info->got_error) - goto err; + set_sort_param_read_write(sort_param); - set_sort_param_read_write(sort_param); - my_b_clear(&sort_param->tempfile); - my_b_clear(&sort_param->tempfile_for_exceptions); - bzero((char*) &sort_param->buffpek,sizeof(sort_param->buffpek)); - bzero((char*) &sort_param->unique, sizeof(sort_param->unique)); + my_b_clear(&sort_param->tempfile); + my_b_clear(&sort_param->tempfile_for_exceptions); + bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek)); + bzero((char*) &sort_param->unique, sizeof(sort_param->unique)); - memavl= max(sort_param->sortbuff_size, MIN_SORT_MEMORY); - idx= (uint)sort_param->sort_info->max_records; - sort_length= sort_param->key_length; - maxbuffer= 1; + memavl= max(sort_param->sortbuff_size, MIN_SORT_MEMORY); + idx= sort_param->sort_info->max_records; + sort_length= sort_param->key_length; + maxbuffer= 1; - while (memavl >= MIN_SORT_MEMORY) + while (memavl >= MIN_SORT_MEMORY) + { + if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= (my_off_t) memavl) + keys= idx+1; + else { - if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= (my_off_t) memavl) - keys= idx+1; - else - { - ulong skr; - do - { - skr= maxbuffer; - if (memavl < sizeof(BUFFPEK)*maxbuffer || - (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/ - (sort_length+sizeof(char*))) <= 1 || - keys < maxbuffer) - { - _ma_check_print_error(sort_param->sort_info->param, - "aria_sort_buffer_size is too small"); - goto err; - } - } - while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr); - } - if ((sort_keys= (uchar **) - my_malloc(keys*(sort_length+sizeof(char*))+ - ((sort_param->keyinfo->flag & HA_FULLTEXT) ? - HA_FT_MAXBYTELEN : 0), MYF(0)))) + ulong skr; + do { - if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK), - maxbuffer, maxbuffer/2)) + skr= maxbuffer; + if (memavl < sizeof(BUFFPEK)*maxbuffer || + (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/ + (sort_length+sizeof(char*))) <= 1 || + keys < maxbuffer) { - my_free(sort_keys); - sort_keys= (uchar **) NULL; /* for err: label */ + _ma_check_print_error(sort_param->sort_info->param, + "aria_sort_buffer_size is too small"); + goto err; } - else - break; } - old_memavl= memavl; - if ((memavl= memavl/4*3) < MIN_SORT_MEMORY && - old_memavl > MIN_SORT_MEMORY) - memavl= MIN_SORT_MEMORY; + while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr); } - if (memavl < MIN_SORT_MEMORY) + if ((sort_keys= (uchar **) + my_malloc(keys*(sort_length+sizeof(char*))+ + ((sort_param->keyinfo->flag & HA_FULLTEXT) ? + HA_FT_MAXBYTELEN : 0), MYF(0)))) { - _ma_check_print_error(sort_param->sort_info->param, - "Aria sort buffer too small"); - goto err; /* purecov: tested */ + if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK), + maxbuffer, maxbuffer / 2)) + { + my_free(sort_keys); + sort_keys= NULL; /* Safety against double free on error. */ + } + else + break; } + old_memavl= memavl; + if ((memavl= memavl/4*3) < MIN_SORT_MEMORY && + old_memavl > MIN_SORT_MEMORY) + memavl= MIN_SORT_MEMORY; + } - if (sort_param->sort_info->param->testflag & T_VERBOSE) - printf("Key %d - Allocating buffer for %lu keys\n", - sort_param->key+1, (ulong) keys); - sort_param->sort_keys= sort_keys; + if (memavl < MIN_SORT_MEMORY) + { + /* purecov: begin inspected */ + _ma_check_print_error(sort_param->sort_info->param, + "aria_sort_buffer_size is too small. Current " + "aria_sort_buffer_size: %llu rows: %llu " + "sort_length: %u", + (ulonglong) sort_param->sortbuff_size, + (ulonglong) idx, sort_length); + my_errno= ENOMEM; + goto err; + /* purecov: end inspected */ + } - idx= error= 0; - sort_keys[0]= (uchar*) (sort_keys+keys); + if (sort_param->sort_info->param->testflag & T_VERBOSE) + printf("Key %d - Allocating buffer for %llu keys\n", + sort_param->key + 1, (ulonglong) keys); + sort_param->sort_keys= sort_keys; - DBUG_PRINT("info", ("reading keys")); - while (!(error= sort_param->sort_info->got_error) && - !(error= (*sort_param->key_read)(sort_param, sort_keys[idx]))) - { - if (sort_param->real_key_length > sort_param->key_length) - { - if (write_key(sort_param,sort_keys[idx], - &sort_param->tempfile_for_exceptions)) - goto err; - continue; - } + idx= error= 0; + sort_keys[0]= (uchar*) (sort_keys+keys); - if (++idx == keys) - { - if (sort_param->write_keys(sort_param, sort_keys, idx - 1, - (BUFFPEK *)alloc_dynamic(&sort_param-> - buffpek), - &sort_param->tempfile)) - goto err; - sort_keys[0]= (uchar*) (sort_keys+keys); - memcpy(sort_keys[0], sort_keys[idx - 1], - (size_t) sort_param->key_length); - idx= 1; - } - sort_keys[idx]=sort_keys[idx - 1] + sort_param->key_length; + DBUG_PRINT("info", ("reading keys")); + while (!(error= sort_param->sort_info->got_error) && + !(error= (*sort_param->key_read)(sort_param, sort_keys[idx]))) + { + if (sort_param->real_key_length > sort_param->key_length) + { + if (write_key(sort_param, sort_keys[idx], + &sort_param->tempfile_for_exceptions)) + goto err; + continue; } - if (error > 0) - goto err; - if (sort_param->buffpek.elements) + + if (++idx == keys) { - if (sort_param->write_keys(sort_param,sort_keys, idx, - (BUFFPEK *) alloc_dynamic(&sort_param-> - buffpek), + if (sort_param->write_keys(sort_param, sort_keys, idx - 1, + (BUFFPEK *)alloc_dynamic(&sort_param->buffpek), &sort_param->tempfile)) goto err; - sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx; + sort_keys[0]= (uchar*) (sort_keys+keys); + memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length); + idx= 1; } - else - sort_param->keys= idx; + sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length; + } + if (error > 0) + goto err; + if (sort_param->buffpek.elements) + { + if (sort_param->write_keys(sort_param,sort_keys, idx, + (BUFFPEK *) alloc_dynamic(&sort_param->buffpek), + &sort_param->tempfile)) + goto err; + sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx; + } + else + sort_param->keys= idx; - sort_param->sort_keys_length= keys; - goto ok; + sort_param->sort_keys_length= keys; + DBUG_RETURN(FALSE); err: - DBUG_PRINT("error", ("got some error")); - sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */ - my_free(sort_keys); - sort_param->sort_keys=0; - delete_dynamic(& sort_param->buffpek); - close_cached_file(&sort_param->tempfile); - close_cached_file(&sort_param->tempfile_for_exceptions); - -ok: - free_root(&sort_param->wordroot, MYF(0)); - /* - Detach from the share if the writer is involved. Avoid others to - be blocked. This includes a flush of the write buffer. This will - also indicate EOF to the readers. - */ - if (sort_param->sort_info->info->rec_cache.share) - remove_io_thread(&sort_param->sort_info->info->rec_cache); - - /* Readers detach from the share if any. Avoid others to be blocked. */ - if (sort_param->read_cache.share) - remove_io_thread(&sort_param->read_cache); - - mysql_mutex_lock(&sort_param->sort_info->mutex); - if (!--sort_param->sort_info->threads_running) - mysql_cond_signal(&sort_param->sort_info->cond); - mysql_mutex_unlock(&sort_param->sort_info->mutex); - DBUG_PRINT("exit", ("======== ending thread ========")); - } + DBUG_PRINT("error", ("got some error")); + my_free(sort_keys); + sort_param->sort_keys= 0; + delete_dynamic(& sort_param->buffpek); + close_cached_file(&sort_param->tempfile); + close_cached_file(&sort_param->tempfile_for_exceptions); + + DBUG_RETURN(TRUE); +} + +/* Search after all keys and place them in a temp. file */ + +pthread_handler_t _ma_thr_find_all_keys(void *arg) +{ + MARIA_SORT_PARAM *sort_param= (MARIA_SORT_PARAM*) arg; + my_bool error= FALSE; + /* If my_thread_init fails */ + if (my_thread_init() || _ma_thr_find_all_keys_exec(sort_param)) + error= TRUE; + + /* + Thread must clean up after itself. + */ + free_root(&sort_param->wordroot, MYF(0)); + /* + Detach from the share if the writer is involved. Avoid others to + be blocked. This includes a flush of the write buffer. This will + also indicate EOF to the readers. + That means that a writer always gets here first and readers - + only when they see EOF. But if a reader finishes prematurely + because of an error it may reach this earlier - don't allow it + to detach the writer thread. + */ + if (sort_param->master && sort_param->sort_info->info->rec_cache.share) + remove_io_thread(&sort_param->sort_info->info->rec_cache); + + /* Readers detach from the share if any. Avoid others to be blocked. */ + if (sort_param->read_cache.share) + remove_io_thread(&sort_param->read_cache); + + mysql_mutex_lock(&sort_param->sort_info->mutex); + if (error) + sort_param->sort_info->got_error= 1; + + if (!--sort_param->sort_info->threads_running) + mysql_cond_signal(&sort_param->sort_info->cond); + mysql_mutex_unlock(&sort_param->sort_info->mutex); + my_thread_end(); return NULL; } diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 983e0fba7f4..473cddee190 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -67,7 +67,8 @@ typedef struct st_maria_sort_info pgcache_page_no_t page; ha_rows max_records; uint current_key, total_keys; - uint got_error, threads_running; + volatile uint got_error; + uint threads_running; myf myf_rw; enum data_file_type new_data_file_type, org_data_file_type; } MARIA_SORT_INFO; diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index 69c0bfc3edc..21f1fa9fd64 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -318,177 +318,194 @@ static ha_rows find_all_keys(MI_SORT_PARAM *info, uint keys, DBUG_RETURN((*maxbuffer)*(keys-1)+idx); } /* find_all_keys */ -/* Search after all keys and place them in a temp. file */ - -pthread_handler_t thr_find_all_keys(void *arg) +static my_bool thr_find_all_keys_exec(MI_SORT_PARAM *sort_param) { - MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg; - int error; - ulonglong memavl, old_memavl; - uint keys, sort_length; - uint idx, maxbuffer; - uchar **sort_keys=0; - - LINT_INIT(keys); + DBUG_ENTER("thr_find_all_keys"); + DBUG_PRINT("enter", ("master: %d", sort_param->master)); - error=1; - - if (my_thread_init()) - goto err; - - { /* Add extra block since DBUG_ENTER declare variables */ - DBUG_ENTER("thr_find_all_keys"); - DBUG_PRINT("enter", ("master: %d", sort_param->master)); - if (sort_param->sort_info->got_error) - goto err; - - set_sort_param_read_write(sort_param); - - my_b_clear(&sort_param->tempfile); - my_b_clear(&sort_param->tempfile_for_exceptions); - bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek)); - bzero((char*) &sort_param->unique, sizeof(sort_param->unique)); - sort_keys= (uchar **) NULL; - - memavl= max(sort_param->sortbuff_size, MIN_SORT_BUFFER); - idx= (uint)sort_param->sort_info->max_records; - sort_length= sort_param->key_length; - maxbuffer= 1; - - if ((memavl - sizeof(BUFFPEK)) / (sort_length + - sizeof(char *)) > UINT_MAX32) - memavl= sizeof(BUFFPEK) + UINT_MAX32 * (sort_length + sizeof(char *)); + ulonglong memavl, old_memavl; + uint UNINIT_VAR(keys), idx; + uint sort_length; + uint maxbuffer; + uchar **sort_keys= NULL; + + my_bool error= FALSE; + if (sort_param->sort_info->got_error) + error= TRUE; + if (error) + DBUG_RETURN(error); + + set_sort_param_read_write(sort_param); + + my_b_clear(&sort_param->tempfile); + my_b_clear(&sort_param->tempfile_for_exceptions); + bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek)); + bzero((char*) &sort_param->unique, sizeof(sort_param->unique)); + + memavl= max(sort_param->sortbuff_size, MIN_SORT_BUFFER); + idx= (uint) sort_param->sort_info->max_records; + sort_length= sort_param->key_length; + maxbuffer= 1; + + if ((memavl - sizeof(BUFFPEK)) / (sort_length + + sizeof(char *)) > UINT_MAX32) + memavl= sizeof(BUFFPEK) + UINT_MAX32 * (sort_length + sizeof(char *)); - while (memavl >= MIN_SORT_BUFFER) + while (memavl >= MIN_SORT_BUFFER) + { + if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= + (my_off_t) memavl) + keys= idx+1; + else { - if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= - (my_off_t) memavl) - keys= idx+1; - else - { - uint skr; - do - { - skr= maxbuffer; - if (memavl < sizeof(BUFFPEK)*maxbuffer || - (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/ - (sort_length+sizeof(char*))) <= 1 || - keys < (uint) maxbuffer) - { - mi_check_print_error(sort_param->sort_info->param, - "myisam_sort_buffer_size is too small"); - goto err; - } - } - while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr); - } - if ((sort_keys= (uchar**) - my_malloc(keys*(sort_length+sizeof(char*))+ - ((sort_param->keyinfo->flag & HA_FULLTEXT) ? - HA_FT_MAXBYTELEN : 0), MYF(0)))) + uint skr; + do { - if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK), - maxbuffer, maxbuffer/2)) + skr= maxbuffer; + if (memavl < sizeof(BUFFPEK)*maxbuffer || + (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/ + (sort_length+sizeof(char*))) <= 1 || + keys < (uint) maxbuffer) { - my_free(sort_keys); - sort_keys= (uchar **) NULL; /* for err: label */ + mi_check_print_error(sort_param->sort_info->param, + "myisam_sort_buffer_size is too small. Current " + "myisam_sort_buffer_size: %llu rows: %llu sort_length: %u", + sort_param->sortbuff_size, (ulonglong) idx, sort_length); + DBUG_RETURN(TRUE); } - else - break; } - old_memavl= memavl; - if ((memavl= memavl / 4 * 3) < MIN_SORT_BUFFER && - old_memavl > MIN_SORT_BUFFER) - memavl= MIN_SORT_BUFFER; + while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr); } - if (memavl < MIN_SORT_BUFFER) + if ((sort_keys= my_malloc(keys * (sort_length + sizeof(char *)) + + ((sort_param->keyinfo->flag & HA_FULLTEXT) ? + HA_FT_MAXBYTELEN : 0), MYF(0)))) { - mi_check_print_error(sort_param->sort_info->param, - "MyISAM sort buffer too small"); - goto err; /* purecov: tested */ + if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK), + maxbuffer, min(maxbuffer / 2, 1000))) + { + my_free(sort_keys); + sort_keys= NULL; /* Safety against double free on error. */ + } + else + break; } + old_memavl= memavl; + if ((memavl= memavl / 4 * 3) < MIN_SORT_BUFFER && + old_memavl > MIN_SORT_BUFFER) + memavl= MIN_SORT_BUFFER; + } + if (memavl < MIN_SORT_BUFFER) + { + /* purecov: begin inspected */ + mi_check_print_error(sort_param->sort_info->param, + "myisam_sort_buffer_size is too small. Current " + "myisam_sort_buffer_size: %llu rows: %llu sort_length: %u", + sort_param->sortbuff_size, (ulonglong) idx, sort_length); + my_errno= ENOMEM; + goto err; + /* purecov: end inspected */ + } - if (sort_param->sort_info->param->testflag & T_VERBOSE) - printf("Key %d - Allocating buffer for %d keys\n", - sort_param->key + 1, keys); - sort_param->sort_keys= sort_keys; + if (sort_param->sort_info->param->testflag & T_VERBOSE) + printf("Key %d - Allocating buffer for %llu keys\n", + sort_param->key + 1, (ulonglong) keys); + sort_param->sort_keys= sort_keys; - idx= error= 0; - sort_keys[0]= (uchar*) (sort_keys+keys); + idx= error= 0; + sort_keys[0]= (uchar*) (sort_keys+keys); - DBUG_PRINT("info", ("reading keys")); - while (!(error= sort_param->sort_info->got_error) && - !(error= (*sort_param->key_read)(sort_param, sort_keys[idx]))) + DBUG_PRINT("info", ("reading keys")); + while (!(error= sort_param->sort_info->got_error) && + !(error= (*sort_param->key_read)(sort_param, sort_keys[idx]))) + { + if (sort_param->real_key_length > sort_param->key_length) { - if (sort_param->real_key_length > sort_param->key_length) - { - if (write_key(sort_param, sort_keys[idx], - &sort_param->tempfile_for_exceptions)) - goto err; - continue; - } - - if (++idx == keys) - { - if (sort_param->write_keys(sort_param, sort_keys, idx - 1, - (BUFFPEK*) alloc_dynamic(&sort_param->buffpek), - &sort_param->tempfile)) - goto err; - sort_keys[0]= (uchar*) (sort_keys+keys); - memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length); - idx= 1; - } - sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length; + if (write_key(sort_param, sort_keys[idx], + &sort_param->tempfile_for_exceptions)) + goto err; + continue; } - if (error > 0) - goto err; - if (sort_param->buffpek.elements) + + if (++idx == keys) { - if (sort_param->write_keys(sort_param, sort_keys, idx, + if (sort_param->write_keys(sort_param, sort_keys, idx - 1, (BUFFPEK*) alloc_dynamic(&sort_param->buffpek), &sort_param->tempfile)) goto err; - sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx; + sort_keys[0]= (uchar*) (sort_keys+keys); + memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length); + idx= 1; } - else - sort_param->keys= idx; + sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length; + } - sort_param->sort_keys_length= keys; - goto ok; + if (error > 0) + goto err; -err: - DBUG_PRINT("error", ("got some error")); - sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */ - my_free(sort_keys); - sort_param->sort_keys= 0; - delete_dynamic(& sort_param->buffpek); - close_cached_file(&sort_param->tempfile); - close_cached_file(&sort_param->tempfile_for_exceptions); - -ok: - free_root(&sort_param->wordroot, MYF(0)); - /* - Detach from the share if the writer is involved. Avoid others to - be blocked. This includes a flush of the write buffer. This will - also indicate EOF to the readers. - That means that a writer always gets here first and readers - - only when they see EOF. But if a reader finishes prematurely - because of an error it may reach this earlier - don't allow it - to detach the writer thread. - */ - if (sort_param->master && sort_param->sort_info->info->rec_cache.share) - remove_io_thread(&sort_param->sort_info->info->rec_cache); - - /* Readers detach from the share if any. Avoid others to be blocked. */ - if (sort_param->read_cache.share) - remove_io_thread(&sort_param->read_cache); - - mysql_mutex_lock(&sort_param->sort_info->mutex); - if (!--sort_param->sort_info->threads_running) - mysql_cond_signal(&sort_param->sort_info->cond); - mysql_mutex_unlock(&sort_param->sort_info->mutex); - DBUG_PRINT("exit", ("======== ending thread ========")); + if (sort_param->buffpek.elements) + { + if (sort_param->write_keys(sort_param, sort_keys, idx, + (BUFFPEK*) alloc_dynamic(&sort_param->buffpek), + &sort_param->tempfile)) + goto err; + sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx; } + else + sort_param->keys= idx; + + sort_param->sort_keys_length= keys; + + DBUG_RETURN(FALSE); + +err: + DBUG_PRINT("error", ("got some error")); + sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */ + my_free(sort_keys); + sort_param->sort_keys= 0; + delete_dynamic(& sort_param->buffpek); + close_cached_file(&sort_param->tempfile); + close_cached_file(&sort_param->tempfile_for_exceptions); + + DBUG_RETURN(TRUE); +} + +/* Search after all keys and place them in a temp. file */ + +pthread_handler_t thr_find_all_keys(void *arg) +{ + MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg; + my_bool error= FALSE; + /* If my_thread_init fails */ + if (my_thread_init() || thr_find_all_keys_exec(sort_param)) + error= TRUE; + + /* + Thread must clean up after itself. + */ + free_root(&sort_param->wordroot, MYF(0)); + /* + Detach from the share if the writer is involved. Avoid others to + be blocked. This includes a flush of the write buffer. This will + also indicate EOF to the readers. + That means that a writer always gets here first and readers - + only when they see EOF. But if a reader finishes prematurely + because of an error it may reach this earlier - don't allow it + to detach the writer thread. + */ + if (sort_param->master && sort_param->sort_info->info->rec_cache.share) + remove_io_thread(&sort_param->sort_info->info->rec_cache); + + /* Readers detach from the share if any. Avoid others to be blocked. */ + if (sort_param->read_cache.share) + remove_io_thread(&sort_param->read_cache); + + mysql_mutex_lock(&sort_param->sort_info->mutex); + if (error) + sort_param->sort_info->got_error= 1; + + if (!--sort_param->sort_info->threads_running) + mysql_cond_signal(&sort_param->sort_info->cond); + mysql_mutex_unlock(&sort_param->sort_info->mutex); my_thread_end(); return NULL; } -- cgit v1.2.1 From 1bf25092cbf700049b16f556980c84a9674a811f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Mon, 13 Jun 2016 23:32:50 +0300 Subject: MDEV-10162: Update repair testcase --- storage/maria/ma_sort.c | 8 ++------ storage/myisam/sort.c | 13 ++++--------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index ea2b61b358a..4f092b17037 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -377,7 +377,7 @@ static my_bool _ma_thr_find_all_keys_exec(MARIA_SORT_PARAM* sort_param) keys < maxbuffer) { _ma_check_print_error(sort_param->sort_info->param, - "aria_sort_buffer_size is too small"); + "aria_sort_buffer_size is too small."); goto err; } } @@ -407,11 +407,7 @@ static my_bool _ma_thr_find_all_keys_exec(MARIA_SORT_PARAM* sort_param) { /* purecov: begin inspected */ _ma_check_print_error(sort_param->sort_info->param, - "aria_sort_buffer_size is too small. Current " - "aria_sort_buffer_size: %llu rows: %llu " - "sort_length: %u", - (ulonglong) sort_param->sortbuff_size, - (ulonglong) idx, sort_length); + "aria_sort_buffer_size is too small."); my_errno= ENOMEM; goto err; /* purecov: end inspected */ diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index 21f1fa9fd64..e10e4e26112 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -190,7 +190,8 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, } if (memavl < MIN_SORT_BUFFER) { - mi_check_print_error(info->sort_info->param,"MyISAM sort buffer too small"); /* purecov: tested */ + mi_check_print_error(info->sort_info->param, + "MyISAM sort buffer too small"); /* purecov: tested */ my_errno= ENOMEM; /* purecov: tested */ goto err; /* purecov: tested */ } @@ -331,8 +332,6 @@ static my_bool thr_find_all_keys_exec(MI_SORT_PARAM *sort_param) my_bool error= FALSE; if (sort_param->sort_info->got_error) - error= TRUE; - if (error) DBUG_RETURN(error); set_sort_param_read_write(sort_param); @@ -368,9 +367,7 @@ static my_bool thr_find_all_keys_exec(MI_SORT_PARAM *sort_param) keys < (uint) maxbuffer) { mi_check_print_error(sort_param->sort_info->param, - "myisam_sort_buffer_size is too small. Current " - "myisam_sort_buffer_size: %llu rows: %llu sort_length: %u", - sort_param->sortbuff_size, (ulonglong) idx, sort_length); + "myisam_sort_buffer_size is too small"); DBUG_RETURN(TRUE); } } @@ -398,9 +395,7 @@ static my_bool thr_find_all_keys_exec(MI_SORT_PARAM *sort_param) { /* purecov: begin inspected */ mi_check_print_error(sort_param->sort_info->param, - "myisam_sort_buffer_size is too small. Current " - "myisam_sort_buffer_size: %llu rows: %llu sort_length: %u", - sort_param->sortbuff_size, (ulonglong) idx, sort_length); + "myisam_sort_buffer_size is too small"); my_errno= ENOMEM; goto err; /* purecov: end inspected */ -- cgit v1.2.1 From 34a104ba0ccbe254100a235c04e4648136c9aa7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 14 Jun 2016 12:28:05 +0300 Subject: MDEV-10229: TokuDB fails to build with CLang Structure initialization must feature all members present within the struct. --- storage/tokudb/ft-index/ft/logger/recover.cc | 6 +++--- .../tokudb/ft-index/ft/serialize/ft_node-serialize.cc | 2 +- storage/tokudb/ft-index/ft/txn/txn.cc | 8 ++++---- storage/tokudb/ft-index/portability/toku_pthread.h | 19 ------------------- .../ft-index/src/tests/threaded_stress_test_helpers.h | 2 +- 5 files changed, 9 insertions(+), 28 deletions(-) diff --git a/storage/tokudb/ft-index/ft/logger/recover.cc b/storage/tokudb/ft-index/ft/logger/recover.cc index 680485201da..7a5fa361e2d 100644 --- a/storage/tokudb/ft-index/ft/logger/recover.cc +++ b/storage/tokudb/ft-index/ft/logger/recover.cc @@ -785,7 +785,7 @@ static int toku_recover_xcommit (struct logtype_xcommit *l, RECOVER_ENV renv) { assert(txn!=NULL); // commit the transaction - toku_txn_progress_extra extra = { time(NULL), l->lsn, "commit", l->xid }; + toku_txn_progress_extra extra = { time(NULL), l->lsn, "commit", l->xid, 0 }; int r = toku_txn_commit_with_lsn(txn, true, l->lsn, toku_recover_txn_progress, &extra); assert(r == 0); @@ -828,7 +828,7 @@ static int toku_recover_xabort (struct logtype_xabort *l, RECOVER_ENV renv) { assert(txn!=NULL); // abort the transaction - toku_txn_progress_extra extra = { time(NULL), l->lsn, "abort", l->xid }; + toku_txn_progress_extra extra = { time(NULL), l->lsn, "abort", l->xid, 0 }; r = toku_txn_abort_with_lsn(txn, l->lsn, toku_recover_txn_progress, &extra); assert(r == 0); @@ -1363,7 +1363,7 @@ static void recover_abort_live_txn(TOKUTXN txn) { // sanity check that the recursive call successfully NULLs out txn->child invariant(txn->child == NULL); // abort the transaction - toku_txn_progress_extra extra = { time(NULL), ZERO_LSN, "abort live", txn->txnid }; + toku_txn_progress_extra extra = { time(NULL), ZERO_LSN, "abort live", txn->txnid, 0 }; int r = toku_txn_abort_txn(txn, toku_recover_txn_progress, &extra); assert(r == 0); diff --git a/storage/tokudb/ft-index/ft/serialize/ft_node-serialize.cc b/storage/tokudb/ft-index/ft/serialize/ft_node-serialize.cc index 6fd452aba54..84f3f98cfb5 100644 --- a/storage/tokudb/ft-index/ft/serialize/ft_node-serialize.cc +++ b/storage/tokudb/ft-index/ft/serialize/ft_node-serialize.cc @@ -643,7 +643,7 @@ serialize_and_compress_in_parallel(FTNODE node, struct serialize_compress_work work[npartitions]; workset_lock(&ws); for (int i = 0; i < npartitions; i++) { - work[i] = (struct serialize_compress_work) { .base = {{NULL}}, + work[i] = (struct serialize_compress_work) { .base = {{NULL, NULL}}, .node = node, .i = i, .compression_method = compression_method, diff --git a/storage/tokudb/ft-index/ft/txn/txn.cc b/storage/tokudb/ft-index/ft/txn/txn.cc index 922c955a6b5..9aa93375126 100644 --- a/storage/tokudb/ft-index/ft/txn/txn.cc +++ b/storage/tokudb/ft-index/ft/txn/txn.cc @@ -333,14 +333,14 @@ static txn_child_manager tcm; .do_fsync = false, .force_fsync_on_commit = false, .do_fsync_lsn = ZERO_LSN, - .xa_xid = {0}, + .xa_xid = {0, 0, 0, {}}, .progress_poll_fun = NULL, .progress_poll_fun_extra = NULL, - .txn_lock = ZERO_MUTEX_INITIALIZER, + .txn_lock = TOKU_MUTEX_INITIALIZER, .open_fts = open_fts, .roll_info = roll_info, - .state_lock = ZERO_MUTEX_INITIALIZER, - .state_cond = ZERO_COND_INITIALIZER, + .state_lock = TOKU_MUTEX_INITIALIZER, + .state_cond = TOKU_COND_INITIALIZER, .state = TOKUTXN_LIVE, .num_pin = 0, .client_id = 0, diff --git a/storage/tokudb/ft-index/portability/toku_pthread.h b/storage/tokudb/ft-index/portability/toku_pthread.h index a9dc660b6a7..4a564e4029b 100644 --- a/storage/tokudb/ft-index/portability/toku_pthread.h +++ b/storage/tokudb/ft-index/portability/toku_pthread.h @@ -125,16 +125,6 @@ typedef struct toku_mutex_aligned { toku_mutex_t aligned_mutex __attribute__((__aligned__(64))); } toku_mutex_aligned_t; -// Different OSes implement mutexes as different amounts of nested structs. -// C++ will fill out all missing values with zeroes if you provide at least one zero, but it needs the right amount of nesting. -#if defined(__FreeBSD__) -# define ZERO_MUTEX_INITIALIZER {0} -#elif defined(__APPLE__) -# define ZERO_MUTEX_INITIALIZER {{0}} -#else // __linux__, at least -# define ZERO_MUTEX_INITIALIZER {{{0}}} -#endif - #if TOKU_PTHREAD_DEBUG # define TOKU_MUTEX_INITIALIZER { .pmutex = PTHREAD_MUTEX_INITIALIZER, .owner = 0, .locked = false, .valid = true } #else @@ -276,15 +266,6 @@ typedef struct toku_cond { pthread_cond_t pcond; } toku_cond_t; -// Different OSes implement mutexes as different amounts of nested structs. -// C++ will fill out all missing values with zeroes if you provide at least one zero, but it needs the right amount of nesting. -#if defined(__FreeBSD__) -# define ZERO_COND_INITIALIZER {0} -#elif defined(__APPLE__) -# define ZERO_COND_INITIALIZER {{0}} -#else // __linux__, at least -# define ZERO_COND_INITIALIZER {{{0}}} -#endif #define TOKU_COND_INITIALIZER {PTHREAD_COND_INITIALIZER} static inline void diff --git a/storage/tokudb/ft-index/src/tests/threaded_stress_test_helpers.h b/storage/tokudb/ft-index/src/tests/threaded_stress_test_helpers.h index f9da1693847..fc4acecff10 100644 --- a/storage/tokudb/ft-index/src/tests/threaded_stress_test_helpers.h +++ b/storage/tokudb/ft-index/src/tests/threaded_stress_test_helpers.h @@ -1825,7 +1825,7 @@ static int run_workers( { int r; const struct perf_formatter *perf_formatter = &perf_formatters[cli_args->perf_output_format]; - toku_mutex_t mutex = ZERO_MUTEX_INITIALIZER; + toku_mutex_t mutex = TOKU_MUTEX_INITIALIZER; toku_mutex_init(&mutex, nullptr); struct rwlock rwlock; rwlock_init(&rwlock); -- cgit v1.2.1 From b644661e5d2fb514d373fe533cd7e0131bae54a0 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 14 Jun 2016 22:29:24 +0200 Subject: MDEV-9256 : Crashes on Windows x64 with aria_pagecache_buffer_size > 4GB Fixed wrong calculation of buffer sizes. ulong datatype was used wrongly, as were the casts to ulong. Buffer sizes should be of type size_t, not ulong, or bad things happen on 64 bit Windows. This patch changes pagecache struct to use size_t/ssize_t where long/ulong were previously used. Also, removed several casts. --- storage/maria/ma_pagecache.c | 34 +++++++++++++++++----------------- storage/maria/ma_pagecache.h | 38 +++++++++++++++++++------------------- storage/maria/ma_sort.c | 2 +- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index 6aaccea219f..1a791d43034 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -500,8 +500,8 @@ static void test_key_cache(PAGECACHE *pagecache, const char *where, my_bool lock); #endif -#define PAGECACHE_HASH(p, f, pos) (((ulong) (pos) + \ - (ulong) (f).file) & (p->hash_entries-1)) +#define PAGECACHE_HASH(p, f, pos) (((size_t) (pos) + \ + (size_t) (f).file) & (p->hash_entries-1)) #define FILE_HASH(f) ((uint) (f).file & (PAGECACHE_CHANGED_BLOCKS_HASH - 1)) #define DEFAULT_PAGECACHE_DEBUG_LOG "pagecache_debug.log" @@ -639,10 +639,10 @@ static my_bool pagecache_fwrite(PAGECACHE *pagecache, { char buff[80]; uint len= my_sprintf(buff, - (buff, "fwrite: fd: %d id: %u page: %lu", + (buff, "fwrite: fd: %d id: %u page: %llu", filedesc->file, _ma_file_callback_to_id(filedesc->callback_data), - (ulong) pageno)); + pageno)); (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY, (uchar*) buff, len); } @@ -741,11 +741,11 @@ static inline uint next_power(uint value) */ -ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, +size_t init_pagecache(PAGECACHE *pagecache, size_t use_mem, uint division_limit, uint age_threshold, uint block_size, myf my_readwrite_flags) { - ulong blocks, hash_links, length; + size_t blocks, hash_links, length; int error; DBUG_ENTER("init_pagecache"); DBUG_ASSERT(block_size >= 512); @@ -782,10 +782,10 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, DBUG_PRINT("info", ("block_size: %u", block_size)); DBUG_ASSERT(((uint)(1 << pagecache->shift)) == block_size); - blocks= (ulong) (use_mem / (sizeof(PAGECACHE_BLOCK_LINK) + + blocks= use_mem / (sizeof(PAGECACHE_BLOCK_LINK) + 2 * sizeof(PAGECACHE_HASH_LINK) + sizeof(PAGECACHE_HASH_LINK*) * - 5/4 + block_size)); + 5/4 + block_size); /* We need to support page cache with just one block to be able to do scanning of rows-in-block files @@ -816,7 +816,7 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, blocks--; /* Allocate memory for cache page buffers */ if ((pagecache->block_mem= - my_large_malloc((ulong) blocks * pagecache->block_size, + my_large_malloc(blocks * pagecache->block_size, MYF(MY_WME)))) { /* @@ -824,7 +824,7 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, For each block 2 hash links are allocated */ if ((pagecache->block_root= - (PAGECACHE_BLOCK_LINK*) my_malloc((size_t) length, MYF(0)))) + (PAGECACHE_BLOCK_LINK*) my_malloc(length, MYF(0)))) break; my_large_free(pagecache->block_mem); pagecache->block_mem= 0; @@ -832,7 +832,7 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, blocks= blocks / 4*3; } pagecache->blocks_unused= blocks; - pagecache->disk_blocks= (long) blocks; + pagecache->disk_blocks= blocks; pagecache->hash_links= hash_links; pagecache->hash_root= (PAGECACHE_HASH_LINK**) ((char*) pagecache->block_root + @@ -887,7 +887,7 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, PAGECACHE_CHANGED_BLOCKS_HASH); pagecache->blocks= pagecache->disk_blocks > 0 ? pagecache->disk_blocks : 0; - DBUG_RETURN((ulong) pagecache->disk_blocks); + DBUG_RETURN((size_t)pagecache->disk_blocks); err: error= my_errno; @@ -978,11 +978,11 @@ static int flush_all_key_blocks(PAGECACHE *pagecache) So we disable it for now. */ #if NOT_USED /* keep disabled until code is fixed see above !! */ -ulong resize_pagecache(PAGECACHE *pagecache, +size_t resize_pagecache(PAGECACHE *pagecache, size_t use_mem, uint division_limit, uint age_threshold) { - ulong blocks; + size_t blocks; struct st_my_thread_var *thread; WQUEUE *wqueue; @@ -1379,7 +1379,7 @@ static void link_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block, ("linked block: %u:%1u status: %x #requests: %u #available: %u", PCBLOCK_NUMBER(pagecache, block), at_end, block->status, block->requests, pagecache->blocks_available)); - KEYCACHE_DBUG_ASSERT((ulong) pagecache->blocks_available <= + KEYCACHE_DBUG_ASSERT(pagecache->blocks_available <= pagecache->blocks_used); #endif DBUG_VOID_RETURN; @@ -2018,7 +2018,7 @@ restart: /* There are some never used blocks, take first of them */ block= &pagecache->block_root[pagecache->blocks_used]; block->buffer= ADD_TO_PTR(pagecache->block_mem, - ((ulong) pagecache->blocks_used* + (pagecache->blocks_used* pagecache->block_size), uchar*); pagecache->blocks_used++; @@ -4870,7 +4870,7 @@ my_bool pagecache_collect_changed_blocks_with_lsn(PAGECACHE *pagecache, LSN *min_rec_lsn) { my_bool error= 0; - ulong stored_list_size= 0; + size_t stored_list_size= 0; uint file_hash; char *ptr; LSN minimum_rec_lsn= LSN_MAX; diff --git a/storage/maria/ma_pagecache.h b/storage/maria/ma_pagecache.h index 8460eaddc57..cb331bae74a 100644 --- a/storage/maria/ma_pagecache.h +++ b/storage/maria/ma_pagecache.h @@ -117,20 +117,20 @@ typedef struct st_pagecache_hash_link PAGECACHE_HASH_LINK; typedef struct st_pagecache { size_t mem_size; /* specified size of the cache memory */ - ulong min_warm_blocks; /* min number of warm blocks; */ - ulong age_threshold; /* age threshold for hot blocks */ + size_t min_warm_blocks; /* min number of warm blocks; */ + size_t age_threshold; /* age threshold for hot blocks */ ulonglong time; /* total number of block link operations */ - ulong hash_entries; /* max number of entries in the hash table */ - long hash_links; /* max number of hash links */ - long hash_links_used; /* number of hash links taken from free links pool */ - long disk_blocks; /* max number of blocks in the cache */ - ulong blocks_used; /* maximum number of concurrently used blocks */ - ulong blocks_unused; /* number of currently unused blocks */ - ulong blocks_changed; /* number of currently dirty blocks */ - ulong warm_blocks; /* number of blocks in warm sub-chain */ - ulong cnt_for_resize_op; /* counter to block resize operation */ - ulong blocks_available; /* number of blocks available in the LRU chain */ - long blocks; /* max number of blocks in the cache */ + size_t hash_entries; /* max number of entries in the hash table */ + ssize_t hash_links; /* max number of hash links */ + ssize_t hash_links_used; /* number of hash links taken from free links pool */ + ssize_t disk_blocks; /* max number of blocks in the cache */ + size_t blocks_used; /* maximum number of concurrently used blocks */ + size_t blocks_unused; /* number of currently unused blocks */ + size_t blocks_changed; /* number of currently dirty blocks */ + size_t warm_blocks; /* number of blocks in warm sub-chain */ + size_t cnt_for_resize_op; /* counter to block resize operation */ + size_t blocks_available; /* number of blocks available in the LRU chain */ + ssize_t blocks; /* max number of blocks in the cache */ uint32 block_size; /* size of the page buffer of a cache block */ PAGECACHE_HASH_LINK **hash_root;/* arr. of entries into hash table buckets */ PAGECACHE_HASH_LINK *hash_link_root;/* memory for hash table links */ @@ -155,12 +155,12 @@ typedef struct st_pagecache */ ulonglong param_buff_size; /* size the memory allocated for the cache */ - ulong param_block_size; /* size of the blocks in the key cache */ - ulong param_division_limit; /* min. percentage of warm blocks */ - ulong param_age_threshold; /* determines when hot block is downgraded */ + size_t param_block_size; /* size of the blocks in the key cache */ + size_t param_division_limit; /* min. percentage of warm blocks */ + size_t param_age_threshold; /* determines when hot block is downgraded */ /* Statistics variables. These are reset in reset_pagecache_counters(). */ - ulong global_blocks_changed; /* number of currently dirty blocks */ + size_t global_blocks_changed; /* number of currently dirty blocks */ ulonglong global_cache_w_requests;/* number of write requests (write hits) */ ulonglong global_cache_write; /* number of writes from cache to files */ ulonglong global_cache_r_requests;/* number of read requests (read hits) */ @@ -193,10 +193,10 @@ typedef enum pagecache_flush_filter_result /* The default key cache */ extern PAGECACHE dflt_pagecache_var, *dflt_pagecache; -extern ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, +extern size_t init_pagecache(PAGECACHE *pagecache, size_t use_mem, uint division_limit, uint age_threshold, uint block_size, myf my_read_flags); -extern ulong resize_pagecache(PAGECACHE *pagecache, +extern size_t resize_pagecache(PAGECACHE *pagecache, size_t use_mem, uint division_limit, uint age_threshold); extern void change_pagecache_param(PAGECACHE *pagecache, uint division_limit, diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index 4f092b17037..3180118a155 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -519,7 +519,7 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) { MARIA_SORT_INFO *sort_info=sort_param->sort_info; HA_CHECK *param=sort_info->param; - ulong UNINIT_VAR(length), keys; + size_t UNINIT_VAR(length), keys; double *rec_per_key_part= param->new_rec_per_key_part; int got_error=sort_info->got_error; uint i; -- cgit v1.2.1 From 7ab7abdb51ab88664f12f1a7be3730aaa0a950db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Thu, 16 Jun 2016 18:52:46 +0300 Subject: Fix compilation failure when compiling with std=c90 Change variable declaration to be before any other statements. --- storage/maria/ma_sort.c | 5 ++--- storage/myisam/sort.c | 7 +++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index 3180118a155..a95f9bb7ddb 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -335,15 +335,14 @@ err: static my_bool _ma_thr_find_all_keys_exec(MARIA_SORT_PARAM* sort_param) { - DBUG_ENTER("_ma_thr_find_all_keys"); - DBUG_PRINT("enter", ("master: %d", sort_param->master)); - my_bool error= FALSE; ulonglong memavl, old_memavl; uint UNINIT_VAR(keys), idx; uint sort_length; uint maxbuffer; uchar **sort_keys= NULL; + DBUG_ENTER("_ma_thr_find_all_keys"); + DBUG_PRINT("enter", ("master: %d", sort_param->master)); if (sort_param->sort_info->got_error) DBUG_RETURN(TRUE); diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index e10e4e26112..b1cdbf450c8 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -321,16 +321,15 @@ static ha_rows find_all_keys(MI_SORT_PARAM *info, uint keys, static my_bool thr_find_all_keys_exec(MI_SORT_PARAM *sort_param) { - DBUG_ENTER("thr_find_all_keys"); - DBUG_PRINT("enter", ("master: %d", sort_param->master)); - ulonglong memavl, old_memavl; uint UNINIT_VAR(keys), idx; uint sort_length; uint maxbuffer; uchar **sort_keys= NULL; - my_bool error= FALSE; + DBUG_ENTER("thr_find_all_keys"); + DBUG_PRINT("enter", ("master: %d", sort_param->master)); + if (sort_param->sort_info->got_error) DBUG_RETURN(error); -- cgit v1.2.1 From c7eef029533d71d1c83c231dde065184589930f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Thu, 16 Jun 2016 22:00:16 +0300 Subject: Increase the number of default build thread ids possibilities When running mysql-test-run without a parallel parameter, it might be impossible to find a free port. --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 63b18c6bebd..a85bed88395 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1803,7 +1803,7 @@ sub set_build_thread_ports($) { $build_thread = 300; # Start attempts from here my $build_thread_upper = $build_thread + ($opt_parallel > 1500 ? 3000 - : 2 * $opt_parallel); + : 2 * $opt_parallel) + 300; while (! $found_free) { $build_thread= mtr_get_unique_id($build_thread, $build_thread_upper); -- cgit v1.2.1 From 12ae840375fe30da1c23647facaa0678858d6d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Thu, 16 Jun 2016 22:04:24 +0300 Subject: Fix typo bug that cause myisam repair to fail We need to return TRUE if got_error == 1, not error, which is initialized to FALSE. --- storage/maria/ma_sort.c | 2 +- storage/myisam/sort.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index a95f9bb7ddb..a49ce8fba1f 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -335,7 +335,7 @@ err: static my_bool _ma_thr_find_all_keys_exec(MARIA_SORT_PARAM* sort_param) { - my_bool error= FALSE; + int error= 0; ulonglong memavl, old_memavl; uint UNINIT_VAR(keys), idx; uint sort_length; diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index b1cdbf450c8..ed9267a6f1f 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -326,12 +326,12 @@ static my_bool thr_find_all_keys_exec(MI_SORT_PARAM *sort_param) uint sort_length; uint maxbuffer; uchar **sort_keys= NULL; - my_bool error= FALSE; + int error= 0; DBUG_ENTER("thr_find_all_keys"); DBUG_PRINT("enter", ("master: %d", sort_param->master)); if (sort_param->sort_info->got_error) - DBUG_RETURN(error); + DBUG_RETURN(TRUE); set_sort_param_read_write(sort_param); -- cgit v1.2.1 From 7ff86b49912df5de7b5a8b9c9134e72134b7ba5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Fri, 17 Jun 2016 14:59:17 +0300 Subject: MDEV-10247 TokuDB assertion error when building with DEBUG Fix the assertion failure by setting the struct to 0. This can not be done using a macro due to different definitions of mutexes on various OS-es. Afterwards we call toku_mutex_init and completely initialize the locks. --- storage/tokudb/ft-index/ft/txn/txn.cc | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/storage/tokudb/ft-index/ft/txn/txn.cc b/storage/tokudb/ft-index/ft/txn/txn.cc index 9aa93375126..34c7e0f2a67 100644 --- a/storage/tokudb/ft-index/ft/txn/txn.cc +++ b/storage/tokudb/ft-index/ft/txn/txn.cc @@ -336,17 +336,26 @@ static txn_child_manager tcm; .xa_xid = {0, 0, 0, {}}, .progress_poll_fun = NULL, .progress_poll_fun_extra = NULL, - .txn_lock = TOKU_MUTEX_INITIALIZER, + .txn_lock = {}, // Needs to be set to 0 after initialization. + // See: + // https://llvm.org/bugs/show_bug.cgi?id=21689 + // and MDEV-10229 .open_fts = open_fts, .roll_info = roll_info, - .state_lock = TOKU_MUTEX_INITIALIZER, - .state_cond = TOKU_COND_INITIALIZER, + .state_lock = {}, // Needs to be set to 0. + .state_cond = {}, // Needs to be set to 0. .state = TOKUTXN_LIVE, .num_pin = 0, .client_id = 0, .start_time = time(NULL), }; + // We initialize the locks afterwards, but to prevent undefined behaviour + // we zero-out the structures containing them. + ZERO_STRUCT(new_txn.txn_lock); + ZERO_STRUCT(new_txn.state_lock); + ZERO_STRUCT(new_txn.state_cond); + TOKUTXN result = NULL; XMEMDUP(result, &new_txn); invalidate_xa_xid(&result->xa_xid); -- cgit v1.2.1 From 128930c19b4ebc6a50f254bcee6af84db79ebe91 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Fri, 17 Jun 2016 12:39:20 -0400 Subject: bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 58a6b369de9..db9d497c141 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=50 +MYSQL_VERSION_PATCH=51 MYSQL_VERSION_EXTRA= -- cgit v1.2.1 From 7f38a070baa503a37af186ff24f39606816f55ec Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 17 Jun 2016 18:54:11 +0400 Subject: MDEV-10043 - main.events_restart fails sporadically in buildbot (crashes upon shutdown) There was race condition between shutdown thread and event worker threads. Shutdown thread waits for thread_count to become 0 in close_connections(). It may happen so that event worker thread was started but didn't increment thread_count by this time. In this case shutdown thread may miss wait for this working thread and continue deinitialization. Worker thread in turn may continue execution and crash on deinitialized data. Fixed by incrementing thread_count before thread is actually created like it is done for connection threads. Also let event scheduler not to inc/dec running threads counter for symmetry with other "service" threads. --- sql/event_scheduler.cc | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index beb3c864662..a5a3f7110b3 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -131,12 +131,6 @@ post_init_event_thread(THD *thd) thd->cleanup(); return TRUE; } - - mysql_mutex_lock(&LOCK_thread_count); - threads.append(thd); - thread_count++; - inc_thread_running(); - mysql_mutex_unlock(&LOCK_thread_count); return FALSE; } @@ -158,7 +152,6 @@ deinit_event_thread(THD *thd) DBUG_PRINT("exit", ("Event thread finishing")); mysql_mutex_lock(&LOCK_thread_count); thread_count--; - dec_thread_running(); delete thd; mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); @@ -195,6 +188,8 @@ pre_init_event_thread(THD* thd) thd->client_capabilities|= CLIENT_MULTI_RESULTS; mysql_mutex_lock(&LOCK_thread_count); thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; + threads.append(thd); + thread_count++; mysql_mutex_unlock(&LOCK_thread_count); /* @@ -241,13 +236,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; @@ -308,6 +298,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; @@ -334,6 +325,7 @@ end: event->name.str)); delete event; + dec_thread_running(); deinit_event_thread(thd); DBUG_VOID_RETURN; @@ -432,13 +424,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; @@ -505,7 +493,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")); @@ -564,10 +551,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; } @@ -579,9 +563,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); } -- cgit v1.2.1 From 95bf696d2c8ee189a1836b5b0e4ec353aa4bda30 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 19 Jun 2016 14:51:03 +0200 Subject: MDEV-9749 InnoDB receives 'Bad file descriptor' error, possibly related to feedback plugin and MDEV-10250 InnoDB: Error: File (unknown): 'close' returned OS error 209. Cannot continue operation" after a failed connect() feedback plugin was continuing with the file descriptor, trying to send the data (which failed) and closing it at the end. Even though this fd might've been reused for something else already. --- plugin/feedback/url_http.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/feedback/url_http.cc b/plugin/feedback/url_http.cc index dff5da56a4f..fbea38c07eb 100644 --- a/plugin/feedback/url_http.cc +++ b/plugin/feedback/url_http.cc @@ -190,6 +190,7 @@ int Url_http::send(const char* data, size_t data_length) break; closesocket(fd); + fd= INVALID_SOCKET; } freeaddrinfo(addrs); -- cgit v1.2.1 From a482e76e65a4fee70479e877929381c86b1ec62f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 20 Jun 2016 16:12:54 +0200 Subject: fix a mysql-5.5.50 merge: mysqlcheck quote identifiers correctly --- client/mysqlcheck.c | 4 ++-- mysql-test/r/mysqlcheck.result | 5 +++++ mysql-test/t/mysqlcheck.test | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 011a0e2d738..75f841f3c5e 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -756,7 +756,7 @@ static int fix_table_storage_name(const char *name) if (strncmp(name, "#mysql50#", 9)) DBUG_RETURN(1); - my_snprintf(qbuf, sizeof(qbuf), "RENAME TABLE `%s` TO `%s`", + my_snprintf(qbuf, sizeof(qbuf), "RENAME TABLE %`s TO %`s", name, name + 9); rc= run_query(qbuf); @@ -773,7 +773,7 @@ static int fix_database_storage_name(const char *name) if (strncmp(name, "#mysql50#", 9)) DBUG_RETURN(1); - my_snprintf(qbuf, sizeof(qbuf), "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY " + my_snprintf(qbuf, sizeof(qbuf), "ALTER DATABASE %`s UPGRADE DATA DIRECTORY " "NAME", name); rc= run_query(qbuf); if (verbose) diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index c5ba3e7dc79..d2f4745c5f1 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -339,3 +339,8 @@ Repairing views test.v1 OK drop view v1; drop table t1; +create table `#mysql50#t1``1` (a int) engine=myisam; +show tables; +Tables_in_test +t1`1 +drop table `t1``1`; diff --git a/mysql-test/t/mysqlcheck.test b/mysql-test/t/mysqlcheck.test index ac42e1e184d..7da14e3742a 100644 --- a/mysql-test/t/mysqlcheck.test +++ b/mysql-test/t/mysqlcheck.test @@ -350,3 +350,8 @@ create table t1(a int); --exec $MYSQL_CHECK --process-views --check-upgrade --auto-repair test drop view v1; drop table t1; + +create table `#mysql50#t1``1` (a int) engine=myisam; +--exec $MYSQL_CHECK --fix-table-names --databases test +show tables; +drop table `t1``1`; -- cgit v1.2.1