Commit aa37b757 authored by monty@mysql.com's avatar monty@mysql.com

Merge mysql.com:/home/my/mysql-5.0

into  mysql.com:/home/my/mysql-5.1
parents 30b360bf f5804869
...@@ -469,6 +469,7 @@ libmysqld/get_password.c ...@@ -469,6 +469,7 @@ libmysqld/get_password.c
libmysqld/gstream.cc libmysqld/gstream.cc
libmysqld/ha_archive.cc libmysqld/ha_archive.cc
libmysqld/ha_berkeley.cc libmysqld/ha_berkeley.cc
libmysqld/ha_blackhole.cc
libmysqld/ha_example.cc libmysqld/ha_example.cc
libmysqld/ha_federated.cc libmysqld/ha_federated.cc
libmysqld/ha_heap.cc libmysqld/ha_heap.cc
......
...@@ -662,11 +662,7 @@ typedef SOCKET_SIZE_TYPE size_socket; ...@@ -662,11 +662,7 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define FN_LEN 256 /* Max file name len */ #define FN_LEN 256 /* Max file name len */
#define FN_HEADLEN 253 /* Max length of filepart of file name */ #define FN_HEADLEN 253 /* Max length of filepart of file name */
#define FN_EXTLEN 20 /* Max length of extension (part of FN_LEN) */ #define FN_EXTLEN 20 /* Max length of extension (part of FN_LEN) */
#ifdef PATH_MAX
#define FN_REFLEN PATH_MAX/* Max length of full path-name */
#else
#define FN_REFLEN 512 /* Max length of full path-name */ #define FN_REFLEN 512 /* Max length of full path-name */
#endif
#define FN_EXTCHAR '.' #define FN_EXTCHAR '.'
#define FN_HOMELIB '~' /* ~/ is used as abbrev for home dir */ #define FN_HOMELIB '~' /* ~/ is used as abbrev for home dir */
#define FN_CURLIB '.' /* ./ is used as abbrev for current dir */ #define FN_CURLIB '.' /* ./ is used as abbrev for current dir */
......
...@@ -9,7 +9,7 @@ use strict; ...@@ -9,7 +9,7 @@ use strict;
sub mtr_full_hostname (); sub mtr_full_hostname ();
sub mtr_short_hostname (); sub mtr_short_hostname ();
sub mtr_init_args ($); sub mtr_init_args ($);
sub mtr_add_arg ($$); sub mtr_add_arg ($$@);
sub mtr_path_exists(@); sub mtr_path_exists(@);
sub mtr_script_exists(@); sub mtr_script_exists(@);
sub mtr_exe_exists(@); sub mtr_exe_exists(@);
...@@ -51,7 +51,7 @@ sub mtr_init_args ($) { ...@@ -51,7 +51,7 @@ sub mtr_init_args ($) {
$$args = []; # Empty list $$args = []; # Empty list
} }
sub mtr_add_arg ($$) { sub mtr_add_arg ($$@) {
my $args= shift; my $args= shift;
my $format= shift; my $format= shift;
my @fargs = @_; my @fargs = @_;
......
# -*- cperl -*-
# This is a library file used by the Perl version of mysql-test-run,
# and is part of the translation of the Bourne shell script with the
# same name.
use strict;
use File::Spec;
# These are not to be prefixed with "mtr_"
sub run_stress_test ();
##############################################################################
#
# Run tests in the stress mode
#
##############################################################################
sub run_stress_test ()
{
my $args;
my $stress_basedir;
my $stress_suitedir;
mtr_report("Starting stress testing\n");
if ( ! $::glob_use_embedded_server and ! $::opt_local_master )
{
$::master->[0]->{'pid'}= mysqld_start('master',0,[],[]);
if ( ! $::master->[0]->{'pid'} )
{
mtr_error("Can't start the mysqld server");
}
}
my $stress_basedir=File::Spec->catdir($::opt_vardir, "stress");
#Clean up stress dir
if ( -d $stress_basedir )
{
rmtree($stress_basedir);
}
mkpath($stress_basedir);
if ($::opt_stress_suite ne 'main' && $::opt_stress_suite ne 'default' )
{
$stress_suitedir=File::Spec->catdir($::glob_mysql_test_dir, "suite",
$::opt_stress_suite);
}
else
{
$stress_suitedir=$::glob_mysql_test_dir;
}
if ( -d $stress_suitedir )
{
#$stress_suite_t_dir=File::Spec->catdir($stress_suitedir, "t");
#$stress_suite_r_dir=File::Spec->catdir($stress_suitedir, "r");
#FIXME: check dirs above for existence to ensure that test suite
# contains tests and results dirs
}
else
{
mtr_error("Specified test suite $::opt_stress_suite doesn't exist");
}
if ( @::opt_cases )
{
$::opt_stress_test_file=File::Spec->catfile($stress_basedir, "stress_tests.txt");
open(STRESS_FILE, ">$::opt_stress_test_file");
print STRESS_FILE join("\n",@::opt_cases),"\n";
close(STRESS_FILE);
}
elsif ( $::opt_stress_test_file )
{
$::opt_stress_test_file=File::Spec->catfile($stress_suitedir,
$::opt_stress_test_file);
if ( ! -f $::opt_stress_test_file )
{
mtr_error("Specified file $::opt_stress_test_file with list of tests does not exist\n",
"Please ensure that file exists and has proper permissions");
}
}
else
{
$::opt_stress_test_file=File::Spec->catfile($stress_suitedir,
"stress_tests.txt");
if ( ! -f $::opt_stress_test_file )
{
mtr_error("Default file $::opt_stress_test_file with list of tests does not exist\n",
"Please use --stress-test-file option to specify custom one or you can\n",
"just specify name of test for testing as last argument in command line");
}
}
if ( $::opt_stress_init_file )
{
$::opt_stress_init_file=File::Spec->catfile($stress_suitedir,
$::opt_stress_init_file);
if ( ! -f $::opt_stress_init_file )
{
mtr_error("Specified file $::opt_stress_init_file with list of tests does not exist\n",
"Please ensure that file exists and has proper permissions");
}
}
else
{
$::opt_stress_init_file=File::Spec->catfile($stress_suitedir,
"stress_init.txt");
if ( ! -f $::opt_stress_init_file )
{
$::opt_stress_init_file='';
}
}
if ( $::opt_stress_mode ne 'random' && $::opt_stress_mode ne 'seq' )
{
mtr_error("You specified wrong mode $::opt_stress_mode for stress test\n",
"Correct values are 'random' or 'seq'");
}
mtr_init_args(\$args);
mtr_add_arg($args, "--server-socket=%s", $::master->[0]->{'path_mysock'});
mtr_add_arg($args, "--server-user=%s", $::opt_user);
mtr_add_arg($args, "--server-database=%s", "test");
mtr_add_arg($args, "--stress-suite-basedir=%s", $::glob_mysql_test_dir);
mtr_add_arg($args, "--suite=%s", $::opt_stress_suite);
mtr_add_arg($args, "--stress-tests-file=%s", $::opt_stress_test_file);
mtr_add_arg($args, "--stress-basedir=%s", $stress_basedir);
mtr_add_arg($args, "--server-logs-dir=%s", $stress_basedir);
mtr_add_arg($args, "--stress-mode=%s", $::opt_stress_mode);
mtr_add_arg($args, "--mysqltest=%s", $::exe_mysqltest);
mtr_add_arg($args, "--threads=%s", $::opt_stress_threads);
mtr_add_arg($args, "--verbose");
mtr_add_arg($args, "--cleanup");
mtr_add_arg($args, "--log-error-details");
mtr_add_arg($args, "--abort-on-error");
if ( $::opt_stress_init_file )
{
mtr_add_arg($args, "--stress-init-file=%", $::opt_stress_init_file);
}
if ( $::opt_stress_loop_count )
{
mtr_add_arg($args, "--loop-count=%s", $::opt_stress_loop_count);
}
if ( $::opt_stress_test_count )
{
mtr_add_arg($args, "--test-count=%s", $::opt_stress_test_count);
}
if ( $::opt_stress_test_duration )
{
mtr_add_arg($args, "--test-duration=%s", $::opt_stress_test_duration);
}
#Run stress test
mtr_run("$::glob_mysql_test_dir/mysql-stress-test.pl", $args, "", "", "", "");
if ( ! $::glob_use_embedded_server )
{
stop_masters();
}
}
1;
...@@ -96,6 +96,7 @@ require "lib/mtr_report.pl"; ...@@ -96,6 +96,7 @@ require "lib/mtr_report.pl";
require "lib/mtr_diff.pl"; require "lib/mtr_diff.pl";
require "lib/mtr_match.pl"; require "lib/mtr_match.pl";
require "lib/mtr_misc.pl"; require "lib/mtr_misc.pl";
require "lib/mtr_stress.pl";
$Devel::Trace::TRACE= 1; $Devel::Trace::TRACE= 1;
...@@ -271,6 +272,16 @@ our $opt_valgrind_mysqltest; ...@@ -271,6 +272,16 @@ our $opt_valgrind_mysqltest;
our $opt_valgrind_all; our $opt_valgrind_all;
our $opt_valgrind_options; our $opt_valgrind_options;
our $opt_stress= "";
our $opt_stress_suite= "main";
our $opt_stress_mode= "random";
our $opt_stress_threads= 5;
our $opt_stress_test_count= 20;
our $opt_stress_loop_count= "";
our $opt_stress_test_duration= "";
our $opt_stress_init_file= "";
our $opt_stress_test_file= "";
our $opt_verbose; our $opt_verbose;
our $opt_wait_for_master; our $opt_wait_for_master;
...@@ -391,6 +402,10 @@ sub main () { ...@@ -391,6 +402,10 @@ sub main () {
{ {
run_benchmarks(shift); # Shift what? Extra arguments?! run_benchmarks(shift); # Shift what? Extra arguments?!
} }
elsif ( $opt_stress )
{
run_stress_test()
}
else else
{ {
run_tests(); run_tests();
...@@ -547,6 +562,17 @@ sub command_line_setup () { ...@@ -547,6 +562,17 @@ sub command_line_setup () {
'valgrind-all:s' => \$opt_valgrind_all, 'valgrind-all:s' => \$opt_valgrind_all,
'valgrind-options=s' => \$opt_valgrind_options, 'valgrind-options=s' => \$opt_valgrind_options,
# Stress testing
'stress' => \$opt_stress,
'stress-suite=s' => \$opt_stress_suite,
'stress-threads=i' => \$opt_stress_threads,
'stress-test-file=s' => \$opt_stress_test_file,
'stress-init-file=s' => \$opt_stress_init_file,
'stress-mode=s' => \$opt_stress_mode,
'stress-loop-count=i' => \$opt_stress_loop_count,
'stress-test-count=i' => \$opt_stress_test_count,
'stress-test-duration=i' => \$opt_stress_test_duration,
# Misc # Misc
'big-test' => \$opt_big_test, 'big-test' => \$opt_big_test,
'debug' => \$opt_debug, 'debug' => \$opt_debug,
......
...@@ -4976,3 +4976,27 @@ c1 ...@@ -4976,3 +4976,27 @@ c1
4 4
5 5
DROP TABLE bug14672; DROP TABLE bug14672;
create table t1 (a int) engine=csv;
insert t1 values (1);
delete from t1;
affected rows: 1
delete from t1;
affected rows: 0
insert t1 values (1),(2);
delete from t1;
affected rows: 2
insert t1 values (1),(2),(3);
flush tables;
delete from t1;
affected rows: 3
insert t1 values (1),(2),(3),(4);
flush tables;
select count(*) from t1;
count(*)
4
delete from t1;
affected rows: 4
insert t1 values (1),(2),(3),(4),(5);
truncate table t1;
affected rows: 0
drop table t1;
...@@ -40,14 +40,14 @@ CREATE TABLE federated.t1 ( ...@@ -40,14 +40,14 @@ CREATE TABLE federated.t1 (
) )
ENGINE="FEDERATED" DEFAULT CHARSET=latin1 ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t3'; CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t3';
ERROR HY000: Can't create federated table. Foreign data src error : ': 1146 : Table 'federated.t3' doesn't exist' ERROR HY000: Can't create federated table. Foreign data src error: error: 1146 'Table 'federated.t3' doesn't exist'
CREATE TABLE federated.t1 ( CREATE TABLE federated.t1 (
`id` int(20) NOT NULL, `id` int(20) NOT NULL,
`name` varchar(32) NOT NULL default '' `name` varchar(32) NOT NULL default ''
) )
ENGINE="FEDERATED" DEFAULT CHARSET=latin1 ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1'; CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1';
ERROR HY000: Unable to connect to foreign data source - database ' database federated username user hostname 127.0.0.1'! ERROR HY000: Unable to connect to foreign data source: database: 'federated' username: 'user' hostname: '127.0.0.1'
DROP TABLE IF EXISTS federated.t1; DROP TABLE IF EXISTS federated.t1;
Warnings: Warnings:
Note 1051 Unknown table 't1' Note 1051 Unknown table 't1'
......
...@@ -238,7 +238,7 @@ Grants for drop_user@localhost ...@@ -238,7 +238,7 @@ Grants for drop_user@localhost
GRANT USAGE ON *.* TO 'drop_user'@'localhost' GRANT USAGE ON *.* TO 'drop_user'@'localhost'
drop user drop_user@localhost; drop user drop_user@localhost;
revoke all privileges, grant option from drop_user@localhost; revoke all privileges, grant option from drop_user@localhost;
ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users ERROR HY000: Can't revoke all privileges for one or more of the requested users
grant select(a) on test.t1 to drop_user1@localhost; grant select(a) on test.t1 to drop_user1@localhost;
grant select on test.t1 to drop_user2@localhost; grant select on test.t1 to drop_user2@localhost;
grant select on test.* to drop_user3@localhost; grant select on test.* to drop_user3@localhost;
...@@ -247,7 +247,7 @@ drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, ...@@ -247,7 +247,7 @@ drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost; drop_user4@localhost;
revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost, revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost,
drop_user3@localhost, drop_user4@localhost; drop_user3@localhost, drop_user4@localhost;
ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users ERROR HY000: Can't revoke all privileges for one or more of the requested users
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost; drop_user4@localhost;
ERROR HY000: Operation DROP USER failed for 'drop_user1'@'localhost','drop_user2'@'localhost','drop_user3'@'localhost','drop_user4'@'localhost' ERROR HY000: Operation DROP USER failed for 'drop_user1'@'localhost','drop_user2'@'localhost','drop_user3'@'localhost','drop_user4'@'localhost'
......
...@@ -191,7 +191,7 @@ flush privileges; ...@@ -191,7 +191,7 @@ flush privileges;
show grants for 'mysqltest_1'; show grants for 'mysqltest_1';
ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%'
revoke all privileges, grant option from 'mysqltest_1'; revoke all privileges, grant option from 'mysqltest_1';
ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users ERROR HY000: Can't revoke all privileges for one or more of the requested users
drop user 'mysqltest_1'; drop user 'mysqltest_1';
select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user; select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user;
host db user host db user
......
...@@ -1352,3 +1352,35 @@ SELECT * FROM bug14672; ...@@ -1352,3 +1352,35 @@ SELECT * FROM bug14672;
DROP TABLE bug14672; DROP TABLE bug14672;
# End of 4.1 tests # End of 4.1 tests
#
# BUG#13406 - incorrect amount of "records deleted"
#
create table t1 (a int) engine=csv;
insert t1 values (1);
--enable_info
delete from t1; -- delete_row
delete from t1; -- delete_all_rows
--disable_info
insert t1 values (1),(2);
--enable_info
delete from t1; -- delete_all_rows
--disable_info
insert t1 values (1),(2),(3);
flush tables;
--enable_info
delete from t1; -- delete_row
--disable_info
insert t1 values (1),(2),(3),(4);
flush tables;
select count(*) from t1;
--enable_info
delete from t1; -- delete_all_rows
--disable_info
insert t1 values (1),(2),(3),(4),(5);
--enable_info
truncate table t1; -- truncate
--disable_info
drop table t1;
...@@ -298,7 +298,7 @@ ha_tina::ha_tina(TABLE *table_arg) ...@@ -298,7 +298,7 @@ ha_tina::ha_tina(TABLE *table_arg)
These are not probably completely right. These are not probably completely right.
*/ */
current_position(0), next_position(0), chain_alloced(0), current_position(0), next_position(0), chain_alloced(0),
chain_size(DEFAULT_CHAIN_LENGTH) chain_size(DEFAULT_CHAIN_LENGTH), records_is_known(0)
{ {
/* Set our original buffers from pre-allocated memory */ /* Set our original buffers from pre-allocated memory */
buffer.set(byte_buffer, IO_SIZE, system_charset_info); buffer.set(byte_buffer, IO_SIZE, system_charset_info);
...@@ -534,6 +534,7 @@ int ha_tina::write_row(byte * buf) ...@@ -534,6 +534,7 @@ int ha_tina::write_row(byte * buf)
*/ */
if (get_mmap(share, 0) > 0) if (get_mmap(share, 0) > 0)
DBUG_RETURN(-1); DBUG_RETURN(-1);
records++;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -700,6 +701,7 @@ int ha_tina::rnd_init(bool scan) ...@@ -700,6 +701,7 @@ int ha_tina::rnd_init(bool scan)
current_position= next_position= 0; current_position= next_position= 0;
records= 0; records= 0;
records_is_known= 0;
chain_ptr= chain; chain_ptr= chain;
#ifdef HAVE_MADVISE #ifdef HAVE_MADVISE
if (scan) if (scan)
...@@ -781,7 +783,7 @@ void ha_tina::info(uint flag) ...@@ -781,7 +783,7 @@ void ha_tina::info(uint flag)
{ {
DBUG_ENTER("ha_tina::info"); DBUG_ENTER("ha_tina::info");
/* This is a lie, but you don't want the optimizer to see zero or 1 */ /* This is a lie, but you don't want the optimizer to see zero or 1 */
if (records < 2) if (!records_is_known && records < 2)
records= 2; records= 2;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -818,6 +820,8 @@ int ha_tina::rnd_end() ...@@ -818,6 +820,8 @@ int ha_tina::rnd_end()
{ {
DBUG_ENTER("ha_tina::rnd_end"); DBUG_ENTER("ha_tina::rnd_end");
records_is_known= 1;
/* First position will be truncate position, second will be increment */ /* First position will be truncate position, second will be increment */
if ((chain_ptr - chain) > 0) if ((chain_ptr - chain) > 0)
{ {
...@@ -862,18 +866,24 @@ int ha_tina::rnd_end() ...@@ -862,18 +866,24 @@ int ha_tina::rnd_end()
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/* /*
Truncate table and others of its ilk call this. DELETE without WHERE calls this
*/ */
int ha_tina::delete_all_rows() int ha_tina::delete_all_rows()
{ {
DBUG_ENTER("ha_tina::delete_all_rows"); DBUG_ENTER("ha_tina::delete_all_rows");
if (!records_is_known)
return (my_errno=HA_ERR_WRONG_COMMAND);
int rc= my_chsize(share->data_file, 0, 0, MYF(MY_WME)); int rc= my_chsize(share->data_file, 0, 0, MYF(MY_WME));
if (get_mmap(share, 0) > 0) if (get_mmap(share, 0) > 0)
DBUG_RETURN(-1); DBUG_RETURN(-1);
records=0;
DBUG_RETURN(rc); DBUG_RETURN(rc);
} }
......
...@@ -53,6 +53,7 @@ class ha_tina: public handler ...@@ -53,6 +53,7 @@ class ha_tina: public handler
tina_set *chain_ptr; tina_set *chain_ptr;
byte chain_alloced; byte chain_alloced;
uint32 chain_size; uint32 chain_size;
bool records_is_known;
public: public:
ha_tina(TABLE *table_arg); ha_tina(TABLE *table_arg);
......
...@@ -488,8 +488,7 @@ int federated_db_end(ha_panic_function type) ...@@ -488,8 +488,7 @@ int federated_db_end(ha_panic_function type)
table, and if so, does the foreign table exist. table, and if so, does the foreign table exist.
*/ */
static int check_foreign_data_source( static int check_foreign_data_source(FEDERATED_SHARE *share,
FEDERATED_SHARE *share,
bool table_create_flag) bool table_create_flag)
{ {
char escaped_table_name[NAME_LEN*2]; char escaped_table_name[NAME_LEN*2];
...@@ -519,11 +518,13 @@ static int check_foreign_data_source( ...@@ -519,11 +518,13 @@ static int check_foreign_data_source(
we want the correct error message, but it to return we want the correct error message, but it to return
ER_CANT_CREATE_FEDERATED_TABLE if called by ::create ER_CANT_CREATE_FEDERATED_TABLE if called by ::create
*/ */
error_code= table_create_flag? error_code= (table_create_flag ?
ER_CANT_CREATE_FEDERATED_TABLE : ER_CONNECT_TO_FOREIGN_DATA_SOURCE; ER_CANT_CREATE_FEDERATED_TABLE :
ER_CONNECT_TO_FOREIGN_DATA_SOURCE);
my_sprintf(error_buffer, my_sprintf(error_buffer,
(error_buffer, " database %s username %s hostname %s", (error_buffer,
"database: '%s' username: '%s' hostname: '%s'",
share->database, share->username, share->hostname)); share->database, share->username, share->hostname));
my_error(ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), error_buffer); my_error(ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), error_buffer);
...@@ -564,7 +565,7 @@ static int check_foreign_data_source( ...@@ -564,7 +565,7 @@ static int check_foreign_data_source(
{ {
error_code= table_create_flag ? error_code= table_create_flag ?
ER_CANT_CREATE_FEDERATED_TABLE : ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST; ER_CANT_CREATE_FEDERATED_TABLE : ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST;
my_sprintf(error_buffer, (error_buffer, ": %d : %s", my_sprintf(error_buffer, (error_buffer, "error: %d '%s'",
mysql_errno(mysql), mysql_error(mysql))); mysql_errno(mysql), mysql_error(mysql)));
my_error(error_code, MYF(0), error_buffer); my_error(error_code, MYF(0), error_buffer);
...@@ -2032,7 +2033,7 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, ...@@ -2032,7 +2033,7 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key,
} }
if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length())) if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length()))
{ {
my_sprintf(error_buffer, (error_buffer, ": %d : %s", my_sprintf(error_buffer, (error_buffer, "error: %d '%s'",
mysql_errno(mysql), mysql_error(mysql))); mysql_errno(mysql), mysql_error(mysql)));
retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE; retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
goto error; goto error;
......
...@@ -101,6 +101,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; ...@@ -101,6 +101,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define MAX_FIELDS_BEFORE_HASH 32 #define MAX_FIELDS_BEFORE_HASH 32
#define USER_VARS_HASH_SIZE 16 #define USER_VARS_HASH_SIZE 16
#define STACK_MIN_SIZE 8192 // Abort if less stack during eval. #define STACK_MIN_SIZE 8192 // Abort if less stack during eval.
#define STACK_MIN_SIZE_FOR_OPEN 1024*80
#define STACK_BUFF_ALLOC 256 // For stack overrun checks #define STACK_BUFF_ALLOC 256 // For stack overrun checks
#ifndef MYSQLD_NET_RETRY_COUNT #ifndef MYSQLD_NET_RETRY_COUNT
#define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int. #define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int.
......
This diff is collapsed.
...@@ -3070,6 +3070,7 @@ pthread_handler_t handle_slave_io(void *arg) ...@@ -3070,6 +3070,7 @@ pthread_handler_t handle_slave_io(void *arg)
THD_CHECK_SENTRY(thd); THD_CHECK_SENTRY(thd);
pthread_detach_this_thread(); pthread_detach_this_thread();
thd->thread_stack= (char*) &thd; // remember where our stack is
if (init_slave_thread(thd, SLAVE_THD_IO)) if (init_slave_thread(thd, SLAVE_THD_IO))
{ {
pthread_cond_broadcast(&mi->start_cond); pthread_cond_broadcast(&mi->start_cond);
...@@ -3078,7 +3079,6 @@ pthread_handler_t handle_slave_io(void *arg) ...@@ -3078,7 +3079,6 @@ pthread_handler_t handle_slave_io(void *arg)
goto err; goto err;
} }
mi->io_thd = thd; mi->io_thd = thd;
thd->thread_stack = (char*)&thd; // remember where our stack is
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
threads.append(thd); threads.append(thd);
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
......
...@@ -157,6 +157,7 @@ my_bool acl_init(bool dont_read_acl_tables) ...@@ -157,6 +157,7 @@ my_bool acl_init(bool dont_read_acl_tables)
*/ */
if (!(thd=new THD)) if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
thd->thread_stack= (char*) &thd;
thd->store_globals(); thd->store_globals();
/* /*
It is safe to call acl_reload() since acl_* arrays and hashes which It is safe to call acl_reload() since acl_* arrays and hashes which
...@@ -3263,6 +3264,7 @@ my_bool grant_init() ...@@ -3263,6 +3264,7 @@ my_bool grant_init()
if (!(thd= new THD)) if (!(thd= new THD))
DBUG_RETURN(1); /* purecov: deadcode */ DBUG_RETURN(1); /* purecov: deadcode */
thd->thread_stack= (char*) &thd;
thd->store_globals(); thd->store_globals();
return_val= grant_reload(thd); return_val= grant_reload(thd);
delete thd; delete thd;
......
...@@ -1090,7 +1090,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, ...@@ -1090,7 +1090,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
*refresh=0; *refresh=0;
/* an open table operation needs a lot of the stack space */ /* an open table operation needs a lot of the stack space */
if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (char *)&alias)) if (check_stack_overrun(thd, STACK_MIN_SIZE_FOR_OPEN, (char *)&alias))
return 0; return 0;
if (thd->killed) if (thd->killed)
......
...@@ -517,6 +517,12 @@ void THD::awake(THD::killed_state state_to_set) ...@@ -517,6 +517,12 @@ void THD::awake(THD::killed_state state_to_set)
bool THD::store_globals() bool THD::store_globals()
{ {
/*
Assert that thread_stack is initialized: it's necessary to be able
to track stack overrun.
*/
DBUG_ASSERT(this->thread_stack);
if (my_pthread_setspecific_ptr(THR_THD, this) || if (my_pthread_setspecific_ptr(THR_THD, this) ||
my_pthread_setspecific_ptr(THR_MALLOC, &mem_root)) my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
return 1; return 1;
......
...@@ -1736,6 +1736,7 @@ pthread_handler_t handle_delayed_insert(void *arg) ...@@ -1736,6 +1736,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
#endif #endif
DBUG_ENTER("handle_delayed_insert"); DBUG_ENTER("handle_delayed_insert");
thd->thread_stack= (char*) &thd;
if (init_thr_lock() || thd->store_globals()) if (init_thr_lock() || thd->store_globals())
{ {
thd->fatal_error(); thd->fatal_error();
......
...@@ -1091,6 +1091,7 @@ pthread_handler_t handle_one_connection(void *arg) ...@@ -1091,6 +1091,7 @@ pthread_handler_t handle_one_connection(void *arg)
VOID(sigemptyset(&set)); // Get mask in use VOID(sigemptyset(&set)); // Get mask in use
VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals)); VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
#endif #endif
thd->thread_stack= (char*) &thd;
if (thd->store_globals()) if (thd->store_globals())
{ {
close_connection(thd, ER_OUT_OF_RESOURCES, 1); close_connection(thd, ER_OUT_OF_RESOURCES, 1);
...@@ -1104,7 +1105,6 @@ pthread_handler_t handle_one_connection(void *arg) ...@@ -1104,7 +1105,6 @@ pthread_handler_t handle_one_connection(void *arg)
int error; int error;
NET *net= &thd->net; NET *net= &thd->net;
Security_context *sctx= thd->security_ctx; Security_context *sctx= thd->security_ctx;
thd->thread_stack= (char*) &thd;
net->no_send_error= 0; net->no_send_error= 0;
if ((error=check_connection(thd))) if ((error=check_connection(thd)))
...@@ -1195,6 +1195,7 @@ pthread_handler_t handle_bootstrap(void *arg) ...@@ -1195,6 +1195,7 @@ pthread_handler_t handle_bootstrap(void *arg)
char *buff; char *buff;
/* The following must be called before DBUG_ENTER */ /* The following must be called before DBUG_ENTER */
thd->thread_stack= (char*) &thd;
if (my_thread_init() || thd->store_globals()) if (my_thread_init() || thd->store_globals())
{ {
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
...@@ -5286,6 +5287,7 @@ bool check_stack_overrun(THD *thd, long margin, ...@@ -5286,6 +5287,7 @@ bool check_stack_overrun(THD *thd, long margin,
char *buf __attribute__((unused))) char *buf __attribute__((unused)))
{ {
long stack_used; long stack_used;
DBUG_ASSERT(thd == current_thd);
if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >= if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >=
(long) (thread_stack - margin)) (long) (thread_stack - margin))
{ {
...@@ -6735,7 +6737,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, ...@@ -6735,7 +6737,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
allocate temporary THD for execution of acl_reload()/grant_reload(). allocate temporary THD for execution of acl_reload()/grant_reload().
*/ */
if (!thd && (thd= (tmp_thd= new THD))) if (!thd && (thd= (tmp_thd= new THD)))
{
thd->thread_stack= (char*) &tmp_thd;
thd->store_globals(); thd->store_globals();
}
if (thd) if (thd)
{ {
(void)acl_reload(thd); (void)acl_reload(thd);
......
...@@ -133,6 +133,7 @@ void udf_init() ...@@ -133,6 +133,7 @@ void udf_init()
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
initialized = 1; initialized = 1;
new_thd->thread_stack= (char*) &new_thd;
new_thd->store_globals(); new_thd->store_globals();
new_thd->db= my_strdup("mysql", MYF(0)); new_thd->db= my_strdup("mysql", MYF(0));
new_thd->db_length=5; new_thd->db_length=5;
......
...@@ -1532,6 +1532,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) ...@@ -1532,6 +1532,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
*/ */
if (!(thd= new THD)) if (!(thd= new THD))
DBUG_RETURN(1); DBUG_RETURN(1);
thd->thread_stack= (char*) &thd;
thd->store_globals(); thd->store_globals();
/* Init all memory structures that require explicit destruction */ /* Init all memory structures that require explicit destruction */
......
...@@ -46,8 +46,8 @@ ...@@ -46,8 +46,8 @@
#define ERRMAPP 1 /* Errormap f|r my_error */ #define ERRMAPP 1 /* Errormap f|r my_error */
#define LIBLEN FN_REFLEN-FN_LEN /* Max l{ngd p} dev */ #define LIBLEN FN_REFLEN-FN_LEN /* Max l{ngd p} dev */
#define MAX_DBKEY_LENGTH (FN_LEN*2+1+1+4+4) /* extra 4+4 bytes for slave tmp /* extra 4+4 bytes for slave tmp tables */
* tables */ #define MAX_DBKEY_LENGTH (NAME_LEN*2+1+1+4+4)
#define MAX_ALIAS_NAME 256 #define MAX_ALIAS_NAME 256
#define MAX_FIELD_NAME 34 /* Max colum name length +2 */ #define MAX_FIELD_NAME 34 /* Max colum name length +2 */
#define MAX_SYS_VAR_LENGTH 32 #define MAX_SYS_VAR_LENGTH 32
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment