#At file:///home/og136792/mysql/shared/mysql-6.0-backup-main/
2643 Oystein Grovlen 2008-06-25 [merge]
Merge main->mysql-6.0-backup. No conflicts observed.
added:
mysql-test/r/innodb-autoinc.result
mysql-test/r/innodb_bug34053.result
mysql-test/r/innodb_bug34300.result
mysql-test/r/innodb_bug35220.result
mysql-test/suite/bugs/r/rpl_bug33029.result
mysql-test/suite/bugs/t/rpl_bug33029.test
mysql-test/t/innodb-autoinc.test
mysql-test/t/innodb_bug34053.test
mysql-test/t/innodb_bug34300.test
mysql-test/t/innodb_bug35220.test
modified:
Makefile.am
client/mysql.cc
config/ac-macros/libevent.m4
mysql-test/lib/mtr_cases.pl
mysql-test/r/innodb.result
mysql-test/r/mysql.result
mysql-test/r/partition_innodb.result
mysql-test/r/repair.result
mysql-test/r/subselect.result
mysql-test/r/subselect_no_mat.result
mysql-test/r/subselect_no_opts.result
mysql-test/r/subselect_no_semijoin.result
mysql-test/suite/binlog/r/binlog_innodb.result
mysql-test/suite/rpl/t/disabled.def
mysql-test/t/innodb.test
mysql-test/t/mysql_delimiter.sql
mysql-test/t/partition_innodb.test
mysql-test/t/subselect.test
scripts/make_binary_distribution.sh
sql/slave.cc
sql/sql_class.cc
sql/sql_plugin.cc
sql/sql_select.cc
sql/sql_table.cc
sql/structs.h
storage/innobase/Makefile.am
storage/innobase/btr/btr0cur.c
storage/innobase/buf/buf0buf.c
storage/innobase/dict/dict0dict.c
storage/innobase/handler/ha_innodb.cc
storage/innobase/handler/ha_innodb.h
storage/innobase/include/buf0buf.h
storage/innobase/include/dict0dict.h
storage/innobase/include/dict0mem.h
storage/innobase/include/mach0data.h
storage/innobase/include/mach0data.ic
storage/innobase/include/os0sync.h
storage/innobase/include/read0read.h
storage/innobase/include/row0mysql.h
storage/innobase/include/row0sel.h
storage/innobase/include/srv0srv.h
storage/innobase/include/sync0arr.h
storage/innobase/include/sync0rw.h
storage/innobase/include/sync0rw.ic
storage/innobase/include/sync0sync.h
storage/innobase/include/sync0sync.ic
storage/innobase/include/trx0undo.h
storage/innobase/include/univ.i
storage/innobase/include/ut0ut.h
storage/innobase/os/os0file.c
storage/innobase/os/os0sync.c
storage/innobase/plug.in
storage/innobase/read/read0read.c
storage/innobase/row/row0mysql.c
storage/innobase/row/row0sel.c
storage/innobase/srv/srv0srv.c
storage/innobase/srv/srv0start.c
storage/innobase/sync/sync0arr.c
storage/innobase/sync/sync0rw.c
storage/innobase/sync/sync0sync.c
storage/innobase/trx/trx0trx.c
storage/innobase/trx/trx0undo.c
storage/innobase/ut/ut0ut.c
=== modified file 'Makefile.am'
--- a/Makefile.am 2008-05-21 10:17:29 +0000
+++ b/Makefile.am 2008-06-16 19:27:44 +0000
@@ -17,9 +17,14 @@
AUTOMAKE_OPTIONS = foreign
-# These are built from source in the Docs directory
+# Files in the first two lines are built from source in the Docs directory,
+# "CMakeLists.txt" is for Windows only,
+# "libevent_configure.m4" is needed in sources but should be evaluated only
+# if "--with-libevent" is given (handled in "config/ac-macros/libevent.m4").
EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \
- README COPYING EXCEPTIONS-CLIENT CMakeLists.txt
+ README COPYING EXCEPTIONS-CLIENT \
+ CMakeLists.txt \
+ config/ac-macros/libevent_configure.m4
SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
@readline_topdir@ sql-common scripts \
=== modified file 'client/mysql.cc'
--- a/client/mysql.cc 2008-04-01 10:45:05 +0000
+++ b/client/mysql.cc 2008-06-20 19:24:46 +0000
@@ -1848,7 +1848,7 @@ static int read_and_execute(bool interac
the very beginning of a text file when
you save the file using "Unicode UTF-8" format.
*/
- if (!line_number &&
+ if (line && !line_number &&
(uchar) line[0] == 0xEF &&
(uchar) line[1] == 0xBB &&
(uchar) line[2] == 0xBF)
@@ -2128,37 +2128,6 @@ static bool add_line(String &buffer,char
continue;
}
}
- else if (!*ml_comment && !*in_string &&
- (end_of_line - pos) >= 10 &&
- !my_strnncoll(charset_info, (uchar*) pos, 10,
- (const uchar*) "delimiter ", 10))
- {
- // Flush previously accepted characters
- if (out != line)
- {
- buffer.append(line, (uint32) (out - line));
- out= line;
- }
-
- // Flush possible comments in the buffer
- if (!buffer.is_empty())
- {
- if (com_go(&buffer, 0) > 0) // < 0 is not fatal
- DBUG_RETURN(1);
- buffer.length(0);
- }
-
- /*
- Delimiter wants the get rest of the given line as argument to
- allow one to change ';' to ';;' and back
- */
- buffer.append(pos);
- if (com_delimiter(&buffer, pos) > 0)
- DBUG_RETURN(1);
-
- buffer.length(0);
- break;
- }
else if (!*ml_comment && !*in_string && is_prefix(pos, delimiter))
{
// Found a statement. Continue parsing after the delimiter
=== modified file 'config/ac-macros/libevent.m4'
--- a/config/ac-macros/libevent.m4 2008-04-28 23:56:34 +0000
+++ b/config/ac-macros/libevent.m4 2008-06-16 19:27:44 +0000
@@ -22,7 +22,8 @@ AC_DEFUN([MYSQL_USE_BUNDLED_LIBEVENT], [
AC_DEFINE([HAVE_LIBEVENT], [1], [If we want to use libevent and have connection pooling])
AC_MSG_RESULT([using bundled libevent])
- dnl Use builtin include to workaround path problems on older versions of aclocal.
+ dnl Get the upstream file with the original libevent configure macros.
+ dnl Use builtin include for this, to work around path problems in old versions of aclocal.
builtin([include],[config/ac-macros/libevent_configure.m4])
])
=== modified file 'mysql-test/lib/mtr_cases.pl'
--- a/mysql-test/lib/mtr_cases.pl 2008-02-11 16:11:22 +0000
+++ b/mysql-test/lib/mtr_cases.pl 2008-06-18 03:30:29 +0000
@@ -773,6 +773,13 @@ sub collect_one_test_case($$$$$$$$$) {
if ( $::used_default_engine =~ /^innodb/i );
}
+ #enable federated for this test
+ if ($tinfo->{'federated_test'})
+ {
+ push(@{$tinfo->{'master_opt'}}, "--loose-federated");
+ push(@{$tinfo->{'slave_opt'}}, "--loose-federated");
+ }
+
if ( $tinfo->{'big_test'} and ! $::opt_big_test )
{
$tinfo->{'skip'}= 1;
@@ -891,6 +898,8 @@ our @tags=
["include/have_ndb_extra.inc", "ndb_extra", 1],
["include/ndb_master-slave.inc", "ndb_test", 1],
["require_manager", "require_manager", 1],
+ ["include/federated.inc", "federated_test", 1],
+ ["include/have_federated_db.inc", "federated_test", 1],
);
sub mtr_options_from_test_file($$) {
=== added file 'mysql-test/r/innodb-autoinc.result'
--- a/mysql-test/r/innodb-autoinc.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/innodb-autoinc.result 2008-06-12 00:08:07 +0000
@@ -0,0 +1,89 @@
+drop table if exists t1;
+CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (9223372036854775807, null);
+INSERT INTO t1 (c2) VALUES ('innodb');
+Got one of the listed errors
+SELECT * FROM t1;
+c1 c2
+9223372036854775807 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (127, null);
+INSERT INTO t1 (c2) VALUES ('innodb');
+Got one of the listed errors
+SELECT * FROM t1;
+c1 c2
+127 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (255, null);
+INSERT INTO t1 (c2) VALUES ('innodb');
+Got one of the listed errors
+SELECT * FROM t1;
+c1 c2
+255 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 SMALLINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (32767, null);
+INSERT INTO t1 (c2) VALUES ('innodb');
+Got one of the listed errors
+SELECT * FROM t1;
+c1 c2
+32767 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (65535, null);
+INSERT INTO t1 (c2) VALUES ('innodb');
+Got one of the listed errors
+SELECT * FROM t1;
+c1 c2
+65535 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 MEDIUMINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (8388607, null);
+INSERT INTO t1 (c2) VALUES ('innodb');
+Got one of the listed errors
+SELECT * FROM t1;
+c1 c2
+8388607 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 MEDIUMINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (16777215, null);
+INSERT INTO t1 (c2) VALUES ('innodb');
+Got one of the listed errors
+SELECT * FROM t1;
+c1 c2
+16777215 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (2147483647, null);
+INSERT INTO t1 (c2) VALUES ('innodb');
+Got one of the listed errors
+SELECT * FROM t1;
+c1 c2
+2147483647 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (4294967295, null);
+INSERT INTO t1 (c2) VALUES ('innodb');
+Got one of the listed errors
+SELECT * FROM t1;
+c1 c2
+4294967295 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (9223372036854775807, null);
+INSERT INTO t1 (c2) VALUES ('innodb');
+Got one of the listed errors
+SELECT * FROM t1;
+c1 c2
+9223372036854775807 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (18446744073709551615, null);
+INSERT INTO t1 (c2) VALUES ('innodb');
+Got one of the listed errors
+SELECT * FROM t1;
+c1 c2
+18446744073709551615 NULL
+DROP TABLE t1;
=== modified file 'mysql-test/r/innodb.result'
--- a/mysql-test/r/innodb.result 2008-05-14 09:24:14 +0000
+++ b/mysql-test/r/innodb.result 2008-06-12 00:08:07 +0000
@@ -1727,10 +1727,10 @@ Variable_name Value
Innodb_page_size 16384
show status like "Innodb_rows_deleted";
Variable_name Value
-Innodb_rows_deleted 70
+Innodb_rows_deleted 71
show status like "Innodb_rows_inserted";
Variable_name Value
-Innodb_rows_inserted 1082
+Innodb_rows_inserted 1084
show status like "Innodb_rows_updated";
Variable_name Value
Innodb_rows_updated 885
@@ -3218,3 +3218,54 @@ a
2
DROP TABLE t1;
DROP TABLE t2;
+create table t1 (i int, j int) engine=innodb;
+insert into t1 (i, j) values (1, 1), (2, 2);
+update t1 set j = 2;
+affected rows: 1
+info: Rows matched: 2 Changed: 1 Warnings: 0
+drop table t1;
+create table t1 (id int) comment='this is a comment' engine=innodb;
+select table_comment, data_free > 0 as data_free_is_set
+from information_schema.tables
+where table_schema='test' and table_name = 't1';
+table_comment data_free_is_set
+this is a comment 1
+drop table t1;
+CREATE TABLE t1 (
+c1 INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+c2 VARCHAR(128) NOT NULL,
+PRIMARY KEY(c1)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=100;
+CREATE TABLE t2 (
+c1 INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+c2 INT(10) UNSIGNED DEFAULT NULL,
+PRIMARY KEY(c1)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=200;
+SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE table_name = 't2';
+AUTO_INCREMENT
+200
+ALTER TABLE t2 ADD CONSTRAINT t1_t2_1 FOREIGN KEY(c1) REFERENCES t1(c1);
+SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE table_name = 't2';
+AUTO_INCREMENT
+200
+DROP TABLE t2;
+DROP TABLE t1;
+CREATE TABLE t1 (c1 int default NULL,
+c2 int default NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+TRUNCATE TABLE t1;
+affected rows: 0
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+TRUNCATE TABLE t1;
+affected rows: 0
+DROP TABLE t1;
+Variable_name Value
+Handler_update 0
+Variable_name Value
+Handler_delete 0
+Variable_name Value
+Handler_update 1
+Variable_name Value
+Handler_delete 1
=== added file 'mysql-test/r/innodb_bug34053.result'
--- a/mysql-test/r/innodb_bug34053.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/innodb_bug34053.result 2008-06-12 00:08:07 +0000
@@ -0,0 +1 @@
+SET storage_engine=InnoDB;
=== added file 'mysql-test/r/innodb_bug34300.result'
--- a/mysql-test/r/innodb_bug34300.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/innodb_bug34300.result 2008-06-12 00:08:07 +0000
@@ -0,0 +1,4 @@
+f4 f8
+xxx zzz
+f4 f8
+xxx zzz
=== added file 'mysql-test/r/innodb_bug35220.result'
--- a/mysql-test/r/innodb_bug35220.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/innodb_bug35220.result 2008-06-12 00:08:07 +0000
@@ -0,0 +1 @@
+SET storage_engine=InnoDB;
=== modified file 'mysql-test/r/mysql.result'
--- a/mysql-test/r/mysql.result 2007-11-27 17:23:39 +0000
+++ b/mysql-test/r/mysql.result 2008-06-20 19:24:46 +0000
@@ -38,6 +38,8 @@ t2
t3
Tables_in_test
t1
+delimiter
+1
_
Test delimiter : from command line
a
=== modified file 'mysql-test/r/partition_innodb.result'
--- a/mysql-test/r/partition_innodb.result 2008-03-27 19:02:15 +0000
+++ b/mysql-test/r/partition_innodb.result 2008-06-12 00:08:07 +0000
@@ -13,33 +13,33 @@ DROP TABLE t1;
create table t1 (a int) engine=innodb partition by hash(a) ;
show table status like 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 InnoDB 10 Compact 2 8192 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
+t1 InnoDB 10 Compact 2 8192 16384 0 0 <datafree> NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
drop table t1;
create table t1 (a int)
engine = innodb
partition by key (a);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 InnoDB 10 Compact 2 8192 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
+t1 InnoDB 10 Compact 2 8192 16384 0 0 <datafree> NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
insert into t1 values (0), (1), (2), (3);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 InnoDB 10 Compact 4 4096 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
+t1 InnoDB 10 Compact 4 4096 16384 0 0 <datafree> NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
drop table t1;
create table t1 (a int auto_increment primary key)
engine = innodb
partition by key (a);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 InnoDB 10 Compact 2 8192 16384 0 0 0 1 NULL NULL NULL latin1_swedish_ci NULL partitioned
+t1 InnoDB 10 Compact 2 8192 16384 0 0 <datafree> 1 NULL NULL NULL latin1_swedish_ci NULL partitioned
insert into t1 values (NULL), (NULL), (NULL), (NULL);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 InnoDB 10 Compact 4 4096 16384 0 0 0 5 NULL NULL NULL latin1_swedish_ci NULL partitioned
+t1 InnoDB 10 Compact 4 4096 16384 0 0 <datafree> 5 NULL NULL NULL latin1_swedish_ci NULL partitioned
insert into t1 values (NULL), (NULL), (NULL), (NULL);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 InnoDB 10 Compact 8 2048 16384 0 0 0 9 NULL NULL NULL latin1_swedish_ci NULL partitioned
+t1 InnoDB 10 Compact 8 2048 16384 0 0 <datafree> 9 NULL NULL NULL latin1_swedish_ci NULL partitioned
drop table t1;
create table t1 (a int)
partition by key (a)
=== modified file 'mysql-test/r/repair.result'
--- a/mysql-test/r/repair.result 2008-05-12 19:38:57 +0000
+++ b/mysql-test/r/repair.result 2008-06-18 03:30:29 +0000
@@ -130,7 +130,7 @@ test.t1 check error Table upgrade requir
# REPAIR old table USE_FRM should fail
REPAIR TABLE t1 USE_FRM;
Table Op Msg_type Msg_text
-t1 repair error Failed reparing incompatible .FRM file
+t1 repair error Failed repairing incompatible .frm file
# Run REPAIR TABLE to upgrade .frm file
REPAIR TABLE t1;
Table Op Msg_type Msg_text
=== modified file 'mysql-test/r/subselect.result'
--- a/mysql-test/r/subselect.result 2008-05-22 18:40:15 +0000
+++ b/mysql-test/r/subselect.result 2008-06-20 19:24:46 +0000
@@ -4593,6 +4593,13 @@ SELECT * FROM t1 WHERE _utf8'a' = ANY (S
s1
a
DROP TABLE t1;
+CREATE TABLE t1(c int, KEY(c));
+CREATE TABLE t2(a int, b int);
+INSERT INTO t2 VALUES (1, 10), (2, NULL);
+INSERT INTO t1 VALUES (1), (3);
+SELECT * FROM t2 WHERE b NOT IN (SELECT max(t.c) FROM t1, t1 t WHERE t.c>10);
+a b
+DROP TABLE t1,t2;
CREATE TABLE t1( a INT );
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2( a INT, b INT );
=== modified file 'mysql-test/r/subselect_no_mat.result'
--- a/mysql-test/r/subselect_no_mat.result 2008-05-22 18:40:15 +0000
+++ b/mysql-test/r/subselect_no_mat.result 2008-06-21 09:05:07 +0000
@@ -4597,6 +4597,13 @@ SELECT * FROM t1 WHERE _utf8'a' = ANY (S
s1
a
DROP TABLE t1;
+CREATE TABLE t1(c int, KEY(c));
+CREATE TABLE t2(a int, b int);
+INSERT INTO t2 VALUES (1, 10), (2, NULL);
+INSERT INTO t1 VALUES (1), (3);
+SELECT * FROM t2 WHERE b NOT IN (SELECT max(t.c) FROM t1, t1 t WHERE t.c>10);
+a b
+DROP TABLE t1,t2;
CREATE TABLE t1( a INT );
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2( a INT, b INT );
=== modified file 'mysql-test/r/subselect_no_opts.result'
--- a/mysql-test/r/subselect_no_opts.result 2008-05-22 18:40:15 +0000
+++ b/mysql-test/r/subselect_no_opts.result 2008-06-21 09:05:07 +0000
@@ -4597,6 +4597,13 @@ SELECT * FROM t1 WHERE _utf8'a' = ANY (S
s1
a
DROP TABLE t1;
+CREATE TABLE t1(c int, KEY(c));
+CREATE TABLE t2(a int, b int);
+INSERT INTO t2 VALUES (1, 10), (2, NULL);
+INSERT INTO t1 VALUES (1), (3);
+SELECT * FROM t2 WHERE b NOT IN (SELECT max(t.c) FROM t1, t1 t WHERE t.c>10);
+a b
+DROP TABLE t1,t2;
CREATE TABLE t1( a INT );
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2( a INT, b INT );
=== modified file 'mysql-test/r/subselect_no_semijoin.result'
--- a/mysql-test/r/subselect_no_semijoin.result 2008-05-22 18:40:15 +0000
+++ b/mysql-test/r/subselect_no_semijoin.result 2008-06-21 09:05:07 +0000
@@ -4597,6 +4597,13 @@ SELECT * FROM t1 WHERE _utf8'a' = ANY (S
s1
a
DROP TABLE t1;
+CREATE TABLE t1(c int, KEY(c));
+CREATE TABLE t2(a int, b int);
+INSERT INTO t2 VALUES (1, 10), (2, NULL);
+INSERT INTO t1 VALUES (1), (3);
+SELECT * FROM t2 WHERE b NOT IN (SELECT max(t.c) FROM t1, t1 t WHERE t.c>10);
+a b
+DROP TABLE t1,t2;
CREATE TABLE t1( a INT );
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2( a INT, b INT );
=== modified file 'mysql-test/suite/binlog/r/binlog_innodb.result'
--- a/mysql-test/suite/binlog/r/binlog_innodb.result 2008-05-15 20:56:38 +0000
+++ b/mysql-test/suite/binlog/r/binlog_innodb.result 2008-06-12 00:08:07 +0000
@@ -110,7 +110,6 @@ master-bin.000001 # Table_map # # table_
master-bin.000001 # Update_rows # # table_id: #
master-bin.000001 # Update_rows # # table_id: #
master-bin.000001 # Update_rows # # table_id: #
-master-bin.000001 # Update_rows # # table_id: #
master-bin.000001 # Update_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; BEGIN
=== added file 'mysql-test/suite/bugs/r/rpl_bug33029.result'
--- a/mysql-test/suite/bugs/r/rpl_bug33029.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/bugs/r/rpl_bug33029.result 2008-06-19 18:47:59 +0000
@@ -0,0 +1,15 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+create table `t1` (`id` int not null auto_increment primary key);
+create trigger `trg` before insert on `t1` for each row begin end;
+set @@global.debug="+d,simulate_bug33029";
+stop slave;
+start slave;
+insert into `t1` values ();
+select * from t1;
+id
+1
=== added file 'mysql-test/suite/bugs/t/rpl_bug33029.test'
--- a/mysql-test/suite/bugs/t/rpl_bug33029.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/bugs/t/rpl_bug33029.test 2008-06-19 18:47:59 +0000
@@ -0,0 +1,25 @@
+#
+# Bug #36443 Server crashes when executing insert when insert trigger on table
+#
+# Emulating the former bug#33029 situation to see that there is no crash anymore.
+#
+
+
+source include/master-slave.inc;
+
+create table `t1` (`id` int not null auto_increment primary key);
+create trigger `trg` before insert on `t1` for each row begin end;
+
+sync_slave_with_master;
+set @@global.debug="+d,simulate_bug33029";
+
+stop slave;
+start slave;
+
+connection master;
+
+insert into `t1` values ();
+
+sync_slave_with_master;
+select * from t1;
+
=== modified file 'mysql-test/suite/rpl/t/disabled.def'
--- a/mysql-test/suite/rpl/t/disabled.def 2008-05-19 08:32:08 +0000
+++ b/mysql-test/suite/rpl/t/disabled.def 2008-06-20 19:24:46 +0000
@@ -29,4 +29,4 @@ rpl_log_pos : Bug#8693 Te
rpl_row_basic_7ndb : BUG#33360 2007-12-19 mats rpl_ndb_idempotent fails due to null field for table on slave side
rpl_redirect : Failure is sporadic and and the test is superfluous (mats)
rpl_innodb_bug28430 : Failure on Solaris Bug #36793
-
+rpl_server_id1 : Bug #36818 rpl_server_id1 fails expecting slave has stopped (azundris)
=== added file 'mysql-test/t/innodb-autoinc.test'
--- a/mysql-test/t/innodb-autoinc.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/innodb-autoinc.test 2008-06-12 00:08:07 +0000
@@ -0,0 +1,107 @@
+-- source include/have_innodb.inc
+# embedded server ignores 'delayed', so skip this
+-- source include/not_embedded.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# Bug #34335
+#
+CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (9223372036854775807, null);
+-- error ER_DUP_ENTRY,1062
+INSERT INTO t1 (c2) VALUES ('innodb');
+SELECT * FROM t1;
+DROP TABLE t1;
+#
+## Test AUTOINC overflow
+##
+
+# TINYINT
+CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (127, null);
+-- error ER_DUP_ENTRY,1062
+-- warning ER_WARN_DATA_OUT_OF_RANGE,1264
+INSERT INTO t1 (c2) VALUES ('innodb');
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (255, null);
+-- error ER_DUP_ENTRY,1062
+-- warning ER_WARN_DATA_OUT_OF_RANGE,1264
+INSERT INTO t1 (c2) VALUES ('innodb');
+SELECT * FROM t1;
+DROP TABLE t1;
+#
+# SMALLINT
+#
+CREATE TABLE t1 (c1 SMALLINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (32767, null);
+-- error ER_DUP_ENTRY,1062
+-- warning ER_WARN_DATA_OUT_OF_RANGE,1264
+INSERT INTO t1 (c2) VALUES ('innodb');
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (65535, null);
+-- error ER_DUP_ENTRY,1062
+-- warning ER_WARN_DATA_OUT_OF_RANGE,1264
+INSERT INTO t1 (c2) VALUES ('innodb');
+SELECT * FROM t1;
+DROP TABLE t1;
+#
+# MEDIUMINT
+#
+CREATE TABLE t1 (c1 MEDIUMINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (8388607, null);
+-- error ER_DUP_ENTRY,1062
+-- warning ER_WARN_DATA_OUT_OF_RANGE,1264
+INSERT INTO t1 (c2) VALUES ('innodb');
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 MEDIUMINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (16777215, null);
+-- error ER_DUP_ENTRY,1062
+-- warning ER_WARN_DATA_OUT_OF_RANGE,1264
+INSERT INTO t1 (c2) VALUES ('innodb');
+SELECT * FROM t1;
+DROP TABLE t1;
+#
+# INT
+#
+CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (2147483647, null);
+-- error ER_DUP_ENTRY,1062
+-- warning ER_WARN_DATA_OUT_OF_RANGE,1264
+INSERT INTO t1 (c2) VALUES ('innodb');
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (4294967295, null);
+-- error ER_DUP_ENTRY,1062
+INSERT INTO t1 (c2) VALUES ('innodb');
+SELECT * FROM t1;
+DROP TABLE t1;
+#
+# BIGINT
+#
+CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (9223372036854775807, null);
+-- error ER_DUP_ENTRY,1062
+-- warning ER_WARN_DATA_OUT_OF_RANGE,1264
+INSERT INTO t1 (c2) VALUES ('innodb');
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (18446744073709551615, null);
+-- error ER_AUTOINC_READ_FAILED,1467
+INSERT INTO t1 (c2) VALUES ('innodb');
+SELECT * FROM t1;
+DROP TABLE t1;
=== modified file 'mysql-test/t/innodb.test'
--- a/mysql-test/t/innodb.test 2008-05-14 09:24:14 +0000
+++ b/mysql-test/t/innodb.test 2008-06-12 00:08:07 +0000
@@ -2381,6 +2381,96 @@ DROP TABLE t1;
DROP TABLE t2;
DISCONNECT c1;
DISCONNECT c2;
+CONNECTION default;
+
+#
+# Bug #29157 UPDATE, changed rows incorrect
+#
+create table t1 (i int, j int) engine=innodb;
+insert into t1 (i, j) values (1, 1), (2, 2);
+--enable_info
+update t1 set j = 2;
+--disable_info
+drop table t1;
+
+#
+# Bug #32440 InnoDB free space info does not appear in SHOW TABLE STATUS or
+# I_S
+#
+create table t1 (id int) comment='this is a comment' engine=innodb;
+select table_comment, data_free > 0 as data_free_is_set
+ from information_schema.tables
+ where table_schema='test' and table_name = 't1';
+drop table t1;
+
+#
+# Bug 34920 test
+#
+CONNECTION default;
+CREATE TABLE t1 (
+ c1 INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ c2 VARCHAR(128) NOT NULL,
+ PRIMARY KEY(c1)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=100;
+
+CREATE TABLE t2 (
+ c1 INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ c2 INT(10) UNSIGNED DEFAULT NULL,
+ PRIMARY KEY(c1)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=200;
+
+SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE table_name = 't2';
+ALTER TABLE t2 ADD CONSTRAINT t1_t2_1 FOREIGN KEY(c1) REFERENCES t1(c1);
+SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE table_name = 't2';
+DROP TABLE t2;
+DROP TABLE t1;
+# End 34920 test
+#
+# Bug #29507 TRUNCATE shows to many rows effected
+#
+CONNECTION default;
+CREATE TABLE t1 (c1 int default NULL,
+ c2 int default NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--enable_info
+TRUNCATE TABLE t1;
+
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);
+TRUNCATE TABLE t1;
+
+--disable_info
+DROP TABLE t1;
+#
+# Bug#35537 Innodb doesn't increment handler_update and handler_delete.
+#
+-- disable_query_log
+-- disable_result_log
+
+CONNECT (c1,localhost,root,,);
+
+DROP TABLE IF EXISTS bug35537;
+CREATE TABLE bug35537 (
+ c1 int
+) ENGINE=InnoDB;
+
+INSERT INTO bug35537 VALUES (1);
+
+-- enable_result_log
+
+SHOW SESSION STATUS LIKE 'Handler_update%';
+SHOW SESSION STATUS LIKE 'Handler_delete%';
+
+UPDATE bug35537 SET c1 = 2 WHERE c1 = 1;
+DELETE FROM bug35537 WHERE c1 = 2;
+
+SHOW SESSION STATUS LIKE 'Handler_update%';
+SHOW SESSION STATUS LIKE 'Handler_delete%';
+
+DROP TABLE bug35537;
+
+DISCONNECT c1;
+CONNECTION default;
#######################################################################
# #
=== added file 'mysql-test/t/innodb_bug34053.test'
--- a/mysql-test/t/innodb_bug34053.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/innodb_bug34053.test 2008-06-12 00:08:07 +0000
@@ -0,0 +1,50 @@
+#
+# Make sure http://bugs.mysql.com/34053 remains fixed.
+#
+
+-- source include/not_embedded.inc
+-- source include/have_innodb.inc
+
+SET storage_engine=InnoDB;
+
+# we do not really care about what gets printed, we are only
+# interested in getting success or failure according to our
+# expectations
+-- disable_query_log
+-- disable_result_log
+
+GRANT USAGE ON *.* TO 'shane'@'localhost' IDENTIFIED BY '12345';
+FLUSH PRIVILEGES;
+
+-- connect (con1,localhost,shane,12345,)
+
+-- connection con1
+-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
+CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;
+-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
+CREATE TABLE innodb_mem_validate (a INT) ENGINE=INNODB;
+CREATE TABLE innodb_monitorx (a INT) ENGINE=INNODB;
+DROP TABLE innodb_monitorx;
+CREATE TABLE innodb_monito (a INT) ENGINE=INNODB;
+DROP TABLE innodb_monito;
+CREATE TABLE xinnodb_monitor (a INT) ENGINE=INNODB;
+DROP TABLE xinnodb_monitor;
+CREATE TABLE nnodb_monitor (a INT) ENGINE=INNODB;
+DROP TABLE nnodb_monitor;
+
+-- connection default
+CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;
+CREATE TABLE innodb_mem_validate (a INT) ENGINE=INNODB;
+
+-- connection con1
+-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
+DROP TABLE innodb_monitor;
+-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
+DROP TABLE innodb_mem_validate;
+
+-- connection default
+DROP TABLE innodb_monitor;
+DROP TABLE innodb_mem_validate;
+DROP USER 'shane'@'localhost';
+
+-- disconnect con1
=== added file 'mysql-test/t/innodb_bug34300.test'
--- a/mysql-test/t/innodb_bug34300.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/innodb_bug34300.test 2008-06-12 00:08:07 +0000
@@ -0,0 +1,30 @@
+#
+# Bug#34300 Tinyblob & tinytext fields currupted after export/import and alter in 5.1
+# http://bugs.mysql.com/34300
+#
+
+-- source include/have_innodb.inc
+
+-- disable_query_log
+-- disable_result_log
+
+SET @@max_allowed_packet=16777216;
+
+DROP TABLE IF EXISTS bug34300;
+CREATE TABLE bug34300 (
+ f4 TINYTEXT,
+ f6 MEDIUMTEXT,
+ f8 TINYBLOB
+) ENGINE=InnoDB;
+
+INSERT INTO bug34300 VALUES ('xxx', repeat('a', 8459264), 'zzz');
+
+-- enable_result_log
+
+SELECT f4, f8 FROM bug34300;
+
+ALTER TABLE bug34300 ADD COLUMN (f10 INT);
+
+SELECT f4, f8 FROM bug34300;
+
+DROP TABLE bug34300;
=== added file 'mysql-test/t/innodb_bug35220.test'
--- a/mysql-test/t/innodb_bug35220.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/innodb_bug35220.test 2008-06-12 00:08:07 +0000
@@ -0,0 +1,16 @@
+#
+# Bug#35220 ALTER TABLE too picky on reserved word "foreign"
+# http://bugs.mysql.com/35220
+#
+
+-- source include/have_innodb.inc
+
+SET storage_engine=InnoDB;
+
+# we care only that the following SQL commands do not produce errors
+-- disable_query_log
+-- disable_result_log
+
+CREATE TABLE bug35220 (foreign_col INT, dummy_cant_delete_all_columns INT);
+ALTER TABLE bug35220 DROP foreign_col;
+DROP TABLE bug35220;
=== modified file 'mysql-test/t/mysql_delimiter.sql'
--- a/mysql-test/t/mysql_delimiter.sql 2006-11-22 06:27:06 +0000
+++ b/mysql-test/t/mysql_delimiter.sql 2008-06-20 16:58:14 +0000
@@ -59,3 +59,9 @@ source t/mysql_delimiter_19799.sql
use test//
show tables//
delimiter ; # Reset delimiter
+
+#
+# Bug #33812: mysql client incorrectly parsing DELIMITER
+#
+select a as delimiter from t1
+delimiter ; # Reset delimiter
=== modified file 'mysql-test/t/partition_innodb.test'
--- a/mysql-test/t/partition_innodb.test 2008-03-27 19:02:15 +0000
+++ b/mysql-test/t/partition_innodb.test 2008-06-12 00:08:07 +0000
@@ -20,6 +20,7 @@ DROP TABLE t1;
# Bug #14673: Wrong InnoDB default row format
#
create table t1 (a int) engine=innodb partition by hash(a) ;
+--replace_column 10 <datafree>
show table status like 't1';
drop table t1;
@@ -29,18 +30,23 @@ drop table t1;
create table t1 (a int)
engine = innodb
partition by key (a);
+--replace_column 10 <datafree>
show table status;
insert into t1 values (0), (1), (2), (3);
+--replace_column 10 <datafree>
show table status;
drop table t1;
create table t1 (a int auto_increment primary key)
engine = innodb
partition by key (a);
+--replace_column 10 <datafree>
show table status;
insert into t1 values (NULL), (NULL), (NULL), (NULL);
+--replace_column 10 <datafree>
show table status;
insert into t1 values (NULL), (NULL), (NULL), (NULL);
+--replace_column 10 <datafree>
show table status;
drop table t1;
=== modified file 'mysql-test/t/subselect.test'
--- a/mysql-test/t/subselect.test 2008-05-22 18:40:15 +0000
+++ b/mysql-test/t/subselect.test 2008-06-20 19:24:46 +0000
@@ -3422,6 +3422,19 @@ SELECT * FROM t1 WHERE _utf8'a' = ANY (S
DROP TABLE t1;
#
+# Bug #37004: NOT IN subquery with MAX over an empty set
+#
+
+CREATE TABLE t1(c int, KEY(c));
+CREATE TABLE t2(a int, b int);
+INSERT INTO t2 VALUES (1, 10), (2, NULL);
+INSERT INTO t1 VALUES (1), (3);
+
+SELECT * FROM t2 WHERE b NOT IN (SELECT max(t.c) FROM t1, t1 t WHERE t.c>10);
+
+DROP TABLE t1,t2;
+
+#
# Bug#33204: INTO is allowed in subselect, causing inconsistent results
#
CREATE TABLE t1( a INT );
=== modified file 'scripts/make_binary_distribution.sh'
--- a/scripts/make_binary_distribution.sh 2008-05-13 13:58:07 +0000
+++ b/scripts/make_binary_distribution.sh 2008-06-18 03:30:29 +0000
@@ -14,36 +14,61 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-# This is a script to create a TAR or ZIP binary distribution out of a
-# built source tree. The output file will be put at the top level of
-# the source tree, as "mysql-<vsn>....{tar.gz,zip}"
+##############################################################################
#
-# The temporary directory path given to "--tmp=<path>" has to be
-# absolute and with no spaces.
+# This is a script to create a TAR or ZIP binary distribution out of a
+# built source tree. The output file will be put at the top level of
+# the source tree, as "mysql-<vsn>....{tar.gz,zip}"
+#
+# Note that the structure created by this script is slightly different from
+# what a normal "make install" would produce. No extra "mysql" sub directory
+# will be created, i.e. no "$prefix/include/mysql", "$prefix/lib/mysql" or
+# "$prefix/share/mysql". This is because the build system explicitly calls
+# make with pkgdatadir=<datadir>, etc.
+#
+# In GNU make/automake terms
+#
+# "pkglibdir" is set to the same as "libdir"
+# "pkgincludedir" is set to the same as "includedir"
+# "pkgdatadir" is set to the same as "datadir"
+# "pkgplugindir" is set to "$pkglibdir/plugin"
+# "pkgsuppdir" is set to "@prefix@/support-files",
+# normally the same as "datadir"
+#
+# The temporary directory path given to "--tmp=<path>" has to be
+# absolute and with no spaces.
+#
+# Note that for best result, the original "make" should be done with
+# the same arguments as used for "make install" below, especially the
+# 'pkglibdir', as the RPATH should to be set correctly.
+#
+##############################################################################
+
+##############################################################################
+#
+# Read the command line arguments that control this script
+#
+##############################################################################
machine=@MACHINE_TYPE@
system=@SYSTEM_TYPE@
-version=@VERSION@
SOURCE=`pwd`
CP="cp -p"
MV="mv"
-STRIP=1
-DEBUG=0
+STRIP=1 # Option ignored
SILENT=0
-MACHINE=""
PLATFORM=""
TMP=/tmp
SUFFIX=""
-NDBCLUSTER=""
+NDBCLUSTER="" # Option ignored
for arg do
case "$arg" in
- --debug) DEBUG=1;;
--tmp=*) TMP=`echo "$arg" | sed -e "s;--tmp=;;"` ;;
--suffix=*) SUFFIX=`echo "$arg" | sed -e "s;--suffix=;;"` ;;
--no-strip) STRIP=0 ;;
- --machine=*) MACHINE=`echo "$arg" | sed -e "s;--machine=;;"` ;;
+ --machine=*) machine=`echo "$arg" | sed -e "s;--machine=;;"` ;;
--platform=*) PLATFORM=`echo "$arg" | sed -e "s;--platform=;;"` ;;
--silent) SILENT=1 ;;
--with-ndbcluster) NDBCLUSTER=1 ;;
@@ -54,53 +79,52 @@ for arg do
esac
done
-# Remove vendor from $system
-system=`echo $system | sed -e 's/[a-z]*-\(.*\)/\1/g'`
-
-# Map OS names to "our" OS names (eg. darwin6.8 -> osx10.2)
-system=`echo $system | sed -e 's/darwin6.*/osx10.2/g'`
-system=`echo $system | sed -e 's/darwin7.*/osx10.3/g'`
-system=`echo $system | sed -e 's/darwin8.*/osx10.4/g'`
-system=`echo $system | sed -e 's/\(aix4.3\).*/\1/g'`
-system=`echo $system | sed -e 's/\(aix5.1\).*/\1/g'`
-system=`echo $system | sed -e 's/\(aix5.2\).*/\1/g'`
-system=`echo $system | sed -e 's/\(aix5.3\).*/\1/g'`
-system=`echo $system | sed -e 's/osf5.1b/tru64/g'`
-system=`echo $system | sed -e 's/linux-gnu/linux/g'`
-system=`echo $system | sed -e 's/solaris2.\([0-9]*\)/solaris\1/g'`
-system=`echo $system | sed -e 's/sco3.2v\(.*\)/openserver\1/g'`
+# ----------------------------------------------------------------------
+# Adjust "system" output from "uname" to be more human readable
+# ----------------------------------------------------------------------
+
+if [ x"$PLATFORM" = x"" ] ; then
+ # FIXME move this to the build tools
+ # Remove vendor from $system
+ system=`echo $system | sed -e 's/[a-z]*-\(.*\)/\1/g'`
+
+ # Map OS names to "our" OS names (eg. darwin6.8 -> osx10.2)
+ system=`echo $system | sed -e 's/darwin6.*/osx10.2/g'`
+ system=`echo $system | sed -e 's/darwin7.*/osx10.3/g'`
+ system=`echo $system | sed -e 's/darwin8.*/osx10.4/g'`
+ system=`echo $system | sed -e 's/\(aix4.3\).*/\1/g'`
+ system=`echo $system | sed -e 's/\(aix5.1\).*/\1/g'`
+ system=`echo $system | sed -e 's/\(aix5.2\).*/\1/g'`
+ system=`echo $system | sed -e 's/\(aix5.3\).*/\1/g'`
+ system=`echo $system | sed -e 's/osf5.1b/tru64/g'`
+ system=`echo $system | sed -e 's/linux-gnu/linux/g'`
+ system=`echo $system | sed -e 's/solaris2.\([0-9]*\)/solaris\1/g'`
+ system=`echo $system | sed -e 's/sco3.2v\(.*\)/openserver\1/g'`
-if [ x"$MACHINE" != x"" ] ; then
- machine=$MACHINE
+ PLATFORM="$system-$machine"
fi
-if [ x"$PLATFORM" != x"" ] ; then
- platform="$PLATFORM"
-else
- platform="$system-$machine"
-fi
+# Print the platform name for build logs
+echo "PLATFORM NAME: $PLATFORM"
+
+case $PLATFORM in
+ *netware*) BASE_SYSTEM="netware" ;;
+esac
-# FIXME This should really be integrated with automake and not duplicate the
-# installation list.
+# Change the distribution to a long descriptive name
+NEW_NAME=mysql@MYSQL_SERVER_SUFFIX@-@VERSION@-$PLATFORM$SUFFIX
+# ----------------------------------------------------------------------
+# Define BASE, and remove the old BASE directory if any
+# ----------------------------------------------------------------------
BASE=$TMP/my_dist$SUFFIX
-
if [ -d $BASE ] ; then
rm -rf $BASE
fi
-BS=""
-BIN_FILES=""
-BASE_SYSTEM="any"
-MYSQL_SHARE=$BASE/share/mysql
-
-case $system in
- *netware*)
- BASE_SYSTEM="netware"
- BS=".nlm"
- MYSQL_SHARE=$BASE/share
- ;;
-esac
+# ----------------------------------------------------------------------
+# Find the TAR to use
+# ----------------------------------------------------------------------
# This is needed to prefer GNU tar over platform tar because that can't
# always handle long filenames
@@ -127,24 +151,149 @@ which_1 ()
}
tar=`which_1 gnutar gtar`
-if [ "$?" = "1" -o x"$tar" = x"" ] ; then
+if [ $? -ne 0 -o x"$tar" = x"" ] ; then
tar=tar
fi
+##############################################################################
+#
+# Handle the Unix/Linux packaging using "make install"
+#
+##############################################################################
+
+if [ x"$BASE_SYSTEM" != x"netware" ] ; then
+
+ # ----------------------------------------------------------------------
+ # Terminate on any base level error
+ # ----------------------------------------------------------------------
+ set -e
+
+ # ----------------------------------------------------------------------
+ # Really ugly, one script, "mysql_install_db", needs prefix set to ".",
+ # i.e. makes access relative the current directory. This matches
+ # the documentation, so better not change this. And for another script,
+ # "mysql.server", we make some relative, others not.
+ # ----------------------------------------------------------------------
+
+ cd scripts
+ rm -f mysql_install_db
+ @MAKE@ mysql_install_db \
+ prefix=. \
+ bindir=./bin \
+ sbindir=./bin \
+ scriptdir=./bin \
+ libexecdir=./bin \
+ pkgdatadir=./share \
+ localstatedir=./data
+ cd ..
+
+ cd support-files
+ rm -f mysql.server
+ @MAKE@ mysql.server \
+ bindir=./bin \
+ sbindir=./bin \
+ scriptdir=./bin \
+ libexecdir=./bin \
+ pkgdatadir=@pkgdatadir@
+ cd ..
+
+ # ----------------------------------------------------------------------
+ # Do a install that we later are to pack. Use the same paths as in
+ # the build for the relevant directories.
+ # ----------------------------------------------------------------------
+ @MAKE@ DESTDIR=$BASE install \
+ pkglibdir=@pkglibdir@ \
+ pkgincludedir=@pkgincludedir@ \
+ pkgdatadir=@pkgdatadir@ \
+ pkgplugindir=@pkgplugindir@ \
+ pkgsuppdir=@pkgsuppdir@ \
+ mandir=@mandir@ \
+ infodir=@infodir@
+
+ # ----------------------------------------------------------------------
+ # Rename top directory, and set DEST to the new directory
+ # ----------------------------------------------------------------------
+ mv $BASE@prefix@ $BASE/$NEW_NAME
+ DEST=$BASE/$NEW_NAME
+
+ # ----------------------------------------------------------------------
+ # If we compiled with gcc, copy libgcc.a to the dist as libmygcc.a
+ # ----------------------------------------------------------------------
+ if [ x"@GXX@" = x"yes" ] ; then
+ gcclib=`@CC@ @CFLAGS@ --print-libgcc-file 2>/dev/null` || true
+ if [ -z "$gcclib" ] ; then
+ echo "Warning: Compiler doesn't tell libgcc.a!"
+ elif [ -f "$gcclib" ] ; then
+ $CP $gcclib $DEST/lib/libmygcc.a
+ else
+ echo "Warning: Compiler result '$gcclib' not found / no file!"
+ fi
+ fi
+
+ # FIXME let this script be in "bin/", where it is in the RPMs?
+ # http://dev.mysql.com/doc/refman/5.1/en/mysql-install-db-problems.html
+ mkdir $DEST/scripts
+ mv $DEST/bin/mysql_install_db $DEST/scripts/
+
+ # Note, no legacy "safe_mysqld" link to "mysqld_safe" in 5.1
+
+ # Copy readme and license files
+ cp README Docs/INSTALL-BINARY $DEST/
+ if [ -f COPYING -a -f EXCEPTIONS-CLIENT ] ; then
+ cp COPYING EXCEPTIONS-CLIENT $DEST/
+ elif [ -f LICENSE.mysql ] ; then
+ cp LICENSE.mysql $DEST/
+ else
+ echo "ERROR: no license files found"
+ exit 1
+ fi
+
+ # FIXME should be handled by make file, and to other dir
+ mkdir -p $DEST/bin $DEST/support-files
+ cp scripts/mysqlaccess.conf $DEST/bin/
+ cp support-files/magic $DEST/support-files/
+
+ # Create empty data directories, set permission (FIXME why?)
+ mkdir $DEST/data $DEST/data/mysql $DEST/data/test
+ chmod o-rwx $DEST/data $DEST/data/mysql $DEST/data/test
+
+ # ----------------------------------------------------------------------
+ # Create the result tar file
+ # ----------------------------------------------------------------------
+
+ echo "Using $tar to create archive"
+ OPT=cvf
+ if [ x$SILENT = x1 ] ; then
+ OPT=cf
+ fi
+
+ echo "Creating and compressing archive"
+ rm -f $NEW_NAME.tar.gz
+ (cd $BASE ; $tar $OPT - $NEW_NAME) | gzip -9 > $NEW_NAME.tar.gz
+ echo "$NEW_NAME.tar.gz created"
+
+ echo "Removing temporary directory"
+ rm -rf $BASE
+ exit 0
+fi
+
+
+##############################################################################
+#
+# Handle the Netware case, until integrated above
+#
+##############################################################################
+
+BS=".nlm"
+MYSQL_SHARE=$BASE/share
+
mkdir $BASE $BASE/bin $BASE/docs \
$BASE/include $BASE/lib $BASE/support-files $BASE/share $BASE/scripts \
$BASE/mysql-test $BASE/mysql-test/t $BASE/mysql-test/r \
$BASE/mysql-test/include $BASE/mysql-test/std_data $BASE/mysql-test/lib \
$BASE/mysql-test/suite
-if [ $BASE_SYSTEM != "netware" ] ; then
- mkdir $BASE/share/mysql $BASE/tests $BASE/sql-bench $BASE/man \
- $BASE/man/man1 $BASE/man/man8 $BASE/data $BASE/data/mysql $BASE/data/test
-
- chmod o-rwx $BASE/data $BASE/data/*
-fi
-
# Copy files if they exists, warn for those that don't.
# Note that when listing files to copy, we might list the file name
# twice, once in the directory location where it is built, and a
@@ -176,12 +325,13 @@ copyfileto $BASE COPYING COPYING.LIB REA
BIN_FILES="extra/comp_err$BS extra/replace$BS extra/perror$BS \
extra/resolveip$BS extra/my_print_defaults$BS \
extra/resolve_stack_dump$BS extra/mysql_waitpid$BS \
- myisam/myisamchk$BS myisam/myisampack$BS myisam/myisamlog$BS \
- myisam/myisam_ftdump$BS \
+ storage/myisam/myisamchk$BS storage/myisam/myisampack$BS \
+ storage/myisam/myisamlog$BS storage/myisam/myisam_ftdump$BS \
sql/mysqld$BS sql/mysqld-debug$BS \
sql/mysql_tzinfo_to_sql$BS \
server-tools/instance-manager/mysqlmanager$BS \
client/mysql$BS client/mysqlshow$BS client/mysqladmin$BS \
+ client/mysqlslap$BS \
client/mysqldump$BS client/mysqlimport$BS \
client/mysqltest$BS client/mysqlcheck$BS \
client/mysqlbinlog$BS client/mysql_upgrade$BS \
@@ -191,42 +341,16 @@ BIN_FILES="extra/comp_err$BS extra/repla
";
# Platform-specific bin dir files:
-if [ $BASE_SYSTEM = "netware" ] ; then
- BIN_FILES="$BIN_FILES \
+BIN_FILES="$BIN_FILES \
netware/mysqld_safe$BS netware/mysql_install_db$BS \
- netware/init_db.sql netware/test_db.sql netware/mysql_explain_log$BS \
+ netware/init_db.sql netware/test_db.sql \
netware/mysqlhotcopy$BS netware/libmysql$BS netware/init_secure_db.sql \
";
-# For all other platforms:
-else
- BIN_FILES="$BIN_FILES \
- server-tools/instance-manager/.libs/mysqlmanager \
- client/mysqltestmanagerc \
- client/mysqltestmanager-pwgen tools/mysqltestmanager \
- client/.libs/mysql client/.libs/mysqlshow client/.libs/mysqladmin \
- client/.libs/mysqldump client/.libs/mysqlimport \
- client/.libs/mysqltest client/.libs/mysqlcheck \
- client/.libs/mysqlbinlog client/.libs/mysqltestmanagerc \
- client/.libs/mysqltestmanager-pwgen tools/.libs/mysqltestmanager \
- tests/.libs/mysql_client_test \
- libmysqld/examples/.libs/mysql_client_test_embedded \
- libmysqld/examples/.libs/mysqltest_embedded \
- ";
-fi
copyfileto $BASE/bin $BIN_FILES
-if [ x$STRIP = x1 ] ; then
- strip $BASE/bin/*
-fi
-
-# Copy not binary files
-copyfileto $BASE/bin sql/mysqld.sym.gz
-
-if [ $BASE_SYSTEM = "netware" ] ; then
- $CP netware/*.pl $BASE/scripts
- $CP scripts/mysqlhotcopy $BASE/scripts/mysqlhotcopy.pl
-fi
+$CP netware/*.pl $BASE/scripts
+$CP scripts/mysqlhotcopy $BASE/scripts/mysqlhotcopy.pl
copyfileto $BASE/lib \
libmysql/.libs/libmysqlclient.a \
@@ -248,31 +372,17 @@ copyfileto $BASE/lib \
zlib/.libs/libz.a
# convert the .a to .lib for NetWare
-if [ $BASE_SYSTEM = "netware" ] ; then
- for i in $BASE/lib/*.a
- do
- libname=`basename $i .a`
- $MV $i $BASE/lib/$libname.lib
- done
- rm -f $BASE/lib/*.la
-fi
+for i in $BASE/lib/*.a
+do
+ libname=`basename $i .a`
+ $MV $i $BASE/lib/$libname.lib
+done
+rm -f $BASE/lib/*.la
-copyfileto $BASE/include include/*
-rm -f $BASE/include/Makefile* $BASE/include/*.in $BASE/include/config-win.h
-if [ $BASE_SYSTEM != "netware" ] ; then
- rm -f $BASE/include/config-netware.h
-fi
+copyfileto $BASE/include config.h include/*
-if [ $BASE_SYSTEM != "netware" ] ; then
- if [ -d tests ] ; then
- $CP tests/*.res tests/*.tst tests/*.pl $BASE/tests
- fi
- if [ -d man ] ; then
- $CP man/*.1 $BASE/man/man1
- $CP man/*.8 $BASE/man/man8
- fi
-fi
+rm -f $BASE/include/Makefile* $BASE/include/*.in $BASE/include/config-win.h
copyfileto $BASE/support-files support-files/*
@@ -291,43 +401,29 @@ copyfileto $BASE/mysql-test \
$CP mysql-test/lib/*.pl $BASE/mysql-test/lib
$CP mysql-test/t/*.def $BASE/mysql-test/t
$CP mysql-test/include/*.inc $BASE/mysql-test/include
+$CP mysql-test/include/*.sql $BASE/mysql-test/include
$CP mysql-test/include/*.test $BASE/mysql-test/include
$CP mysql-test/t/*.def $BASE/mysql-test/t
+$CP mysql-test/std_data/*.dat mysql-test/std_data/*.frm \
+ mysql-test/std_data/*.MYD mysql-test/std_data/*.MYI \
+ mysql-test/std_data/*.pem mysql-test/std_data/Moscow_leap \
+ mysql-test/std_data/Index.xml \
+ mysql-test/std_data/des_key_file mysql-test/std_data/*.*001 \
+ mysql-test/std_data/*.cnf mysql-test/std_data/*.MY* \
+ $BASE/mysql-test/std_data
$CP mysql-test/t/*.test mysql-test/t/*.imtest \
mysql-test/t/*.disabled mysql-test/t/*.opt \
mysql-test/t/*.slave-mi mysql-test/t/*.sh mysql-test/t/*.sql $BASE/mysql-test/t
$CP mysql-test/r/*.result mysql-test/r/*.require \
$BASE/mysql-test/r
-# Copy the additional suites and data "as is", they are in flux
-$tar cf - mysql-test/suite | ( cd $BASE ; $tar xf - )
-$tar cf - mysql-test/std_data | ( cd $BASE ; $tar xf - )
+# Copy the additional suites "as is", they are in flux
+$tar cf - mysql-test/suite | ( cd $BASE ; $tar xf - )
# Clean up if we did this from a bk tree
if [ -d mysql-test/SCCS ] ; then
find $BASE/mysql-test -name SCCS -print | xargs rm -rf
fi
-if [ $BASE_SYSTEM != "netware" ] ; then
- chmod a+x $BASE/bin/*
- copyfileto $BASE/bin scripts/*
- $BASE/bin/replace \@localstatedir\@ ./data \@bindir\@ ./bin \@scriptdir\@ \
- ./bin \@libexecdir\@ ./bin \@sbindir\@ ./bin \@prefix\@ . \@HOSTNAME\@ \
- @HOSTNAME@ \@pkgdatadir\@ ./share \
- < scripts/mysql_install_db.sh > $BASE/scripts/mysql_install_db
- $BASE/bin/replace \@prefix\@ /usr/local/mysql \@bindir\@ ./bin \
- \@sbindir\@ ./bin \@libexecdir\@ ./bin \
- \@MYSQLD_USER\@ @MYSQLD_USER@ \@localstatedir\@ /usr/local/mysql/data \
- \@HOSTNAME\@ @HOSTNAME@ \
- < support-files/mysql.server.sh > $BASE/support-files/mysql.server
- $BASE/bin/replace /my/gnu/bin/hostname /bin/hostname -- $BASE/bin/mysqld_safe
- mv $BASE/support-files/binary-configure $BASE/configure
- chmod a+x $BASE/bin/* $BASE/scripts/* $BASE/support-files/mysql-log-rotate \
- $BASE/support-files/*.server $BASE/configure
- $CP -r sql-bench/* $BASE/sql-bench
- rm -f $BASE/sql-bench/*.sh $BASE/sql-bench/Makefile* $BASE/lib/*.la
- rm -f $BASE/bin/*.sql
-fi
-
rm -f $BASE/bin/Makefile* $BASE/bin/*.in $BASE/bin/*.sh \
$BASE/bin/mysql_install_db $BASE/bin/make_binary_distribution \
$BASE/bin/setsomevars $BASE/support-files/Makefile* \
@@ -336,29 +432,19 @@ rm -f $BASE/bin/Makefile* $BASE/bin/*.in
#
# Copy system dependent files
#
-if [ $BASE_SYSTEM = "netware" ] ; then
- ./scripts/fill_help_tables < ./Docs/manual.texi >> ./netware/init_db.sql
-fi
+./scripts/fill_help_tables < ./Docs/manual.texi >> ./netware/init_db.sql
#
# Remove system dependent files
#
-if [ $BASE_SYSTEM = "netware" ] ; then
- rm -f $BASE/support-files/magic \
+rm -f $BASE/support-files/magic \
$BASE/support-files/mysql.server \
$BASE/support-files/mysql*.spec \
$BASE/support-files/mysql-log-rotate \
$BASE/support-files/binary-configure \
$BASE/support-files/build-tags \
$BASE/support-files/MySQL-shared-compat.spec \
- $BASE/support-files/ndb-config-2-node.ini \
$BASE/INSTALL-BINARY
-fi
-
-# Make safe_mysqld a symlink to mysqld_safe for backwards portability
-if [ $BASE_SYSTEM != "netware" ] ; then
- (cd $BASE/bin ; ln -s mysqld_safe safe_mysqld )
-fi
# Clean up if we did this from a bk tree
if [ -d $BASE/sql-bench/SCCS ] ; then
@@ -366,78 +452,17 @@ if [ -d $BASE/sql-bench/SCCS ] ; then
find $BASE/sql-bench -name SCCS -print | xargs rm -rf
fi
-# NDB Cluster
-if [ x$NDBCLUSTER = x1 ]; then
- ( cd ndb ; @MAKE@ DESTDIR=$BASE/ndb-stage install )
- ( cd mysql-test/ndb ; @MAKE@ DESTDIR=$BASE/ndb-stage install )
- $CP $BASE/ndb-stage@bindir@/* $BASE/bin/.
- $CP $BASE/ndb-stage@libexecdir@/* $BASE/bin/.
- $CP $BASE/ndb-stage@pkglibdir@/* $BASE/lib/.
- $CP $BASE/ndb-stage@pkgdatadir@/* $BASE/share/mysql/.
- $CP -r $BASE/ndb-stage@pkgincludedir@/ndb $BASE/include
- $CP -r $BASE/ndb-stage@prefix@/mysql-test/ndb $BASE/mysql-test/. || exit 1
- rm -rf $BASE/ndb-stage
-fi
-
-# Change the distribution to a long descriptive name
-NEW_NAME=mysql@MYSQL_SERVER_SUFFIX@-$version-$platform$SUFFIX
-
-# Print the platform name for build logs
-echo "PLATFORM NAME: $platform"
-
BASE2=$TMP/$NEW_NAME
rm -rf $BASE2
mv $BASE $BASE2
BASE=$BASE2
+
#
-# If we are compiling with gcc, copy libgcc.a to the distribution as libmygcc.a
+# Create a zip file for NetWare users
#
-
-if [ x"@GXX@" = x"yes" ] ; then
- gcclib=`@CC@ @CFLAGS@ --print-libgcc-file 2>/dev/null` || true
- if [ -z "$gcclib" ] ; then
- echo "Warning: Compiler doesn't tell libgcc.a!"
- elif [ -f "$gcclib" ] ; then
- $CP $gcclib $BASE/lib/libmygcc.a
- else
- echo "Warning: Compiler result '$gcclib' not found / no file!"
- fi
-fi
-
-#if we are debugging, do not do tar/gz
-if [ x$DEBUG = x1 ] ; then
- exit
-fi
-
-if [ $BASE_SYSTEM != "netware" ] ; then
-
- #
- # Create the result tar file
- #
-
- echo "Using $tar to create archive"
-
- OPT=cvf
- if [ x$SILENT = x1 ] ; then
- OPT=cf
- fi
-
- echo "Creating and compressing archive"
- rm -f $NEW_NAME.tar.gz
- (cd $TMP ; $tar $OPT - $NEW_NAME) | gzip -9 > $NEW_NAME.tar.gz
- echo "$NEW_NAME.tar.gz created"
-
-else
-
- #
- # Create a zip file for NetWare users
- #
-
- rm -f $NEW_NAME.zip
- (cd $TMP; zip -r "$SOURCE/$NEW_NAME.zip" $NEW_NAME)
- echo "$NEW_NAME.zip created"
-
-fi
+rm -f $NEW_NAME.zip
+(cd $TMP; zip -r "$SOURCE/$NEW_NAME.zip" $NEW_NAME)
+echo "$NEW_NAME.zip created"
echo "Removing temporary directory"
rm -rf $BASE
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2008-05-08 16:01:15 +0000
+++ b/sql/slave.cc 2008-06-23 11:55:24 +0000
@@ -4024,6 +4024,7 @@ bool rpl_master_erroneous_autoinc(THD *t
if (active_mi && active_mi->rli.sql_thd == thd)
{
Relay_log_info *rli= &active_mi->rli;
+ DBUG_EXECUTE_IF("simulate_bug33029", return TRUE;);
return rpl_master_has_bug(rli, 33029, FALSE);
}
return FALSE;
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2008-05-27 19:47:15 +0000
+++ b/sql/sql_class.cc 2008-06-25 14:49:43 +0000
@@ -2960,8 +2960,8 @@ void THD::reset_sub_statement_state(Sub_
*/
if (rpl_master_erroneous_autoinc(this))
{
- backup->auto_inc_intervals_forced= auto_inc_intervals_forced;
- auto_inc_intervals_forced.empty();
+ DBUG_ASSERT(backup->auto_inc_intervals_forced.nb_elements() == 0);
+ auto_inc_intervals_forced.swap(&backup->auto_inc_intervals_forced);
}
#endif
@@ -3009,8 +3009,8 @@ void THD::restore_sub_statement_state(Su
*/
if (rpl_master_erroneous_autoinc(this))
{
- auto_inc_intervals_forced= backup->auto_inc_intervals_forced;
- backup->auto_inc_intervals_forced.empty();
+ backup->auto_inc_intervals_forced.swap(&auto_inc_intervals_forced);
+ DBUG_ASSERT(backup->auto_inc_intervals_forced.nb_elements() == 0);
}
#endif
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2008-05-08 16:01:15 +0000
+++ b/sql/sql_plugin.cc 2008-06-18 03:30:29 +0000
@@ -1146,9 +1146,10 @@ int plugin_init(int *argc, char **argv,
{
for (plugin= *builtins; plugin->info; plugin++)
{
- /* by default, only ndbcluster is disabled */
+ /* by default, ndbcluster and federated are disabled */
def_enabled=
- my_strcasecmp(&my_charset_latin1, plugin->name, "NDBCLUSTER") != 0;
+ my_strcasecmp(&my_charset_latin1, plugin->name, "NDBCLUSTER") != 0 &&
+ my_strcasecmp(&my_charset_latin1, plugin->name, "FEDERATED") != 0;
bzero(&tmp, sizeof(tmp));
tmp.plugin= plugin;
tmp.name.str= (char *)plugin->name;
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2008-05-23 05:03:07 +0000
+++ b/sql/sql_select.cc 2008-06-20 19:24:46 +0000
@@ -1479,6 +1479,7 @@ JOIN::optimize()
{
DBUG_PRINT("info",("No matching min/max row"));
zero_result_cause= "No matching min/max row";
+ tables= 0;
error=0;
DBUG_RETURN(0);
}
@@ -1492,6 +1493,7 @@ JOIN::optimize()
{
DBUG_PRINT("info",("No matching min/max row"));
zero_result_cause= "No matching min/max row";
+ tables= 0;
error=0;
DBUG_RETURN(0);
}
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2008-06-04 13:20:03 +0000
+++ b/sql/sql_table.cc 2008-06-25 14:49:43 +0000
@@ -3978,7 +3978,7 @@ static int prepare_for_repair(THD *thd,
if (table->s->frm_version != FRM_VER_TRUE_VARCHAR)
{
error= send_check_errmsg(thd, table_list, "repair",
- "Failed reparing incompatible .FRM file");
+ "Failed repairing incompatible .frm file");
goto end;
}
=== modified file 'sql/structs.h'
--- a/sql/structs.h 2008-04-01 15:13:57 +0000
+++ b/sql/structs.h 2008-06-23 11:55:24 +0000
@@ -320,31 +320,22 @@ private:
*/
Discrete_interval *current;
uint elements; // number of elements
-
- /* helper function for copy construct and assignment operator */
- void copy_(const Discrete_intervals_list& from)
- {
- for (Discrete_interval *i= from.head; i; i= i->next)
- {
- Discrete_interval j= *i;
- append(&j);
- }
+ void set_members(Discrete_interval *h, Discrete_interval *t,
+ Discrete_interval *c, uint el)
+ {
+ head= h;
+ tail= t;
+ current= c;
+ elements= el;
}
+ void operator=(Discrete_intervals_list &); /* prevent use of these */
+ Discrete_intervals_list(const Discrete_intervals_list &);
+
public:
Discrete_intervals_list() : head(NULL), current(NULL), elements(0) {};
- Discrete_intervals_list(const Discrete_intervals_list& from)
- {
- copy_(from);
- }
- void operator=(const Discrete_intervals_list& from)
- {
- empty();
- copy_(from);
- }
void empty_no_free()
{
- head= current= NULL;
- elements= 0;
+ set_members(NULL, NULL, NULL, 0);
}
void empty()
{
@@ -356,7 +347,24 @@ public:
}
empty_no_free();
}
-
+ void copy_shallow(const Discrete_intervals_list * dli)
+ {
+ head= dli->get_head();
+ tail= dli->get_tail();
+ current= dli->get_current();
+ elements= dli->nb_elements();
+ }
+ void swap (Discrete_intervals_list * dli)
+ {
+ Discrete_interval *h, *t, *c;
+ uint el;
+ h= dli->get_head();
+ t= dli->get_tail();
+ c= dli->get_current();
+ el= dli->nb_elements();
+ dli->copy_shallow(this);
+ set_members(h, t, c, el);
+ }
const Discrete_interval* get_next()
{
Discrete_interval *tmp= current;
@@ -370,4 +378,7 @@ public:
ulonglong minimum() const { return (head ? head->minimum() : 0); };
ulonglong maximum() const { return (head ? tail->maximum() : 0); };
uint nb_elements() const { return elements; }
+ Discrete_interval* get_head() const { return head; };
+ Discrete_interval* get_tail() const { return tail; };
+ Discrete_interval* get_current() const { return current; };
};
=== modified file 'storage/innobase/Makefile.am'
--- a/storage/innobase/Makefile.am 2008-05-14 09:24:14 +0000
+++ b/storage/innobase/Makefile.am 2008-06-20 19:24:46 +0000
@@ -15,21 +15,21 @@
# Process this file with automake to create Makefile.in
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-pkgplugindir = $(pkglibdir)/plugin
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
+MYSQLDATAdir= $(localstatedir)
+MYSQLSHAREdir= $(pkgdatadir)
+MYSQLBASEdir= $(prefix)
+MYSQLLIBdir= $(pkglibdir)
+pkgplugindir= $(pkglibdir)/plugin
+INCLUDES= -I$(top_srcdir)/include -I$(top_builddir)/include \
-I$(top_srcdir)/regex \
-I$(top_srcdir)/storage/innobase/include \
-I$(top_srcdir)/sql \
- -I$(srcdir)
+ -I$(srcdir)
-DEFS = @DEFS@
+DEFS= @DEFS@
-noinst_HEADERS = include/btr0btr.h include/btr0btr.ic \
+noinst_HEADERS= include/btr0btr.h include/btr0btr.ic \
include/btr0cur.h include/btr0cur.ic \
include/btr0pcur.h include/btr0pcur.ic \
include/btr0sea.h include/btr0sea.ic \
@@ -121,9 +121,9 @@ noinst_HEADERS = include/btr0btr.h inclu
include/ut0list.ic include/ut0wqueue.h \
include/ha_prototypes.h handler/ha_innodb.h
-EXTRA_LIBRARIES = libinnobase.a
-noinst_LIBRARIES = @plugin_innobase_static_target@
-libinnobase_a_SOURCES = btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c \
+EXTRA_LIBRARIES= libinnobase.a
+noinst_LIBRARIES= @plugin_innobase_static_target@
+libinnobase_a_SOURCES= btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c \
btr/btr0sea.c buf/buf0buf.c buf/buf0flu.c \
buf/buf0lru.c buf/buf0rea.c data/data0data.c \
data/data0type.c dict/dict0boot.c \
@@ -156,17 +156,17 @@ libinnobase_a_SOURCES = btr/btr0btr.c bt
handler/ha_innodb.cc
libinnobase_a_CXXFLAGS= $(AM_CFLAGS)
-libinnobase_a_CFLAGS = $(AM_CFLAGS)
+libinnobase_a_CFLAGS= $(AM_CFLAGS)
-EXTRA_LTLIBRARIES = ha_innodb.la
-pkglib_LTLIBRARIES = @plugin_innobase_shared_target@
+EXTRA_LTLIBRARIES= ha_innodb.la
+pkgplugin_LTLIBRARIES= @plugin_innobase_shared_target@
-ha_innodb_la_LDFLAGS = -module -rpath $(pkgplugindir)
-ha_innodb_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_innodb_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_innodb_la_SOURCES = $(libinnobase_a_SOURCES)
+ha_innodb_la_LDFLAGS= -module -rpath $(pkgplugindir)
+ha_innodb_la_CXXFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
+ha_innodb_la_CFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
+ha_innodb_la_SOURCES= $(libinnobase_a_SOURCES)
-EXTRA_DIST = CMakeLists.txt plug.in \
+EXTRA_DIST= CMakeLists.txt plug.in \
pars/make_bison.sh pars/make_flex.sh \
pars/pars0grm.y pars/pars0lex.l
=== modified file 'storage/innobase/btr/btr0cur.c'
--- a/storage/innobase/btr/btr0cur.c 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/btr/btr0cur.c 2008-06-12 00:08:07 +0000
@@ -52,7 +52,7 @@ can be released by page reorganize, then
#define BTR_CUR_PAGE_REORGANIZE_LIMIT (UNIV_PAGE_SIZE / 32)
-/* When estimating number of different kay values in an index sample
+/* When estimating number of different key values in an index, sample
this many index pages */
#define BTR_KEY_VAL_ESTIMATE_N_PAGES 8
=== modified file 'storage/innobase/buf/buf0buf.c'
--- a/storage/innobase/buf/buf0buf.c 2008-02-01 10:55:39 +0000
+++ b/storage/innobase/buf/buf0buf.c 2008-06-12 00:08:07 +0000
@@ -2328,7 +2328,6 @@ buf_print(void)
ut_a(buf_validate());
}
-#endif /* UNIV_DEBUG */
/*************************************************************************
Returns the number of latched pages in the buffer pool. */
@@ -2361,6 +2360,7 @@ buf_get_latched_pages_number(void)
return(fixed_pages_number);
}
+#endif /* UNIV_DEBUG */
/*************************************************************************
Returns the number of pending buf pool ios. */
=== modified file 'storage/innobase/dict/dict0dict.c'
--- a/storage/innobase/dict/dict0dict.c 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/dict/dict0dict.c 2008-06-12 00:08:07 +0000
@@ -429,7 +429,7 @@ void
dict_table_autoinc_initialize(
/*==========================*/
dict_table_t* table, /* in: table */
- ib_longlong value) /* in: next value to assign to a row */
+ ib_ulonglong value) /* in: next value to assign to a row */
{
ut_ad(mutex_own(&table->autoinc_mutex));
@@ -441,7 +441,7 @@ dict_table_autoinc_initialize(
Reads the next autoinc value (== autoinc counter value), 0 if not yet
initialized. */
-ib_longlong
+ib_ulonglong
dict_table_autoinc_read(
/*====================*/
/* out: value for a new row, or 0 */
@@ -470,7 +470,7 @@ dict_table_autoinc_update(
/*======================*/
dict_table_t* table, /* in: table */
- ib_longlong value) /* in: value which was assigned to a row */
+ ib_ulonglong value) /* in: value which was assigned to a row */
{
if (table->autoinc_inited && value > table->autoinc) {
@@ -3395,7 +3395,7 @@ loop:
ptr = dict_accept(cs, ptr, "FOREIGN", &success);
- if (!success) {
+ if (!success || !my_isspace(cs, *ptr)) {
goto loop;
}
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc 2008-05-22 18:40:15 +0000
+++ b/storage/innobase/handler/ha_innodb.cc 2008-06-12 00:08:07 +0000
@@ -135,7 +135,7 @@ static my_bool innobase_locks_unsafe_for
static my_bool innobase_rollback_on_timeout = FALSE;
static my_bool innobase_create_status_file = FALSE;
static my_bool innobase_stats_on_metadata = TRUE;
-static my_bool innobase_use_adaptive_hash_indexes = TRUE;
+static my_bool innobase_adaptive_hash_index = TRUE;
static char* internal_innobase_data_file_path = NULL;
@@ -340,8 +340,10 @@ static SHOW_VAR innodb_status_variables[
(char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG},
{"buffer_pool_pages_free",
(char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG},
+#ifdef UNIV_DEBUG
{"buffer_pool_pages_latched",
(char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG},
+#endif /* UNIV_DEBUG */
{"buffer_pool_pages_misc",
(char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
{"buffer_pool_pages_total",
@@ -606,7 +608,9 @@ convert_error_code_to_mysql(
tell it also to MySQL so that MySQL knows to empty the
cached binlog for this transaction */
- thd_mark_transaction_to_rollback(thd, TRUE);
+ if (thd) {
+ thd_mark_transaction_to_rollback(thd, TRUE);
+ }
return(HA_ERR_LOCK_DEADLOCK);
} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
@@ -615,8 +619,10 @@ convert_error_code_to_mysql(
latest SQL statement in a lock wait timeout. Previously, we
rolled back the whole transaction. */
- thd_mark_transaction_to_rollback(thd,
- (bool)row_rollback_on_timeout);
+ if (thd) {
+ thd_mark_transaction_to_rollback(
+ thd, (bool)row_rollback_on_timeout);
+ }
return(HA_ERR_LOCK_WAIT_TIMEOUT);
@@ -668,7 +674,9 @@ convert_error_code_to_mysql(
tell it also to MySQL so that MySQL knows to empty the
cached binlog for this transaction */
- thd_mark_transaction_to_rollback(thd, TRUE);
+ if (thd) {
+ thd_mark_transaction_to_rollback(thd, TRUE);
+ }
return(HA_ERR_LOCK_TABLE_FULL);
} else if (error == DB_TOO_MANY_CONCURRENT_TRXS) {
@@ -1635,7 +1643,7 @@ innobase_init(
srv_stats_on_metadata = (ibool) innobase_stats_on_metadata;
srv_use_adaptive_hash_indexes =
- (ibool) innobase_use_adaptive_hash_indexes;
+ (ibool) innobase_adaptive_hash_index;
srv_print_verbose_log = mysqld_embedded ? 0 : 1;
@@ -2283,6 +2291,8 @@ ha_innobase::open(
dict_table_t* ib_table;
char norm_name[1000];
THD* thd;
+ ulint retries = 0;
+ char* is_part = NULL;
DBUG_ENTER("ha_innobase::open");
@@ -2316,11 +2326,29 @@ ha_innobase::open(
DBUG_RETURN(1);
}
+ /* We look for pattern #P# to see if the table is partitioned
+ MySQL table. The retry logic for partitioned tables is a
+ workaround for http://bugs.mysql.com/bug.php?id=33349. Look
+ at support issue https://support.mysql.com/view.php?id=21080
+ for more details. */
+ is_part = strstr(norm_name, "#P#");
+retry:
/* Get pointer to a table object in InnoDB dictionary cache */
-
ib_table = dict_table_get(norm_name, TRUE);
-
+
if (NULL == ib_table) {
+ if (is_part && retries < 10) {
+ ++retries;
+ os_thread_sleep(100000);
+ goto retry;
+ }
+
+ if (is_part) {
+ sql_print_error("Failed to open table %s after "
+ "%lu attemtps.\n", norm_name,
+ retries);
+ }
+
sql_print_error("Cannot find or open table %s from\n"
"the internal data dictionary of InnoDB "
"though the .frm file for the\n"
@@ -3305,7 +3333,8 @@ ha_innobase::innobase_autoinc_lock(void)
old style only if another transaction has already acquired
the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
etc. type of statement. */
- if (thd_sql_command(user_thd) == SQLCOM_INSERT) {
+ if (thd_sql_command(user_thd) == SQLCOM_INSERT
+ || thd_sql_command(user_thd) == SQLCOM_REPLACE) {
dict_table_t* table = prebuilt->table;
/* Acquire the AUTOINC mutex. */
@@ -3576,7 +3605,19 @@ no_commit:
if (auto_inc > prebuilt->last_value) {
set_max_autoinc:
ut_a(prebuilt->table->autoinc_increment > 0);
- auto_inc += prebuilt->table->autoinc_increment;
+
+ ulonglong have;
+ ulonglong need;
+
+ /* Check for overflow conditions. */
+ need = prebuilt->table->autoinc_increment;
+ have = ~0x0ULL - auto_inc;
+
+ if (have < need) {
+ need = have;
+ }
+
+ auto_inc += need;
err = innobase_set_max_autoinc(auto_inc);
@@ -3771,6 +3812,8 @@ ha_innobase::update_row(
ut_a(prebuilt->trx == trx);
+ ha_statistic_increment(&SSV::ha_update_count);
+
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
@@ -3826,6 +3869,16 @@ ha_innobase::update_row(
error = convert_error_code_to_mysql(error, user_thd);
+ if (error == 0 /* success */
+ && uvect->n_fields == 0 /* no columns were updated */) {
+
+ /* This is the same as success, but instructs
+ MySQL that the row is not really updated and it
+ should not increase the count of updated rows.
+ This is fix for http://bugs.mysql.com/29157 */
+ error = HA_ERR_RECORD_IS_THE_SAME;
+ }
+
/* Tell InnoDB server that there might be work for
utility threads: */
@@ -3850,6 +3903,8 @@ ha_innobase::delete_row(
ut_a(prebuilt->trx == trx);
+ ha_statistic_increment(&SSV::ha_delete_count);
+
/* Only if the table has an AUTOINC column */
if (table->found_next_number_field && record == table->record[0]) {
ulonglong dummy = 0;
@@ -4653,6 +4708,12 @@ innodb_check_for_record_too_big_error(
}
}
+/* limit innodb monitor access to users with PROCESS privilege.
+See http://bugs.mysql.com/32710 for expl. why we choose PROCESS. */
+#define IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(table_name, thd) \
+ (row_is_magic_monitor_table(table_name) \
+ && check_global_access(thd, PROCESS_ACL))
+
/*********************************************************************
Creates a table definition to an InnoDB database. */
static
@@ -4689,6 +4750,12 @@ create_table_def(
DBUG_ENTER("create_table_def");
DBUG_PRINT("enter", ("table_name: %s", table_name));
+ ut_a(trx->mysql_thd != NULL);
+ if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(table_name,
+ (THD*) trx->mysql_thd)) {
+ DBUG_RETURN(HA_ERR_GENERIC);
+ }
+
n_cols = form->s->fields;
/* We pass 0 as the space id, and determine at a lower level the space
@@ -4967,6 +5034,29 @@ ha_innobase::create(
DBUG_ENTER("ha_innobase::create");
DBUG_ASSERT(thd != NULL);
+ DBUG_ASSERT(create_info != NULL);
+
+#ifdef __WIN__
+ /* Names passed in from server are in two formats:
+ 1. <database_name>/<table_name>: for normal table creation
+ 2. full path: for temp table creation, or sym link
+
+ When srv_file_per_table is on, check for full path pattern, i.e.
+ X:\dir\..., X is a driver letter, or
+ \\dir1\dir2\..., UNC path
+ returns error if it is in full path format, but not creating a temp.
+ table. Currently InnoDB does not support symbolic link on Windows. */
+
+ if (srv_file_per_table
+ && (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
+
+ if ((name[1] == ':')
+ || (name[0] == '\\' && name[1] == '\\')) {
+ sql_print_error("Cannot create table %s\n", name);
+ DBUG_RETURN(HA_ERR_GENERIC);
+ }
+ }
+#endif
if (form->s->fields > 1000) {
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
@@ -5101,8 +5191,15 @@ ha_innobase::create(
DBUG_ASSERT(innobase_table != 0);
- if ((create_info->used_fields & HA_CREATE_USED_AUTO) &&
- (create_info->auto_increment_value != 0)) {
+ /* Note: We can't call update_thd() as prebuilt will not be
+ setup at this stage and so we use thd. */
+
+ /* We need to copy the AUTOINC value from the old table if
+ this is an ALTER TABLE. */
+
+ if (((create_info->used_fields & HA_CREATE_USED_AUTO)
+ || thd_sql_command(thd) == SQLCOM_ALTER_TABLE)
+ && create_info->auto_increment_value != 0) {
/* Query was ALTER TABLE...AUTO_INCREMENT = x; or
CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
@@ -5229,6 +5326,14 @@ ha_innobase::delete_table(
DBUG_ENTER("ha_innobase::delete_table");
+ /* Strangely, MySQL passes the table name without the '.frm'
+ extension, in contrast to ::create */
+ normalize_table_name(norm_name, name);
+
+ if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(norm_name, thd)) {
+ DBUG_RETURN(HA_ERR_GENERIC);
+ }
+
/* Get the transaction associated with the current thd, or create one
if not yet created */
@@ -5262,11 +5367,6 @@ ha_innobase::delete_table(
assert(name_len < 1000);
- /* Strangely, MySQL passes the table name without the '.frm'
- extension, in contrast to ::create */
-
- normalize_table_name(norm_name, name);
-
/* Drop the table in InnoDB */
error = row_drop_table_for_mysql(norm_name, trx,
@@ -5756,6 +5856,13 @@ ha_innobase::info(
n_rows++;
}
+ /* Fix bug#29507: TRUNCATE shows too many rows affected.
+ Do not show the estimates for TRUNCATE command. */
+ if (thd_sql_command(user_thd) == SQLCOM_TRUNCATE) {
+
+ n_rows = 0;
+ }
+
stats.records = (ha_rows)n_rows;
stats.deleted = 0;
stats.data_file_length = ((ulonglong)
@@ -5764,7 +5871,9 @@ ha_innobase::info(
stats.index_file_length = ((ulonglong)
ib_table->stat_sum_of_other_index_sizes)
* UNIV_PAGE_SIZE;
- stats.delete_length = 0;
+ stats.delete_length =
+ fsp_get_available_space_in_free_extents(
+ ib_table->space) * 1024;
stats.check_time = 0;
if (stats.records == 0) {
@@ -5847,7 +5956,7 @@ ha_innobase::info(
}
if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
- longlong auto_inc;
+ ulonglong auto_inc;
int ret;
/* The following function call can the first time fail in
@@ -7211,9 +7320,9 @@ ha_innobase::innobase_read_and_init_auto
/*=========================================*/
/* out: 0 or generic MySQL
error code */
- longlong* value) /* out: the autoinc value */
+ ulonglong* value) /* out: the autoinc value */
{
- longlong auto_inc;
+ ulonglong auto_inc;
ibool stmt_start;
int mysql_error = 0;
dict_table_t* innodb_table = prebuilt->table;
@@ -7264,7 +7373,9 @@ ha_innobase::innobase_read_and_init_auto
index, autoinc_col_name, &auto_inc);
if (error == DB_SUCCESS) {
- ++auto_inc;
+ if (auto_inc < ~0x0ULL) {
+ ++auto_inc;
+ }
dict_table_autoinc_initialize(innodb_table, auto_inc);
} else {
ut_print_timestamp(stderr);
@@ -7303,6 +7414,7 @@ On return if there is no error then the
ulong
ha_innobase::innobase_get_auto_increment(
+/*=====================================*/
ulonglong* value) /* out: autoinc value */
{
ulong error;
@@ -7316,14 +7428,14 @@ ha_innobase::innobase_get_auto_increment
error = innobase_autoinc_lock();
if (error == DB_SUCCESS) {
- ib_longlong autoinc;
+ ulonglong autoinc;
/* Determine the first value of the interval */
autoinc = dict_table_autoinc_read(prebuilt->table);
/* We need to initialize the AUTO-INC value, for
that we release all locks.*/
- if (autoinc <= 0) {
+ if (autoinc == 0) {
trx_t* trx;
trx = prebuilt->trx;
@@ -7342,14 +7454,11 @@ ha_innobase::innobase_get_auto_increment
mysql_error = innobase_read_and_init_auto_inc(
&autoinc);
- if (!mysql_error) {
- /* Should have read the proper value */
- ut_a(autoinc > 0);
- } else {
+ if (mysql_error) {
error = DB_ERROR;
}
} else {
- *value = (ulonglong) autoinc;
+ *value = autoinc;
}
/* A deadlock error during normal processing is OK
and can be ignored. */
@@ -7434,10 +7543,19 @@ ha_innobase::get_auto_increment(
/* With old style AUTOINC locking we only update the table's
AUTOINC counter after attempting to insert the row. */
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
+ ulonglong have;
+ ulonglong need;
+
+ /* Check for overflow conditions. */
+ need = *nb_reserved_values * increment;
+ have = ~0x0ULL - *first_value;
+
+ if (have < need) {
+ need = have;
+ }
/* Compute the last value in the interval */
- prebuilt->last_value = *first_value +
- (*nb_reserved_values * increment);
+ prebuilt->last_value = *first_value + need;
ut_a(prebuilt->last_value >= *first_value);
@@ -7911,7 +8029,7 @@ bool ha_innobase::check_if_incompatible_
}
/* Check that row format didn't change */
- if ((info->used_fields & HA_CREATE_USED_AUTO) &&
+ if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) &&
get_row_type() != info->row_type) {
return COMPATIBLE_DATA_NO;
@@ -8026,9 +8144,10 @@ static MYSQL_SYSVAR_BOOL(stats_on_metada
"Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
NULL, NULL, TRUE);
-static MYSQL_SYSVAR_BOOL(use_adaptive_hash_indexes, innobase_use_adaptive_hash_indexes,
+static MYSQL_SYSVAR_BOOL(adaptive_hash_index, innobase_adaptive_hash_index,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
- "Enable the InnoDB adaptive hash indexes (enabled by default)",
+ "Enable InnoDB adaptive hash index (enabled by default). "
+ "Disable with --skip-innodb-adaptive-hash-index.",
NULL, NULL, TRUE);
static MYSQL_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
@@ -8118,10 +8237,11 @@ static MYSQL_SYSVAR_STR(data_file_path,
static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
- "The AUTOINC lock modes supported by InnoDB:\n"
- " 0 => Old style AUTOINC locking (for backward compatibility)\n"
- " 1 => New style AUTOINC locking\n"
- " 2 => No AUTOINC locking (unsafe for SBR)",
+ "The AUTOINC lock modes supported by InnoDB: "
+ "0 => Old style AUTOINC locking (for backward"
+ " compatibility) "
+ "1 => New style AUTOINC locking "
+ "2 => No AUTOINC locking (unsafe for SBR)",
NULL, NULL,
AUTOINC_NEW_STYLE_LOCKING, /* Default setting */
AUTOINC_OLD_STYLE_LOCKING, /* Minimum value */
@@ -8159,7 +8279,7 @@ static struct st_mysql_sys_var* innobase
MYSQL_SYSVAR(open_files),
MYSQL_SYSVAR(rollback_on_timeout),
MYSQL_SYSVAR(stats_on_metadata),
- MYSQL_SYSVAR(use_adaptive_hash_indexes),
+ MYSQL_SYSVAR(adaptive_hash_index),
MYSQL_SYSVAR(status_file),
MYSQL_SYSVAR(support_xa),
MYSQL_SYSVAR(sync_spin_loops),
=== modified file 'storage/innobase/handler/ha_innodb.h'
--- a/storage/innobase/handler/ha_innodb.h 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/handler/ha_innodb.h 2008-06-12 00:08:07 +0000
@@ -72,7 +72,7 @@ class ha_innobase: public handler
int update_thd(THD* thd);
int change_active_index(uint keynr);
int general_fetch(uchar* buf, uint direction, uint match_mode);
- int innobase_read_and_init_auto_inc(longlong* ret);
+ int innobase_read_and_init_auto_inc(ulonglong* ret);
ulong innobase_autoinc_lock();
ulong innobase_set_max_autoinc(ulonglong auto_inc);
ulong innobase_reset_autoinc(ulonglong auto_inc);
=== modified file 'storage/innobase/include/buf0buf.h'
--- a/storage/innobase/include/buf0buf.h 2008-02-01 10:55:39 +0000
+++ b/storage/innobase/include/buf0buf.h 2008-06-12 00:08:07 +0000
@@ -495,7 +495,15 @@ Prints info of the buffer pool data stru
void
buf_print(void);
/*============*/
+
+/*************************************************************************
+Returns the number of latched pages in the buffer pool. */
+
+ulint
+buf_get_latched_pages_number(void);
+/*==============================*/
#endif /* UNIV_DEBUG */
+
/************************************************************************
Prints a page to stderr. */
@@ -503,12 +511,7 @@ void
buf_page_print(
/*===========*/
byte* read_buf); /* in: a database page */
-/*************************************************************************
-Returns the number of latched pages in the buffer pool. */
-ulint
-buf_get_latched_pages_number(void);
-/*==============================*/
/*************************************************************************
Returns the number of pending buf pool ios. */
=== modified file 'storage/innobase/include/dict0dict.h'
--- a/storage/innobase/include/dict0dict.h 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/dict0dict.h 2008-06-12 00:08:07 +0000
@@ -185,12 +185,12 @@ void
dict_table_autoinc_initialize(
/*==========================*/
dict_table_t* table, /* in: table */
- ib_longlong value); /* in: next value to assign to a row */
+ ib_ulonglong value); /* in: next value to assign to a row */
/************************************************************************
Reads the next autoinc value (== autoinc counter value), 0 if not yet
initialized. */
-ib_longlong
+ib_ulonglong
dict_table_autoinc_read(
/*====================*/
/* out: value for a new row, or 0 */
@@ -204,7 +204,7 @@ dict_table_autoinc_update(
/*======================*/
dict_table_t* table, /* in: table */
- ib_longlong value); /* in: value which was assigned to a row */
+ ib_ulonglong value); /* in: value which was assigned to a row */
/************************************************************************
Release the autoinc lock.*/
=== modified file 'storage/innobase/include/dict0mem.h'
--- a/storage/innobase/include/dict0mem.h 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/dict0mem.h 2008-06-12 00:08:07 +0000
@@ -409,7 +409,7 @@ struct dict_table_struct{
/* TRUE if the autoinc counter has been
inited; MySQL gets the init value by executing
SELECT MAX(auto inc column) */
- ib_longlong autoinc;/* autoinc counter value to give to the
+ ib_ulonglong autoinc;/* autoinc counter value to give to the
next inserted row */
ib_longlong autoinc_increment;
=== modified file 'storage/innobase/include/mach0data.h'
--- a/storage/innobase/include/mach0data.h 2007-11-06 22:42:58 +0000
+++ b/storage/innobase/include/mach0data.h 2008-06-12 00:08:07 +0000
@@ -331,10 +331,10 @@ mach_write_to_2_little_endian(
Convert integral type from storage byte order (big endian) to
host byte order. */
UNIV_INLINE
-void
+ullint
mach_read_int_type(
/*===============*/
- byte* dest, /* out: where to write */
+ /* out: integer value */
const byte* src, /* in: where to read from */
ulint len, /* in: length of src */
ibool unsigned_type); /* in: signed or unsigned flag */
=== modified file 'storage/innobase/include/mach0data.ic'
--- a/storage/innobase/include/mach0data.ic 2007-11-06 22:42:58 +0000
+++ b/storage/innobase/include/mach0data.ic 2008-06-12 00:08:07 +0000
@@ -696,33 +696,39 @@ mach_write_to_2_little_endian(
Convert integral type from storage byte order (big endian) to
host byte order. */
UNIV_INLINE
-void
+ullint
mach_read_int_type(
/*===============*/
- byte* dest, /* out: where to write */
+ /* out: integer value */
const byte* src, /* in: where to read from */
ulint len, /* in: length of src */
ibool unsigned_type) /* in: signed or unsigned flag */
{
-#ifdef WORDS_BIGENDIAN
- memcpy(dest, src, len);
+ /* XXX this can be optimized on big-endian machines */
- if (!unsigned_type) {
- dest[0] ^= 128;
+ ullint ret;
+ uint i;
+
+ if (unsigned_type || (src[0] & 0x80)) {
+
+ ret = 0x0000000000000000ULL;
+ } else {
+
+ ret = 0xFFFFFFFFFFFFFF00ULL;
}
-#else
- byte* ptr;
- /* Convert integer data from Innobase to a little-endian format,
- sign bit restored to normal. */
+ if (unsigned_type) {
- for (ptr = dest + len; ptr != dest; ++src) {
- --ptr;
- *ptr = *src;
+ ret |= src[0];
+ } else {
+
+ ret |= src[0] ^ 0x80;
}
- if (!unsigned_type) {
- dest[len - 1] ^= 128;
+ for (i = 1; i < len; i++) {
+ ret <<= 8;
+ ret |= src[i];
}
-#endif
+
+ return(ret);
}
=== modified file 'storage/innobase/include/os0sync.h'
--- a/storage/innobase/include/os0sync.h 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/os0sync.h 2008-06-12 00:08:07 +0000
@@ -112,9 +112,13 @@ os_event_set(
os_event_t event); /* in: event to set */
/**************************************************************
Resets an event semaphore to the nonsignaled state. Waiting threads will
-stop to wait for the event. */
+stop to wait for the event.
+The return value should be passed to os_even_wait_low() if it is desired
+that this thread should not wait in case of an intervening call to
+os_event_set() between this os_event_reset() and the
+os_event_wait_low() call. See comments for os_event_wait_low(). */
-void
+ib_longlong
os_event_reset(
/*===========*/
os_event_t event); /* in: event to reset */
@@ -125,16 +129,38 @@ void
os_event_free(
/*==========*/
os_event_t event); /* in: event to free */
+
/**************************************************************
Waits for an event object until it is in the signaled state. If
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
waiting thread when the event becomes signaled (or immediately if the
-event is already in the signaled state). */
+event is already in the signaled state).
+
+Typically, if the event has been signalled after the os_event_reset()
+we'll return immediately because event->is_set == TRUE.
+There are, however, situations (e.g.: sync_array code) where we may
+lose this information. For example:
+
+thread A calls os_event_reset()
+thread B calls os_event_set() [event->is_set == TRUE]
+thread C calls os_event_reset() [event->is_set == FALSE]
+thread A calls os_event_wait() [infinite wait!]
+thread C calls os_event_wait() [infinite wait!]
+
+Where such a scenario is possible, to avoid infinite wait, the
+value returned by os_event_reset() should be passed in as
+reset_sig_count. */
+
+#define os_event_wait(event) os_event_wait_low((event), 0)
+
+void
+os_event_wait_low(
+/*==============*/
+ os_event_t event, /* in: event to wait */
+ ib_longlong reset_sig_count);/* in: zero or the value
+ returned by previous call of
+ os_event_reset(). */
-void
-os_event_wait(
-/*==========*/
- os_event_t event); /* in: event to wait */
/**************************************************************
Waits for an event object until it is in the signaled state or
a timeout is exceeded. In Unix the timeout is always infinite. */
=== modified file 'storage/innobase/include/read0read.h'
--- a/storage/innobase/include/read0read.h 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/read0read.h 2008-06-12 00:08:07 +0000
@@ -111,10 +111,6 @@ struct read_view_struct{
dulint undo_no; /* (0, 0) or if type is VIEW_HIGH_GRANULARITY
transaction undo_no when this high-granularity
consistent read view was created */
- ibool can_be_too_old; /* TRUE if the system has had to purge old
- versions which this read view should be able
- to access: the read view can bump into the
- DB_MISSING_HISTORY error */
dulint low_limit_no; /* The view does not need to see the undo
logs for transactions whose transaction number
is strictly smaller (<) than this value: they
=== modified file 'storage/innobase/include/row0mysql.h'
--- a/storage/innobase/include/row0mysql.h 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/row0mysql.h 2008-06-12 00:08:07 +0000
@@ -319,7 +319,7 @@ row_mysql_unfreeze_data_dictionary(
/*===============================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
-Drops a table for MySQL. If the name of the table ends in
+Creates a table for MySQL. If the name of the table ends in
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
"innodb_table_monitor", then this will also start the printing of monitor
output by the master thread. If the table name ends in "innodb_mem_validate",
@@ -464,6 +464,16 @@ row_check_table_for_mysql(
row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL
handle */
+/*************************************************************************
+Determines if a table is a magic monitor table. */
+
+ibool
+row_is_magic_monitor_table(
+/*=======================*/
+ /* out: TRUE if monitor table */
+ const char* table_name); /* in: name of the table, in the
+ form database/table_name */
+
/* A struct describing a place for an individual column in the MySQL
row format which is presented to the table handler in ha_innobase.
This template struct is used to speed up row transformations between
@@ -671,7 +681,7 @@ struct row_prebuilt_struct {
fetched row in fetch_cache */
ulint n_fetch_cached; /* number of not yet fetched rows
in fetch_cache */
- mem_heap_t* blob_heap; /* in SELECTS BLOB fie lds are copied
+ mem_heap_t* blob_heap; /* in SELECTS BLOB fields are copied
to this heap */
mem_heap_t* old_vers_heap; /* memory heap where a previous
version is built in consistent read */
=== modified file 'storage/innobase/include/row0sel.h'
--- a/storage/innobase/include/row0sel.h 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/row0sel.h 2008-06-12 00:08:07 +0000
@@ -181,7 +181,7 @@ row_search_max_autoinc(
error code */
dict_index_t* index, /* in: index to search */
const char* col_name, /* in: autoinc column name */
- ib_longlong* value); /* out: AUTOINC value read */
+ ib_ulonglong* value); /* out: AUTOINC value read */
/* A structure for caching column values for prefetched rows */
struct sel_buf_struct{
=== modified file 'storage/innobase/include/srv0srv.h'
--- a/storage/innobase/include/srv0srv.h 2008-03-31 09:37:03 +0000
+++ b/storage/innobase/include/srv0srv.h 2008-06-12 00:08:07 +0000
@@ -249,11 +249,7 @@ extern srv_sys_t* srv_sys;
/* Alternatives for the file flush option in Unix; see the InnoDB manual
about what these mean */
-#define SRV_UNIX_FDATASYNC 1 /* This is the default; it is
- currently mapped to a call of
- fsync() because fdatasync() seemed
- to corrupt files in Linux and
- Solaris */
+#define SRV_UNIX_FSYNC 1 /* This is the default */
#define SRV_UNIX_O_DSYNC 2
#define SRV_UNIX_LITTLESYNC 3
#define SRV_UNIX_NOSYNC 4
@@ -505,7 +501,9 @@ struct export_var_struct{
ulint innodb_buffer_pool_pages_dirty;
ulint innodb_buffer_pool_pages_misc;
ulint innodb_buffer_pool_pages_free;
+#ifdef UNIV_DEBUG
ulint innodb_buffer_pool_pages_latched;
+#endif /* UNIV_DEBUG */
ulint innodb_buffer_pool_read_requests;
ulint innodb_buffer_pool_reads;
ulint innodb_buffer_pool_wait_free;
=== modified file 'storage/innobase/include/sync0arr.h'
--- a/storage/innobase/include/sync0arr.h 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/sync0arr.h 2008-06-12 00:08:07 +0000
@@ -66,26 +66,21 @@ sync_array_wait_event(
sync_array_t* arr, /* in: wait array */
ulint index); /* in: index of the reserved cell */
/**********************************************************************
-Frees the cell safely by reserving the sync array mutex and decrementing
-n_reserved if necessary. Should only be called from mutex_spin_wait. */
+Frees the cell. NOTE! sync_array_wait_event frees the cell
+automatically! */
void
-sync_array_free_cell_protected(
-/*===========================*/
+sync_array_free_cell(
+/*=================*/
sync_array_t* arr, /* in: wait array */
ulint index); /* in: index of the cell in array */
/**************************************************************************
-Looks for the cells in the wait array which refer
-to the wait object specified,
-and sets their corresponding events to the signaled state. In this
-way releases the threads waiting for the object to contend for the object.
-It is possible that no such cell is found, in which case does nothing. */
+Note that one of the wait objects was signalled. */
void
-sync_array_signal_object(
-/*=====================*/
- sync_array_t* arr, /* in: wait array */
- void* object);/* in: wait object */
+sync_array_object_signalled(
+/*========================*/
+ sync_array_t* arr); /* in: wait array */
/**************************************************************************
If the wakeup algorithm does not work perfectly at semaphore relases,
this function will do the waking (see the comment in mutex_exit). This
=== modified file 'storage/innobase/include/sync0rw.h'
--- a/storage/innobase/include/sync0rw.h 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/sync0rw.h 2008-06-12 00:08:07 +0000
@@ -421,6 +421,18 @@ blocked by readers, a writer may queue f
field. Then no new readers are allowed in. */
struct rw_lock_struct {
+ os_event_t event; /* Used by sync0arr.c for thread queueing */
+
+#ifdef __WIN__
+ os_event_t wait_ex_event; /* This windows specific event is
+ used by the thread which has set the
+ lock state to RW_LOCK_WAIT_EX. The
+ rw_lock design guarantees that this
+ thread will be the next one to proceed
+ once the current the event gets
+ signalled. See LEMMA 2 in sync0sync.c */
+#endif
+
ulint reader_count; /* Number of readers who have locked this
lock in the shared mode */
ulint writer; /* This field is set to RW_LOCK_EX if there
=== modified file 'storage/innobase/include/sync0rw.ic'
--- a/storage/innobase/include/sync0rw.ic 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/sync0rw.ic 2008-06-12 00:08:07 +0000
@@ -381,7 +381,11 @@ rw_lock_s_unlock_func(
mutex_exit(mutex);
if (UNIV_UNLIKELY(sg)) {
- sync_array_signal_object(sync_primary_wait_array, lock);
+#ifdef __WIN__
+ os_event_set(lock->wait_ex_event);
+#endif
+ os_event_set(lock->event);
+ sync_array_object_signalled(sync_primary_wait_array);
}
ut_ad(rw_lock_validate(lock));
@@ -461,7 +465,11 @@ rw_lock_x_unlock_func(
mutex_exit(&(lock->mutex));
if (UNIV_UNLIKELY(sg)) {
- sync_array_signal_object(sync_primary_wait_array, lock);
+#ifdef __WIN__
+ os_event_set(lock->wait_ex_event);
+#endif
+ os_event_set(lock->event);
+ sync_array_object_signalled(sync_primary_wait_array);
}
ut_ad(rw_lock_validate(lock));
=== modified file 'storage/innobase/include/sync0sync.h'
--- a/storage/innobase/include/sync0sync.h 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/sync0sync.h 2008-06-12 00:08:07 +0000
@@ -470,6 +470,7 @@ Do not use its fields directly! The stru
implementation of a mutual exclusion semaphore. */
struct mutex_struct {
+ os_event_t event; /* Used by sync0arr.c for the wait queue */
ulint lock_word; /* This ulint is the target of the atomic
test-and-set instruction in Win32 */
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
=== modified file 'storage/innobase/include/sync0sync.ic'
--- a/storage/innobase/include/sync0sync.ic 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/sync0sync.ic 2008-06-12 00:08:07 +0000
@@ -211,7 +211,7 @@ mutex_exit(
perform the read first, which could leave a waiting
thread hanging indefinitely.
- Our current solution call every 10 seconds
+ Our current solution call every second
sync_arr_wake_threads_if_sema_free()
to wake up possible hanging threads if
they are missed in mutex_signal_object. */
=== modified file 'storage/innobase/include/trx0undo.h'
--- a/storage/innobase/include/trx0undo.h 2008-03-31 09:37:03 +0000
+++ b/storage/innobase/include/trx0undo.h 2008-06-12 00:08:07 +0000
@@ -240,6 +240,7 @@ trx_undo_set_state_at_finish(
/*=========================*/
/* out: undo log segment header page,
x-latched */
+ trx_rseg_t* rseg, /* in: rollback segment memory object */
trx_t* trx, /* in: transaction */
trx_undo_t* undo, /* in: undo log memory copy */
mtr_t* mtr); /* in: mtr */
=== modified file 'storage/innobase/include/univ.i'
--- a/storage/innobase/include/univ.i 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/include/univ.i 2008-06-12 00:08:07 +0000
@@ -212,8 +212,11 @@ typedef long int lint;
#ifdef __WIN__
typedef __int64 ib_longlong;
+typedef unsigned __int64 ib_ulonglong;
#else
+/* Note: longlong and ulonglong come from MySQL headers. */
typedef longlong ib_longlong;
+typedef ulonglong ib_ulonglong;
#endif
typedef unsigned long long int ullint;
=== modified file 'storage/innobase/include/ut0ut.h'
--- a/storage/innobase/include/ut0ut.h 2007-11-06 22:42:58 +0000
+++ b/storage/innobase/include/ut0ut.h 2008-06-12 00:08:07 +0000
@@ -145,11 +145,15 @@ ib_time_t
ut_time(void);
/*=========*/
/**************************************************************
-Returns system time. */
+Returns system time.
+Upon successful completion, the value 0 is returned; otherwise the
+value -1 is returned and the global variable errno is set to indicate the
+error. */
-void
+int
ut_usectime(
/*========*/
+ /* out: 0 on success, -1 otherwise */
ulint* sec, /* out: seconds since the Epoch */
ulint* ms); /* out: microseconds since the Epoch+*sec */
/**************************************************************
=== modified file 'storage/innobase/os/os0file.c'
--- a/storage/innobase/os/os0file.c 2008-03-31 09:37:03 +0000
+++ b/storage/innobase/os/os0file.c 2008-06-12 00:08:07 +0000
@@ -22,8 +22,6 @@ Created 10/21/1995 Heikki Tuuri
#include <errno.h>
#endif /* UNIV_HOTBACKUP */
-#undef HAVE_FDATASYNC
-
#ifdef POSIX_ASYNC_IO
/* We assume in this case that the OS has standard Posix aio (at least SunOS
2.6, HP-UX 11i and AIX 4.3 have) */
@@ -1269,9 +1267,19 @@ try_again:
if (file == INVALID_HANDLE_VALUE) {
*success = FALSE;
- retry = os_file_handle_error(name,
- create_mode == OS_FILE_CREATE ?
- "create" : "open");
+ /* When srv_file_per_table is on, file creation failure may not
+ be critical to the whole instance. Do not crash the server in
+ case of unknown errors. */
+ if (srv_file_per_table) {
+ retry = os_file_handle_error_no_exit(name,
+ create_mode == OS_FILE_CREATE ?
+ "create" : "open");
+ } else {
+ retry = os_file_handle_error(name,
+ create_mode == OS_FILE_CREATE ?
+ "create" : "open");
+ }
+
if (retry) {
goto try_again;
}
@@ -1346,9 +1354,19 @@ try_again:
if (file == -1) {
*success = FALSE;
- retry = os_file_handle_error(name,
- create_mode == OS_FILE_CREATE ?
- "create" : "open");
+ /* When srv_file_per_table is on, file creation failure may not
+ be critical to the whole instance. Do not crash the server in
+ case of unknown errors. */
+ if (srv_file_per_table) {
+ retry = os_file_handle_error_no_exit(name,
+ create_mode == OS_FILE_CREATE ?
+ "create" : "open");
+ } else {
+ retry = os_file_handle_error(name,
+ create_mode == OS_FILE_CREATE ?
+ "create" : "open");
+ }
+
if (retry) {
goto try_again;
} else {
@@ -1812,6 +1830,55 @@ os_file_set_eof(
#endif /* __WIN__ */
}
+#ifndef __WIN__
+/***************************************************************************
+Wrapper to fsync(2) that retries the call on some errors.
+Returns the value 0 if successful; otherwise the value -1 is returned and
+the global variable errno is set to indicate the error. */
+
+static
+int
+os_file_fsync(
+/*==========*/
+ /* out: 0 if success, -1 otherwise */
+ os_file_t file) /* in: handle to a file */
+{
+ int ret;
+ int failures;
+ ibool retry;
+
+ failures = 0;
+
+ do {
+ ret = fsync(file);
+
+ os_n_fsyncs++;
+
+ if (ret == -1 && errno == ENOLCK) {
+
+ if (failures % 100 == 0) {
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: fsync(): "
+ "No locks available; retrying\n");
+ }
+
+ os_thread_sleep(200000 /* 0.2 sec */);
+
+ failures++;
+
+ retry = TRUE;
+ } else {
+
+ retry = FALSE;
+ }
+ } while (retry);
+
+ return(ret);
+}
+#endif /* !__WIN__ */
+
/***************************************************************************
Flushes the write buffers of a given file to the disk. */
@@ -1869,23 +1936,19 @@ os_file_flush(
/* If we are not on an operating system that supports this,
then fall back to a plain fsync. */
- ret = fsync(file);
+ ret = os_file_fsync(file);
} else {
ret = fcntl(file, F_FULLFSYNC, NULL);
if (ret) {
/* If we are not on a file system that supports this,
then fall back to a plain fsync. */
- ret = fsync(file);
+ ret = os_file_fsync(file);
}
}
-#elif HAVE_FDATASYNC
- ret = fdatasync(file);
#else
- /* fprintf(stderr, "Flushing to file %p\n", file); */
- ret = fsync(file);
+ ret = os_file_fsync(file);
#endif
- os_n_fsyncs++;
if (ret == 0) {
return(TRUE);
=== modified file 'storage/innobase/os/os0sync.c'
--- a/storage/innobase/os/os0sync.c 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/os/os0sync.c 2008-06-12 00:08:07 +0000
@@ -21,6 +21,7 @@ Created 9/6/1995 Heikki Tuuri
/* Type definition for an operating system mutex struct */
struct os_mutex_struct{
+ os_event_t event; /* Used by sync0arr.c for queing threads */
void* handle; /* OS handle to mutex */
ulint count; /* we use this counter to check
that the same thread does not
@@ -35,6 +36,7 @@ struct os_mutex_struct{
/* Mutex protecting counts and the lists of OS mutexes and events */
os_mutex_t os_sync_mutex;
ibool os_sync_mutex_inited = FALSE;
+ibool os_sync_free_called = FALSE;
/* This is incremented by 1 in os_thread_create and decremented by 1 in
os_thread_exit */
@@ -50,6 +52,10 @@ ulint os_event_count = 0;
ulint os_mutex_count = 0;
ulint os_fast_mutex_count = 0;
+/* Because a mutex is embedded inside an event and there is an
+event embedded inside a mutex, on free, this generates a recursive call.
+This version of the free event function doesn't acquire the global lock */
+static void os_event_free_internal(os_event_t event);
/*************************************************************
Initializes global event and OS 'slow' mutex lists. */
@@ -76,6 +82,7 @@ os_sync_free(void)
os_event_t event;
os_mutex_t mutex;
+ os_sync_free_called = TRUE;
event = UT_LIST_GET_FIRST(os_event_list);
while (event) {
@@ -99,6 +106,7 @@ os_sync_free(void)
mutex = UT_LIST_GET_FIRST(os_mutex_list);
}
+ os_sync_free_called = FALSE;
}
/*************************************************************
@@ -144,17 +152,31 @@ os_event_create(
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
#endif
event->is_set = FALSE;
- event->signal_count = 0;
+
+ /* We return this value in os_event_reset(), which can then be
+ be used to pass to the os_event_wait_low(). The value of zero
+ is reserved in os_event_wait_low() for the case when the
+ caller does not want to pass any signal_count value. To
+ distinguish between the two cases we initialize signal_count
+ to 1 here. */
+ event->signal_count = 1;
#endif /* __WIN__ */
- /* Put to the list of events */
- os_mutex_enter(os_sync_mutex);
+ /* The os_sync_mutex can be NULL because during startup an event
+ can be created [ because it's embedded in the mutex/rwlock ] before
+ this module has been initialized */
+ if (os_sync_mutex != NULL) {
+ os_mutex_enter(os_sync_mutex);
+ }
+ /* Put to the list of events */
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
os_event_count++;
- os_mutex_exit(os_sync_mutex);
+ if (os_sync_mutex != NULL) {
+ os_mutex_exit(os_sync_mutex);
+ }
return(event);
}
@@ -231,13 +253,20 @@ os_event_set(
/**************************************************************
Resets an event semaphore to the nonsignaled state. Waiting threads will
-stop to wait for the event. */
+stop to wait for the event.
+The return value should be passed to os_even_wait_low() if it is desired
+that this thread should not wait in case of an intervening call to
+os_event_set() between this os_event_reset() and the
+os_event_wait_low() call. See comments for os_event_wait_low(). */
-void
+ib_longlong
os_event_reset(
/*===========*/
+ /* out: current signal_count. */
os_event_t event) /* in: event to reset */
{
+ ib_longlong ret = 0;
+
#ifdef __WIN__
ut_a(event);
@@ -252,9 +281,40 @@ os_event_reset(
} else {
event->is_set = FALSE;
}
+ ret = event->signal_count;
os_fast_mutex_unlock(&(event->os_mutex));
#endif
+ return(ret);
+}
+
+/**************************************************************
+Frees an event object, without acquiring the global lock. */
+static
+void
+os_event_free_internal(
+/*===================*/
+ os_event_t event) /* in: event to free */
+{
+#ifdef __WIN__
+ ut_a(event);
+
+ ut_a(CloseHandle(event->handle));
+#else
+ ut_a(event);
+
+ /* This is to avoid freeing the mutex twice */
+ os_fast_mutex_free(&(event->os_mutex));
+
+ ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
+#endif
+ /* Remove from the list of events */
+
+ UT_LIST_REMOVE(os_event_list, os_event_list, event);
+
+ os_event_count--;
+
+ ut_free(event);
}
/**************************************************************
@@ -293,18 +353,38 @@ os_event_free(
Waits for an event object until it is in the signaled state. If
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
waiting thread when the event becomes signaled (or immediately if the
-event is already in the signaled state). */
+event is already in the signaled state).
+
+Typically, if the event has been signalled after the os_event_reset()
+we'll return immediately because event->is_set == TRUE.
+There are, however, situations (e.g.: sync_array code) where we may
+lose this information. For example:
+
+thread A calls os_event_reset()
+thread B calls os_event_set() [event->is_set == TRUE]
+thread C calls os_event_reset() [event->is_set == FALSE]
+thread A calls os_event_wait() [infinite wait!]
+thread C calls os_event_wait() [infinite wait!]
+
+Where such a scenario is possible, to avoid infinite wait, the
+value returned by os_event_reset() should be passed in as
+reset_sig_count. */
void
-os_event_wait(
-/*==========*/
- os_event_t event) /* in: event to wait */
+os_event_wait_low(
+/*==============*/
+ os_event_t event, /* in: event to wait */
+ ib_longlong reset_sig_count)/* in: zero or the value
+ returned by previous call of
+ os_event_reset(). */
{
#ifdef __WIN__
DWORD err;
ut_a(event);
+ UT_NOT_USED(reset_sig_count);
+
/* Specify an infinite time limit for waiting */
err = WaitForSingleObject(event->handle, INFINITE);
@@ -318,7 +398,11 @@ os_event_wait(
os_fast_mutex_lock(&(event->os_mutex));
- old_signal_count = event->signal_count;
+ if (reset_sig_count) {
+ old_signal_count = reset_sig_count;
+ } else {
+ old_signal_count = event->signal_count;
+ }
for (;;) {
if (event->is_set == TRUE
@@ -458,6 +542,7 @@ os_mutex_create(
mutex_str->handle = mutex;
mutex_str->count = 0;
+ mutex_str->event = os_event_create(NULL);
if (os_sync_mutex_inited) {
/* When creating os_sync_mutex itself we cannot reserve it */
@@ -534,6 +619,10 @@ os_mutex_free(
{
ut_a(mutex);
+ if (!os_sync_free_called) {
+ os_event_free_internal(mutex->event);
+ }
+
if (os_sync_mutex_inited) {
os_mutex_enter(os_sync_mutex);
}
=== modified file 'storage/innobase/plug.in'
--- a/storage/innobase/plug.in 2008-05-14 09:24:14 +0000
+++ b/storage/innobase/plug.in 2008-06-12 00:08:07 +0000
@@ -15,25 +15,30 @@ MYSQL_PLUGIN_ACTIONS(innobase, [
AC_CHECK_FUNCS(localtime_r)
AC_C_BIGENDIAN
case "$target_os" in
- lin*)
- CFLAGS="$CFLAGS -DUNIV_LINUX";;
- hpux10*)
- CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";;
- hp*)
- CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX";;
- aix*)
- CFLAGS="$CFLAGS -DUNIV_AIX";;
- irix*)
- CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
- osf*)
- CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
- *solaris*|*SunOS*)
- CFLAGS="$CFLAGS -DUNIV_SOLARIS";;
- sysv5uw7*)
- # Problem when linking on SCO
- CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
- openbsd*)
- CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
+ lin*)
+ CFLAGS="$CFLAGS -DUNIV_LINUX";;
+ hpux10*)
+ CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";;
+ hp*)
+ CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX";;
+ aix*)
+ CFLAGS="$CFLAGS -DUNIV_AIX";;
+ irix*|osf*|sysv5uw7*|openbsd*)
+ CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
+ *solaris*|*SunOS*)
+ CFLAGS="$CFLAGS -DUNIV_SOLARIS";;
esac
+ INNODB_DYNAMIC_CFLAGS="-DMYSQL_DYNAMIC_PLUGIN"
+ case "$target_cpu" in
+ x86_64)
+ # The AMD64 ABI forbids absolute addresses in shared libraries
+ ;;
+ *86)
+ # Use absolute addresses on IA-32
+ INNODB_DYNAMIC_CFLAGS="$INNODB_DYNAMIC_CFLAGS -prefer-non-pic"
+ ;;
+ esac
+ AC_SUBST(INNODB_DYNAMIC_CFLAGS)
])
+# vim: set ft=config:
=== modified file 'storage/innobase/read/read0read.c'
--- a/storage/innobase/read/read0read.c 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/read/read0read.c 2008-06-12 00:08:07 +0000
@@ -212,7 +212,6 @@ read_view_oldest_copy_or_open_new(
view_copy->low_limit_no = old_view->low_limit_no;
view_copy->low_limit_id = old_view->low_limit_id;
- view_copy->can_be_too_old = FALSE;
if (n > 0) {
/* The last active transaction has the smallest id: */
@@ -258,8 +257,6 @@ read_view_open_now(
view->low_limit_no = trx_sys->max_trx_id;
view->low_limit_id = view->low_limit_no;
- view->can_be_too_old = FALSE;
-
n = 0;
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
@@ -432,8 +429,6 @@ read_cursor_view_create_for_mysql(
view->low_limit_no = trx_sys->max_trx_id;
view->low_limit_id = view->low_limit_no;
- view->can_be_too_old = FALSE;
-
n = 0;
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
=== modified file 'storage/innobase/row/row0mysql.c'
--- a/storage/innobase/row/row0mysql.c 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/row/row0mysql.c 2008-06-12 00:08:07 +0000
@@ -57,6 +57,12 @@ static const char S_innodb_tablespace_mo
static const char S_innodb_table_monitor[] = "innodb_table_monitor";
static const char S_innodb_mem_validate[] = "innodb_mem_validate";
+/* Evaluates to true if str1 equals str2_onstack, used for comparing
+the above strings. */
+#define STR_EQ(str1, str1_len, str2_onstack) \
+ ((str1_len) == sizeof(str2_onstack) \
+ && memcmp(str1, str2_onstack, sizeof(str2_onstack)) == 0)
+
/***********************************************************************
Determine if the given name is a name reserved for MySQL system tables. */
static
@@ -1728,7 +1734,7 @@ row_mysql_unlock_data_dictionary(
}
/*************************************************************************
-Drops a table for MySQL. If the name of the table ends in
+Creates a table for MySQL. If the name of the table ends in
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
"innodb_table_monitor", then this will also start the printing of monitor
output by the master thread. If the table name ends in "innodb_mem_validate",
@@ -1809,9 +1815,7 @@ row_create_table_for_mysql(
table_name++;
table_name_len = strlen(table_name) + 1;
- if (table_name_len == sizeof S_innodb_monitor
- && !memcmp(table_name, S_innodb_monitor,
- sizeof S_innodb_monitor)) {
+ if (STR_EQ(table_name, table_name_len, S_innodb_monitor)) {
/* Table equals "innodb_monitor":
start monitor prints */
@@ -1822,28 +1826,24 @@ row_create_table_for_mysql(
of InnoDB monitor prints */
os_event_set(srv_lock_timeout_thread_event);
- } else if (table_name_len == sizeof S_innodb_lock_monitor
- && !memcmp(table_name, S_innodb_lock_monitor,
- sizeof S_innodb_lock_monitor)) {
+ } else if (STR_EQ(table_name, table_name_len,
+ S_innodb_lock_monitor)) {
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
- } else if (table_name_len == sizeof S_innodb_tablespace_monitor
- && !memcmp(table_name, S_innodb_tablespace_monitor,
- sizeof S_innodb_tablespace_monitor)) {
+ } else if (STR_EQ(table_name, table_name_len,
+ S_innodb_tablespace_monitor)) {
srv_print_innodb_tablespace_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
- } else if (table_name_len == sizeof S_innodb_table_monitor
- && !memcmp(table_name, S_innodb_table_monitor,
- sizeof S_innodb_table_monitor)) {
+ } else if (STR_EQ(table_name, table_name_len,
+ S_innodb_table_monitor)) {
srv_print_innodb_table_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
- } else if (table_name_len == sizeof S_innodb_mem_validate
- && !memcmp(table_name, S_innodb_mem_validate,
- sizeof S_innodb_mem_validate)) {
+ } else if (STR_EQ(table_name, table_name_len,
+ S_innodb_mem_validate)) {
/* We define here a debugging feature intended for
developers */
@@ -1963,6 +1963,7 @@ row_create_index_for_mysql(
ulint err;
ulint i, j;
ulint len;
+ char* table_name;
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
@@ -1972,6 +1973,11 @@ row_create_index_for_mysql(
trx->op_info = "creating index";
+ /* Copy the table name because we may want to drop the
+ table later, after the index object is freed (inside
+ que_run_threads()) and thus index->table_name is not available. */
+ table_name = mem_strdup(index->table_name);
+
trx_start_if_not_started(trx);
/* Check that the same column does not appear twice in the index.
@@ -2044,13 +2050,15 @@ error_handling:
trx_general_rollback_for_mysql(trx, FALSE, NULL);
- row_drop_table_for_mysql(index->table_name, trx, FALSE);
+ row_drop_table_for_mysql(table_name, trx, FALSE);
trx->error_state = DB_SUCCESS;
}
trx->op_info = "";
+ mem_free(table_name);
+
return((int) err);
}
@@ -3312,6 +3320,66 @@ funct_exit:
return((int) err);
}
+/***********************************************************************
+Drop all foreign keys in a database, see Bug#18942.
+Called at the end of row_drop_database_for_mysql(). */
+static
+ulint
+drop_all_foreign_keys_in_db(
+/*========================*/
+ /* out: error code or DB_SUCCESS */
+ const char* name, /* in: database name which ends to '/' */
+ trx_t* trx) /* in: transaction handle */
+{
+ pars_info_t* pinfo;
+ ulint err;
+
+ ut_a(name[strlen(name) - 1] == '/');
+
+ pinfo = pars_info_create();
+
+ pars_info_add_str_literal(pinfo, "dbname", name);
+
+/* true if for_name is not prefixed with dbname */
+#define TABLE_NOT_IN_THIS_DB \
+"SUBSTR(for_name, 0, LENGTH(:dbname)) <> :dbname"
+
+ err = que_eval_sql(pinfo,
+ "PROCEDURE DROP_ALL_FOREIGN_KEYS_PROC () IS\n"
+ "foreign_id CHAR;\n"
+ "for_name CHAR;\n"
+ "found INT;\n"
+ "DECLARE CURSOR cur IS\n"
+ "SELECT ID, FOR_NAME FROM SYS_FOREIGN\n"
+ "WHERE FOR_NAME >= :dbname\n"
+ "LOCK IN SHARE MODE\n"
+ "ORDER BY FOR_NAME;\n"
+ "BEGIN\n"
+ "found := 1;\n"
+ "OPEN cur;\n"
+ "WHILE found = 1 LOOP\n"
+ " FETCH cur INTO foreign_id, for_name;\n"
+ " IF (SQL % NOTFOUND) THEN\n"
+ " found := 0;\n"
+ " ELSIF (" TABLE_NOT_IN_THIS_DB ") THEN\n"
+ " found := 0;\n"
+ " ELSIF (1=1) THEN\n"
+ " DELETE FROM SYS_FOREIGN_COLS\n"
+ " WHERE ID = foreign_id;\n"
+ " DELETE FROM SYS_FOREIGN\n"
+ " WHERE ID = foreign_id;\n"
+ " END IF;\n"
+ "END LOOP;\n"
+ "CLOSE cur;\n"
+ "COMMIT WORK;\n"
+ "END;\n",
+ FALSE, /* do not reserve dict mutex,
+ we are already holding it */
+ trx);
+
+ return(err);
+}
+
/*************************************************************************
Drops a database for MySQL. */
@@ -3382,6 +3450,19 @@ loop:
}
}
+ if (err == DB_SUCCESS) {
+ /* after dropping all tables try to drop all leftover
+ foreign keys in case orphaned ones exist */
+ err = (int) drop_all_foreign_keys_in_db(name, trx);
+
+ if (err != DB_SUCCESS) {
+ fputs("InnoDB: DROP DATABASE ", stderr);
+ ut_print_name(stderr, trx, TRUE, name);
+ fprintf(stderr, " failed with error %d while "
+ "dropping all foreign keys", err);
+ }
+ }
+
trx_commit_for_mysql(trx);
row_mysql_unlock_data_dictionary(trx);
@@ -4057,3 +4138,33 @@ row_check_table_for_mysql(
return(ret);
}
+
+/*************************************************************************
+Determines if a table is a magic monitor table. */
+
+ibool
+row_is_magic_monitor_table(
+/*=======================*/
+ /* out: TRUE if monitor table */
+ const char* table_name) /* in: name of the table, in the
+ form database/table_name */
+{
+ const char* name; /* table_name without database/ */
+ ulint len;
+
+ name = strchr(table_name, '/');
+ ut_a(name != NULL);
+ name++;
+ len = strlen(name) + 1;
+
+ if (STR_EQ(name, len, S_innodb_monitor)
+ || STR_EQ(name, len, S_innodb_lock_monitor)
+ || STR_EQ(name, len, S_innodb_tablespace_monitor)
+ || STR_EQ(name, len, S_innodb_table_monitor)
+ || STR_EQ(name, len, S_innodb_mem_validate)) {
+
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
=== modified file 'storage/innobase/row/row0sel.c'
--- a/storage/innobase/row/row0sel.c 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/row/row0sel.c 2008-06-12 00:08:07 +0000
@@ -2645,6 +2645,25 @@ row_sel_store_mysql_rec(
data = rec_get_nth_field(rec, offsets,
templ->rec_field_no, &len);
+
+ if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
+ && len != UNIV_SQL_NULL) {
+
+ /* It is a BLOB field locally stored in the
+ InnoDB record: we MUST copy its contents to
+ prebuilt->blob_heap here because later code
+ assumes all BLOB values have been copied to a
+ safe place. */
+
+ if (prebuilt->blob_heap == NULL) {
+ prebuilt->blob_heap = mem_heap_create(
+ UNIV_PAGE_SIZE);
+ }
+
+ data = memcpy(mem_heap_alloc(
+ prebuilt->blob_heap, len),
+ data, len);
+ }
}
if (len != UNIV_SQL_NULL) {
@@ -3583,7 +3602,9 @@ shortcut_fails_too_big_rec:
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
&& prebuilt->select_lock_type != LOCK_NONE
- && trx->mysql_query_str && trx->mysql_thd) {
+ && trx->mysql_thd != NULL
+ && trx->mysql_query_str != NULL
+ && *trx->mysql_query_str != NULL) {
/* Scan the MySQL query string; check if SELECT is the first
word there */
@@ -4582,7 +4603,7 @@ row_search_check_if_query_cache_permitte
Read the AUTOINC column from the current row. If the value is less than
0 and the type is not unsigned then we reset the value to 0. */
static
-ib_longlong
+ib_ulonglong
row_search_autoinc_read_column(
/*===========================*/
/* out: value read from the column */
@@ -4593,10 +4614,8 @@ row_search_autoinc_read_column(
{
ulint len;
const byte* data;
- ib_longlong value;
+ ib_ulonglong value;
mem_heap_t* heap = NULL;
- /* Our requirement is that dest should be word aligned. */
- byte dest[sizeof(value)];
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -4614,41 +4633,14 @@ row_search_autoinc_read_column(
ut_a(len != UNIV_SQL_NULL);
ut_a(len <= sizeof value);
- mach_read_int_type(dest, data, len, unsigned_type);
-
- /* The assumption here is that the AUTOINC value can't be negative
- and that dest is word aligned. */
- switch (len) {
- case 8:
- value = *(ib_longlong*) dest;
- break;
-
- case 4:
- value = *(ib_uint32_t*) dest;
- break;
-
- case 3:
- value = *(ib_uint32_t*) dest;
- value &= 0xFFFFFF;
- break;
-
- case 2:
- value = *(uint16 *) dest;
- break;
-
- case 1:
- value = *dest;
- break;
-
- default:
- ut_error;
- }
+ value = mach_read_int_type(data, len, unsigned_type);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
- if (!unsigned_type && value < 0) {
+ /* We assume that the autoinc counter can't be negative. */
+ if (!unsigned_type && (ib_longlong) value < 0) {
value = 0;
}
@@ -4687,7 +4679,7 @@ row_search_max_autoinc(
column name can't be found in index */
dict_index_t* index, /* in: index to search */
const char* col_name, /* in: name of autoinc column */
- ib_longlong* value) /* out: AUTOINC value read */
+ ib_ulonglong* value) /* out: AUTOINC value read */
{
ulint i;
ulint n_cols;
=== modified file 'storage/innobase/srv/srv0srv.c'
--- a/storage/innobase/srv/srv0srv.c 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/srv/srv0srv.c 2008-06-12 00:08:07 +0000
@@ -192,7 +192,7 @@ a heavier load on the I/O sub system. */
ulong srv_insert_buffer_batch_size = 20;
char* srv_file_flush_method_str = NULL;
-ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
+ulint srv_unix_file_flush_method = SRV_UNIX_FSYNC;
ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
ulint srv_max_n_open_files = 300;
@@ -1453,8 +1453,11 @@ srv_suspend_mysql_thread(
srv_n_lock_wait_count++;
srv_n_lock_wait_current_count++;
- ut_usectime(&sec, &ms);
- start_time = (ib_longlong)sec * 1000000 + ms;
+ if (ut_usectime(&sec, &ms) == -1) {
+ start_time = -1;
+ } else {
+ start_time = (ib_longlong)sec * 1000000 + ms;
+ }
}
/* Wake the lock timeout monitor thread, if it is suspended */
@@ -1508,14 +1511,20 @@ srv_suspend_mysql_thread(
wait_time = ut_difftime(ut_time(), slot->suspend_time);
if (thr->lock_state == QUE_THR_LOCK_ROW) {
- ut_usectime(&sec, &ms);
- finish_time = (ib_longlong)sec * 1000000 + ms;
+ if (ut_usectime(&sec, &ms) == -1) {
+ finish_time = -1;
+ } else {
+ finish_time = (ib_longlong)sec * 1000000 + ms;
+ }
diff_time = (ulint) (finish_time - start_time);
srv_n_lock_wait_current_count--;
srv_n_lock_wait_time = srv_n_lock_wait_time + diff_time;
- if (diff_time > srv_n_lock_max_wait_time) {
+ if (diff_time > srv_n_lock_max_wait_time &&
+ /* only update the variable if we successfully
+ retrieved the start and finish times. See Bug#36819. */
+ start_time != -1 && finish_time != -1) {
srv_n_lock_max_wait_time = diff_time;
}
}
@@ -1825,8 +1834,10 @@ srv_export_innodb_status(void)
= UT_LIST_GET_LEN(buf_pool->flush_list);
export_vars.innodb_buffer_pool_pages_free
= UT_LIST_GET_LEN(buf_pool->free);
+#ifdef UNIV_DEBUG
export_vars.innodb_buffer_pool_pages_latched
= buf_get_latched_pages_number();
+#endif /* UNIV_DEBUG */
export_vars.innodb_buffer_pool_pages_total = buf_pool->curr_size;
export_vars.innodb_buffer_pool_pages_misc = buf_pool->max_size
@@ -1904,12 +1915,6 @@ loop:
os_thread_sleep(1000000);
- /* In case mutex_exit is not a memory barrier, it is
- theoretically possible some threads are left waiting though
- the semaphore is already released. Wake up those threads: */
-
- sync_arr_wake_threads_if_sema_free();
-
current_time = time(NULL);
time_elapsed = difftime(current_time, last_monitor_time);
@@ -2106,9 +2111,15 @@ loop:
srv_refresh_innodb_monitor_stats();
}
+ /* In case mutex_exit is not a memory barrier, it is
+ theoretically possible some threads are left waiting though
+ the semaphore is already released. Wake up those threads: */
+
+ sync_arr_wake_threads_if_sema_free();
+
if (sync_array_print_long_waits()) {
fatal_cnt++;
- if (fatal_cnt > 5) {
+ if (fatal_cnt > 10) {
fprintf(stderr,
"InnoDB: Error: semaphore wait has lasted"
@@ -2128,7 +2139,7 @@ loop:
fflush(stderr);
- os_thread_sleep(2000000);
+ os_thread_sleep(1000000);
if (srv_shutdown_state < SRV_SHUTDOWN_CLEANUP) {
=== modified file 'storage/innobase/srv/srv0start.c'
--- a/storage/innobase/srv/srv0start.c 2008-03-31 09:37:03 +0000
+++ b/storage/innobase/srv/srv0start.c 2008-06-12 00:08:07 +0000
@@ -202,13 +202,13 @@ srv_parse_data_file_paths_and_sizes(
str = srv_parse_megabytes(str, &size);
- if (0 == memcmp(str, ":autoextend",
- (sizeof ":autoextend") - 1)) {
+ if (0 == strncmp(str, ":autoextend",
+ (sizeof ":autoextend") - 1)) {
str += (sizeof ":autoextend") - 1;
- if (0 == memcmp(str, ":max:",
- (sizeof ":max:") - 1)) {
+ if (0 == strncmp(str, ":max:",
+ (sizeof ":max:") - 1)) {
str += (sizeof ":max:") - 1;
@@ -290,14 +290,15 @@ srv_parse_data_file_paths_and_sizes(
(*data_file_names)[i] = path;
(*data_file_sizes)[i] = size;
- if (0 == memcmp(str, ":autoextend",
- (sizeof ":autoextend") - 1)) {
+ if (0 == strncmp(str, ":autoextend",
+ (sizeof ":autoextend") - 1)) {
*is_auto_extending = TRUE;
str += (sizeof ":autoextend") - 1;
- if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) {
+ if (0 == strncmp(str, ":max:",
+ (sizeof ":max:") - 1)) {
str += (sizeof ":max:") - 1;
@@ -1122,12 +1123,12 @@ innobase_start_or_create_for_mysql(void)
if (srv_file_flush_method_str == NULL) {
/* These are the default options */
- srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
+ srv_unix_file_flush_method = SRV_UNIX_FSYNC;
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
#ifndef __WIN__
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) {
- srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "fsync")) {
+ srv_unix_file_flush_method = SRV_UNIX_FSYNC;
} else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
=== modified file 'storage/innobase/sync/sync0arr.c'
--- a/storage/innobase/sync/sync0arr.c 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/sync/sync0arr.c 2008-06-12 00:08:07 +0000
@@ -40,24 +40,23 @@ because we can do with a very small numb
say 200. In NT 3.51, allocating events seems to be a quadratic
algorithm, because 10 000 events are created fast, but
100 000 events takes a couple of minutes to create.
-*/
+
+As of 5.0.30 the above mentioned design is changed. Since now
+OS can handle millions of wait events efficiently, we no longer
+have this concept of each cell of wait array having one event.
+Instead, now the event that a thread wants to wait on is embedded
+in the wait object (mutex or rw_lock). We still keep the global
+wait array for the sake of diagnostics and also to avoid infinite
+wait The error_monitor thread scans the global wait array to signal
+any waiting threads who have missed the signal. */
/* A cell where an individual thread may wait suspended
until a resource is released. The suspending is implemented
using an operating system event semaphore. */
struct sync_cell_struct {
- /* State of the cell. SC_WAKING_UP means
- sync_array_struct->n_reserved has been decremented, but the thread
- in this cell has not waken up yet. When it does, it will set the
- state to SC_FREE. Note that this is done without the protection of
- any mutex. */
- enum { SC_FREE, SC_RESERVED, SC_WAKING_UP } state;
-
void* wait_object; /* pointer to the object the
- thread is waiting for; this is not
- reseted to NULL when a cell is
- freed. */
-
+ thread is waiting for; if NULL
+ the cell is free for use */
mutex_t* old_wait_mutex; /* the latest wait mutex in cell */
rw_lock_t* old_wait_rw_lock;/* the latest wait rw-lock in cell */
ulint request_type; /* lock type requested on the
@@ -71,13 +70,23 @@ struct sync_cell_struct {
ibool waiting; /* TRUE if the thread has already
called sync_array_event_wait
on this cell */
- ibool event_set; /* TRUE if the event is set */
- os_event_t event; /* operating system event
- semaphore handle */
+ ib_longlong signal_count; /* We capture the signal_count
+ of the wait_object when we
+ reset the event. This value is
+ then passed on to os_event_wait
+ and we wait only if the event
+ has not been signalled in the
+ period between the reset and
+ wait call. */
time_t reservation_time;/* time when the thread reserved
the wait cell */
};
+/* NOTE: It is allowed for a thread to wait
+for an event allocated for the array without owning the
+protecting mutex (depending on the case: OS or database mutex), but
+all changes (set or reset) to the state of the event must be made
+while owning the mutex. */
struct sync_array_struct {
ulint n_reserved; /* number of currently reserved
cells in the wait array */
@@ -220,12 +229,9 @@ sync_array_create(
for (i = 0; i < n_cells; i++) {
cell = sync_array_get_nth_cell(arr, i);
- cell->state = SC_FREE;
- cell->wait_object = NULL;
-
- /* Create an operating system event semaphore with no name */
- cell->event = os_event_create(NULL);
- cell->event_set = FALSE; /* it is created in reset state */
+ cell->wait_object = NULL;
+ cell->waiting = FALSE;
+ cell->signal_count = 0;
}
return(arr);
@@ -239,19 +245,12 @@ sync_array_free(
/*============*/
sync_array_t* arr) /* in, own: sync wait array */
{
- ulint i;
- sync_cell_t* cell;
ulint protection;
ut_a(arr->n_reserved == 0);
sync_array_validate(arr);
- for (i = 0; i < arr->n_cells; i++) {
- cell = sync_array_get_nth_cell(arr, i);
- os_event_free(cell->event);
- }
-
protection = arr->protection;
/* Release the mutex protecting the wait array complex */
@@ -285,8 +284,7 @@ sync_array_validate(
for (i = 0; i < arr->n_cells; i++) {
cell = sync_array_get_nth_cell(arr, i);
-
- if (cell->state == SC_RESERVED) {
+ if (cell->wait_object != NULL) {
count++;
}
}
@@ -296,6 +294,29 @@ sync_array_validate(
sync_array_exit(arr);
}
+/***********************************************************************
+Puts the cell event in reset state. */
+static
+ib_longlong
+sync_cell_event_reset(
+/*==================*/
+ /* out: value of signal_count
+ at the time of reset. */
+ ulint type, /* in: lock type mutex/rw_lock */
+ void* object) /* in: the rw_lock/mutex object */
+{
+ if (type == SYNC_MUTEX) {
+ return(os_event_reset(((mutex_t *) object)->event));
+#ifdef __WIN__
+ } else if (type == RW_LOCK_WAIT_EX) {
+ return(os_event_reset(
+ ((rw_lock_t *) object)->wait_ex_event));
+#endif
+ } else {
+ return(os_event_reset(((rw_lock_t *) object)->event));
+ }
+}
+
/**********************************************************************
Reserves a wait array cell for waiting for an object.
The event of the cell is reset to nonsignalled state. */
@@ -324,21 +345,9 @@ sync_array_reserve_cell(
for (i = 0; i < arr->n_cells; i++) {
cell = sync_array_get_nth_cell(arr, i);
- if (cell->state == SC_FREE) {
-
- /* We do not check cell->event_set because it is
- set outside the protection of the sync array mutex
- and we had a bug regarding it, and since resetting
- an event when it is not needed does no harm it is
- safer always to do it. */
-
- cell->event_set = FALSE;
- os_event_reset(cell->event);
-
- cell->state = SC_RESERVED;
- cell->reservation_time = time(NULL);
- cell->thread = os_thread_get_curr_id();
+ if (cell->wait_object == NULL) {
+ cell->waiting = FALSE;
cell->wait_object = object;
if (type == SYNC_MUTEX) {
@@ -348,7 +357,6 @@ sync_array_reserve_cell(
}
cell->request_type = type;
- cell->waiting = FALSE;
cell->file = file;
cell->line = line;
@@ -359,6 +367,16 @@ sync_array_reserve_cell(
sync_array_exit(arr);
+ /* Make sure the event is reset and also store
+ the value of signal_count at which the event
+ was reset. */
+ cell->signal_count = sync_cell_event_reset(type,
+ object);
+
+ cell->reservation_time = time(NULL);
+
+ cell->thread = os_thread_get_curr_id();
+
return;
}
}
@@ -369,68 +387,6 @@ sync_array_reserve_cell(
}
/**********************************************************************
-Frees the cell. Note that we don't have any mutex reserved when calling
-this. */
-static
-void
-sync_array_free_cell(
-/*=================*/
- sync_array_t* arr, /* in: wait array */
- ulint index) /* in: index of the cell in array */
-{
- sync_cell_t* cell;
-
- cell = sync_array_get_nth_cell(arr, index);
-
- ut_a(cell->state == SC_WAKING_UP);
- ut_a(cell->wait_object != NULL);
-
- cell->state = SC_FREE;
-}
-
-/**********************************************************************
-Frees the cell safely by reserving the sync array mutex and decrementing
-n_reserved if necessary. Should only be called from mutex_spin_wait. */
-
-void
-sync_array_free_cell_protected(
-/*===========================*/
- sync_array_t* arr, /* in: wait array */
- ulint index) /* in: index of the cell in array */
-{
- sync_cell_t* cell;
-
- sync_array_enter(arr);
-
- cell = sync_array_get_nth_cell(arr, index);
-
- ut_a(cell->state != SC_FREE);
- ut_a(cell->wait_object != NULL);
-
- /* We only need to decrement n_reserved if it has not already been
- done by sync_array_signal_object. */
- if (cell->state == SC_RESERVED) {
- ut_a(arr->n_reserved > 0);
- arr->n_reserved--;
- } else if (cell->state == SC_WAKING_UP) {
- /* This is tricky; if we don't wait for the event to be
- signaled, signal_object can set the state of a cell to
- SC_WAKING_UP, mutex_spin_wait can call this and set the
- state to SC_FREE, and then signal_object gets around to
- calling os_set_event for the cell but since it's already
- been freed things break horribly. */
-
- sync_array_exit(arr);
- os_event_wait(cell->event);
- sync_array_enter(arr);
- }
-
- cell->state = SC_FREE;
-
- sync_array_exit(arr);
-}
-
-/**********************************************************************
This function should be called when a thread starts to wait on
a wait array cell. In the debug version this function checks
if the wait for a semaphore will result in a deadlock, in which
@@ -447,15 +403,28 @@ sync_array_wait_event(
ut_a(arr);
+ sync_array_enter(arr);
+
cell = sync_array_get_nth_cell(arr, index);
- ut_a((cell->state == SC_RESERVED) || (cell->state == SC_WAKING_UP));
ut_a(cell->wait_object);
ut_a(!cell->waiting);
ut_ad(os_thread_get_curr_id() == cell->thread);
- event = cell->event;
- cell->waiting = TRUE;
+ if (cell->request_type == SYNC_MUTEX) {
+ event = ((mutex_t*) cell->wait_object)->event;
+#ifdef __WIN__
+ /* On windows if the thread about to wait is the one which
+ has set the state of the rw_lock to RW_LOCK_WAIT_EX, then
+ it waits on a special event i.e.: wait_ex_event. */
+ } else if (cell->request_type == RW_LOCK_WAIT_EX) {
+ event = ((rw_lock_t*) cell->wait_object)->wait_ex_event;
+#endif
+ } else {
+ event = ((rw_lock_t*) cell->wait_object)->event;
+ }
+
+ cell->waiting = TRUE;
#ifdef UNIV_SYNC_DEBUG
@@ -464,7 +433,6 @@ sync_array_wait_event(
recursively sync_array routines, leading to trouble.
rw_lock_debug_mutex freezes the debug lists. */
- sync_array_enter(arr);
rw_lock_debug_mutex_enter();
if (TRUE == sync_array_detect_deadlock(arr, cell, cell, 0)) {
@@ -474,16 +442,16 @@ sync_array_wait_event(
}
rw_lock_debug_mutex_exit();
- sync_array_exit(arr);
#endif
- os_event_wait(event);
+ sync_array_exit(arr);
+
+ os_event_wait_low(event, cell->signal_count);
sync_array_free_cell(arr, index);
}
/**********************************************************************
-Reports info of a wait array cell. Note: sync_array_print_long_waits()
-calls this without mutex protection. */
+Reports info of a wait array cell. */
static
void
sync_array_cell_print(
@@ -503,17 +471,8 @@ sync_array_cell_print(
(ulong) os_thread_pf(cell->thread), cell->file,
(ulong) cell->line,
difftime(time(NULL), cell->reservation_time));
- fprintf(file, "Wait array cell state %lu\n", (ulong)cell->state);
-
- /* If the memory area pointed to by old_wait_mutex /
- old_wait_rw_lock has been freed, this can crash. */
-
- if (cell->state != SC_RESERVED) {
- /* If cell has this state, then even if we are holding the sync
- array mutex, the wait object may get freed meanwhile. Do not
- print the wait object then. */
- } else if (type == SYNC_MUTEX) {
+ if (type == SYNC_MUTEX) {
/* We use old_wait_mutex in case the cell has already
been freed meanwhile */
mutex = cell->old_wait_mutex;
@@ -531,7 +490,11 @@ sync_array_cell_print(
#endif /* UNIV_SYNC_DEBUG */
(ulong) mutex->waiters);
- } else if (type == RW_LOCK_EX || type == RW_LOCK_SHARED) {
+ } else if (type == RW_LOCK_EX
+#ifdef __WIN__
+ || type == RW_LOCK_WAIT_EX
+#endif
+ || type == RW_LOCK_SHARED) {
fputs(type == RW_LOCK_EX ? "X-lock on" : "S-lock on", file);
@@ -565,8 +528,8 @@ sync_array_cell_print(
ut_error;
}
- if (cell->event_set) {
- fputs("wait is ending\n", file);
+ if (!cell->waiting) {
+ fputs("wait has ended\n", file);
}
}
@@ -589,7 +552,7 @@ sync_array_find_thread(
cell = sync_array_get_nth_cell(arr, i);
- if ((cell->state == SC_RESERVED)
+ if (cell->wait_object != NULL
&& os_thread_eq(cell->thread, thread)) {
return(cell); /* Found */
@@ -679,7 +642,7 @@ sync_array_detect_deadlock(
depth++;
- if (cell->event_set || !cell->waiting) {
+ if (!cell->waiting) {
return(FALSE); /* No deadlock here */
}
@@ -704,10 +667,8 @@ sync_array_detect_deadlock(
depth);
if (ret) {
fprintf(stderr,
- "Mutex %p owned by thread %lu"
- " file %s line %lu\n",
- (void*) mutex,
- (ulong) os_thread_pf(mutex->thread_id),
+ "Mutex %p owned by thread %lu file %s line %lu\n",
+ mutex, (ulong) os_thread_pf(mutex->thread_id),
mutex->file_name, (ulong) mutex->line);
sync_array_cell_print(stderr, cell);
@@ -717,7 +678,8 @@ sync_array_detect_deadlock(
return(FALSE); /* No deadlock */
- } else if (cell->request_type == RW_LOCK_EX) {
+ } else if (cell->request_type == RW_LOCK_EX
+ || cell->request_type == RW_LOCK_WAIT_EX) {
lock = cell->wait_object;
@@ -816,7 +778,8 @@ sync_arr_cell_can_wake_up(
return(TRUE);
}
- } else if (cell->request_type == RW_LOCK_EX) {
+ } else if (cell->request_type == RW_LOCK_EX
+ || cell->request_type == RW_LOCK_WAIT_EX) {
lock = cell->wait_object;
@@ -845,101 +808,47 @@ sync_arr_cell_can_wake_up(
return(FALSE);
}
-/**************************************************************************
-Looks for the cells in the wait array which refer to the wait object
-specified, and sets their corresponding events to the signaled state. In this
-way releases the threads waiting for the object to contend for the object.
-It is possible that no such cell is found, in which case does nothing. */
+/**********************************************************************
+Frees the cell. NOTE! sync_array_wait_event frees the cell
+automatically! */
void
-sync_array_signal_object(
-/*=====================*/
+sync_array_free_cell(
+/*=================*/
sync_array_t* arr, /* in: wait array */
- void* object) /* in: wait object */
+ ulint index) /* in: index of the cell in array */
{
sync_cell_t* cell;
- ulint count;
- ulint i;
- ulint res_count;
-
- /* We store the addresses of cells we need to signal and signal
- them only after we have released the sync array's mutex (for
- performance reasons). cell_count is the number of such cells, and
- cell_ptr points to the first one. If there are less than
- UT_ARR_SIZE(cells) of them, cell_ptr == &cells[0], otherwise
- cell_ptr points to malloc'd memory that we must free. */
-
- sync_cell_t* cells[100];
- sync_cell_t** cell_ptr = &cells[0];
- ulint cell_count = 0;
- ulint cell_max_count = UT_ARR_SIZE(cells);
-
- ut_a(100 == cell_max_count);
sync_array_enter(arr);
- arr->sg_count++;
-
- i = 0;
- count = 0;
-
- /* We need to store this to a local variable because it is modified
- inside the loop */
- res_count = arr->n_reserved;
-
- while (count < res_count) {
+ cell = sync_array_get_nth_cell(arr, index);
- cell = sync_array_get_nth_cell(arr, i);
+ ut_a(cell->wait_object != NULL);
- if (cell->state == SC_RESERVED) {
+ cell->waiting = FALSE;
+ cell->wait_object = NULL;
+ cell->signal_count = 0;
- count++;
- if (cell->wait_object == object) {
- cell->state = SC_WAKING_UP;
+ ut_a(arr->n_reserved > 0);
+ arr->n_reserved--;
- ut_a(arr->n_reserved > 0);
- arr->n_reserved--;
+ sync_array_exit(arr);
+}
- if (cell_count == cell_max_count) {
- sync_cell_t** old_cell_ptr = cell_ptr;
- size_t old_size, new_size;
-
- old_size = cell_max_count
- * sizeof(sync_cell_t*);
- cell_max_count *= 2;
- new_size = cell_max_count
- * sizeof(sync_cell_t*);
-
- cell_ptr = malloc(new_size);
- ut_a(cell_ptr);
- memcpy(cell_ptr, old_cell_ptr,
- old_size);
-
- if (old_cell_ptr != &cells[0]) {
- free(old_cell_ptr);
- }
- }
+/**************************************************************************
+Increments the signalled count. */
- cell_ptr[cell_count] = cell;
- cell_count++;
- }
- }
+void
+sync_array_object_signalled(
+/*========================*/
+ sync_array_t* arr) /* in: wait array */
+{
+ sync_array_enter(arr);
- i++;
- }
+ arr->sg_count++;
sync_array_exit(arr);
-
- for (i = 0; i < cell_count; i++) {
- cell = cell_ptr[i];
-
- cell->event_set = TRUE;
- os_event_set(cell->event);
- }
-
- if (cell_ptr != &cells[0]) {
- free(cell_ptr);
- }
}
/**************************************************************************
@@ -959,33 +868,41 @@ sync_arr_wake_threads_if_sema_free(void)
sync_cell_t* cell;
ulint count;
ulint i;
- ulint res_count;
sync_array_enter(arr);
i = 0;
count = 0;
- /* We need to store this to a local variable because it is modified
- inside the loop */
-
- res_count = arr->n_reserved;
-
- while (count < res_count) {
+ while (count < arr->n_reserved) {
cell = sync_array_get_nth_cell(arr, i);
- if (cell->state == SC_RESERVED) {
+ if (cell->wait_object != NULL) {
count++;
if (sync_arr_cell_can_wake_up(cell)) {
- cell->state = SC_WAKING_UP;
- cell->event_set = TRUE;
- os_event_set(cell->event);
- ut_a(arr->n_reserved > 0);
- arr->n_reserved--;
+ if (cell->request_type == SYNC_MUTEX) {
+ mutex_t* mutex;
+
+ mutex = cell->wait_object;
+ os_event_set(mutex->event);
+#ifdef __WIN__
+ } else if (cell->request_type
+ == RW_LOCK_WAIT_EX) {
+ rw_lock_t* lock;
+
+ lock = cell->wait_object;
+ os_event_set(lock->wait_ex_event);
+#endif
+ } else {
+ rw_lock_t* lock;
+
+ lock = cell->wait_object;
+ os_event_set(lock->event);
+ }
}
}
@@ -1015,7 +932,7 @@ sync_array_print_long_waits(void)
cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
- if ((cell->state != SC_FREE)
+ if (cell->wait_object != NULL && cell->waiting
&& difftime(time(NULL), cell->reservation_time) > 240) {
fputs("InnoDB: Warning: a long semaphore wait:\n",
stderr);
@@ -1023,7 +940,7 @@ sync_array_print_long_waits(void)
noticed = TRUE;
}
- if ((cell->state != SC_FREE)
+ if (cell->wait_object != NULL && cell->waiting
&& difftime(time(NULL), cell->reservation_time)
> fatal_timeout) {
fatal = TRUE;
@@ -1072,20 +989,25 @@ sync_array_output_info(
mutex */
{
sync_cell_t* cell;
+ ulint count;
ulint i;
fprintf(file,
- "OS WAIT ARRAY INFO: reservation count %ld,"
- " signal count %ld\n",
- (long) arr->res_count,
- (long) arr->sg_count);
- for (i = 0; i < arr->n_cells; i++) {
+ "OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n",
+ (long) arr->res_count, (long) arr->sg_count);
+ i = 0;
+ count = 0;
+
+ while (count < arr->n_reserved) {
cell = sync_array_get_nth_cell(arr, i);
- if (cell->state != SC_FREE) {
+ if (cell->wait_object != NULL) {
+ count++;
sync_array_cell_print(file, cell);
}
+
+ i++;
}
}
=== modified file 'storage/innobase/sync/sync0rw.c'
--- a/storage/innobase/sync/sync0rw.c 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/sync/sync0rw.c 2008-06-12 00:08:07 +0000
@@ -151,6 +151,11 @@ rw_lock_create_func(
lock->last_x_file_name = "not yet reserved";
lock->last_s_line = 0;
lock->last_x_line = 0;
+ lock->event = os_event_create(NULL);
+
+#ifdef __WIN__
+ lock->wait_ex_event = os_event_create(NULL);
+#endif
mutex_enter(&rw_lock_list_mutex);
@@ -184,6 +189,11 @@ rw_lock_free(
mutex_free(rw_lock_get_mutex(lock));
mutex_enter(&rw_lock_list_mutex);
+ os_event_free(lock->event);
+
+#ifdef __WIN__
+ os_event_free(lock->wait_ex_event);
+#endif
if (UT_LIST_GET_PREV(list, lock)) {
ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
@@ -544,7 +554,15 @@ lock_loop:
rw_x_system_call_count++;
sync_array_reserve_cell(sync_primary_wait_array,
- lock, RW_LOCK_EX,
+ lock,
+#ifdef __WIN__
+ /* On windows RW_LOCK_WAIT_EX signifies
+ that this thread should wait on the
+ special wait_ex_event. */
+ (state == RW_LOCK_WAIT_EX)
+ ? RW_LOCK_WAIT_EX :
+#endif
+ RW_LOCK_EX,
file_name, line,
&index);
=== modified file 'storage/innobase/sync/sync0sync.c'
--- a/storage/innobase/sync/sync0sync.c 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/sync/sync0sync.c 2008-06-12 00:08:07 +0000
@@ -95,17 +95,47 @@ have happened that the thread which was
it and did not see the waiters byte set to 1, a case which would lead the
other thread to an infinite wait.
-LEMMA 1: After a thread resets the event of the cell it reserves for waiting
-========
-for a mutex, some thread will eventually call sync_array_signal_object with
-the mutex as an argument. Thus no infinite wait is possible.
+LEMMA 1: After a thread resets the event of a mutex (or rw_lock), some
+=======
+thread will eventually call os_event_set() on that particular event.
+Thus no infinite wait is possible in this case.
Proof: After making the reservation the thread sets the waiters field in the
mutex to 1. Then it checks that the mutex is still reserved by some thread,
or it reserves the mutex for itself. In any case, some thread (which may be
also some earlier thread, not necessarily the one currently holding the mutex)
will set the waiters field to 0 in mutex_exit, and then call
-sync_array_signal_object with the mutex as an argument.
+os_event_set() with the mutex as an argument.
+Q.E.D.
+
+LEMMA 2: If an os_event_set() call is made after some thread has called
+=======
+the os_event_reset() and before it starts wait on that event, the call
+will not be lost to the second thread. This is true even if there is an
+intervening call to os_event_reset() by another thread.
+Thus no infinite wait is possible in this case.
+
+Proof (non-windows platforms): os_event_reset() returns a monotonically
+increasing value of signal_count. This value is increased at every
+call of os_event_set() If thread A has called os_event_reset() followed
+by thread B calling os_event_set() and then some other thread C calling
+os_event_reset(), the is_set flag of the event will be set to FALSE;
+but now if thread A calls os_event_wait_low() with the signal_count
+value returned from the earlier call of os_event_reset(), it will
+return immediately without waiting.
+Q.E.D.
+
+Proof (windows): If there is a writer thread which is forced to wait for
+the lock, it may be able to set the state of rw_lock to RW_LOCK_WAIT_EX
+The design of rw_lock ensures that there is one and only one thread
+that is able to change the state to RW_LOCK_WAIT_EX and this thread is
+guaranteed to acquire the lock after it is released by the current
+holders and before any other waiter gets the lock.
+On windows this thread waits on a separate event i.e.: wait_ex_event.
+Since only one thread can wait on this event there is no chance
+of this event getting reset before the writer starts wait on it.
+Therefore, this thread is guaranteed to catch the os_set_event()
+signalled unconditionally at the release of the lock.
Q.E.D. */
/* The number of system calls made in this module. Intended for performance
@@ -217,6 +247,7 @@ mutex_create_func(
os_fast_mutex_init(&(mutex->os_fast_mutex));
mutex->lock_word = 0;
#endif
+ mutex->event = os_event_create(NULL);
mutex_set_waiters(mutex, 0);
#ifdef UNIV_DEBUG
mutex->magic_n = MUTEX_MAGIC_N;
@@ -300,6 +331,8 @@ mutex_free(
mutex_exit(&mutex_list_mutex);
}
+ os_event_free(mutex->event);
+
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
os_fast_mutex_free(&(mutex->os_fast_mutex));
#endif
@@ -509,8 +542,7 @@ spin_loop:
if (mutex_test_and_set(mutex) == 0) {
/* Succeeded! Free the reserved wait cell */
- sync_array_free_cell_protected(sync_primary_wait_array,
- index);
+ sync_array_free_cell(sync_primary_wait_array, index);
ut_d(mutex->thread_id = os_thread_get_curr_id());
#ifdef UNIV_SYNC_DEBUG
@@ -591,8 +623,8 @@ mutex_signal_object(
/* The memory order of resetting the waiters field and
signaling the object is important. See LEMMA 1 above. */
-
- sync_array_signal_object(sync_primary_wait_array, mutex);
+ os_event_set(mutex->event);
+ sync_array_object_signalled(sync_primary_wait_array);
}
#ifdef UNIV_SYNC_DEBUG
@@ -1130,6 +1162,7 @@ sync_thread_add_level(
break;
case SYNC_TREE_NODE:
ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE)
+ || sync_thread_levels_contain(array, SYNC_DICT_OPERATION)
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1));
break;
case SYNC_TREE_NODE_NEW:
=== modified file 'storage/innobase/trx/trx0trx.c'
--- a/storage/innobase/trx/trx0trx.c 2008-05-15 20:56:38 +0000
+++ b/storage/innobase/trx/trx0trx.c 2008-06-12 00:08:07 +0000
@@ -757,8 +757,8 @@ trx_commit_off_kernel(
mutex_enter(&(rseg->mutex));
if (trx->insert_undo != NULL) {
- trx_undo_set_state_at_finish(trx, trx->insert_undo,
- &mtr);
+ trx_undo_set_state_at_finish(
+ rseg, trx, trx->insert_undo, &mtr);
}
undo = trx->update_undo;
@@ -774,7 +774,7 @@ trx_commit_off_kernel(
transaction commit for this transaction. */
update_hdr_page = trx_undo_set_state_at_finish(
- trx, undo, &mtr);
+ rseg, trx, undo, &mtr);
/* We have to do the cleanup for the update log while
holding the rseg mutex because update log headers
@@ -933,6 +933,7 @@ trx_commit_off_kernel(
trx->rseg = NULL;
trx->undo_no = ut_dulint_zero;
trx->last_sql_stat_start.least_undo_no = ut_dulint_zero;
+ trx->mysql_query_str = NULL;
ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
ut_ad(UT_LIST_GET_LEN(trx->trx_locks) == 0);
=== modified file 'storage/innobase/trx/trx0undo.c'
--- a/storage/innobase/trx/trx0undo.c 2008-03-31 09:37:03 +0000
+++ b/storage/innobase/trx/trx0undo.c 2008-06-12 00:08:07 +0000
@@ -1725,6 +1725,7 @@ trx_undo_set_state_at_finish(
/*=========================*/
/* out: undo log segment header page,
x-latched */
+ trx_rseg_t* rseg, /* in: rollback segment memory object */
trx_t* trx __attribute__((unused)), /* in: transaction */
trx_undo_t* undo, /* in: undo log memory copy */
mtr_t* mtr) /* in: mtr */
@@ -1734,7 +1735,10 @@ trx_undo_set_state_at_finish(
page_t* undo_page;
ulint state;
- ut_ad(trx && undo && mtr);
+ ut_ad(trx);
+ ut_ad(undo);
+ ut_ad(mtr);
+ ut_ad(mutex_own(&rseg->mutex));
if (undo->id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
@@ -1748,9 +1752,23 @@ trx_undo_set_state_at_finish(
seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
- if (undo->size == 1 && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE)
- < TRX_UNDO_PAGE_REUSE_LIMIT) {
- state = TRX_UNDO_CACHED;
+ if (undo->size == 1
+ && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE)
+ < TRX_UNDO_PAGE_REUSE_LIMIT) {
+
+ /* This is a heuristic to avoid the problem of all UNDO
+ slots ending up in one of the UNDO lists. Previously if
+ the server crashed with all the slots in one of the lists,
+ transactions that required the slots of a different type
+ would fail for lack of slots. */
+
+ if (UT_LIST_GET_LEN(rseg->update_undo_list) < 500
+ && UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) {
+
+ state = TRX_UNDO_CACHED;
+ } else {
+ state = TRX_UNDO_TO_FREE;
+ }
} else if (undo->type == TRX_UNDO_INSERT) {
=== modified file 'storage/innobase/ut/ut0ut.c'
--- a/storage/innobase/ut/ut0ut.c 2007-11-06 22:42:58 +0000
+++ b/storage/innobase/ut/ut0ut.c 2008-06-12 00:08:07 +0000
@@ -112,19 +112,45 @@ ut_time(void)
}
/**************************************************************
-Returns system time. */
+Returns system time.
+Upon successful completion, the value 0 is returned; otherwise the
+value -1 is returned and the global variable errno is set to indicate the
+error. */
-void
+int
ut_usectime(
/*========*/
+ /* out: 0 on success, -1 otherwise */
ulint* sec, /* out: seconds since the Epoch */
ulint* ms) /* out: microseconds since the Epoch+*sec */
{
struct timeval tv;
+ int ret;
+ int errno_gettimeofday;
+ int i;
+
+ for (i = 0; i < 10; i++) {
+
+ ret = ut_gettimeofday(&tv, NULL);
+
+ if (ret == -1) {
+ errno_gettimeofday = errno;
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: gettimeofday(): %s\n",
+ strerror(errno_gettimeofday));
+ os_thread_sleep(100000); /* 0.1 sec */
+ errno = errno_gettimeofday;
+ } else {
+ break;
+ }
+ }
+
+ if (ret != -1) {
+ *sec = (ulint) tv.tv_sec;
+ *ms = (ulint) tv.tv_usec;
+ }
- ut_gettimeofday(&tv, NULL);
- *sec = (ulint) tv.tv_sec;
- *ms = (ulint) tv.tv_usec;
+ return(ret);
}
/**************************************************************
| Thread |
|---|
| • bzr commit into mysql-6.0-backup branch (oystein.grovlen:2643) | Oystein Grovlen | 25 Jun |