diff options
79 files changed, 1440 insertions, 406 deletions
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index b2d672453cf..04d5ee99789 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1783,7 +1783,6 @@ show variables like "innodb_sync_spin_loops"; Variable_name Value innodb_sync_spin_loops 20 set global innodb_sync_spin_loops=@innodb_sync_spin_loops_orig; -SET @old_innodb_thread_concurrency= @@global.innodb_thread_concurrency; show variables like "innodb_thread_concurrency"; Variable_name Value innodb_thread_concurrency 0 @@ -1801,7 +1800,6 @@ set global innodb_thread_concurrency=16; show variables like "innodb_thread_concurrency"; Variable_name Value innodb_thread_concurrency 16 -SET @@global.innodb_thread_concurrency= @old_innodb_thread_concurrency; show variables like "innodb_concurrency_tickets"; Variable_name Value innodb_concurrency_tickets 500 @@ -3090,7 +3088,7 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction commit; drop table t1, t2, t3, t5, t6, t8, t9; CREATE TABLE t1 (DB_ROW_ID int) engine=innodb; -ERROR HY000: Can't create table 'test.t1' (errno: -1) +ERROR 42000: Incorrect column name 'DB_ROW_ID' CREATE TABLE t1 ( a BIGINT(20) NOT NULL, PRIMARY KEY (a) diff --git a/mysql-test/r/innodb_bug34300.result b/mysql-test/r/innodb_bug34300.result index 4e3d3c17040..ae9fee81ad7 100644 --- a/mysql-test/r/innodb_bug34300.result +++ b/mysql-test/r/innodb_bug34300.result @@ -1,10 +1,4 @@ -SELECT f4, f8 FROM bug34300; f4 f8 xxx zzz -ALTER TABLE bug34300 ADD COLUMN (f10 INT); -SELECT f4, f8 FROM bug34300; f4 f8 xxx zzz -DROP TABLE bug34300; -SET @@global.max_allowed_packet=1048576; -SET @@global.max_allowed_packet=default; diff --git a/mysql-test/r/innodb_bug44369.result b/mysql-test/r/innodb_bug44369.result index 9cf79aeffab..ff25c774aa2 100644 --- a/mysql-test/r/innodb_bug44369.result +++ b/mysql-test/r/innodb_bug44369.result @@ -1,14 +1,6 @@ create table bug44369 (DB_ROW_ID int) engine=innodb; -ERROR HY000: Can't create table 'test.bug44369' (errno: -1) +ERROR 42000: Incorrect column name 'DB_ROW_ID' create table bug44369 (db_row_id int) engine=innodb; -ERROR HY000: Can't create table 'test.bug44369' (errno: -1) -show warnings; -Level Code Message -Warning 1005 Error creating table 'test/bug44369' with column name 'db_row_id'. 'db_row_id' is a reserved name. Please try to re-create the table with a different column name. -Error 1005 Can't create table 'test.bug44369' (errno: -1) +ERROR 42000: Incorrect column name 'db_row_id' create table bug44369 (db_TRX_Id int) engine=innodb; -ERROR HY000: Can't create table 'test.bug44369' (errno: -1) -show warnings; -Level Code Message -Warning 1005 Error creating table 'test/bug44369' with column name 'db_TRX_Id'. 'db_TRX_Id' is a reserved name. Please try to re-create the table with a different column name. -Error 1005 Can't create table 'test.bug44369' (errno: -1) +ERROR 42000: Incorrect column name 'db_TRX_Id' diff --git a/mysql-test/r/partition_innodb_builtin.result b/mysql-test/r/partition_innodb_builtin.result deleted file mode 100644 index 384ce0790a4..00000000000 --- a/mysql-test/r/partition_innodb_builtin.result +++ /dev/null @@ -1,39 +0,0 @@ -SET NAMES utf8; -CREATE TABLE `t``\""e` (a INT, PRIMARY KEY (a)) -ENGINE=InnoDB -PARTITION BY RANGE (a) -SUBPARTITION BY HASH (a) -(PARTITION `p0``\""e` VALUES LESS THAN (100) -(SUBPARTITION `sp0``\""e`, -SUBPARTITION `sp1``\""e`), -PARTITION `p1``\""e` VALUES LESS THAN (MAXVALUE) -(SUBPARTITION `sp2``\""e`, -SUBPARTITION `sp3``\""e`)); -INSERT INTO `t``\""e` VALUES (0), (2), (6), (10), (14), (18), (22); -START TRANSACTION; -# con1 -SET NAMES utf8; -START TRANSACTION; -# default connection -UPDATE `t``\""e` SET a = 16 WHERE a = 0; -# con1 -UPDATE `t``\""e` SET a = 8 WHERE a = 22; -UPDATE `t``\""e` SET a = 12 WHERE a = 0; -# default connection -UPDATE `t``\""e` SET a = 4 WHERE a = 22; -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -# First table reported in 'SHOW ENGINE InnoDB STATUS' -SHOW ENGINE InnoDB STATUS; -Type Name Status -InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */ -set @old_sql_mode = @@sql_mode; -set sql_mode = 'ANSI_QUOTES'; -SHOW ENGINE InnoDB STATUS; -Type Name Status -InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */ -set @@sql_mode = @old_sql_mode; -# con1 -ROLLBACK; -# default connection -DROP TABLE `t``\""e`; -SET NAMES DEFAULT; diff --git a/mysql-test/suite/innodb/r/innodb-index.result b/mysql-test/suite/innodb/r/innodb-index.result index a7d66b15300..67fbe0dce02 100644 --- a/mysql-test/suite/innodb/r/innodb-index.result +++ b/mysql-test/suite/innodb/r/innodb-index.result @@ -968,6 +968,7 @@ create index t1u on t1 (u(1)); drop table t1; set global innodb_file_per_table=0; set global innodb_file_format=Antelope; +set global innodb_file_format_check=Antelope; SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; CREATE TABLE t1( diff --git a/mysql-test/suite/innodb/r/innodb_bug46676.result b/mysql-test/suite/innodb/r/innodb_bug46676.result new file mode 100644 index 00000000000..996799ce931 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug46676.result @@ -0,0 +1,9 @@ +SET foreign_key_checks=0; +CREATE TABLE t1 (id int, foreign key (id) references t2(id)) ENGINE=INNODB; +CREATE TABLE t2 (id int, foreign key (id) references t1(id)) ENGINE=INNODB; +SET foreign_key_checks=1; +SELECT COUNT(*) FROM information_schema.key_column_usage WHERE REFERENCED_TABLE_NAME in ('t1', 't2'); +COUNT(*) +2 +SET foreign_key_checks=0; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/innodb/r/innodb_bug47167.result b/mysql-test/suite/innodb/r/innodb_bug47167.result new file mode 100644 index 00000000000..cbec363d78f --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug47167.result @@ -0,0 +1,24 @@ +set @old_innodb_file_format_check=@@innodb_file_format_check; +select @old_innodb_file_format_check; +@old_innodb_file_format_check +Antelope +set global innodb_file_format_check = Barracuda; +select @@innodb_file_format_check; +@@innodb_file_format_check +Barracuda +set global innodb_file_format_check = DEFAULT; +select @@innodb_file_format_check; +@@innodb_file_format_check +Barracuda +set global innodb_file_format_check = @old_innodb_file_format_check; +select @@innodb_file_format_check; +@@innodb_file_format_check +Antelope +set global innodb_file_format_check = cheetah; +ERROR HY000: Incorrect arguments to SET +set global innodb_file_format_check = Bear; +ERROR HY000: Incorrect arguments to SET +set global innodb_file_format_check = on; +ERROR HY000: Incorrect arguments to SET +set global innodb_file_format_check = off; +ERROR HY000: Incorrect arguments to SET diff --git a/mysql-test/suite/innodb/r/innodb_file_format.result b/mysql-test/suite/innodb/r/innodb_file_format.result index fbc67ada1bb..36f176c616a 100644 --- a/mysql-test/suite/innodb/r/innodb_file_format.result +++ b/mysql-test/suite/innodb/r/innodb_file_format.result @@ -31,8 +31,6 @@ select @@innodb_file_format_check; @@innodb_file_format_check Barracuda set global innodb_file_format_check=default; -Warnings: -Warning 1210 Ignoring SET innodb_file_format=on select @@innodb_file_format_check; @@innodb_file_format_check Barracuda diff --git a/mysql-test/suite/innodb/t/disabled.def b/mysql-test/suite/innodb/t/disabled.def deleted file mode 100644 index a1ccbbd3603..00000000000 --- a/mysql-test/suite/innodb/t/disabled.def +++ /dev/null @@ -1 +0,0 @@ -innodb-index : Bug#47563 2009-06-11 svoj InnoDB: Error: table `test`.`t1#1` already exists in InnoDB internal diff --git a/mysql-test/suite/innodb/t/innodb-index.test b/mysql-test/suite/innodb/t/innodb-index.test index 54aff3a42c0..b5dd2e037e7 100644 --- a/mysql-test/suite/innodb/t/innodb-index.test +++ b/mysql-test/suite/innodb/t/innodb-index.test @@ -1,5 +1,7 @@ -- source include/have_innodb.inc +let $innodb_file_format_check_orig=`select @@innodb_file_format_check`; + create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb; insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak'); commit; @@ -398,6 +400,7 @@ create index t1u on t1 (u(1)); drop table t1; eval set global innodb_file_per_table=$per_table; eval set global innodb_file_format=$format; +eval set global innodb_file_format_check=$format; # # Test to check whether CREATE INDEX handles implicit foreign key @@ -532,3 +535,10 @@ disconnect a; disconnect b; DROP TABLE t1; + +# +# restore environment to the state it was before this test execution +# + +-- disable_query_log +eval SET GLOBAL innodb_file_format_check=$innodb_file_format_check_orig; diff --git a/mysql-test/suite/innodb/t/innodb_bug46676.test b/mysql-test/suite/innodb/t/innodb_bug46676.test new file mode 100644 index 00000000000..440666c4226 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug46676.test @@ -0,0 +1,16 @@ +# This is the test for bug 46676: mysqld got exception 0xc0000005 +# It is reproducible with InnoDB plugin 1.0.4 + MySQL 5.1.37. +# But no longer reproducible after MySQL 5.1.38 (with plugin 1.0.5). + +--source include/have_innodb.inc + +SET foreign_key_checks=0; +CREATE TABLE t1 (id int, foreign key (id) references t2(id)) ENGINE=INNODB; +CREATE TABLE t2 (id int, foreign key (id) references t1(id)) ENGINE=INNODB; +SET foreign_key_checks=1; + +# Server crashes +SELECT COUNT(*) FROM information_schema.key_column_usage WHERE REFERENCED_TABLE_NAME in ('t1', 't2'); + +SET foreign_key_checks=0; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/innodb/t/innodb_bug47167.test b/mysql-test/suite/innodb/t/innodb_bug47167.test new file mode 100644 index 00000000000..88e927c01bd --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug47167.test @@ -0,0 +1,45 @@ +# This is the unit test for bug *47167. +# It tests setting the global variable +# "innodb_file_format_check" with a +# user-Defined Variable. + +--source include/have_innodb.inc + +# Save the value (Antelope) in 'innodb_file_format_check' to +# 'old_innodb_file_format_check' +set @old_innodb_file_format_check=@@innodb_file_format_check; + +# @old_innodb_file_format_check shall have the value of 'Antelope' +select @old_innodb_file_format_check; + +# Reset the value in 'innodb_file_format_check' to 'Barracuda' +set global innodb_file_format_check = Barracuda; + +select @@innodb_file_format_check; + +# Set 'innodb_file_format_check' to its default value, which +# is the latest file format supported in the current release. +set global innodb_file_format_check = DEFAULT; + +select @@innodb_file_format_check; + +# Put the saved value back to 'innodb_file_format_check' +set global innodb_file_format_check = @old_innodb_file_format_check; + +# Check whether 'innodb_file_format_check' get its original value. +select @@innodb_file_format_check; + +# Following are negative tests, all should fail. +--disable_warnings +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = cheetah; + +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = Bear; + +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = on; + +--error ER_WRONG_ARGUMENTS +set global innodb_file_format_check = off; +--enable_warnings diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index ad7617b9403..06d3dbb4e57 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -11,7 +11,4 @@ ############################################################################## kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically -partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes -partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes -innodb-autoinc : Bug#48482 2009-11-02 svoj innodb-autoinc.test fails with results difference rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2 diff --git a/mysql-test/t/innodb-master.opt b/mysql-test/t/innodb-master.opt index 4901efb416c..72c88068345 100644 --- a/mysql-test/t/innodb-master.opt +++ b/mysql-test/t/innodb-master.opt @@ -1 +1 @@ ---binlog_cache_size=32768 --innodb_lock_wait_timeout=1 +--binlog_cache_size=32768 --loose_innodb_lock_wait_timeout=1 diff --git a/mysql-test/t/innodb-semi-consistent-master.opt b/mysql-test/t/innodb-semi-consistent-master.opt index e76299453d3..cb48f1aaf60 100644 --- a/mysql-test/t/innodb-semi-consistent-master.opt +++ b/mysql-test/t/innodb-semi-consistent-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 2879a4c0b9f..075058d42c2 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -15,8 +15,6 @@ -- source include/have_innodb.inc -let $MYSQLD_DATADIR= `select @@datadir`; - # Save the original values of some variables in order to be able to # estimate how much they have changed during the tests. Previously this # test assumed that e.g. rows_deleted is 0 here and after deleting 23 @@ -1187,6 +1185,8 @@ drop table t2; # Test error handling +# Embedded server doesn't chdir to data directory +--replace_result $MYSQLTEST_VARDIR . master-data/ '' --error ER_WRONG_FK_DEF create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb; @@ -1343,7 +1343,6 @@ show variables like "innodb_sync_spin_loops"; set global innodb_sync_spin_loops=@innodb_sync_spin_loops_orig; # Test for innodb_thread_concurrency variable -SET @old_innodb_thread_concurrency= @@global.innodb_thread_concurrency; show variables like "innodb_thread_concurrency"; set global innodb_thread_concurrency=1001; show variables like "innodb_thread_concurrency"; @@ -1351,7 +1350,6 @@ set global innodb_thread_concurrency=0; show variables like "innodb_thread_concurrency"; set global innodb_thread_concurrency=16; show variables like "innodb_thread_concurrency"; -SET @@global.innodb_thread_concurrency= @old_innodb_thread_concurrency; # Test for innodb_concurrency_tickets variable show variables like "innodb_concurrency_tickets"; @@ -1383,6 +1381,8 @@ source include/varchar.inc; # Some errors/warnings on create # +# Embedded server doesn't chdir to data directory +--replace_result $MYSQLTEST_VARDIR . master-data/ '' create table t1 (v varchar(65530), key(v)); drop table t1; create table t1 (v varchar(65536)); @@ -1656,6 +1656,8 @@ disconnect b; set foreign_key_checks=0; create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; +# Embedded server doesn't chdir to data directory +--replace_result $MYSQLTEST_VARDIR . master-data/ '' -- error 1005 create table t1(a char(10) primary key, b varchar(20)) engine = innodb; set foreign_key_checks=1; @@ -1666,6 +1668,8 @@ drop table t2; set foreign_key_checks=0; create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +# Embedded server doesn't chdir to data directory +--replace_result $MYSQLTEST_VARDIR . master-data/ '' -- error 1005 create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8; set foreign_key_checks=1; @@ -1695,7 +1699,8 @@ drop table t2,t1; set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; ---replace_result $MYSQLD_DATADIR ./ +# Embedded server doesn't chdir to data directory +--replace_result $MYSQLTEST_VARDIR . master-data/ '' -- error 1025 rename table t3 to t1; set foreign_key_checks=1; @@ -2259,7 +2264,7 @@ disconnect j; drop table t1, t2, t3, t5, t6, t8, t9; # bug 18934, "InnoDB crashes when table uses column names like DB_ROW_ID" ---error 1005 +--error ER_WRONG_COLUMN_NAME CREATE TABLE t1 (DB_ROW_ID int) engine=innodb; # @@ -2334,7 +2339,8 @@ INSERT INTO t2 VALUES (1); ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL; # mysqltest first does replace_regex, then replace_result --replace_regex /'[^']*test\/#sql-[0-9a-f_]*'/'#sql-temporary'/ ---replace_result $MYSQLD_DATADIR ./ +# Embedded server doesn't chdir to data directory +--replace_result $MYSQLTEST_VARDIR . master-data/ '' --error 1025 ALTER TABLE t2 MODIFY a INT NOT NULL; DELETE FROM t1; diff --git a/mysql-test/t/innodb_bug34300.test b/mysql-test/t/innodb_bug34300.test index 0bd50abcabf..68c385fd72a 100644 --- a/mysql-test/t/innodb_bug34300.test +++ b/mysql-test/t/innodb_bug34300.test @@ -22,7 +22,6 @@ CREATE TABLE bug34300 ( INSERT INTO bug34300 VALUES ('xxx', repeat('a', 8459264), 'zzz'); --- enable_query_log -- enable_result_log SELECT f4, f8 FROM bug34300; @@ -32,8 +31,4 @@ ALTER TABLE bug34300 ADD COLUMN (f10 INT); SELECT f4, f8 FROM bug34300; DROP TABLE bug34300; - EVAL SET @@global.max_allowed_packet=$max_packet; -disconnect newconn; -connection default; -SET @@global.max_allowed_packet=default; diff --git a/mysql-test/t/innodb_bug42101-nonzero-master.opt b/mysql-test/t/innodb_bug42101-nonzero-master.opt index d71dbe17d5b..455d66a06b8 100644 --- a/mysql-test/t/innodb_bug42101-nonzero-master.opt +++ b/mysql-test/t/innodb_bug42101-nonzero-master.opt @@ -1 +1 @@ ---innodb_commit_concurrency=1 +--loose_innodb_commit_concurrency=1 diff --git a/mysql-test/t/innodb_bug44369.test b/mysql-test/t/innodb_bug44369.test index 238dc3d8fb1..f5d85cd5815 100644 --- a/mysql-test/t/innodb_bug44369.test +++ b/mysql-test/t/innodb_bug44369.test @@ -6,16 +6,12 @@ --source include/have_innodb.inc # This create table operation should fail. ---error ER_CANT_CREATE_TABLE +--error ER_WRONG_COLUMN_NAME create table bug44369 (DB_ROW_ID int) engine=innodb; # This create should fail as well ---error ER_CANT_CREATE_TABLE +--error ER_WRONG_COLUMN_NAME create table bug44369 (db_row_id int) engine=innodb; -show warnings; - ---error ER_CANT_CREATE_TABLE +--error ER_WRONG_COLUMN_NAME create table bug44369 (db_TRX_Id int) engine=innodb; - -show warnings; diff --git a/mysql-test/t/partition_innodb_builtin.test b/mysql-test/t/partition_innodb_builtin.test deleted file mode 100644 index a9be41c7455..00000000000 --- a/mysql-test/t/partition_innodb_builtin.test +++ /dev/null @@ -1,67 +0,0 @@ ---source include/have_partition.inc ---source include/have_innodb.inc ---source include/have_not_innodb_plugin.inc - -# -# Bug#32430 - show engine innodb status causes errors -# -SET NAMES utf8; -CREATE TABLE `t``\""e` (a INT, PRIMARY KEY (a)) -ENGINE=InnoDB -PARTITION BY RANGE (a) -SUBPARTITION BY HASH (a) -(PARTITION `p0``\""e` VALUES LESS THAN (100) - (SUBPARTITION `sp0``\""e`, - SUBPARTITION `sp1``\""e`), - PARTITION `p1``\""e` VALUES LESS THAN (MAXVALUE) - (SUBPARTITION `sp2``\""e`, - SUBPARTITION `sp3``\""e`)); -INSERT INTO `t``\""e` VALUES (0), (2), (6), (10), (14), (18), (22); -START TRANSACTION; ---echo # con1 -connect(con1,localhost,root,,); -SET NAMES utf8; -START TRANSACTION; ---echo # default connection -connection default; -UPDATE `t``\""e` SET a = 16 WHERE a = 0; ---echo # con1 -connection con1; -UPDATE `t``\""e` SET a = 8 WHERE a = 22; -let $id_1= `SELECT CONNECTION_ID()`; -SEND; -UPDATE `t``\""e` SET a = 12 WHERE a = 0; ---echo # default connection -connection default; -let $wait_timeout= 2; -let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST -WHERE ID = $id_1 AND STATE = 'Searching rows for update'; ---source include/wait_condition.inc -#--echo # tested wait condition $wait_condition_reps times ---error ER_LOCK_DEADLOCK -UPDATE `t``\""e` SET a = 4 WHERE a = 22; ---echo # First table reported in 'SHOW ENGINE InnoDB STATUS' -# RECORD LOCKS space id 0 page no 50 n bits 80 index `PRIMARY` in \ -# Database `test`, Table `t1`, Partition `p0`, Subpartition `sp0` \ -# trx id 0 775 -# NOTE: replace_regex is very slow on match copy/past '(.*)' regex's -# on big texts, removing a lot of text before + after makes it much faster. -#/.*in (.*) trx.*/\1/ ---replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in // -SHOW ENGINE InnoDB STATUS; -set @old_sql_mode = @@sql_mode; -set sql_mode = 'ANSI_QUOTES'; -# INNODB_LOCKS only exists in innodb_plugin -#SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; ---replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in // -SHOW ENGINE InnoDB STATUS; -set @@sql_mode = @old_sql_mode; ---echo # con1 -connection con1; -REAP; -ROLLBACK; -disconnect con1; ---echo # default connection -connection default; -DROP TABLE `t``\""e`; -SET NAMES DEFAULT; diff --git a/mysql-test/t/partition_innodb_plugin.test b/mysql-test/t/partition_innodb_plugin.test index fed8c96424a..04c72127394 100644 --- a/mysql-test/t/partition_innodb_plugin.test +++ b/mysql-test/t/partition_innodb_plugin.test @@ -1,6 +1,5 @@ --source include/have_partition.inc --source include/have_innodb.inc ---source suite/innodb/include/have_innodb_plugin.inc # # Bug#32430 - show engine innodb status causes errors diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 57ad7f4b28c..d67b518642c 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -86,12 +86,12 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION) IF (MYSQL_VERSION_ID GREATER "50137") - IF (WITH_INNOBASE_STORAGE_ENGINE) - MYSQL_STORAGE_ENGINE(INNOBASE) - ELSE (WITH_INNOBASE_STORAGE_ENGINE) - SET (INNODB_SOURCES ${INNOBASE_SOURCES}) - MYSQL_STORAGE_ENGINE(INNODB) - ENDIF (WITH_INNOBASE_STORAGE_ENGINE) + MYSQL_STORAGE_ENGINE(INNOBASE) + # Use ha_innodb for plugin name, if plugin is built + GET_TARGET_PROPERTY(LIB_LOCATION ha_innobase LOCATION) + IF(LIB_LOCATION) + SET_TARGET_PROPERTIES(ha_innobase PROPERTIES OUTPUT_NAME ha_innodb) + ENDIF(LIB_LOCATION) ELSE (MYSQL_VERSION_ID GREATER "50137") IF (NOT SOURCE_SUBLIBS) ADD_DEFINITIONS(-D_WIN32 -DMYSQL_SERVER) diff --git a/storage/innobase/ChangeLog b/storage/innobase/ChangeLog index 70225ffd9d9..1a6e07fd147 100644 --- a/storage/innobase/ChangeLog +++ b/storage/innobase/ChangeLog @@ -1,3 +1,87 @@ +2009-11-20 The InnoDB Team + + * handler/ha_innodb.cc: + Add a workaround to prevent a crash due to Bug#45961 DDL on + partitioned innodb tables leaves data dictionary in an inconsistent + state + +2009-11-19 The InnoDB Team + + * btr/btr0btr.c: + Fix Bug#48469 when innodb tablespace is configured too small, crash + and corruption! + +2009-11-19 The InnoDB Team + + * data/data0type.c: + Fix Bug#48526 Data type for float and double is incorrectly reported + in InnoDB table monitor + +2009-11-19 The InnoDB Team + + * CMakeLists.txt: + Fix Bug#48317 cannot build innodb as static library + +2009-11-18 The InnoDB Team + + * handler/handler0alter.cc: + Fix Bug#48782 On lock wait timeout, CREATE INDEX (creating primary key) + attempts DROP TABLE + +2009-11-17 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb.result, + mysql-test/innodb.test, mysql-test/innodb_bug44369.result, + mysql-test/innodb_bug44369.test, mysql-test/patches/innodb-index.diff, + row/row0mysql.c: + Report duplicate table names to the client connection, not to the + error log. + +2009-11-12 The InnoDB Team + + * handler/ha_innodb.cc, include/db0err.h, row/row0merge.c, + row/row0mysql.c: + Allow CREATE INDEX to be interrupted. + Also, when CHECK TABLE is interrupted, report ER_QUERY_INTERRUPTED. + +2009-11-11 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb_bug47167.result, + mysql-test/innodb_bug47167.test, mysql-test/innodb_file_format.result: + Fix Bug#47167 "set global innodb_file_format_check" cannot set value + by User-Defined Variable + +2009-11-11 The InnoDB Team + + * include/os0file.h, os/os0file.c: + Fix Bug#3139 Mysql crashes: 'windows error 995' after several selects + on a large DB + +2009-11-04 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#32430 'show innodb status' causes errors + Invalid (old?) table or database name in logs + +2009-11-02 The InnoDB Team + + * btr/btr0sea.c, buf/buf0buf.c, dict/dict0dict.c, fil/fil0fil.c, + ibuf/ibuf0ibuf.c, include/btr0sea.h, include/dict0dict.h, + include/fil0fil.h, include/ibuf0ibuf.h, include/lock0lock.h, + include/log0log.h, include/log0recv.h, include/mem0mem.h, + include/mem0pool.h, include/os0file.h, include/pars0pars.h, + include/srv0srv.h, include/thr0loc.h, include/trx0i_s.h, + include/trx0purge.h, include/trx0rseg.h, include/trx0sys.h, + include/trx0undo.h, include/usr0sess.h, lock/lock0lock.c, + log/log0log.c, log/log0recv.c, mem/mem0dbg.c, mem/mem0pool.c, + os/os0file.c, os/os0sync.c, os/os0thread.c, pars/lexyy.c, + pars/pars0lex.l, que/que0que.c, srv/srv0srv.c, srv/srv0start.c, + sync/sync0arr.c, sync/sync0sync.c, thr/thr0loc.c, trx/trx0i_s.c, + trx/trx0purge.c, trx/trx0rseg.c, trx/trx0sys.c, trx/trx0undo.c, + usr/usr0sess.c, ut/ut0mem.c: + Fix Bug #45992 innodb memory not freed after shutdown + Fix Bug #46656 InnoDB plugin: memory leaks (Valgrind) + 2009-10-29 The InnoDB Team * handler/ha_innodb.cc, mysql-test/innodb-autoinc.result, @@ -66,6 +150,12 @@ Fix Bug#47058 Failure to compile innodb_plugin on solaris 10u7 + spro cc/CC 5.10 +2009-10-13 The InnoDB Team + + * buf/buf0flu.c: + Call fsync() on datafiles after a batch of pages is written to disk + even when skip_innodb_doublewrite is set. + 2009-10-05 The InnoDB Team * buf/buf0buf.c: diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index 94b34ecece1..086b3a0a599 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/storage/innobase/btr/btr0btr.c @@ -790,8 +790,15 @@ btr_create( } else { /* It is a non-ibuf tree: create a file segment for leaf pages */ - fseg_create(space, page_no, - PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr); + if (!fseg_create(space, page_no, + PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) { + /* Not enough space for new segment, free root + segment before return. */ + btr_free_root(space, zip_size, page_no, mtr); + + return(FIL_NULL); + } + /* The fseg create acquires a second latch on the page, therefore we must declare it: */ buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW); diff --git a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c index 0a80c61a58d..ef7afeb1039 100644 --- a/storage/innobase/btr/btr0sea.c +++ b/storage/innobase/btr/btr0sea.c @@ -175,6 +175,21 @@ btr_search_sys_create( btr_search_sys->hash_index = ha_create(hash_size, 0, 0); } +/*****************************************************************//** +Frees the adaptive search system at a database shutdown. */ +UNIV_INTERN +void +btr_search_sys_free(void) +/*=====================*/ +{ + mem_free(btr_search_latch_temp); + btr_search_latch_temp = NULL; + mem_heap_free(btr_search_sys->hash_index->heap); + hash_table_free(btr_search_sys->hash_index); + mem_free(btr_search_sys); + btr_search_sys = NULL; +} + /********************************************************************//** Disable the adaptive hash search system and empty the index. */ UNIV_INTERN diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index ff31457d200..111d396fbc5 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -1020,7 +1020,11 @@ buf_pool_free(void) os_mem_free_large(chunk->mem, chunk->mem_size); } - buf_pool->n_chunks = 0; + mem_free(buf_pool->chunks); + hash_table_free(buf_pool->page_hash); + hash_table_free(buf_pool->zip_hash); + mem_free(buf_pool); + buf_pool = NULL; } /********************************************************************//** diff --git a/storage/innobase/data/data0type.c b/storage/innobase/data/data0type.c index 8429775e7d8..e834fd2ec55 100644 --- a/storage/innobase/data/data0type.c +++ b/storage/innobase/data/data0type.c @@ -237,6 +237,22 @@ dtype_print( fputs("DATA_SYS", stderr); break; + case DATA_FLOAT: + fputs("DATA_FLOAT", stderr); + break; + + case DATA_DOUBLE: + fputs("DATA_DOUBLE", stderr); + break; + + case DATA_DECIMAL: + fputs("DATA_DECIMAL", stderr); + break; + + case DATA_VARMYSQL: + fputs("DATA_VARMYSQL", stderr); + break; + default: fprintf(stderr, "type %lu", (ulong) mtype); break; diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index aedaf7cec1d..2e524a5a2e3 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -1200,7 +1200,7 @@ dict_index_too_big_for_undo( = TRX_UNDO_PAGE_HDR - TRX_UNDO_PAGE_HDR_SIZE + 2 /* next record pointer */ + 1 /* type_cmpl */ - + 11 /* trx->undo_no */ - 11 /* table->id */ + + 11 /* trx->undo_no */ + 11 /* table->id */ + 1 /* rec_get_info_bits() */ + 11 /* DB_TRX_ID */ + 11 /* DB_ROLL_PTR */ @@ -4652,6 +4652,26 @@ dict_ind_init(void) dict_ind_redundant->cached = dict_ind_compact->cached = TRUE; } +/**********************************************************************//** +Frees dict_ind_redundant and dict_ind_compact. */ +static +void +dict_ind_free(void) +/*===============*/ +{ + dict_table_t* table; + + table = dict_ind_compact->table; + dict_mem_index_free(dict_ind_compact); + dict_ind_compact = NULL; + dict_mem_table_free(table); + + table = dict_ind_redundant->table; + dict_mem_index_free(dict_ind_redundant); + dict_ind_redundant = NULL; + dict_mem_table_free(table); +} + #ifndef UNIV_HOTBACKUP /**********************************************************************//** Get index by name @@ -4777,4 +4797,55 @@ dict_table_check_for_dup_indexes( } } #endif /* UNIV_DEBUG */ + +/************************************************************************** +Closes the data dictionary module. */ +UNIV_INTERN +void +dict_close(void) +/*============*/ +{ + ulint i; + + /* Free the hash elements. We don't remove them from the table + because we are going to destroy the table anyway. */ + for (i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) { + dict_table_t* table; + + table = HASH_GET_FIRST(dict_sys->table_hash, i); + + while (table) { + dict_table_t* prev_table = table; + + table = HASH_GET_NEXT(name_hash, prev_table); +#ifdef UNIV_DEBUG + ut_a(prev_table->magic_n == DICT_TABLE_MAGIC_N); +#endif + /* Acquire only because it's a pre-condition. */ + mutex_enter(&dict_sys->mutex); + + dict_table_remove_from_cache(prev_table); + + mutex_exit(&dict_sys->mutex); + } + } + + hash_table_free(dict_sys->table_hash); + + /* The elements are the same instance as in dict_sys->table_hash, + therefore we don't delete the individual elements. */ + hash_table_free(dict_sys->table_id_hash); + + dict_ind_free(); + + mutex_free(&dict_sys->mutex); + + rw_lock_free(&dict_operation_lock); + memset(&dict_operation_lock, 0x0, sizeof(dict_operation_lock)); + + mutex_free(&dict_foreign_err_mutex); + + mem_free(dict_sys); + dict_sys = NULL; +} #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index ba6f2f8666f..112a0e27d50 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -321,6 +321,17 @@ fil_get_space_id_for_table( /*=======================*/ const char* name); /*!< in: table name in the standard 'databasename/tablename' format */ +/*******************************************************************//** +Frees a space object from the tablespace memory cache. Closes the files in +the chain but does not delete them. There must not be any pending i/o's or +flushes on the files. */ +static +ibool +fil_space_free( +/*===========*/ + /* out: TRUE if success */ + ulint id, /* in: space id */ + ibool own_mutex);/* in: TRUE if own system->mutex */ /********************************************************************//** Reads data from a space to a buffer. Remember that the possible incomplete blocks at the end of file are ignored: they are not taken into account when @@ -1144,7 +1155,7 @@ try_again: mutex_exit(&fil_system->mutex); - fil_space_free(namesake_id); + fil_space_free(namesake_id, FALSE); goto try_again; } @@ -1269,17 +1280,21 @@ Frees a space object from the tablespace memory cache. Closes the files in the chain but does not delete them. There must not be any pending i/o's or flushes on the files. @return TRUE if success */ -UNIV_INTERN +static ibool fil_space_free( /*===========*/ - ulint id) /*!< in: space id */ + /* out: TRUE if success */ + ulint id, /* in: space id */ + ibool own_mutex) /* in: TRUE if own system->mutex */ { fil_space_t* space; fil_space_t* namespace; fil_node_t* fil_node; - mutex_enter(&fil_system->mutex); + if (!own_mutex) { + mutex_enter(&fil_system->mutex); + } space = fil_space_get_by_id(id); @@ -1326,7 +1341,9 @@ fil_space_free( ut_a(0 == UT_LIST_GET_LEN(space->chain)); - mutex_exit(&fil_system->mutex); + if (!own_mutex) { + mutex_exit(&fil_system->mutex); + } rw_lock_free(&(space->latch)); @@ -1586,6 +1603,8 @@ fil_close_all_files(void) space = UT_LIST_GET_FIRST(fil_system->space_list); while (space != NULL) { + fil_space_t* prev_space = space; + node = UT_LIST_GET_FIRST(space->chain); while (node != NULL) { @@ -1595,6 +1614,7 @@ fil_close_all_files(void) node = UT_LIST_GET_NEXT(chain, node); } space = UT_LIST_GET_NEXT(space_list, space); + fil_space_free(prev_space->id, TRUE); } mutex_exit(&fil_system->mutex); @@ -2226,7 +2246,7 @@ try_again: #endif /* printf("Deleting tablespace %s id %lu\n", space->name, id); */ - success = fil_space_free(id); + success = fil_space_free(id, FALSE); if (success) { success = os_file_delete(path); @@ -4753,3 +4773,26 @@ fil_page_get_type( return(mach_read_from_2(page + FIL_PAGE_TYPE)); } + +/******************************************************************** +Initializes the tablespace memory cache. */ +UNIV_INTERN +void +fil_close(void) +/*===========*/ +{ + /* The mutex should already have been freed. */ + ut_ad(fil_system->mutex.magic_n == 0); + + hash_table_free(fil_system->spaces); + + hash_table_free(fil_system->name_hash); + + ut_a(UT_LIST_GET_LEN(fil_system->LRU) == 0); + ut_a(UT_LIST_GET_LEN(fil_system->unflushed_spaces) == 0); + ut_a(UT_LIST_GET_LEN(fil_system->space_list) == 0); + + mem_free(fil_system); + + fil_system = NULL; +} diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 84930c327a0..919f8736043 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -269,10 +269,10 @@ innobase_file_format_check_on_off( /************************************************************//** Validate the file format check config parameters, as a side effect it sets the srv_check_file_format_at_startup variable. -@return true if valid config value */ +@return the format_id if valid config value, otherwise, return -1 */ static -bool -innobase_file_format_check_validate( +int +innobase_file_format_validate_and_set( /*================================*/ const char* format_check); /*!< in: parameter value */ /****************************************************************//** @@ -785,11 +785,20 @@ convert_error_code_to_mysql( case DB_SUCCESS: return(0); + case DB_INTERRUPTED: + my_error(ER_QUERY_INTERRUPTED, MYF(0)); + /* fall through */ case DB_ERROR: default: return(-1); /* unspecified error */ case DB_DUPLICATE_KEY: + /* Be cautious with returning this error, since + mysql could re-enter the storage layer to get + duplicated key info, the operation requires a + valid table handle and/or transaction information, + which might not always be available in the error + handling stage. */ return(HA_ERR_FOUND_DUPP_KEY); case DB_FOREIGN_DUPLICATE_KEY: @@ -1707,15 +1716,19 @@ innobase_convert_identifier( FALSE=id is an UTF-8 string */ { char nz[NAME_LEN + 1]; +#if MYSQL_VERSION_ID >= 50141 + char nz2[NAME_LEN + 1 + EXPLAIN_FILENAME_MAX_EXTRA_LENGTH]; +#else /* MYSQL_VERSION_ID >= 50141 */ char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix]; +#endif /* MYSQL_VERSION_ID >= 50141 */ const char* s = id; int q; if (file_id) { - /* Decode the table name. The filename_to_tablename() - function expects a NUL-terminated string. The input and - output strings buffers must not be shared. */ + /* Decode the table name. The MySQL function expects + a NUL-terminated string. The input and output strings + buffers must not be shared. */ if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) { idlen = (sizeof nz) - 1; @@ -1725,7 +1738,13 @@ innobase_convert_identifier( nz[idlen] = 0; s = nz2; +#if MYSQL_VERSION_ID >= 50141 + idlen = explain_filename((THD*) thd, nz, nz2, sizeof nz2, + EXPLAIN_PARTITIONS_AS_COMMENT); + goto no_quote; +#else /* MYSQL_VERSION_ID >= 50141 */ idlen = filename_to_tablename(nz, nz2, sizeof nz2); +#endif /* MYSQL_VERSION_ID >= 50141 */ } /* See if the identifier needs to be quoted. */ @@ -1736,6 +1755,9 @@ innobase_convert_identifier( } if (q == EOF) { +#if MYSQL_VERSION_ID >= 50141 +no_quote: +#endif /* MYSQL_VERSION_ID >= 50141 */ if (UNIV_UNLIKELY(idlen > buflen)) { idlen = buflen; } @@ -2133,8 +2155,8 @@ mem_free_and_error: /* Did the user specify a format name that we support ? As a side effect it will update the variable srv_check_file_format_at_startup */ - if (!innobase_file_format_check_validate( - innobase_file_format_check)) { + if (innobase_file_format_validate_and_set( + innobase_file_format_check) < 0) { sql_print_error("InnoDB: invalid " "innodb_file_format_check value: " @@ -5225,8 +5247,10 @@ ha_innobase::change_active_index( prebuilt->index); if (UNIV_UNLIKELY(!prebuilt->index_usable)) { - sql_print_warning("InnoDB: insufficient history for index %u", - keynr); + push_warning_printf(user_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_TABLE_DEF_CHANGED, + "InnoDB: insufficient history for index %u", + keynr); /* The caller seems to ignore this. Thus, we must check this again in row_search_for_mysql(). */ DBUG_RETURN(2); @@ -5713,17 +5737,8 @@ create_table_def( /* First check whether the column to be added has a system reserved name. */ if (dict_col_name_is_reserved(field->field_name)){ - push_warning_printf( - (THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_WARN, - ER_CANT_CREATE_TABLE, - "Error creating table '%s' with " - "column name '%s'. '%s' is a " - "reserved name. Please try to " - "re-create the table with a " - "different column name.", - table->name, (char*) field->field_name, - (char*) field->field_name); + my_error(ER_WRONG_COLUMN_NAME, MYF(0), + field->field_name); dict_mem_table_free(table); trx_commit_for_mysql(trx); @@ -5745,6 +5760,14 @@ create_table_def( error = row_create_table_for_mysql(table, trx); + if (error == DB_DUPLICATE_KEY) { + char buf[100]; + innobase_convert_identifier(buf, sizeof buf, + table_name, strlen(table_name), + trx->mysql_thd, TRUE); + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), buf); + } + error_ret: error = convert_error_code_to_mysql(error, flags, NULL); @@ -6798,6 +6821,24 @@ ha_innobase::rename_table( innobase_commit_low(trx); trx_free_for_mysql(trx); + /* Add a special case to handle the Duplicated Key error + and return DB_ERROR instead. + This is to avoid a possible SIGSEGV error from mysql error + handling code. Currently, mysql handles the Duplicated Key + error by re-entering the storage layer and getting dup key + info by calling get_dup_key(). This operation requires a valid + table handle ('row_prebuilt_t' structure) which could no + longer be available in the error handling stage. The suggested + solution is to report a 'table exists' error message (since + the dup key error here is due to an existing table whose name + is the one we are trying to rename to) and return the generic + error code. */ + if (error == (int) DB_DUPLICATE_KEY) { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to); + + error = DB_ERROR; + } + error = convert_error_code_to_mysql(error, 0, NULL); DBUG_RETURN(error); @@ -7348,11 +7389,15 @@ ha_innobase::check( ret = row_check_table_for_mysql(prebuilt); - if (ret == DB_SUCCESS) { + switch (ret) { + case DB_SUCCESS: return(HA_ADMIN_OK); + case DB_INTERRUPTED: + my_error(ER_QUERY_INTERRUPTED, MYF(0)); + return(-1); + default: + return(HA_ADMIN_CORRUPT); } - - return(HA_ADMIN_CORRUPT); } /*************************************************************//** @@ -7899,7 +7944,10 @@ ha_innobase::external_lock( ulong const tx_isolation = thd_tx_isolation(ha_thd()); if (tx_isolation <= ISO_READ_COMMITTED && binlog_format == BINLOG_FORMAT_STMT - && thd_binlog_filter_ok(thd)) +#if MYSQL_VERSION_ID > 50140 + && thd_binlog_filter_ok(thd) +#endif /* MYSQL_VERSION_ID > 50140 */ + ) { char buf[256]; my_snprintf(buf, sizeof(buf), @@ -9148,8 +9196,7 @@ innobase_xa_prepare( executing XA PREPARE and XA COMMIT commands. In this case we cannot know how many minutes or hours will be between XA PREPARE and XA COMMIT, and we don't want - to block for undefined period of time. - */ + to block for undefined period of time. */ pthread_mutex_lock(&prepare_commit_mutex); trx->active_trans = 2; } @@ -9491,25 +9538,24 @@ innobase_file_format_check_on_off( /************************************************************//** Validate the file format check config parameters, as a side effect it sets the srv_check_file_format_at_startup variable. -@return true if valid config value */ +@return the format_id if valid config value, otherwise, return -1 */ static -bool -innobase_file_format_check_validate( +int +innobase_file_format_validate_and_set( /*================================*/ const char* format_check) /*!< in: parameter value */ { uint format_id; - bool ret = true; format_id = innobase_file_format_name_lookup(format_check); if (format_id < DICT_TF_FORMAT_MAX + 1) { srv_check_file_format_at_startup = format_id; + + return((int) format_id); } else { - ret = false; + return(-1); } - - return(ret); } /*************************************************************//** @@ -9544,7 +9590,11 @@ innodb_file_format_name_validate( if (format_id <= DICT_TF_FORMAT_MAX) { - *static_cast<const char**>(save) = file_format_input; + /* Save a pointer to the name in the + 'file_format_name_map' constant array. */ + *static_cast<const char**>(save) = + trx_sys_file_format_id_to_name(format_id); + return(0); } } @@ -9607,6 +9657,7 @@ innodb_file_format_check_validate( const char* file_format_input; char buff[STRING_BUFFER_USUAL_SIZE]; int len = sizeof(buff); + int format_id; ut_a(save != NULL); ut_a(value != NULL); @@ -9619,24 +9670,35 @@ innodb_file_format_check_validate( message if they did so. */ if (innobase_file_format_check_on_off(file_format_input)) { - sql_print_warning( + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, "InnoDB: invalid innodb_file_format_check " "value; on/off can only be set at startup or " "in the configuration file"); - } else if (innobase_file_format_check_validate( - file_format_input)) { + } else { + format_id = innobase_file_format_validate_and_set( + file_format_input); - *static_cast<const char**>(save) = file_format_input; + if (format_id >= 0) { + /* Save a pointer to the name in the + 'file_format_name_map' constant array. */ + *static_cast<const char**>(save) = + trx_sys_file_format_id_to_name( + (uint)format_id); - return(0); + return(0); - } else { - sql_print_warning( - "InnoDB: invalid innodb_file_format_check " - "value; can be any format up to %s " - "or its equivalent numeric id", - trx_sys_file_format_id_to_name( - DICT_TF_FORMAT_MAX)); + } else { + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: invalid innodb_file_format_check " + "value; can be any format up to %s " + "or its equivalent numeric id", + trx_sys_file_format_id_to_name( + DICT_TF_FORMAT_MAX)); + } } } @@ -9906,12 +9968,15 @@ static MYSQL_SYSVAR_STR(file_format, innobase_file_format_name, innodb_file_format_name_validate, innodb_file_format_name_update, "Antelope"); +/* If a new file format is introduced, the file format +name needs to be updated accordingly. Please refer to +file_format_name_map[] defined in trx0sys.c for the next +file format name. */ static MYSQL_SYSVAR_STR(file_format_check, innobase_file_format_check, PLUGIN_VAR_OPCMDARG, "The highest file format in the tablespace.", innodb_file_format_check_validate, - innodb_file_format_check_update, - "on"); + innodb_file_format_check_update, "Barracuda"); static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit, PLUGIN_VAR_OPCMDARG, diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 4779651ee27..31e88ed8530 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -258,12 +258,14 @@ int thd_binlog_format(const MYSQL_THD thd); */ void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all); +#if MYSQL_VERSION_ID > 50140 /** Check if binary logging is filtered for thread's current db. @param thd Thread handle @retval 1 the query is not filtered, 0 otherwise. */ bool thd_binlog_filter_ok(const MYSQL_THD thd); +#endif /* MYSQL_VERSION_ID > 50140 */ } typedef struct trx_struct trx_t; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 37aed06b28a..a5008991400 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -765,10 +765,11 @@ err_exit: ut_ad(error == DB_SUCCESS); /* Commit the data dictionary transaction in order to release - the table locks on the system tables. Unfortunately, this - means that if MySQL crashes while creating a new primary key - inside row_merge_build_indexes(), indexed_table will not be - dropped on crash recovery. Thus, it will become orphaned. */ + the table locks on the system tables. This means that if + MySQL crashes while creating a new primary key inside + row_merge_build_indexes(), indexed_table will not be dropped + by trx_rollback_active(). It will have to be recovered or + dropped by the database administrator. */ trx_commit_for_mysql(trx); row_mysql_unlock_data_dictionary(trx); @@ -882,7 +883,9 @@ error: /* fall through */ default: if (new_primary) { - row_merge_drop_table(trx, indexed_table); + if (indexed_table != innodb_table) { + row_merge_drop_table(trx, indexed_table); + } } else { if (!dict_locked) { row_mysql_lock_data_dictionary(trx); diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index 37c68391477..08986fac0ef 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -390,6 +390,27 @@ ibuf_count_set( #endif /******************************************************************//** +Closes insert buffer and frees the data structures. */ +UNIV_INTERN +void +ibuf_close(void) +/*============*/ +{ + mutex_free(&ibuf_pessimistic_insert_mutex); + memset(&ibuf_pessimistic_insert_mutex, + 0x0, sizeof(ibuf_pessimistic_insert_mutex)); + + mutex_free(&ibuf_mutex); + memset(&ibuf_mutex, 0x0, sizeof(ibuf_mutex)); + + mutex_free(&ibuf_bitmap_mutex); + memset(&ibuf_bitmap_mutex, 0x0, sizeof(ibuf_mutex)); + + mem_free(ibuf); + ibuf = NULL; +} + +/******************************************************************//** Updates the size information of the ibuf, assuming the segment size has not changed. */ static diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h index 631b3bd386c..f98ba386f9c 100644 --- a/storage/innobase/include/btr0sea.h +++ b/storage/innobase/include/btr0sea.h @@ -41,6 +41,12 @@ void btr_search_sys_create( /*==================*/ ulint hash_size); /*!< in: hash index hash table size */ +/*****************************************************************//** +Frees the adaptive search system at a database shutdown. */ +UNIV_INTERN +void +btr_search_sys_free(void); +/*=====================*/ /********************************************************************//** Disable the adaptive hash search system and empty the index. */ diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index 23898583b72..747e9b5364e 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -32,6 +32,7 @@ enum db_err { /* The following are error codes */ DB_ERROR, + DB_INTERRUPTED, DB_OUT_OF_MEMORY, DB_OUT_OF_FILE_SPACE, DB_LOCK_WAIT, diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index d425241a3a2..12396556c2d 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1151,6 +1151,13 @@ void dict_ind_init(void); /*===============*/ +/**********************************************************************//** +Closes the data dictionary module. */ +UNIV_INTERN +void +dict_close(void); +/*============*/ + #ifndef UNIV_NONINL #include "dict0dict.ic" #endif diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index a36deaf16ce..74d0fbcdacd 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -224,15 +224,6 @@ fil_space_create( 0 for uncompressed tablespaces */ ulint purpose);/*!< in: FIL_TABLESPACE, or FIL_LOG if log */ /*******************************************************************//** -Frees a space object from a the tablespace memory cache. Closes the files in -the chain but does not delete them. -@return TRUE if success */ -UNIV_INTERN -ibool -fil_space_free( -/*===========*/ - ulint id); /*!< in: space id */ -/*******************************************************************//** Returns the size of the space in pages. The tablespace must be cached in the memory cache. @return space size, 0 if space not found */ @@ -278,6 +269,12 @@ fil_init( ulint hash_size, /*!< in: hash table size */ ulint max_n_open); /*!< in: max number of open files */ /*******************************************************************//** +Initializes the tablespace memory cache. */ +UNIV_INTERN +void +fil_close(void); +/*===========*/ +/*******************************************************************//** Opens all log files and system tablespace data files. They stay open until the database server shutdown. This should be called at a server startup after the space objects for the log and the system tablespace have been created. The diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index 21330997df3..8aa21fb9d95 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -356,6 +356,12 @@ void ibuf_print( /*=======*/ FILE* file); /*!< in: file where to print */ +/******************************************************************//** +Closes insert buffer and frees the data structures. */ +UNIV_INTERN +void +ibuf_close(void); +/*============*/ #define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO #define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index aeabe39e1a9..82e4c9bd976 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -59,6 +59,12 @@ lock_sys_create( /*============*/ ulint n_cells); /*!< in: number of slots in lock hash table */ /*********************************************************************//** +Closes the lock system at database shutdown. */ +UNIV_INTERN +void +lock_sys_close(void); +/*================*/ +/*********************************************************************//** Checks if some transaction has an implicit x-lock on a record in a clustered index. @return transaction which has the x-lock, or NULL */ diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 299b4a05b40..135aeb69e2d 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -572,6 +572,18 @@ UNIV_INTERN void log_refresh_stats(void); /*===================*/ +/********************************************************** +Shutdown the log system but do not release all the memory. */ +UNIV_INTERN +void +log_shutdown(void); +/*==============*/ +/********************************************************** +Free the log system data structures. */ +UNIV_INTERN +void +log_mem_free(void); +/*==============*/ extern log_t* log_sys; @@ -584,7 +596,7 @@ extern log_t* log_sys; #define LOG_RECOVER 98887331 /* The counting of lsn's starts from this value: this must be non-zero */ -#define LOG_START_LSN ((ib_uint64_t) (16 * OS_FILE_LOG_BLOCK_SIZE)) +#define LOG_START_LSN ((ib_uint64_t) (16 * OS_FILE_LOG_BLOCK_SIZE)) #define LOG_BUFFER_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE) #define LOG_ARCHIVE_BUF_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE / 4) @@ -721,9 +733,12 @@ struct log_group_struct{ ulint lsn_offset; /*!< the offset of the above lsn */ ulint n_pending_writes;/*!< number of currently pending flush writes for this log group */ + byte** file_header_bufs_ptr;/*!< unaligned buffers */ byte** file_header_bufs;/*!< buffers for each file header in the group */ +#ifdef UNIV_LOG_ARCHIVE /*-----------------------------*/ + byte** archive_file_header_bufs_ptr;/*!< unaligned buffers */ byte** archive_file_header_bufs;/*!< buffers for each file header in the group */ ulint archive_space_id;/*!< file space which @@ -742,10 +757,12 @@ struct log_group_struct{ completion function then sets the new value to ..._file_no */ ulint next_archived_offset; /*!< like the preceding field */ +#endif /* UNIV_LOG_ARCHIVE */ /*-----------------------------*/ ib_uint64_t scanned_lsn; /*!< used only in recovery: recovery scan succeeded up to this lsn in this log group */ + byte* checkpoint_buf_ptr;/*!< unaligned checkpoint header */ byte* checkpoint_buf; /*!< checkpoint header is written from this buffer to the group */ UT_LIST_NODE_T(log_group_t) @@ -763,6 +780,7 @@ struct log_struct{ #ifndef UNIV_HOTBACKUP mutex_t mutex; /*!< mutex protecting the log */ #endif /* !UNIV_HOTBACKUP */ + byte* buf_ptr; /* unaligned log buffer */ byte* buf; /*!< log buffer */ ulint buf_size; /*!< log buffer size in bytes */ ulint max_buf_free; /*!< recommended maximum value of @@ -899,6 +917,7 @@ struct log_struct{ should wait for this without owning the log mutex */ #endif /* !UNIV_HOTBACKUP */ + byte* checkpoint_buf_ptr;/* unaligned checkpoint header */ byte* checkpoint_buf; /*!< checkpoint header is read to this buffer */ /* @} */ diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 6de735be945..a3d2bd050f5 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -239,6 +239,18 @@ UNIV_INTERN void recv_sys_create(void); /*=================*/ +/**********************************************************//** +Release recovery system mutexes. */ +UNIV_INTERN +void +recv_sys_close(void); +/*================*/ +/********************************************************//** +Frees the recovery system memory. */ +UNIV_INTERN +void +recv_sys_mem_free(void); +/*===================*/ /********************************************************//** Inits the recovery system for a recovery operation. */ UNIV_INTERN @@ -246,6 +258,12 @@ void recv_sys_init( /*==========*/ ulint available_memory); /*!< in: available memory in bytes */ +/********************************************************//** +Reset the state of the recovery system variables. */ +UNIV_INTERN +void +recv_sys_var_init(void); +/*===================*/ /*******************************************************************//** Empties the hash table of stored log records, applying them to appropriate pages. */ diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h index a092b024219..98f8748e529 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -82,6 +82,13 @@ void mem_init( /*=====*/ ulint size); /*!< in: common pool size in bytes */ +/******************************************************************//** +Closes the memory system. */ +UNIV_INTERN +void +mem_close(void); +/*===========*/ + /**************************************************************//** Use this macro instead of the corresponding function! Macro for memory heap creation. */ diff --git a/storage/innobase/include/mem0pool.h b/storage/innobase/include/mem0pool.h index 18f988241d6..5e93bf88a47 100644 --- a/storage/innobase/include/mem0pool.h +++ b/storage/innobase/include/mem0pool.h @@ -62,6 +62,13 @@ mem_pool_create( /*============*/ ulint size); /*!< in: pool size in bytes */ /********************************************************************//** +Frees a memory pool. */ +UNIV_INTERN +void +mem_pool_free( +/*==========*/ + mem_pool_t* pool); /*!< in, own: memory pool */ +/********************************************************************//** Allocates memory from a pool. NOTE: This low-level function should only be used in mem0mem.*! @return own: allocated memory buffer */ diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 8535ef092c3..16568579f31 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -158,6 +158,7 @@ log. */ #define OS_FILE_SHARING_VIOLATION 76 #define OS_FILE_ERROR_NOT_SPECIFIED 77 #define OS_FILE_INSUFFICIENT_RESOURCE 78 +#define OS_FILE_OPERATION_ABORTED 79 /* @} */ /** Types for aio operations @{ */ @@ -620,6 +621,13 @@ os_aio_init( ulint n_write_segs, /*<! in: number of writer threads */ ulint n_slots_sync); /*<! in: number of slots in the sync aio array */ +/*********************************************************************** +Frees the asynchronous io system. */ +UNIV_INTERN +void +os_aio_free(void); +/*=============*/ + /*******************************************************************//** Requests an asynchronous i/o operation. @return TRUE if request was queued successfully, FALSE if fail */ diff --git a/storage/innobase/include/pars0pars.h b/storage/innobase/include/pars0pars.h index a7de7f2292e..fe5d76ebbb0 100644 --- a/storage/innobase/include/pars0pars.h +++ b/storage/innobase/include/pars0pars.h @@ -583,6 +583,12 @@ pars_info_get_bound_id( pars_info_t* info, /*!< in: info struct */ const char* name); /*!< in: bound id name to find */ +/******************************************************************//** +Release any resources used by the lexer. */ +UNIV_INTERN +void +pars_lexer_close(void); +/*==================*/ /** Extra information supplied for pars_sql(). */ struct pars_info_struct { diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 23472bd100e..228c9f6600a 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -411,7 +411,7 @@ void srv_init(void); /*==========*/ /*********************************************************************//** -Frees the OS fast mutex created in srv_boot(). */ +Frees the data structures created in srv_init(). */ UNIV_INTERN void srv_free(void); diff --git a/storage/innobase/include/thr0loc.h b/storage/innobase/include/thr0loc.h index b4bdc33e615..b7eb29f2ed0 100644 --- a/storage/innobase/include/thr0loc.h +++ b/storage/innobase/include/thr0loc.h @@ -39,6 +39,12 @@ UNIV_INTERN void thr_local_init(void); /*================*/ + /****************************************************************//** +Close the thread local storage module. */ +UNIV_INTERN +void +thr_local_close(void); +/*=================*/ /*******************************************************************//** Creates a local storage struct for the calling new thread. */ UNIV_INTERN diff --git a/storage/innobase/include/trx0i_s.h b/storage/innobase/include/trx0i_s.h index 9bf032de9f9..7bd4e1b88c8 100644 --- a/storage/innobase/include/trx0i_s.h +++ b/storage/innobase/include/trx0i_s.h @@ -141,6 +141,13 @@ void trx_i_s_cache_init( /*===============*/ trx_i_s_cache_t* cache); /*!< out: cache to init */ +/*******************************************************************//** +Free the INFORMATION SCHEMA trx related cache. */ +UNIV_INTERN +void +trx_i_s_cache_free( +/*===============*/ + trx_i_s_cache_t* cache); /*!< in/out: cache to free */ /*******************************************************************//** Issue a shared/read lock on the tables cache. */ diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 7812ad7eb92..908760580f6 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -71,6 +71,12 @@ void trx_purge_sys_create(void); /*======================*/ /********************************************************************//** +Frees the global purge system control structure. */ +UNIV_INTERN +void +trx_purge_sys_close(void); +/*======================*/ +/************************************************************************ Adds the update undo log as the first log in the history list. Removes the update undo log segment from the rseg slot if it is too big for reuse. */ UNIV_INTERN diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h index dbc732651ca..ba1fc88b6c4 100644 --- a/storage/innobase/include/trx0rseg.h +++ b/storage/innobase/include/trx0rseg.h @@ -125,6 +125,13 @@ trx_rseg_create( ulint max_size, /*!< in: max size in pages */ ulint* id, /*!< out: rseg id */ mtr_t* mtr); /*!< in: mtr */ +/*************************************************************************** +Free's an instance of the rollback segment in memory. */ +UNIV_INTERN +void +trx_rseg_mem_free( +/*==============*/ + trx_rseg_t* rseg); /* in, own: instance to free */ /* Number of undo log slots in a rollback segment file copy */ diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 812e8cfa0ba..a53296a06d9 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -334,6 +334,12 @@ void trx_sys_file_format_tag_init(void); /*==============================*/ /*****************************************************************//** +Shutdown/Close the transaction system. */ +UNIV_INTERN +void +trx_sys_close(void); +/*===============*/ +/*****************************************************************//** Get the name representation of the file format from its id. @return pointer to the name */ UNIV_INTERN diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h index 4db10eaa92e..a084f2394b5 100644 --- a/storage/innobase/include/trx0undo.h +++ b/storage/innobase/include/trx0undo.h @@ -333,6 +333,13 @@ trx_undo_parse_discard_latest( byte* end_ptr,/*!< in: buffer end */ page_t* page, /*!< in: page or NULL */ mtr_t* mtr); /*!< in: mtr or NULL */ +/************************************************************************ +Frees an undo log memory copy. */ +UNIV_INTERN +void +trx_undo_mem_free( +/*==============*/ + trx_undo_t* undo); /* in: the undo object to be freed */ /* Types of an undo log segment */ #define TRX_UNDO_INSERT 1 /* contains undo entries for inserts */ diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 5d0361658af..2081e136590 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -46,7 +46,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 1 #define INNODB_VERSION_MINOR 0 -#define INNODB_VERSION_BUGFIX 5 +#define INNODB_VERSION_BUGFIX 6 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; diff --git a/storage/innobase/include/usr0sess.h b/storage/innobase/include/usr0sess.h index 7638a0c69e2..2c288f7d455 100644 --- a/storage/innobase/include/usr0sess.h +++ b/storage/innobase/include/usr0sess.h @@ -44,14 +44,12 @@ sess_t* sess_open(void); /*============*/ /*********************************************************************//** -Closes a session, freeing the memory occupied by it, if it is in a state -where it should be closed. -@return TRUE if closed */ +Closes a session, freeing the memory occupied by it. */ UNIV_INTERN -ibool -sess_try_close( -/*===========*/ - sess_t* sess); /*!< in, own: session object */ +void +sess_close( +/*=======*/ + sess_t* sess); /* in, own: session object */ /* The session handle. All fields are protected by the kernel mutex */ struct sess_struct{ diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 67b2eac7219..736198dc346 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -578,6 +578,23 @@ lock_sys_create( } /*********************************************************************//** +Closes the lock system at database shutdown. */ +UNIV_INTERN +void +lock_sys_close(void) +/*================*/ +{ + if (lock_latest_err_file != NULL) { + fclose(lock_latest_err_file); + lock_latest_err_file = NULL; + } + + hash_table_free(lock_sys->rec_hash); + mem_free(lock_sys); + lock_sys = NULL; +} + +/*********************************************************************//** Gets the size of a lock struct. @return size in bytes */ UNIV_INTERN diff --git a/storage/innobase/log/log0log.c b/storage/innobase/log/log0log.c index a23dd20772a..d5b696074b3 100644 --- a/storage/innobase/log/log0log.c +++ b/storage/innobase/log/log0log.c @@ -771,8 +771,6 @@ void log_init(void) /*==========*/ { - byte* buf; - log_sys = mem_alloc(sizeof(log_t)); mutex_create(&log_sys->mutex, SYNC_LOG); @@ -787,8 +785,8 @@ log_init(void) ut_a(LOG_BUFFER_SIZE >= 16 * OS_FILE_LOG_BLOCK_SIZE); ut_a(LOG_BUFFER_SIZE >= 4 * UNIV_PAGE_SIZE); - buf = mem_alloc(LOG_BUFFER_SIZE + OS_FILE_LOG_BLOCK_SIZE); - log_sys->buf = ut_align(buf, OS_FILE_LOG_BLOCK_SIZE); + log_sys->buf_ptr = mem_alloc(LOG_BUFFER_SIZE + OS_FILE_LOG_BLOCK_SIZE); + log_sys->buf = ut_align(log_sys->buf_ptr, OS_FILE_LOG_BLOCK_SIZE); log_sys->buf_size = LOG_BUFFER_SIZE; @@ -833,9 +831,9 @@ log_init(void) rw_lock_create(&log_sys->checkpoint_lock, SYNC_NO_ORDER_CHECK); - log_sys->checkpoint_buf - = ut_align(mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE), - OS_FILE_LOG_BLOCK_SIZE); + log_sys->checkpoint_buf_ptr = mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE); + log_sys->checkpoint_buf = ut_align(log_sys->checkpoint_buf_ptr, + OS_FILE_LOG_BLOCK_SIZE); memset(log_sys->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE); /*----------------------------*/ @@ -918,23 +916,33 @@ log_group_init( group->lsn_offset = LOG_FILE_HDR_SIZE; group->n_pending_writes = 0; + group->file_header_bufs_ptr = mem_alloc(sizeof(byte*) * n_files); group->file_header_bufs = mem_alloc(sizeof(byte*) * n_files); #ifdef UNIV_LOG_ARCHIVE + group->archive_file_header_bufs_ptr = mem_alloc( + sizeof(byte*) * n_files); group->archive_file_header_bufs = mem_alloc(sizeof(byte*) * n_files); #endif /* UNIV_LOG_ARCHIVE */ for (i = 0; i < n_files; i++) { - *(group->file_header_bufs + i) = ut_align( - mem_alloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE), + group->file_header_bufs_ptr[i] = mem_alloc( + LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE); + + group->file_header_bufs[i] = ut_align( + group->file_header_bufs_ptr[i], OS_FILE_LOG_BLOCK_SIZE); memset(*(group->file_header_bufs + i), '\0', LOG_FILE_HDR_SIZE); #ifdef UNIV_LOG_ARCHIVE - *(group->archive_file_header_bufs + i) = ut_align( - mem_alloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE), + group->archive_file_header_bufs_ptr[i] = mem_alloc( + LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE); + + group->archive_file_header_bufs[i] = ut_align( + group->archive_file_header_bufs_ptr[i], OS_FILE_LOG_BLOCK_SIZE); + memset(*(group->archive_file_header_bufs + i), '\0', LOG_FILE_HDR_SIZE); #endif /* UNIV_LOG_ARCHIVE */ @@ -947,8 +955,9 @@ log_group_init( group->archived_offset = 0; #endif /* UNIV_LOG_ARCHIVE */ - group->checkpoint_buf = ut_align( - mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE), OS_FILE_LOG_BLOCK_SIZE); + group->checkpoint_buf_ptr = mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE); + group->checkpoint_buf = ut_align(group->checkpoint_buf_ptr, + OS_FILE_LOG_BLOCK_SIZE); memset(group->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE); @@ -3364,4 +3373,95 @@ log_refresh_stats(void) log_sys->n_log_ios_old = log_sys->n_log_ios; log_sys->last_printout_time = time(NULL); } + +/********************************************************************** +Closes a log group. */ +static +void +log_group_close( +/*===========*/ + log_group_t* group) /* in,own: log group to close */ +{ + ulint i; + + for (i = 0; i < group->n_files; i++) { + mem_free(group->file_header_bufs_ptr[i]); +#ifdef UNIV_LOG_ARCHIVE + mem_free(group->archive_file_header_bufs_ptr[i]); +#endif /* UNIV_LOG_ARCHIVE */ + } + + mem_free(group->file_header_bufs_ptr); + mem_free(group->file_header_bufs); + +#ifdef UNIV_LOG_ARCHIVE + mem_free(group->archive_file_header_bufs_ptr); + mem_free(group->archive_file_header_bufs); +#endif /* UNIV_LOG_ARCHIVE */ + + mem_free(group->checkpoint_buf_ptr); + + mem_free(group); +} + +/********************************************************** +Shutdown the log system but do not release all the memory. */ +UNIV_INTERN +void +log_shutdown(void) +/*==============*/ +{ + log_group_t* group; + + group = UT_LIST_GET_FIRST(log_sys->log_groups); + + while (UT_LIST_GET_LEN(log_sys->log_groups) > 0) { + log_group_t* prev_group = group; + + group = UT_LIST_GET_NEXT(log_groups, group); + UT_LIST_REMOVE(log_groups, log_sys->log_groups, prev_group); + + log_group_close(prev_group); + } + + mem_free(log_sys->buf_ptr); + log_sys->buf_ptr = NULL; + log_sys->buf = NULL; + mem_free(log_sys->checkpoint_buf_ptr); + log_sys->checkpoint_buf_ptr = NULL; + log_sys->checkpoint_buf = NULL; + + os_event_free(log_sys->no_flush_event); + os_event_free(log_sys->one_flushed_event); + + rw_lock_free(&log_sys->checkpoint_lock); + + mutex_free(&log_sys->mutex); + +#ifdef UNIV_LOG_ARCHIVE + rw_lock_free(&log_sys->archive_lock); + os_event_create(log_sys->archiving_on); +#endif /* UNIV_LOG_ARCHIVE */ + +#ifdef UNIV_LOG_DEBUG + recv_sys_debug_free(); +#endif + + recv_sys_close(); +} + +/********************************************************** +Free the log system data structures. */ +UNIV_INTERN +void +log_mem_free(void) +/*==============*/ +{ + if (log_sys != NULL) { + recv_sys_mem_free(); + mem_free(log_sys); + + log_sys = NULL; + } +} #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c index 81dcc9cd4f8..ddbc71d4b71 100644 --- a/storage/innobase/log/log0recv.c +++ b/storage/innobase/log/log0recv.c @@ -69,15 +69,15 @@ UNIV_INTERN recv_sys_t* recv_sys = NULL; /** TRUE when applying redo log records during crash recovery; FALSE otherwise. Note that this is FALSE while a background thread is rolling back incomplete transactions. */ -UNIV_INTERN ibool recv_recovery_on = FALSE; +UNIV_INTERN ibool recv_recovery_on; #ifdef UNIV_LOG_ARCHIVE /** TRUE when applying redo log records from an archived log file */ -UNIV_INTERN ibool recv_recovery_from_backup_on = FALSE; +UNIV_INTERN ibool recv_recovery_from_backup_on; #endif /* UNIV_LOG_ARCHIVE */ #ifndef UNIV_HOTBACKUP /** TRUE when recv_init_crash_recovery() has been called. */ -UNIV_INTERN ibool recv_needed_recovery = FALSE; +UNIV_INTERN ibool recv_needed_recovery; # ifdef UNIV_DEBUG /** TRUE if writing to the redo log (mtr_commit) is forbidden. Protected by log_sys->mutex. */ @@ -87,7 +87,7 @@ UNIV_INTERN ibool recv_no_log_write = FALSE; /** TRUE if buf_page_is_corrupted() should check if the log sequence number (FIL_PAGE_LSN) is in the future. Initially FALSE, and set by recv_recovery_from_checkpoint_start_func(). */ -UNIV_INTERN ibool recv_lsn_checks_on = FALSE; +UNIV_INTERN ibool recv_lsn_checks_on; /** There are two conditions under which we scan the logs, the first is normal startup and the second is when we do a recovery from an @@ -97,7 +97,7 @@ startup. If we find log entries that were written after the last checkpoint we know that the server was not cleanly shutdown. We must then initialize the crash recovery environment before attempting to store these entries in the log hash table. */ -static ibool recv_log_scan_is_startup_type = FALSE; +static ibool recv_log_scan_is_startup_type; /** If the following is TRUE, the buffer pool file pages must be invalidated after recovery and no ibuf operations are allowed; this becomes TRUE if @@ -108,7 +108,7 @@ buffer pool before the pages have been recovered to the up-to-date state. TRUE means that recovery is running and no operations on the log files are allowed yet: the variable name is misleading. */ -UNIV_INTERN ibool recv_no_ibuf_operations = FALSE; +UNIV_INTERN ibool recv_no_ibuf_operations; /** TRUE when the redo log is being backed up */ # define recv_is_making_a_backup FALSE /** TRUE when recovering from a backed up redo log file */ @@ -116,30 +116,30 @@ UNIV_INTERN ibool recv_no_ibuf_operations = FALSE; #else /* !UNIV_HOTBACKUP */ # define recv_needed_recovery FALSE /** TRUE when the redo log is being backed up */ -UNIV_INTERN ibool recv_is_making_a_backup = FALSE; +UNIV_INTERN ibool recv_is_making_a_backup = FALSE; /** TRUE when recovering from a backed up redo log file */ UNIV_INTERN ibool recv_is_from_backup = FALSE; # define buf_pool_get_curr_size() (5 * 1024 * 1024) #endif /* !UNIV_HOTBACKUP */ /** The following counter is used to decide when to print info on log scan */ -static ulint recv_scan_print_counter = 0; +static ulint recv_scan_print_counter; /** The type of the previous parsed redo log record */ -static ulint recv_previous_parsed_rec_type = 999999; +static ulint recv_previous_parsed_rec_type; /** The offset of the previous parsed redo log record */ -static ulint recv_previous_parsed_rec_offset = 0; +static ulint recv_previous_parsed_rec_offset; /** The 'multi' flag of the previous parsed redo log record */ -static ulint recv_previous_parsed_rec_is_multi = 0; +static ulint recv_previous_parsed_rec_is_multi; /** Maximum page number encountered in the redo log */ -UNIV_INTERN ulint recv_max_parsed_page_no = 0; +UNIV_INTERN ulint recv_max_parsed_page_no; /** This many frames must be left free in the buffer pool when we scan the log and store the scanned log records in the buffer pool: we will use these free frames to read in pages when we start applying the log records to the database. */ -UNIV_INTERN ulint recv_n_pool_free_frames = 256; +UNIV_INTERN ulint recv_n_pool_free_frames; /** The maximum lsn we see for a page during the recovery process. If this is bigger than the lsn we are able to scan up to, that is an indication that @@ -170,7 +170,8 @@ recv_sys_create(void) return; } - recv_sys = mem_alloc(sizeof(recv_sys_t)); + recv_sys = mem_alloc(sizeof(*recv_sys)); + memset(recv_sys, 0x0, sizeof(*recv_sys)); mutex_create(&recv_sys->mutex, SYNC_RECV); @@ -179,6 +180,106 @@ recv_sys_create(void) } /********************************************************//** +Release recovery system mutexes. */ +UNIV_INTERN +void +recv_sys_close(void) +/*================*/ +{ + if (recv_sys != NULL) { + if (recv_sys->addr_hash != NULL) { + hash_table_free(recv_sys->addr_hash); + } + + if (recv_sys->heap != NULL) { + mem_heap_free(recv_sys->heap); + } + + if (recv_sys->buf != NULL) { + ut_free(recv_sys->buf); + } + + if (recv_sys->last_block_buf_start != NULL) { + mem_free(recv_sys->last_block_buf_start); + } + + mutex_free(&recv_sys->mutex); + + mem_free(recv_sys); + recv_sys = NULL; + } +} + +/********************************************************//** +Frees the recovery system memory. */ +UNIV_INTERN +void +recv_sys_mem_free(void) +/*===================*/ +{ + if (recv_sys != NULL) { + if (recv_sys->addr_hash != NULL) { + hash_table_free(recv_sys->addr_hash); + } + + if (recv_sys->heap != NULL) { + mem_heap_free(recv_sys->heap); + } + + if (recv_sys->buf != NULL) { + ut_free(recv_sys->buf); + } + + if (recv_sys->last_block_buf_start != NULL) { + mem_free(recv_sys->last_block_buf_start); + } + + mem_free(recv_sys); + recv_sys = NULL; + } +} + +/************************************************************ +Reset the state of the recovery system variables. */ +UNIV_INTERN +void +recv_sys_var_init(void) +/*===================*/ +{ + recv_lsn_checks_on = FALSE; + + recv_n_pool_free_frames = 256; + + recv_recovery_on = FALSE; + +#ifdef UNIV_LOG_ARCHIVE + recv_recovery_from_backup_on = FALSE; +#endif /* UNIV_LOG_ARCHIVE */ + + recv_needed_recovery = FALSE; + + recv_lsn_checks_on = FALSE; + + recv_log_scan_is_startup_type = FALSE; + + recv_no_ibuf_operations = FALSE; + + recv_scan_print_counter = 0; + + recv_previous_parsed_rec_type = 999999; + + recv_previous_parsed_rec_offset = 0; + + recv_previous_parsed_rec_is_multi = 0; + + recv_max_parsed_page_no = 0; + + recv_n_pool_free_frames = 256; + + recv_max_page_lsn = 0; +} + +/************************************************************ Inits the recovery system for a recovery operation. */ UNIV_INTERN void @@ -253,8 +354,8 @@ recv_sys_empty_hash(void) Frees the recovery system. */ static void -recv_sys_free(void) -/*===============*/ +recv_sys_debug_free(void) +/*=====================*/ { mutex_enter(&(recv_sys->mutex)); @@ -263,8 +364,10 @@ recv_sys_free(void) ut_free(recv_sys->buf); mem_free(recv_sys->last_block_buf_start); - recv_sys->addr_hash = NULL; + recv_sys->buf = NULL; recv_sys->heap = NULL; + recv_sys->addr_hash = NULL; + recv_sys->last_block_buf_start = NULL; mutex_exit(&(recv_sys->mutex)); } @@ -3149,7 +3252,7 @@ recv_recovery_from_checkpoint_finish(void) recv_recovery_on = FALSE; #ifndef UNIV_LOG_DEBUG - recv_sys_free(); + recv_sys_debug_free(); #endif /* Roll back any recovered data dictionary transactions, so that the data dictionary tables will be free of any locks. diff --git a/storage/innobase/mem/mem0dbg.c b/storage/innobase/mem/mem0dbg.c index a20eb2ad7d2..01eda20ec45 100644 --- a/storage/innobase/mem/mem0dbg.c +++ b/storage/innobase/mem/mem0dbg.c @@ -170,6 +170,17 @@ mem_init( mem_comm_pool = mem_pool_create(size); } + +/******************************************************************//** +Closes the memory system. */ +UNIV_INTERN +void +mem_close(void) +/*===========*/ +{ + mem_pool_free(mem_comm_pool); + mem_comm_pool = NULL; +} #endif /* !UNIV_HOTBACKUP */ #ifdef UNIV_MEM_DEBUG diff --git a/storage/innobase/mem/mem0pool.c b/storage/innobase/mem/mem0pool.c index c8fea97a6a3..c4f8af607e0 100644 --- a/storage/innobase/mem/mem0pool.c +++ b/storage/innobase/mem/mem0pool.c @@ -261,6 +261,18 @@ mem_pool_create( } /********************************************************************//** +Frees a memory pool. */ +UNIV_INTERN +void +mem_pool_free( +/*==========*/ + mem_pool_t* pool) /*!< in, own: memory pool */ +{ + ut_free(pool->buf); + ut_free(pool); +} + +/********************************************************************//** Fills the specified free list. @return TRUE if we were able to insert a block to the free list */ static diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index 0cb76d1796f..37edad442db 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -323,6 +323,13 @@ os_file_get_last_error( "InnoDB: The error means that there are no" " sufficient system resources or quota to" " complete the operation.\n"); + } else if (err == ERROR_OPERATION_ABORTED) { + fprintf(stderr, + "InnoDB: The error means that the I/O" + " operation has been aborted\n" + "InnoDB: because of either a thread exit" + " or an application request.\n" + "InnoDB: Retry attempt is made.\n"); } else { fprintf(stderr, "InnoDB: Some operating system error numbers" @@ -347,6 +354,8 @@ os_file_get_last_error( } else if (err == ERROR_WORKING_SET_QUOTA || err == ERROR_NO_SYSTEM_RESOURCES) { return(OS_FILE_INSUFFICIENT_RESOURCE); + } else if (err == ERROR_OPERATION_ABORTED) { + return(OS_FILE_OPERATION_ABORTED); } else { return(100 + err); } @@ -469,6 +478,10 @@ os_file_handle_error_cond_exit( os_thread_sleep(100000); /* 100 ms */ return(TRUE); + } else if (err == OS_FILE_OPERATION_ABORTED) { + + os_thread_sleep(100000); /* 100 ms */ + return(TRUE); } else { if (name) { fprintf(stderr, "InnoDB: File name %s\n", name); @@ -3029,6 +3042,34 @@ os_aio_array_create( return(array); } +/************************************************************************//** +Frees an aio wait array. */ +static +void +os_aio_array_free( +/*==============*/ + os_aio_array_t* array) /*!< in, own: array to free */ +{ +#ifdef WIN_ASYNC_IO + ulint i; + + for (i = 0; i < array->n_slots; i++) { + os_aio_slot_t* slot = os_aio_array_get_nth_slot(array, i); + os_event_free(slot->event); + } +#endif /* WIN_ASYNC_IO */ + +#ifdef __WIN__ + ut_free(array->native_events); +#endif /* __WIN__ */ + os_mutex_free(array->mutex); + os_event_free(array->not_full); + os_event_free(array->is_empty); + + ut_free(array->slots); + ut_free(array); +} + /*********************************************************************** Initializes the asynchronous io system. Creates one array each for ibuf and log i/o. Also creates one array each for read and write where each @@ -3099,6 +3140,35 @@ os_aio_init( } +/*********************************************************************** +Frees the asynchronous io system. */ +UNIV_INTERN +void +os_aio_free(void) +/*=============*/ +{ + ulint i; + + os_aio_array_free(os_aio_ibuf_array); + os_aio_ibuf_array = NULL; + os_aio_array_free(os_aio_log_array); + os_aio_log_array = NULL; + os_aio_array_free(os_aio_read_array); + os_aio_read_array = NULL; + os_aio_array_free(os_aio_write_array); + os_aio_write_array = NULL; + os_aio_array_free(os_aio_sync_array); + os_aio_sync_array = NULL; + + for (i = 0; i < os_aio_n_segments; i++) { + os_event_free(os_aio_segment_wait_events[i]); + } + + ut_free(os_aio_segment_wait_events); + os_aio_segment_wait_events = 0; + os_aio_n_segments = 0; +} + #ifdef WIN_ASYNC_IO /************************************************************************//** Wakes up all async i/o threads in the array in Windows async i/o at @@ -3709,6 +3779,7 @@ os_aio_windows_handle( ibool ret_val; BOOL ret; DWORD len; + BOOL retry = FALSE; if (segment == ULINT_UNDEFINED) { array = os_aio_sync_array; @@ -3762,14 +3833,52 @@ os_aio_windows_handle( ut_a(TRUE == os_file_flush(slot->file)); } #endif /* UNIV_DO_FLUSH */ + } else if (os_file_handle_error(slot->name, "Windows aio")) { + + retry = TRUE; } else { - os_file_handle_error(slot->name, "Windows aio"); ret_val = FALSE; } os_mutex_exit(array->mutex); + if (retry) { + /* retry failed read/write operation synchronously. + No need to hold array->mutex. */ + + switch (slot->type) { + case OS_FILE_WRITE: + ret = WriteFile(slot->file, slot->buf, + slot->len, &len, + &(slot->control)); + + break; + case OS_FILE_READ: + ret = ReadFile(slot->file, slot->buf, + slot->len, &len, + &(slot->control)); + + break; + default: + ut_error; + } + + if (!ret && GetLastError() == ERROR_IO_PENDING) { + /* aio was queued successfully! + We want a synchronous i/o operation on a + file where we also use async i/o: in Windows + we must use the same wait mechanism as for + async i/o */ + + ret = GetOverlappedResult(slot->file, + &(slot->control), + &len, TRUE); + } + + ret_val = ret && len == slot->len; + } + os_aio_array_free_slot(array, slot); return(ret_val); diff --git a/storage/innobase/os/os0sync.c b/storage/innobase/os/os0sync.c index 4ec340b72b5..60467242e14 100644 --- a/storage/innobase/os/os0sync.c +++ b/storage/innobase/os/os0sync.c @@ -86,6 +86,9 @@ os_sync_init(void) UT_LIST_INIT(os_event_list); UT_LIST_INIT(os_mutex_list); + os_sync_mutex = NULL; + os_sync_mutex_inited = FALSE; + os_sync_mutex = os_mutex_create(NULL); os_sync_mutex_inited = TRUE; @@ -713,6 +716,7 @@ os_fast_mutex_free( os_mutex_enter(os_sync_mutex); } + ut_ad(os_fast_mutex_count > 0); os_fast_mutex_count--; if (UNIV_LIKELY(os_sync_mutex_inited)) { diff --git a/storage/innobase/os/os0thread.c b/storage/innobase/os/os0thread.c index 9a2d95cb166..34818ada804 100644 --- a/storage/innobase/os/os0thread.c +++ b/storage/innobase/os/os0thread.c @@ -233,6 +233,7 @@ os_thread_exit( #ifdef __WIN__ ExitThread((DWORD)exit_value); #else + pthread_detach(pthread_self()); pthread_exit(exit_value); #endif } diff --git a/storage/innobase/pars/lexyy.c b/storage/innobase/pars/lexyy.c index 37d892e51e3..815395ea316 100644 --- a/storage/innobase/pars/lexyy.c +++ b/storage/innobase/pars/lexyy.c @@ -2778,3 +2778,16 @@ static void yyfree (void * ptr ) + +/********************************************************************** +Release any resources used by the lexer. */ +UNIV_INTERN +void +pars_lexer_close(void) +/*==================*/ +{ + yylex_destroy(); + free(stringbuf); + stringbuf = NULL; + stringbuf_len_alloc = stringbuf_len = 0; +} diff --git a/storage/innobase/pars/pars0lex.l b/storage/innobase/pars/pars0lex.l index 4abff65e98b..55ed17f82e1 100644 --- a/storage/innobase/pars/pars0lex.l +++ b/storage/innobase/pars/pars0lex.l @@ -661,3 +661,16 @@ In the state 'id', only two actions are possible (defined below). */ } %% + +/********************************************************************** +Release any resources used by the lexer. */ +UNIV_INTERN +void +pars_lexer_close(void) +/*==================*/ +{ + yylex_destroy(); + free(stringbuf); + stringbuf = NULL; + stringbuf_len_alloc = stringbuf_len = 0; +} diff --git a/storage/innobase/que/que0que.c b/storage/innobase/que/que0que.c index 54b1e7535fa..2fe046fa9b8 100644 --- a/storage/innobase/que/que0que.c +++ b/storage/innobase/que/que0que.c @@ -518,6 +518,7 @@ que_graph_free_recursive( upd_node_t* upd; tab_node_t* cre_tab; ind_node_t* cre_ind; + purge_node_t* purge; if (node == NULL) { @@ -579,6 +580,13 @@ que_graph_free_recursive( mem_heap_free(ins->entry_sys_heap); break; + case QUE_NODE_PURGE: + purge = node; + + mem_heap_free(purge->heap); + + break; + case QUE_NODE_UPDATE: upd = node; diff --git a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c index a303a2f3278..25f041c0885 100644 --- a/storage/innobase/row/row0merge.c +++ b/storage/innobase/row/row0merge.c @@ -1200,6 +1200,12 @@ row_merge_read_clustered_index( in order to release the latch on the old page. */ if (btr_pcur_is_after_last_on_page(&pcur)) { + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + i = 0; + err = DB_INTERRUPTED; + goto err_exit; + } + btr_pcur_store_position(&pcur, &mtr); mtr_commit(&mtr); mtr_start(&mtr); @@ -1557,6 +1563,7 @@ static __attribute__((nonnull)) ulint row_merge( /*======*/ + trx_t* trx, /*!< in: transaction */ const dict_index_t* index, /*!< in: index being created */ merge_file_t* file, /*!< in/out: file containing index entries */ @@ -1590,6 +1597,10 @@ row_merge( for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) { ulint ahalf; /*!< arithmetic half the input file */ + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + return(DB_INTERRUPTED); + } + error = row_merge_blocks(index, file, block, &foffs0, &foffs1, &of, table); @@ -1617,6 +1628,10 @@ row_merge( /* Copy the last blocks, if there are any. */ while (foffs0 < ihalf) { + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + return(DB_INTERRUPTED); + } + if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) { return(DB_CORRUPTION); } @@ -1625,6 +1640,10 @@ row_merge( ut_ad(foffs0 == ihalf); while (foffs1 < file->offset) { + if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { + return(DB_INTERRUPTED); + } + if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) { return(DB_CORRUPTION); } @@ -1653,6 +1672,7 @@ static ulint row_merge_sort( /*===========*/ + trx_t* trx, /*!< in: transaction */ const dict_index_t* index, /*!< in: index being created */ merge_file_t* file, /*!< in/out: file containing index entries */ @@ -1671,7 +1691,8 @@ row_merge_sort( do { ulint error; - error = row_merge(index, file, &half, block, tmpfd, table); + error = row_merge(trx, index, file, &half, + block, tmpfd, table); if (error != DB_SUCCESS) { return(error); @@ -2490,7 +2511,7 @@ row_merge_build_indexes( sorting and inserting. */ for (i = 0; i < n_indexes; i++) { - error = row_merge_sort(indexes[i], &merge_files[i], + error = row_merge_sort(trx, indexes[i], &merge_files[i], block, &tmpfd, table); if (error == DB_SUCCESS) { diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 540a4450045..181c39de881 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -1880,6 +1880,8 @@ err_exit: if (UNIV_UNLIKELY(err != DB_SUCCESS)) { trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, NULL); + /* TO DO: free table? The code below will dereference + table->name, though. */ } switch (err) { @@ -1898,31 +1900,6 @@ err_exit: break; case DB_DUPLICATE_KEY: - ut_print_timestamp(stderr); - fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, TRUE, table->name); - fputs(" already exists in InnoDB internal\n" - "InnoDB: data dictionary. Have you deleted" - " the .frm file\n" - "InnoDB: and not used DROP TABLE?" - " Have you used DROP DATABASE\n" - "InnoDB: for InnoDB tables in" - " MySQL version <= 3.23.43?\n" - "InnoDB: See the Restrictions section" - " of the InnoDB manual.\n" - "InnoDB: You can drop the orphaned table" - " inside InnoDB by\n" - "InnoDB: creating an InnoDB table with" - " the same name in another\n" - "InnoDB: database and copying the .frm file" - " to the current database.\n" - "InnoDB: Then MySQL thinks the table exists," - " and DROP TABLE will\n" - "InnoDB: succeed.\n" - "InnoDB: You can look for further help from\n" - "InnoDB: " REFMAN "innodb-troubleshooting.html\n", - stderr); - /* We may also get err == DB_ERROR if the .ibd file for the table already exists */ @@ -4157,6 +4134,7 @@ row_check_table_for_mysql( } if (trx_is_interrupted(prebuilt->trx)) { + ret = DB_INTERRUPTED; break; } diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index d638b23692e..639da1ed2f3 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -1006,13 +1006,26 @@ srv_init(void) } /*********************************************************************//** -Frees the OS fast mutex created in srv_init(). */ +Frees the data structures created in srv_init(). */ UNIV_INTERN void srv_free(void) /*==========*/ { os_fast_mutex_free(&srv_conc_mutex); + mem_free(srv_conc_slots); + srv_conc_slots = NULL; + + mem_free(srv_sys->threads); + mem_free(srv_sys); + srv_sys = NULL; + + mem_free(kernel_mutex_temp); + kernel_mutex_temp = NULL; + mem_free(srv_mysql_table); + srv_mysql_table = NULL; + + trx_i_s_cache_free(trx_i_s_cache); } /*********************************************************************//** @@ -1024,6 +1037,8 @@ srv_general_init(void) /*==================*/ { ut_mem_init(); + /* Reset the system variables in the recovery module. */ + recv_sys_var_init(); os_sync_init(); sync_init(); mem_init(srv_mem_pool_size); diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c index 796541a9f1a..d5f6120ca31 100644 --- a/storage/innobase/srv/srv0start.c +++ b/storage/innobase/srv/srv0start.c @@ -103,6 +103,7 @@ Created 2/16/1996 Heikki Tuuri # include "row0row.h" # include "row0mysql.h" # include "btr0pcur.h" +# include "thr0loc.h" # include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */ /** Log sequence number immediately after startup */ @@ -495,6 +496,8 @@ io_handler_thread( mutex_exit(&ios_mutex); } + thr_local_free(os_thread_get_curr_id()); + /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. The thread actually never comes here because it is exited in an @@ -531,32 +534,6 @@ srv_normalize_path_for_win( #endif } -/*********************************************************************//** -Adds a slash or a backslash to the end of a string if it is missing -and the string is not empty. -@return string which has the separator if the string is not empty */ -UNIV_INTERN -char* -srv_add_path_separator_if_needed( -/*=============================*/ - char* str) /*!< in: null-terminated character string */ -{ - char* out_str; - ulint len = ut_strlen(str); - - if (len == 0 || str[len - 1] == SRV_PATH_SEPARATOR) { - - return(str); - } - - out_str = ut_malloc(len + 2); - memcpy(out_str, str, len); - out_str[len] = SRV_PATH_SEPARATOR; - out_str[len + 1] = 0; - - return(out_str); -} - #ifndef UNIV_HOTBACKUP /*********************************************************************//** Calculates the low 32 bits when a file size which is given as a number @@ -605,19 +582,24 @@ open_or_create_log_file( ulint size; ulint size_high; char name[10000]; + ulint dirnamelen; UT_NOT_USED(create_new_db); *log_file_created = FALSE; srv_normalize_path_for_win(srv_log_group_home_dirs[k]); - srv_log_group_home_dirs[k] = srv_add_path_separator_if_needed( - srv_log_group_home_dirs[k]); - ut_a(strlen(srv_log_group_home_dirs[k]) - < (sizeof name) - 10 - sizeof "ib_logfile"); - sprintf(name, "%s%s%lu", srv_log_group_home_dirs[k], - "ib_logfile", (ulong) i); + dirnamelen = strlen(srv_log_group_home_dirs[k]); + ut_a(dirnamelen < (sizeof name) - 10 - sizeof "ib_logfile"); + memcpy(name, srv_log_group_home_dirs[k], dirnamelen); + + /* Add a path separator if needed. */ + if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) { + name[dirnamelen++] = SRV_PATH_SEPARATOR; + } + + sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i); files[i] = os_file_create(name, OS_FILE_CREATE, OS_FILE_NORMAL, OS_LOG_FILE, &ret); @@ -780,14 +762,22 @@ open_or_create_data_files( *create_new_db = FALSE; srv_normalize_path_for_win(srv_data_home); - srv_data_home = srv_add_path_separator_if_needed(srv_data_home); for (i = 0; i < srv_n_data_files; i++) { + ulint dirnamelen; + srv_normalize_path_for_win(srv_data_file_names[i]); + dirnamelen = strlen(srv_data_home); - ut_a(strlen(srv_data_home) + strlen(srv_data_file_names[i]) + ut_a(dirnamelen + strlen(srv_data_file_names[i]) < (sizeof name) - 1); - sprintf(name, "%s%s", srv_data_home, srv_data_file_names[i]); + memcpy(name, srv_data_home, dirnamelen); + /* Add a path separator if needed. */ + if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) { + name[dirnamelen++] = SRV_PATH_SEPARATOR; + } + + strcpy(name + dirnamelen, srv_data_file_names[i]); if (srv_data_file_is_raw_partition[i] == 0) { @@ -1009,7 +999,7 @@ skip_size_check: return(DB_SUCCESS); } -/****************************************************************//** +/******************************************************************** Starts InnoDB and creates a new database if database files are not found and the user wants. @return DB_SUCCESS or error code */ @@ -1120,7 +1110,7 @@ innobase_start_or_create_for_mysql(void) if (srv_start_has_been_called) { fprintf(stderr, - "InnoDB: Error:startup called second time" + "InnoDB: Error: startup called second time" " during the process lifetime.\n" "InnoDB: In the MySQL Embedded Server Library" " you cannot call server_init()\n" @@ -1959,8 +1949,10 @@ innobase_shutdown_for_mysql(void) /* All the threads have exited or are just exiting; NOTE that the threads may not have completed their exit yet. Should we use pthread_join() to make sure - they have exited? Now we just sleep 0.1 seconds and - hope that is enough! */ + they have exited? If we did, we would have to + remove the pthread_detach() from + os_thread_exit(). Now we just sleep 0.1 + seconds and hope that is enough! */ os_mutex_exit(os_sync_mutex); @@ -1999,37 +1991,41 @@ innobase_shutdown_for_mysql(void) srv_misc_tmpfile = 0; } + /* This must be disabled before closing the buffer pool + and closing the data dictionary. */ + btr_search_disable(); + + ibuf_close(); + log_shutdown(); + lock_sys_close(); + thr_local_close(); trx_sys_file_format_close(); + trx_sys_close(); mutex_free(&srv_monitor_file_mutex); mutex_free(&srv_dict_tmpfile_mutex); mutex_free(&srv_misc_tmpfile_mutex); + dict_close(); + btr_search_sys_free(); /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside them */ + os_aio_free(); sync_close(); + srv_free(); + fil_close(); /* 4. Free the os_conc_mutex and all os_events and os_mutexes */ - srv_free(); os_sync_free(); - /* Check that all read views are closed except read view owned - by a purge. */ - - if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) { - fprintf(stderr, - "InnoDB: Error: all read views were not closed" - " before shutdown:\n" - "InnoDB: %lu read views open \n", - UT_LIST_GET_LEN(trx_sys->view_list) - 1); - } - - /* 5. Free all allocated memory and the os_fast_mutex created in - ut0mem.c */ + /* 5. Free all allocated memory */ + pars_lexer_close(); + log_mem_free(); buf_pool_free(); ut_free_all_mem(); + mem_close(); if (os_thread_count != 0 || os_event_count != 0 @@ -2060,6 +2056,7 @@ innobase_shutdown_for_mysql(void) } srv_was_started = FALSE; + srv_start_has_been_called = FALSE; return((int) DB_SUCCESS); } diff --git a/storage/innobase/sync/sync0arr.c b/storage/innobase/sync/sync0arr.c index d78ee8f3191..ed9e25bf2f2 100644 --- a/storage/innobase/sync/sync0arr.c +++ b/storage/innobase/sync/sync0arr.c @@ -227,24 +227,21 @@ sync_array_create( SYNC_ARRAY_MUTEX: determines the type of mutex protecting the data structure */ { + ulint sz; sync_array_t* arr; - sync_cell_t* cell_array; - sync_cell_t* cell; - ulint i; ut_a(n_cells > 0); /* Allocate memory for the data structures */ arr = ut_malloc(sizeof(sync_array_t)); + memset(arr, 0x0, sizeof(*arr)); - cell_array = ut_malloc(sizeof(sync_cell_t) * n_cells); + sz = sizeof(sync_cell_t) * n_cells; + arr->array = ut_malloc(sz); + memset(arr->array, 0x0, sz); arr->n_cells = n_cells; - arr->n_reserved = 0; - arr->array = cell_array; arr->protection = protection; - arr->sg_count = 0; - arr->res_count = 0; /* Then create the mutex to protect the wait array complex */ if (protection == SYNC_ARRAY_OS_MUTEX) { @@ -255,13 +252,6 @@ sync_array_create( ut_error; } - for (i = 0; i < n_cells; i++) { - cell = sync_array_get_nth_cell(arr, i); - cell->wait_object = NULL; - cell->waiting = FALSE; - cell->signal_count = 0; - } - return(arr); } diff --git a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c index 5ad143075a7..569fc6328c4 100644 --- a/storage/innobase/sync/sync0sync.c +++ b/storage/innobase/sync/sync0sync.c @@ -1377,7 +1377,12 @@ sync_close(void) mutex_free(&mutex_list_mutex); #ifdef UNIV_SYNC_DEBUG mutex_free(&sync_thread_mutex); + + /* Switch latching order checks on in sync0sync.c */ + sync_order_checks_on = FALSE; #endif /* UNIV_SYNC_DEBUG */ + + sync_initialized = FALSE; } /*******************************************************************//** diff --git a/storage/innobase/thr/thr0loc.c b/storage/innobase/thr/thr0loc.c index 49275be1d7d..59a234a6b72 100644 --- a/storage/innobase/thr/thr0loc.c +++ b/storage/innobase/thr/thr0loc.c @@ -246,3 +246,34 @@ thr_local_init(void) mutex_create(&thr_local_mutex, SYNC_THR_LOCAL); } + +/******************************************************************** +Close the thread local storage module. */ +UNIV_INTERN +void +thr_local_close(void) +/*=================*/ +{ + ulint i; + + ut_a(thr_local_hash != NULL); + + /* Free the hash elements. We don't remove them from the table + because we are going to destroy the table anyway. */ + for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) { + thr_local_t* local; + + local = HASH_GET_FIRST(thr_local_hash, i); + + while (local) { + thr_local_t* prev_local = local; + + local = HASH_GET_NEXT(hash, prev_local); + ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N); + mem_free(prev_local); + } + } + + hash_table_free(thr_local_hash); + thr_local_hash = NULL; +} diff --git a/storage/innobase/trx/trx0i_s.c b/storage/innobase/trx/trx0i_s.c index 0d809806edc..ef2e6850d6c 100644 --- a/storage/innobase/trx/trx0i_s.c +++ b/storage/innobase/trx/trx0i_s.c @@ -60,7 +60,7 @@ Created July 17, 2007 Vasil Dimov /** @brief The maximum number of chunks to allocate for a table cache. The rows of a table cache are stored in a set of chunks. When a new -row is added a new chunk is allocated if necessary. Assuming that the +row is added a new chunk is allocated if necessary. Assuming that the first one is 1024 rows (TABLE_CACHE_INITIAL_ROWSNUM) and each subsequent is N/2 where N is the number of rows we have allocated till now, then 39th chunk would accommodate 1677416425 rows and all chunks @@ -238,6 +238,27 @@ table_cache_init( } /*******************************************************************//** +Frees a table cache. */ +static +void +table_cache_free( +/*=============*/ + i_s_table_cache_t* table_cache) /*!< in/out: table cache */ +{ + ulint i; + + for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) { + + /* the memory is actually allocated in + table_cache_create_empty_row() */ + if (table_cache->chunks[i].base) { + mem_free(table_cache->chunks[i].base); + table_cache->chunks[i].base = NULL; + } + } +} + +/*******************************************************************//** Returns an empty row from a table cache. The row is allocated if no more empty rows are available. The number of used rows is incremented. If the memory limit is hit then NULL is returned and nothing is @@ -1252,6 +1273,22 @@ trx_i_s_cache_init( } /*******************************************************************//** +Free the INFORMATION SCHEMA trx related cache. */ +UNIV_INTERN +void +trx_i_s_cache_free( +/*===============*/ + trx_i_s_cache_t* cache) /*!< in, own: cache to free */ +{ + hash_table_free(cache->locks_hash); + ha_storage_free(cache->storage); + table_cache_free(&cache->innodb_trx); + table_cache_free(&cache->innodb_locks); + table_cache_free(&cache->innodb_lock_waits); + memset(cache, 0, sizeof *cache); +} + +/*******************************************************************//** Issue a shared/read lock on the tables cache. */ UNIV_INTERN void diff --git a/storage/innobase/trx/trx0purge.c b/storage/innobase/trx/trx0purge.c index cd79fd1c315..abbfa3d7f81 100644 --- a/storage/innobase/trx/trx0purge.c +++ b/storage/innobase/trx/trx0purge.c @@ -249,6 +249,44 @@ trx_purge_sys_create(void) purge_sys->heap); } +/************************************************************************ +Frees the global purge system control structure. */ +UNIV_INTERN +void +trx_purge_sys_close(void) +/*======================*/ +{ + ut_ad(!mutex_own(&kernel_mutex)); + + que_graph_free(purge_sys->query); + + ut_a(purge_sys->sess->trx->is_purge); + purge_sys->sess->trx->conc_state = TRX_NOT_STARTED; + sess_close(purge_sys->sess); + purge_sys->sess = NULL; + + if (purge_sys->view != NULL) { + /* Because acquiring the kernel mutex is a pre-condition + of read_view_close(). We don't really need it here. */ + mutex_enter(&kernel_mutex); + + read_view_close(purge_sys->view); + purge_sys->view = NULL; + + mutex_exit(&kernel_mutex); + } + + trx_undo_arr_free(purge_sys->arr); + + rw_lock_free(&purge_sys->latch); + mutex_free(&purge_sys->mutex); + + mem_heap_free(purge_sys->heap); + mem_free(purge_sys); + + purge_sys = NULL; +} + /*================ UNDO LOG HISTORY LIST =============================*/ /********************************************************************//** diff --git a/storage/innobase/trx/trx0rseg.c b/storage/innobase/trx/trx0rseg.c index 580762e8716..8d754788e2a 100644 --- a/storage/innobase/trx/trx0rseg.c +++ b/storage/innobase/trx/trx0rseg.c @@ -132,6 +132,49 @@ trx_rseg_header_create( } /***********************************************************************//** +Free's an instance of the rollback segment in memory. */ +UNIV_INTERN +void +trx_rseg_mem_free( +/*==============*/ + trx_rseg_t* rseg) /* in, own: instance to free */ +{ + trx_undo_t* undo; + + mutex_free(&rseg->mutex); + + /* There can't be any active transactions. */ + ut_a(UT_LIST_GET_LEN(rseg->update_undo_list) == 0); + ut_a(UT_LIST_GET_LEN(rseg->insert_undo_list) == 0); + + undo = UT_LIST_GET_FIRST(rseg->update_undo_cached); + + while (undo != NULL) { + trx_undo_t* prev_undo = undo; + + undo = UT_LIST_GET_NEXT(undo_list, undo); + UT_LIST_REMOVE(undo_list, rseg->update_undo_cached, prev_undo); + + trx_undo_mem_free(prev_undo); + } + + undo = UT_LIST_GET_FIRST(rseg->insert_undo_cached); + + while (undo != NULL) { + trx_undo_t* prev_undo = undo; + + undo = UT_LIST_GET_NEXT(undo_list, undo); + UT_LIST_REMOVE(undo_list, rseg->insert_undo_cached, prev_undo); + + trx_undo_mem_free(prev_undo); + } + + trx_sys_set_nth_rseg(trx_sys, rseg->id, NULL); + + mem_free(rseg); +} + +/*************************************************************************** Creates and initializes a rollback segment object. The values for the fields are read from the header. The object is inserted to the rseg list of the trx system object and a pointer is inserted in the rseg diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index ef10119587d..79e5af1c677 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -40,6 +40,7 @@ Created 3/26/1996 Heikki Tuuri #include "trx0purge.h" #include "log0log.h" #include "os0file.h" +#include "read0read.h" /** The file format tag structure with id and name. */ struct file_format_struct { @@ -1533,3 +1534,80 @@ trx_sys_file_format_id_to_name( } #endif /* !UNIV_HOTBACKUP */ + +/********************************************************************* +Shutdown/Close the transaction system. */ +UNIV_INTERN +void +trx_sys_close(void) +/*===============*/ +{ + trx_rseg_t* rseg; + read_view_t* view; + + ut_ad(trx_sys != NULL); + + /* Check that all read views are closed except read view owned + by a purge. */ + + if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) { + fprintf(stderr, + "InnoDB: Error: all read views were not closed" + " before shutdown:\n" + "InnoDB: %lu read views open \n", + UT_LIST_GET_LEN(trx_sys->view_list) - 1); + } + + sess_close(trx_dummy_sess); + trx_dummy_sess = NULL; + + trx_purge_sys_close(); + + mutex_enter(&kernel_mutex); + + /* Free the double write data structures. */ + ut_a(trx_doublewrite != NULL); + ut_free(trx_doublewrite->write_buf_unaligned); + trx_doublewrite->write_buf_unaligned = NULL; + + mem_free(trx_doublewrite->buf_block_arr); + trx_doublewrite->buf_block_arr = NULL; + + mutex_free(&trx_doublewrite->mutex); + mem_free(trx_doublewrite); + trx_doublewrite = NULL; + + /* There can't be any active transactions. */ + rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list); + + while (rseg != NULL) { + trx_rseg_t* prev_rseg = rseg; + + rseg = UT_LIST_GET_NEXT(rseg_list, prev_rseg); + UT_LIST_REMOVE(rseg_list, trx_sys->rseg_list, prev_rseg); + + trx_rseg_mem_free(prev_rseg); + } + + view = UT_LIST_GET_FIRST(trx_sys->view_list); + + while (view != NULL) { + read_view_t* prev_view = view; + + view = UT_LIST_GET_NEXT(view_list, prev_view); + + /* Views are allocated from the trx_sys->global_read_view_heap. + So, we simply remove the element here. */ + UT_LIST_REMOVE(view_list, trx_sys->view_list, prev_view); + } + + ut_a(UT_LIST_GET_LEN(trx_sys->trx_list) == 0); + ut_a(UT_LIST_GET_LEN(trx_sys->rseg_list) == 0); + ut_a(UT_LIST_GET_LEN(trx_sys->view_list) == 0); + ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0); + + mem_free(trx_sys); + + trx_sys = NULL; + mutex_exit(&kernel_mutex); +} diff --git a/storage/innobase/trx/trx0undo.c b/storage/innobase/trx/trx0undo.c index 9af96f14526..3bb1b1cdf6c 100644 --- a/storage/innobase/trx/trx0undo.c +++ b/storage/innobase/trx/trx0undo.c @@ -1522,7 +1522,7 @@ trx_undo_mem_init_for_reuse( /********************************************************************//** Frees an undo log memory copy. */ -static +UNIV_INTERN void trx_undo_mem_free( /*==============*/ diff --git a/storage/innobase/usr/usr0sess.c b/storage/innobase/usr/usr0sess.c index 990991a2c06..8087dcb4170 100644 --- a/storage/innobase/usr/usr0sess.c +++ b/storage/innobase/usr/usr0sess.c @@ -32,14 +32,6 @@ Created 6/25/1996 Heikki Tuuri #include "trx0trx.h" /*********************************************************************//** -Closes a session, freeing the memory occupied by it. */ -static -void -sess_close( -/*=======*/ - sess_t* sess); /*!< in, own: session object */ - -/*********************************************************************//** Opens a session. @return own: session object */ UNIV_INTERN @@ -64,35 +56,16 @@ sess_open(void) /*********************************************************************//** Closes a session, freeing the memory occupied by it. */ -static +UNIV_INTERN void sess_close( /*=======*/ sess_t* sess) /*!< in, own: session object */ { - ut_ad(mutex_own(&kernel_mutex)); - ut_ad(sess->trx == NULL); - - mem_free(sess); -} - -/*********************************************************************//** -Closes a session, freeing the memory occupied by it, if it is in a state -where it should be closed. -@return TRUE if closed */ -UNIV_INTERN -ibool -sess_try_close( -/*===========*/ - sess_t* sess) /*!< in, own: session object */ -{ - ut_ad(mutex_own(&kernel_mutex)); + ut_ad(!mutex_own(&kernel_mutex)); - if (UT_LIST_GET_LEN(sess->graphs) == 0) { - sess_close(sess); + ut_a(UT_LIST_GET_LEN(sess->graphs) == 0); - return(TRUE); - } - - return(FALSE); + trx_free_for_background(sess->trx); + mem_free(sess); } diff --git a/storage/innobase/ut/ut0mem.c b/storage/innobase/ut/ut0mem.c index edb63c95700..35a325b9ccd 100644 --- a/storage/innobase/ut/ut0mem.c +++ b/storage/innobase/ut/ut0mem.c @@ -433,6 +433,8 @@ ut_free_all_mem(void) " total allocated memory is %lu\n", (ulong) ut_total_allocated_memory); } + + ut_mem_block_list_inited = FALSE; } #endif /* !UNIV_HOTBACKUP */ |