diff options
217 files changed, 17682 insertions, 14864 deletions
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 67820e289ab..de2fbb3c295 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1784,7 +1784,7 @@ innodb_sync_spin_loops 20 show variables like "innodb_thread_concurrency"; Variable_name Value innodb_thread_concurrency 20 -set global innodb_thread_concurrency=1000; +set global innodb_thread_concurrency=1001; show variables like "innodb_thread_concurrency"; Variable_name Value innodb_thread_concurrency 1000 @@ -2661,6 +2661,32 @@ insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +a hex(b) hex(c) filler +1 61626364656667 61626364656667 boo +4 D0B1 D0B1 eight +4 5B 5B five +4 E880BD E880BD four +4 E880BDD0B1E880BD E880BDD0B1E880BD seven +4 E880BDE880BD E880BDE880BD six +3 71727374757677 71727374757677 three +2 696A6B696C6D6E 696A6B696C6D6E two +select a,hex(b),hex(c),filler from t2 order by filler; +a hex(b) hex(c) filler +4 05630563 05630563 email +4 0563 0563 email +4 05612020 05612020 email +4 01FC 01FC email +4 0120 0120 email +4 00640065 00640065 email +4 00E400E50068 00E400E50068 email +4 0000E400 0000E400 email +4 0000563001FC0563 0000563001FC0563 email +1 0061006200630064006500660067 0061006200630064006500660067 one +3 0071007200730074007500760077 0071007200730074007500760077 three +2 0069006A006B0069006C006D006E 0069006A006B0069006C006D006E two drop table t1; drop table t2; create table t1 ( @@ -2689,6 +2715,32 @@ insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +a hex(b) hex(c) filler +1 61626364656667 61626364656667 boo +4 D0B1 D0B1 eight +4 5B 5B five +4 E880BD E880BD four +4 E880BDD0B1E880BD E880BDD0B1E880BD seven +4 E880BDE880BD E880BDE880BD six +3 71727374757677 71727374757677 three +2 696A6B696C6D6E 696A6B696C6D6E two +select a,hex(b),hex(c),filler from t2 order by filler; +a hex(b) hex(c) filler +4 05630563 05630563 email +4 0563 0563 email +4 05612020 05612020 email +4 01FC 01FC email +4 0120 0120 email +4 00640065 00640065 email +4 00E400E50068 00E400E50068 email +4 0000E400 0000E400 email +4 0000563001FC0563 0000563001FC0563 email +1 0061006200630064006500660067 0061006200630064006500660067 one +3 0071007200730074007500760077 0071007200730074007500760077 three +2 0069006A006B0069006C006D006E 0069006A006B0069006C006D006E two drop table t1; drop table t2; create table t1 ( @@ -2717,6 +2769,32 @@ insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +a hex(b) hex(c) filler +1 61626364656667 61626364656667 boo +4 D0B1 D0B1 eight +4 5B 5B five +4 E880BD E880BD four +4 E880BDD0B1E880BD E880BDD0B1E880BD seven +4 E880BDE880BD E880BDE880BD six +3 71727374757677 71727374757677 three +2 696A6B696C6D6E 696A6B696C6D6E two +select a,hex(b),hex(c),filler from t2 order by filler; +a hex(b) hex(c) filler +4 0120 0120 email +4 01FC 01FC email +4 0563 0563 email +4 0000563001FC0563 0000563001FC0563 email +4 0000E400 0000E400 email +4 00640065 00640065 email +4 00E400E50068 00E400E50068 email +4 05612020 05612020 email +4 05630563 05630563 email +1 0061006200630064006500660067 0061006200630064006500660067 one +3 0071007200730074007500760077 0071007200730074007500760077 three +2 0069006A006B0069006C006D006E 0069006A006B0069006C006D006E two drop table t1; drop table t2; create table t1 ( @@ -2741,9 +2819,92 @@ insert into t2 values (4,_ucs2 0x01fc,_ucs2 0x01fc,'seven'); insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight'); insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +a hex(b) hex(c) filler +1 61626364656667 61626364656667 boo +4 D0B1 D0B1 eight +4 5B 5B five +4 E880BD E880BD four +3 71727374757677 71727374757677 three +2 696A6B696C6D6E 696A6B696C6D6E two +select a,hex(b),hex(c),filler from t2 order by filler; +a hex(b) hex(c) filler +4 0000E400 0000E400 email +4 00640065 00640065 email +4 00E400E50068 00E400E50068 email +4 0120 0120 email +4 01FC 01FC email +4 05612020 05612020 email +4 0563 0563 email +1 61626364656667 61626364656667 one +3 71727374757677 71727374757677 three +2 696A6B696C6D6E 696A6B696C6D6E two drop table t1; drop table t2; commit; +set foreign_key_checks=0; +create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +ERROR HY000: Can't create table 'test.t1' (errno: 150) +set foreign_key_checks=1; +drop table t2; +set foreign_key_checks=0; +create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8; +ERROR HY000: Can't create table 'test.t2' (errno: 150) +set foreign_key_checks=1; +drop table t1; +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb; +create table t1(a varchar(10) primary key) engine = innodb; +alter table t1 modify column a int; +Got one of the listed errors +set foreign_key_checks=1; +drop table t2,t1; +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; +create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +alter table t1 convert to character set utf8; +set foreign_key_checks=1; +drop table t2,t1; +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; +create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; +rename table t3 to t1; +ERROR HY000: Error on rename of './test/t3' to './test/t1' (errno: 150) +set foreign_key_checks=1; +drop table t2,t3; +create table t1(a int primary key) row_format=redundant engine=innodb; +create table t2(a int primary key,constraint foreign key(a)references t1(a)) row_format=compact engine=innodb; +create table t3(a int primary key) row_format=compact engine=innodb; +create table t4(a int primary key,constraint foreign key(a)references t3(a)) row_format=redundant engine=innodb; +insert into t1 values(1); +insert into t3 values(1); +insert into t2 values(2); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +insert into t4 values(2); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +insert into t2 values(1); +insert into t4 values(1); +update t1 set a=2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +update t2 set a=2; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +update t3 set a=2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +update t4 set a=2; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +truncate t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +truncate t3; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +truncate t2; +truncate t4; +truncate t1; +truncate t3; +drop table t4,t3,t2,t1; create table t1 (a varchar(255) character set utf8, b varchar(255) character set utf8, c varchar(255) character set utf8, @@ -2757,7 +2918,284 @@ d varchar(255) character set utf8, e varchar(255) character set utf8, key (a,b,c,d,e)) engine=innodb; ERROR 42000: Specified key was too long; max key length is 3072 bytes -End of 5.0 tests +create table t1 (s1 varbinary(2),primary key (s1)) engine=innodb; +create table t2 (s1 binary(2),primary key (s1)) engine=innodb; +create table t3 (s1 varchar(2) binary,primary key (s1)) engine=innodb; +create table t4 (s1 char(2) binary,primary key (s1)) engine=innodb; +insert into t1 values (0x41),(0x4120),(0x4100); +insert into t2 values (0x41),(0x4120),(0x4100); +ERROR 23000: Duplicate entry 'A' for key 'PRIMARY' +insert into t2 values (0x41),(0x4120); +insert into t3 values (0x41),(0x4120),(0x4100); +ERROR 23000: Duplicate entry 'A ' for key 'PRIMARY' +insert into t3 values (0x41),(0x4100); +insert into t4 values (0x41),(0x4120),(0x4100); +ERROR 23000: Duplicate entry 'A' for key 'PRIMARY' +insert into t4 values (0x41),(0x4100); +select hex(s1) from t1; +hex(s1) +41 +4100 +4120 +select hex(s1) from t2; +hex(s1) +4100 +4120 +select hex(s1) from t3; +hex(s1) +4100 +41 +select hex(s1) from t4; +hex(s1) +4100 +41 +drop table t1,t2,t3,t4; +create table t1 (a int primary key,s1 varbinary(3) not null unique) engine=innodb; +create table t2 (s1 binary(2) not null, constraint c foreign key(s1) references t1(s1) on update cascade) engine=innodb; +insert into t1 values(1,0x4100),(2,0x41),(3,0x4120),(4,0x42); +insert into t2 values(0x42); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +insert into t2 values(0x41); +select hex(s1) from t2; +hex(s1) +4100 +update t1 set s1=0x123456 where a=2; +select hex(s1) from t2; +hex(s1) +4100 +update t1 set s1=0x12 where a=1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +update t1 set s1=0x12345678 where a=1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +update t1 set s1=0x123457 where a=1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +update t1 set s1=0x1220 where a=1; +select hex(s1) from t2; +hex(s1) +1220 +update t1 set s1=0x1200 where a=1; +select hex(s1) from t2; +hex(s1) +1200 +update t1 set s1=0x4200 where a=1; +select hex(s1) from t2; +hex(s1) +4200 +delete from t1 where a=1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +delete from t1 where a=2; +update t2 set s1=0x4120; +delete from t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +delete from t1 where a!=3; +select a,hex(s1) from t1; +a hex(s1) +3 4120 +select hex(s1) from t2; +hex(s1) +4120 +drop table t2,t1; +create table t1 (a int primary key,s1 varchar(2) binary not null unique) engine=innodb; +create table t2 (s1 char(2) binary not null, constraint c foreign key(s1) references t1(s1) on update cascade) engine=innodb; +insert into t1 values(1,0x4100),(2,0x41); +insert into t2 values(0x41); +select hex(s1) from t2; +hex(s1) +41 +update t1 set s1=0x1234 where a=1; +select hex(s1) from t2; +hex(s1) +41 +update t1 set s1=0x12 where a=2; +select hex(s1) from t2; +hex(s1) +12 +delete from t1 where a=1; +delete from t1 where a=2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +select a,hex(s1) from t1; +a hex(s1) +2 12 +select hex(s1) from t2; +hex(s1) +12 +drop table t2,t1; +CREATE TABLE t1 ( +ind enum('0','1','2') NOT NULL default '0', +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( +ind enum('0','1','2') NOT NULL default '0', +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; +INSERT INTO t1 VALUES ('1', ''),('2', ''); +INSERT INTO t2 VALUES ('1', ''),('2', ''); +SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1; +hex(ind) hex(string1) +31 +32 +SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1; +hex(ind) hex(string1) +0031 +0032 +drop table t1,t2; +CREATE TABLE t1 ( +ind set('0','1','2') NOT NULL default '0', +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( +ind set('0','1','2') NOT NULL default '0', +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; +INSERT INTO t1 VALUES ('1', ''),('2', ''); +INSERT INTO t2 VALUES ('1', ''),('2', ''); +SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1; +hex(ind) hex(string1) +31 +32 +SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1; +hex(ind) hex(string1) +0031 +0032 +drop table t1,t2; +CREATE TABLE t1 ( +ind bit not null, +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( +ind bit not null, +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; +insert into t1 values(0,''),(1,''); +insert into t2 values(0,''),(1,''); +select hex(ind),hex(string1) from t1 order by string1; +hex(ind) hex(string1) +0 +1 +select hex(ind),hex(string1) from t2 order by string1; +hex(ind) hex(string1) +0 +1 +drop table t1,t2; +create table t2 ( +a int, b char(10), filler char(10), primary key(a, b(2)) +) character set utf8 engine = innodb; +insert into t2 values (1,'abcdefg','one'); +insert into t2 values (2,'ijkilmn','two'); +insert into t2 values (3, 'qrstuvw','three'); +update t2 set a=5, filler='booo' where a=1; +drop table t2; +create table t2 ( +a int, b char(10), filler char(10), primary key(a, b(2)) +) character set ucs2 engine = innodb; +insert into t2 values (1,'abcdefg','one'); +insert into t2 values (2,'ijkilmn','two'); +insert into t2 values (3, 'qrstuvw','three'); +update t2 set a=5, filler='booo' where a=1; +drop table t2; +create table t1(a int not null, b char(110),primary key(a,b(100))) engine=innodb default charset=utf8; +insert into t1 values(1,'abcdefg'),(2,'defghijk'); +insert into t1 values(6,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1); +insert into t1 values(7,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2); +select a,hex(b) from t1 order by b; +a hex(b) +1 61626364656667 +2 6465666768696A6B +6 D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1 +7 D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2 +update t1 set b = 'three' where a = 6; +drop table t1; +create table t1(a int not null, b text(110),primary key(a,b(100))) engine=innodb default charset=utf8; +insert into t1 values(1,'abcdefg'),(2,'defghijk'); +insert into t1 values(6,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1); +insert into t1 values(7,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2); +select a,hex(b) from t1 order by b; +a hex(b) +1 61626364656667 +2 6465666768696A6B +6 D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1 +7 D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2 +update t1 set b = 'three' where a = 6; +drop table t1; +CREATE TABLE t1(a INT, PRIMARY KEY(a)) ENGINE=InnoDB; +CREATE TABLE t2(a INT) ENGINE=InnoDB; +ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1(a); +ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_1; +ALTER TABLE t2 ADD CONSTRAINT t2_ibfk_0 FOREIGN KEY (a) REFERENCES t1(a); +ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_0; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` int(11) DEFAULT NULL, + KEY `t2_ibfk_0` (`a`), + CONSTRAINT `t2_ibfk_0` FOREIGN KEY (`a`) REFERENCES `t1` (`a`), + CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t2,t1; +create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +insert into t1(a) values (1),(2),(3); +commit; +set autocommit = 0; +update t1 set b = 5 where a = 2; +create trigger t1t before insert on t1 for each row begin set NEW.b = NEW.a * 10 + 5, NEW.c = NEW.a / 10; end | +set autocommit = 0; +insert into t1(a) values (10),(20),(30),(40),(50),(60),(70),(80),(90),(100), +(11),(21),(31),(41),(51),(61),(71),(81),(91),(101), +(12),(22),(32),(42),(52),(62),(72),(82),(92),(102), +(13),(23),(33),(43),(53),(63),(73),(83),(93),(103), +(14),(24),(34),(44),(54),(64),(74),(84),(94),(104); +commit; +commit; +drop trigger t1t; +drop table t1; +create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +create table t2(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +create table t3(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +create table t4(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +create table t5(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +insert into t1(a) values (1),(2),(3); +insert into t2(a) values (1),(2),(3); +insert into t3(a) values (1),(2),(3); +insert into t4(a) values (1),(2),(3); +insert into t3(a) values (5),(7),(8); +insert into t4(a) values (5),(7),(8); +insert into t5(a) values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12); +create trigger t1t before insert on t1 for each row begin +INSERT INTO t2 SET a = NEW.a; +end | +create trigger t2t before insert on t2 for each row begin +DELETE FROM t3 WHERE a = NEW.a; +end | +create trigger t3t before delete on t3 for each row begin +UPDATE t4 SET b = b + 1 WHERE a = OLD.a; +end | +create trigger t4t before update on t4 for each row begin +UPDATE t5 SET b = b + 1 where a = NEW.a; +end | +commit; +set autocommit = 0; +update t1 set b = b + 5 where a = 1; +update t2 set b = b + 5 where a = 1; +update t3 set b = b + 5 where a = 1; +update t4 set b = b + 5 where a = 1; +insert into t5(a) values(20); +set autocommit = 0; +insert into t1(a) values(7); +insert into t2(a) values(8); +delete from t2 where a = 3; +update t4 set b = b + 1 where a = 3; +commit; +drop trigger t1t; +drop trigger t2t; +drop trigger t3t; +drop trigger t4t; +drop table t1, t2, t3, t4, t5; CREATE TABLE t1 ( field1 varchar(8) NOT NULL DEFAULT '', field2 varchar(8) NOT NULL DEFAULT '', diff --git a/mysql-test/r/innodb_unsafe_binlog.result b/mysql-test/r/innodb_unsafe_binlog.result new file mode 100644 index 00000000000..e741fbb75a4 --- /dev/null +++ b/mysql-test/r/innodb_unsafe_binlog.result @@ -0,0 +1,35 @@ +drop table if exists t1,t2; +create table t1 (id int not null, f_id int not null, f int not null, +primary key(f_id, id)) engine=innodb; +create table t2 (id int not null,s_id int not null,s varchar(200), +primary key(id)) engine=innodb; +INSERT INTO t1 VALUES (8, 1, 3); +INSERT INTO t1 VALUES (1, 2, 1); +INSERT INTO t2 VALUES (1, 0, ''); +INSERT INTO t2 VALUES (8, 1, ''); +commit; +DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id) +WHERE mm.id IS NULL; +select ml.* from t1 as ml left join t2 as mm on (mm.id=ml.id) +where mm.id is null lock in share mode; +id f_id f +drop table t1,t2; +create table t1(a int not null, b int, primary key(a)) engine=innodb; +insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2); +commit; +set autocommit = 0; +select * from t1 lock in share mode; +a b +1 1 +2 2 +3 1 +4 2 +5 1 +6 2 +update t1 set b = 5 where b = 1; +set autocommit = 0; +select * from t1 where a = 2 and b = 2 for update; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +commit; +commit; +drop table t1; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index ceffc3ada5b..27d9814404d 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1273,7 +1273,7 @@ show variables like "innodb_sync_spin_loops"; # Test for innodb_thread_concurrency variable show variables like "innodb_thread_concurrency"; -set global innodb_thread_concurrency=1000; +set global innodb_thread_concurrency=1001; show variables like "innodb_thread_concurrency"; set global innodb_thread_concurrency=0; show variables like "innodb_thread_concurrency"; @@ -1610,6 +1610,10 @@ insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +select a,hex(b),hex(c),filler from t2 order by filler; drop table t1; drop table t2; @@ -1639,6 +1643,10 @@ insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +select a,hex(b),hex(c),filler from t2 order by filler; drop table t1; drop table t2; @@ -1668,6 +1676,10 @@ insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +select a,hex(b),hex(c),filler from t2 order by filler; drop table t1; drop table t2; @@ -1693,10 +1705,102 @@ insert into t2 values (4,_ucs2 0x01fc,_ucs2 0x01fc,'seven'); insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight'); insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +select a,hex(b),hex(c),filler from t2 order by filler; drop table t1; drop table t2; commit; +# tests for bugs #9802 and #13778 + +# test that FKs between invalid types are not accepted + +set foreign_key_checks=0; +create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; +--replace_result $MYSQLTEST_VARDIR . master-data/ '' +-- error 1005 +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +set foreign_key_checks=1; +drop table t2; + +# test that FKs between different charsets are not accepted in CREATE even +# when f_k_c is 0 + +set foreign_key_checks=0; +create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +--replace_result $MYSQLTEST_VARDIR . master-data/ '' +-- error 1005 +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8; +set foreign_key_checks=1; +drop table t1; + +# test that invalid datatype conversions with ALTER are not allowed + +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb; +create table t1(a varchar(10) primary key) engine = innodb; +-- error 1025,1025 +alter table t1 modify column a int; +set foreign_key_checks=1; +drop table t2,t1; + +# test that charset conversions with ALTER are allowed when f_k_c is 0 + +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; +create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +alter table t1 convert to character set utf8; +set foreign_key_checks=1; +drop table t2,t1; + +# test that RENAME does not allow invalid charsets when f_k_c is 0 + +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; +create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; +--replace_result $MYSQLTEST_VARDIR . master-data/ '' +-- error 1025 +rename table t3 to t1; +set foreign_key_checks=1; +drop table t2,t3; + +# test that foreign key errors are reported correctly (Bug #15550) + +create table t1(a int primary key) row_format=redundant engine=innodb; +create table t2(a int primary key,constraint foreign key(a)references t1(a)) row_format=compact engine=innodb; +create table t3(a int primary key) row_format=compact engine=innodb; +create table t4(a int primary key,constraint foreign key(a)references t3(a)) row_format=redundant engine=innodb; + +insert into t1 values(1); +insert into t3 values(1); +-- error 1452 +insert into t2 values(2); +-- error 1452 +insert into t4 values(2); +insert into t2 values(1); +insert into t4 values(1); +-- error 1451 +update t1 set a=2; +-- error 1452 +update t2 set a=2; +-- error 1451 +update t3 set a=2; +-- error 1452 +update t4 set a=2; +-- error 1451 +truncate t1; +-- error 1451 +truncate t3; +truncate t2; +truncate t4; +truncate t1; +truncate t3; + +drop table t4,t3,t2,t1; + + # # Test that we can create a large (>1K) key # @@ -1714,7 +1818,272 @@ create table t1 (a varchar(255) character set utf8, e varchar(255) character set utf8, key (a,b,c,d,e)) engine=innodb; ---echo End of 5.0 tests + +# test the padding of BINARY types and collations (Bug #14189) + +create table t1 (s1 varbinary(2),primary key (s1)) engine=innodb; +create table t2 (s1 binary(2),primary key (s1)) engine=innodb; +create table t3 (s1 varchar(2) binary,primary key (s1)) engine=innodb; +create table t4 (s1 char(2) binary,primary key (s1)) engine=innodb; + +insert into t1 values (0x41),(0x4120),(0x4100); +-- error 1062 +insert into t2 values (0x41),(0x4120),(0x4100); +insert into t2 values (0x41),(0x4120); +-- error 1062 +insert into t3 values (0x41),(0x4120),(0x4100); +insert into t3 values (0x41),(0x4100); +-- error 1062 +insert into t4 values (0x41),(0x4120),(0x4100); +insert into t4 values (0x41),(0x4100); +select hex(s1) from t1; +select hex(s1) from t2; +select hex(s1) from t3; +select hex(s1) from t4; +drop table t1,t2,t3,t4; + +create table t1 (a int primary key,s1 varbinary(3) not null unique) engine=innodb; +create table t2 (s1 binary(2) not null, constraint c foreign key(s1) references t1(s1) on update cascade) engine=innodb; + +insert into t1 values(1,0x4100),(2,0x41),(3,0x4120),(4,0x42); +-- error 1452 +insert into t2 values(0x42); +insert into t2 values(0x41); +select hex(s1) from t2; +update t1 set s1=0x123456 where a=2; +select hex(s1) from t2; +-- error 1451 +update t1 set s1=0x12 where a=1; +-- error 1451 +update t1 set s1=0x12345678 where a=1; +-- error 1451 +update t1 set s1=0x123457 where a=1; +update t1 set s1=0x1220 where a=1; +select hex(s1) from t2; +update t1 set s1=0x1200 where a=1; +select hex(s1) from t2; +update t1 set s1=0x4200 where a=1; +select hex(s1) from t2; +-- error 1451 +delete from t1 where a=1; +delete from t1 where a=2; +update t2 set s1=0x4120; +-- error 1451 +delete from t1; +delete from t1 where a!=3; +select a,hex(s1) from t1; +select hex(s1) from t2; + +drop table t2,t1; + +create table t1 (a int primary key,s1 varchar(2) binary not null unique) engine=innodb; +create table t2 (s1 char(2) binary not null, constraint c foreign key(s1) references t1(s1) on update cascade) engine=innodb; + +insert into t1 values(1,0x4100),(2,0x41); +insert into t2 values(0x41); +select hex(s1) from t2; +update t1 set s1=0x1234 where a=1; +select hex(s1) from t2; +update t1 set s1=0x12 where a=2; +select hex(s1) from t2; +delete from t1 where a=1; +-- error 1451 +delete from t1 where a=2; +select a,hex(s1) from t1; +select hex(s1) from t2; + +drop table t2,t1; +# +# Test cases for bug #15308 Problem of Order with Enum Column in Primary Key +# +CREATE TABLE t1 ( + ind enum('0','1','2') NOT NULL default '0', + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( + ind enum('0','1','2') NOT NULL default '0', + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; + +INSERT INTO t1 VALUES ('1', ''),('2', ''); +INSERT INTO t2 VALUES ('1', ''),('2', ''); +SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1; +SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1; +drop table t1,t2; + +CREATE TABLE t1 ( + ind set('0','1','2') NOT NULL default '0', + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( + ind set('0','1','2') NOT NULL default '0', + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; + +INSERT INTO t1 VALUES ('1', ''),('2', ''); +INSERT INTO t2 VALUES ('1', ''),('2', ''); +SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1; +SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1; +drop table t1,t2; + +CREATE TABLE t1 ( + ind bit not null, + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( + ind bit not null, + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; +insert into t1 values(0,''),(1,''); +insert into t2 values(0,''),(1,''); +select hex(ind),hex(string1) from t1 order by string1; +select hex(ind),hex(string1) from t2 order by string1; +drop table t1,t2; + +# tests for bug #14056 Column prefix index on UTF-8 primary key column causes 'Can't find record..' + +create table t2 ( + a int, b char(10), filler char(10), primary key(a, b(2)) +) character set utf8 engine = innodb; + +insert into t2 values (1,'abcdefg','one'); +insert into t2 values (2,'ijkilmn','two'); +insert into t2 values (3, 'qrstuvw','three'); +update t2 set a=5, filler='booo' where a=1; +drop table t2; +create table t2 ( + a int, b char(10), filler char(10), primary key(a, b(2)) +) character set ucs2 engine = innodb; + +insert into t2 values (1,'abcdefg','one'); +insert into t2 values (2,'ijkilmn','two'); +insert into t2 values (3, 'qrstuvw','three'); +update t2 set a=5, filler='booo' where a=1; +drop table t2; + +create table t1(a int not null, b char(110),primary key(a,b(100))) engine=innodb default charset=utf8; +insert into t1 values(1,'abcdefg'),(2,'defghijk'); +insert into t1 values(6,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1); +insert into t1 values(7,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2); +select a,hex(b) from t1 order by b; +update t1 set b = 'three' where a = 6; +drop table t1; +create table t1(a int not null, b text(110),primary key(a,b(100))) engine=innodb default charset=utf8; +insert into t1 values(1,'abcdefg'),(2,'defghijk'); +insert into t1 values(6,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1); +insert into t1 values(7,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2); +select a,hex(b) from t1 order by b; +update t1 set b = 'three' where a = 6; +drop table t1; + +# Ensure that <tablename>_ibfk_0 is not mistreated as a +# generated foreign key identifier. (Bug #16387) + +CREATE TABLE t1(a INT, PRIMARY KEY(a)) ENGINE=InnoDB; +CREATE TABLE t2(a INT) ENGINE=InnoDB; +ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1(a); +ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_1; +ALTER TABLE t2 ADD CONSTRAINT t2_ibfk_0 FOREIGN KEY (a) REFERENCES t1(a); +ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_0; +SHOW CREATE TABLE t2; +DROP TABLE t2,t1; + +# +# Test case for bug #16229: MySQL/InnoDB uses full explicit table locks in trigger processing +# + +connect (a,localhost,root,,); +connect (b,localhost,root,,); +connection a; +create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +insert into t1(a) values (1),(2),(3); +commit; +connection b; +set autocommit = 0; +update t1 set b = 5 where a = 2; +connection a; +delimiter |; +create trigger t1t before insert on t1 for each row begin set NEW.b = NEW.a * 10 + 5, NEW.c = NEW.a / 10; end | +delimiter ;| +set autocommit = 0; +connection a; +insert into t1(a) values (10),(20),(30),(40),(50),(60),(70),(80),(90),(100), +(11),(21),(31),(41),(51),(61),(71),(81),(91),(101), +(12),(22),(32),(42),(52),(62),(72),(82),(92),(102), +(13),(23),(33),(43),(53),(63),(73),(83),(93),(103), +(14),(24),(34),(44),(54),(64),(74),(84),(94),(104); +connection b; +commit; +connection a; +commit; +drop trigger t1t; +drop table t1; +disconnect a; +disconnect b; +# +# Another trigger test +# +connect (a,localhost,root,,); +connect (b,localhost,root,,); +connection a; +create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +create table t2(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +create table t3(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +create table t4(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +create table t5(a int not null, b int, c int, d int, primary key(a)) engine=innodb; +insert into t1(a) values (1),(2),(3); +insert into t2(a) values (1),(2),(3); +insert into t3(a) values (1),(2),(3); +insert into t4(a) values (1),(2),(3); +insert into t3(a) values (5),(7),(8); +insert into t4(a) values (5),(7),(8); +insert into t5(a) values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12); + +delimiter |; +create trigger t1t before insert on t1 for each row begin + INSERT INTO t2 SET a = NEW.a; +end | + +create trigger t2t before insert on t2 for each row begin + DELETE FROM t3 WHERE a = NEW.a; +end | + +create trigger t3t before delete on t3 for each row begin + UPDATE t4 SET b = b + 1 WHERE a = OLD.a; +end | + +create trigger t4t before update on t4 for each row begin + UPDATE t5 SET b = b + 1 where a = NEW.a; +end | +delimiter ;| +commit; +set autocommit = 0; +update t1 set b = b + 5 where a = 1; +update t2 set b = b + 5 where a = 1; +update t3 set b = b + 5 where a = 1; +update t4 set b = b + 5 where a = 1; +insert into t5(a) values(20); +connection b; +set autocommit = 0; +insert into t1(a) values(7); +insert into t2(a) values(8); +delete from t2 where a = 3; +update t4 set b = b + 1 where a = 3; +commit; +drop trigger t1t; +drop trigger t2t; +drop trigger t3t; +drop trigger t4t; +drop table t1, t2, t3, t4, t5; +connection default; +disconnect a; +disconnect b; # # Test that cascading updates leading to duplicate keys give the correct diff --git a/mysql-test/t/innodb_unsafe_binlog-master.opt b/mysql-test/t/innodb_unsafe_binlog-master.opt new file mode 100644 index 00000000000..503c8457b2c --- /dev/null +++ b/mysql-test/t/innodb_unsafe_binlog-master.opt @@ -0,0 +1 @@ +--innodb_locks_unsafe_for_binlog=true diff --git a/mysql-test/t/innodb_unsafe_binlog.test b/mysql-test/t/innodb_unsafe_binlog.test new file mode 100644 index 00000000000..e4cb683e59d --- /dev/null +++ b/mysql-test/t/innodb_unsafe_binlog.test @@ -0,0 +1,55 @@ +-- source include/have_innodb.inc +# +# Note that these tests uses a innodb_locks_unsafe_for_binlog option. +# +# +# Test cases for a bug #15650 +# + +--disable_warnings +drop table if exists t1,t2; +--enable_warnings +create table t1 (id int not null, f_id int not null, f int not null, +primary key(f_id, id)) engine=innodb; +create table t2 (id int not null,s_id int not null,s varchar(200), +primary key(id)) engine=innodb; +INSERT INTO t1 VALUES (8, 1, 3); +INSERT INTO t1 VALUES (1, 2, 1); +INSERT INTO t2 VALUES (1, 0, ''); +INSERT INTO t2 VALUES (8, 1, ''); +commit; +DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id) +WHERE mm.id IS NULL; +select ml.* from t1 as ml left join t2 as mm on (mm.id=ml.id) +where mm.id is null lock in share mode; +drop table t1,t2; + +# +# Test case for unlock row bug where unlock releases all locks granted for +# a row. Only the latest lock should be released. +# + +connect (a,localhost,root,,); +connect (b,localhost,root,,); +connection a; +create table t1(a int not null, b int, primary key(a)) engine=innodb; +insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2); +commit; +set autocommit = 0; +select * from t1 lock in share mode; +update t1 set b = 5 where b = 1; +connection b; +set autocommit = 0; +# +# S-lock to records (2,2),(4,2), and (6,2) should not be released in a update +# +--error 1205 +select * from t1 where a = 2 and b = 2 for update; +connection a; +commit; +connection b; +commit; +drop table t1; +disconnect a; +disconnect b; + diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 153c456c06c..1f849f89272 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -7,12 +7,12 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This file defines the InnoDB handler: the interface between MySQL and InnoDB NOTE: You can only use noninlined InnoDB functions in this file, because we @@ -44,9 +44,9 @@ have disables the InnoDB inlining in this file. */ #include "ha_innodb.h" -pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */ - prepare_commit_mutex; /* to force correct commit order in - binlog */ +pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */ + prepare_commit_mutex; /* to force correct commit order in + binlog */ ulong commit_threads= 0; pthread_mutex_t commit_threads_m; pthread_cond_t commit_cond; @@ -57,45 +57,45 @@ bool innodb_inited= 0; /* These variables are used to implement (semi-)synchronous MySQL binlog replication for InnoDB tables. */ -pthread_cond_t innobase_repl_cond; /* Posix cond variable; - this variable is signaled - when enough binlog has been - sent to slave, so that a - waiting trx can return the - 'ok' message to the client - for a commit */ -pthread_mutex_t innobase_repl_cond_mutex; /* Posix cond variable mutex - that also protects the next - innobase_repl_... variables */ -uint innobase_repl_state; /* 1 if synchronous replication - is switched on and is working - ok; else 0 */ -uint innobase_repl_file_name_inited = 0; /* This is set to 1 when - innobase_repl_file_name - contains meaningful data */ -char* innobase_repl_file_name; /* The binlog name up to which - we have sent some binlog to - the slave */ -my_off_t innobase_repl_pos; /* The position in that file - up to which we have sent the - binlog to the slave */ -uint innobase_repl_n_wait_threads = 0; /* This tells how many - transactions currently are - waiting for the binlog to be - sent to the client */ -uint innobase_repl_wait_file_name_inited = 0; /* This is set to 1 - when we know the 'smallest' - wait position */ -char* innobase_repl_wait_file_name; /* NULL, or the 'smallest' - innobase_repl_file_name that - a transaction is waiting for */ -my_off_t innobase_repl_wait_pos; /* The smallest position in - that file that a trx is - waiting for: the trx can - proceed and send an 'ok' to - the client when MySQL has sent - the binlog up to this position - to the slave */ +pthread_cond_t innobase_repl_cond; /* Posix cond variable; + this variable is signaled + when enough binlog has been + sent to slave, so that a + waiting trx can return the + 'ok' message to the client + for a commit */ +pthread_mutex_t innobase_repl_cond_mutex; /* Posix cond variable mutex + that also protects the next + innobase_repl_... variables */ +uint innobase_repl_state; /* 1 if synchronous replication + is switched on and is working + ok; else 0 */ +uint innobase_repl_file_name_inited = 0; /* This is set to 1 when + innobase_repl_file_name + contains meaningful data */ +char* innobase_repl_file_name; /* The binlog name up to which + we have sent some binlog to + the slave */ +my_off_t innobase_repl_pos; /* The position in that file + up to which we have sent the + binlog to the slave */ +uint innobase_repl_n_wait_threads = 0; /* This tells how many + transactions currently are + waiting for the binlog to be + sent to the client */ +uint innobase_repl_wait_file_name_inited = 0; /* This is set to 1 + when we know the 'smallest' + wait position */ +char* innobase_repl_wait_file_name; /* NULL, or the 'smallest' + innobase_repl_file_name that + a transaction is waiting for */ +my_off_t innobase_repl_wait_pos; /* The smallest position in + that file that a trx is + waiting for: the trx can + proceed and send an 'ok' to + the client when MySQL has sent + the binlog up to this position + to the slave */ /*-----------------------------------------------------------------*/ @@ -137,26 +137,24 @@ extern "C" { #define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */ #define HA_INNOBASE_RANGE_COUNT 100 -uint innobase_init_flags = 0; -ulong innobase_cache_size = 0; -ulong innobase_large_page_size = 0; +ulong innobase_large_page_size = 0; /* The default values for the following, type long or longlong, start-up parameters are declared in mysqld.cc: */ long innobase_mirrored_log_groups, innobase_log_files_in_group, - innobase_log_buffer_size, innobase_buffer_pool_awe_mem_mb, - innobase_additional_mem_pool_size, innobase_file_io_threads, - innobase_lock_wait_timeout, innobase_force_recovery, - innobase_open_files; + innobase_log_buffer_size, innobase_buffer_pool_awe_mem_mb, + innobase_additional_mem_pool_size, innobase_file_io_threads, + innobase_lock_wait_timeout, innobase_force_recovery, + innobase_open_files; longlong innobase_buffer_pool_size, innobase_log_file_size; /* The default values for the following char* start-up parameters are determined in innobase_init below: */ - + char* innobase_data_home_dir = NULL; -char* innobase_data_file_path = NULL; +char* innobase_data_file_path = NULL; char* innobase_log_group_home_dir = NULL; char* innobase_log_arch_dir = NULL;/* unused */ /* The following has a misleading name: starting from 4.0.5, this also @@ -169,12 +167,12 @@ values */ uint innobase_flush_log_at_trx_commit = 1; ulong innobase_fast_shutdown = 1; my_bool innobase_log_archive = FALSE;/* unused */ -my_bool innobase_use_doublewrite = TRUE; -my_bool innobase_use_checksums = TRUE; -my_bool innobase_use_large_pages = FALSE; +my_bool innobase_use_doublewrite = TRUE; +my_bool innobase_use_checksums = TRUE; +my_bool innobase_use_large_pages = FALSE; my_bool innobase_use_native_aio = FALSE; my_bool innobase_file_per_table = FALSE; -my_bool innobase_locks_unsafe_for_binlog = FALSE; +my_bool innobase_locks_unsafe_for_binlog = FALSE; my_bool innobase_create_status_file = FALSE; static char *internal_innobase_data_file_path = NULL; @@ -187,16 +185,14 @@ it every INNOBASE_WAKE_INTERVAL'th step. */ #define INNOBASE_WAKE_INTERVAL 32 ulong innobase_active_counter = 0; -char* innobase_home = NULL; - -static HASH innobase_open_tables; +static HASH innobase_open_tables; -#ifdef __NETWARE__ /* some special cleanup for NetWare */ +#ifdef __NETWARE__ /* some special cleanup for NetWare */ bool nw_panic = FALSE; #endif static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length, - my_bool not_used __attribute__((unused))); + my_bool not_used __attribute__((unused))); static INNOBASE_SHARE *get_share(const char *table_name); static void free_share(INNOBASE_SHARE *share); static int innobase_close_connection(THD* thd); @@ -211,7 +207,7 @@ handlerton innobase_hton = { MYSQL_HANDLERTON_INTERFACE_VERSION, "InnoDB", SHOW_OPTION_YES, - "Supports transactions, row-level locking, and foreign keys", + "Supports transactions, row-level locking, and foreign keys", DB_TYPE_INNODB, innobase_init, 0, /* slot */ @@ -225,7 +221,7 @@ handlerton innobase_hton = { innobase_xa_prepare, /* prepare */ innobase_xa_recover, /* recover */ innobase_commit_by_xid, /* commit_by_xid */ - innobase_rollback_by_xid, /* rollback_by_xid */ + innobase_rollback_by_xid, /* rollback_by_xid */ innobase_create_cursor_view, innobase_set_cursor_view, innobase_close_cursor_view, @@ -261,19 +257,19 @@ innobase_commit_low( SHOW_VAR innodb_status_variables[]= { {"buffer_pool_pages_data", - (char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG}, + (char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG}, {"buffer_pool_pages_dirty", - (char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG}, + (char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG}, {"buffer_pool_pages_flushed", (char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG}, {"buffer_pool_pages_free", - (char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG}, + (char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG}, {"buffer_pool_pages_latched", (char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG}, {"buffer_pool_pages_misc", - (char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG}, + (char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG}, {"buffer_pool_pages_total", - (char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG}, + (char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG}, {"buffer_pool_read_ahead_rnd", (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG}, {"buffer_pool_read_ahead_seq", @@ -281,71 +277,71 @@ SHOW_VAR innodb_status_variables[]= { {"buffer_pool_read_requests", (char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG}, {"buffer_pool_reads", - (char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG}, + (char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG}, {"buffer_pool_wait_free", - (char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG}, + (char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG}, {"buffer_pool_write_requests", (char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG}, {"data_fsyncs", - (char*) &export_vars.innodb_data_fsyncs, SHOW_LONG}, + (char*) &export_vars.innodb_data_fsyncs, SHOW_LONG}, {"data_pending_fsyncs", - (char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG}, + (char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG}, {"data_pending_reads", - (char*) &export_vars.innodb_data_pending_reads, SHOW_LONG}, + (char*) &export_vars.innodb_data_pending_reads, SHOW_LONG}, {"data_pending_writes", - (char*) &export_vars.innodb_data_pending_writes, SHOW_LONG}, + (char*) &export_vars.innodb_data_pending_writes, SHOW_LONG}, {"data_read", - (char*) &export_vars.innodb_data_read, SHOW_LONG}, + (char*) &export_vars.innodb_data_read, SHOW_LONG}, {"data_reads", - (char*) &export_vars.innodb_data_reads, SHOW_LONG}, + (char*) &export_vars.innodb_data_reads, SHOW_LONG}, {"data_writes", - (char*) &export_vars.innodb_data_writes, SHOW_LONG}, + (char*) &export_vars.innodb_data_writes, SHOW_LONG}, {"data_written", - (char*) &export_vars.innodb_data_written, SHOW_LONG}, + (char*) &export_vars.innodb_data_written, SHOW_LONG}, {"dblwr_pages_written", - (char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG}, + (char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG}, {"dblwr_writes", - (char*) &export_vars.innodb_dblwr_writes, SHOW_LONG}, + (char*) &export_vars.innodb_dblwr_writes, SHOW_LONG}, {"log_waits", - (char*) &export_vars.innodb_log_waits, SHOW_LONG}, + (char*) &export_vars.innodb_log_waits, SHOW_LONG}, {"log_write_requests", - (char*) &export_vars.innodb_log_write_requests, SHOW_LONG}, + (char*) &export_vars.innodb_log_write_requests, SHOW_LONG}, {"log_writes", - (char*) &export_vars.innodb_log_writes, SHOW_LONG}, + (char*) &export_vars.innodb_log_writes, SHOW_LONG}, {"os_log_fsyncs", - (char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG}, + (char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG}, {"os_log_pending_fsyncs", - (char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG}, + (char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG}, {"os_log_pending_writes", - (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG}, + (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG}, {"os_log_written", - (char*) &export_vars.innodb_os_log_written, SHOW_LONG}, + (char*) &export_vars.innodb_os_log_written, SHOW_LONG}, {"page_size", - (char*) &export_vars.innodb_page_size, SHOW_LONG}, + (char*) &export_vars.innodb_page_size, SHOW_LONG}, {"pages_created", - (char*) &export_vars.innodb_pages_created, SHOW_LONG}, + (char*) &export_vars.innodb_pages_created, SHOW_LONG}, {"pages_read", - (char*) &export_vars.innodb_pages_read, SHOW_LONG}, + (char*) &export_vars.innodb_pages_read, SHOW_LONG}, {"pages_written", - (char*) &export_vars.innodb_pages_written, SHOW_LONG}, + (char*) &export_vars.innodb_pages_written, SHOW_LONG}, {"row_lock_current_waits", - (char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG}, + (char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG}, {"row_lock_time", - (char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG}, + (char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG}, {"row_lock_time_avg", - (char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG}, + (char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG}, {"row_lock_time_max", - (char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG}, + (char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG}, {"row_lock_waits", - (char*) &export_vars.innodb_row_lock_waits, SHOW_LONG}, + (char*) &export_vars.innodb_row_lock_waits, SHOW_LONG}, {"rows_deleted", - (char*) &export_vars.innodb_rows_deleted, SHOW_LONG}, + (char*) &export_vars.innodb_rows_deleted, SHOW_LONG}, {"rows_inserted", - (char*) &export_vars.innodb_rows_inserted, SHOW_LONG}, + (char*) &export_vars.innodb_rows_inserted, SHOW_LONG}, {"rows_read", - (char*) &export_vars.innodb_rows_read, SHOW_LONG}, + (char*) &export_vars.innodb_rows_read, SHOW_LONG}, {"rows_updated", - (char*) &export_vars.innodb_rows_updated, SHOW_LONG}, + (char*) &export_vars.innodb_rows_updated, SHOW_LONG}, {NullS, NullS, SHOW_LONG}}; /* General functions */ @@ -359,7 +355,7 @@ innodb_srv_conc_enter_innodb( /*=========================*/ trx_t* trx) /* in: transaction handle */ { - if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) { + if (UNIV_LIKELY(!srv_thread_concurrency)) { return; } @@ -376,7 +372,7 @@ innodb_srv_conc_exit_innodb( /*========================*/ trx_t* trx) /* in: transaction handle */ { - if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) { + if (UNIV_LIKELY(!srv_thread_concurrency)) { return; } @@ -414,19 +410,19 @@ documentation, see handler.cc. */ int innobase_release_temporary_latches( /*===============================*/ - THD *thd) + THD *thd) { trx_t* trx; if (!innodb_inited) { - + return 0; } trx = (trx_t*) thd->ha_data[innobase_hton.slot]; if (trx) { - innobase_release_stat_resources(trx); + innobase_release_stat_resources(trx); } return 0; } @@ -464,90 +460,90 @@ convert_error_code_to_mysql( return(0); - } else if (error == (int) DB_DUPLICATE_KEY) { + } else if (error == (int) DB_DUPLICATE_KEY) { - return(HA_ERR_FOUND_DUPP_KEY); + return(HA_ERR_FOUND_DUPP_KEY); - } else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) { + } else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) { return(HA_ERR_FOREIGN_DUPLICATE_KEY); - } else if (error == (int) DB_RECORD_NOT_FOUND) { + } else if (error == (int) DB_RECORD_NOT_FOUND) { - return(HA_ERR_NO_ACTIVE_RECORD); + return(HA_ERR_NO_ACTIVE_RECORD); - } else if (error == (int) DB_ERROR) { + } else if (error == (int) DB_ERROR) { - return(-1); /* unspecified error */ + return(-1); /* unspecified error */ - } else if (error == (int) DB_DEADLOCK) { - /* Since we rolled back the whole transaction, we must - tell it also to MySQL so that MySQL knows to empty the - cached binlog for this transaction */ + } else if (error == (int) DB_DEADLOCK) { + /* Since we rolled back the whole transaction, we must + tell it also to MySQL so that MySQL knows to empty the + cached binlog for this transaction */ - if (thd) { - ha_rollback(thd); - } + if (thd) { + ha_rollback(thd); + } - return(HA_ERR_LOCK_DEADLOCK); + return(HA_ERR_LOCK_DEADLOCK); - } else if (error == (int) DB_LOCK_WAIT_TIMEOUT) { + } else if (error == (int) DB_LOCK_WAIT_TIMEOUT) { /* Starting from 5.0.13, we let MySQL just roll back the latest SQL statement in a lock wait timeout. Previously, we rolled back the whole transaction. */ - return(HA_ERR_LOCK_WAIT_TIMEOUT); + return(HA_ERR_LOCK_WAIT_TIMEOUT); - } else if (error == (int) DB_NO_REFERENCED_ROW) { + } else if (error == (int) DB_NO_REFERENCED_ROW) { - return(HA_ERR_NO_REFERENCED_ROW); + return(HA_ERR_NO_REFERENCED_ROW); - } else if (error == (int) DB_ROW_IS_REFERENCED) { + } else if (error == (int) DB_ROW_IS_REFERENCED) { - return(HA_ERR_ROW_IS_REFERENCED); + return(HA_ERR_ROW_IS_REFERENCED); - } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) { + } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) { - return(HA_ERR_CANNOT_ADD_FOREIGN); + return(HA_ERR_CANNOT_ADD_FOREIGN); - } else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) { + } else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) { - return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit + return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit misleading, a new MySQL error code should be introduced */ - } else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) { + } else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) { - return(HA_ERR_CRASHED); + return(HA_ERR_CRASHED); - } else if (error == (int) DB_OUT_OF_FILE_SPACE) { + } else if (error == (int) DB_OUT_OF_FILE_SPACE) { - return(HA_ERR_RECORD_FILE_FULL); + return(HA_ERR_RECORD_FILE_FULL); - } else if (error == (int) DB_TABLE_IS_BEING_USED) { + } else if (error == (int) DB_TABLE_IS_BEING_USED) { - return(HA_ERR_WRONG_COMMAND); + return(HA_ERR_WRONG_COMMAND); - } else if (error == (int) DB_TABLE_NOT_FOUND) { + } else if (error == (int) DB_TABLE_NOT_FOUND) { - return(HA_ERR_KEY_NOT_FOUND); + return(HA_ERR_KEY_NOT_FOUND); - } else if (error == (int) DB_TOO_BIG_RECORD) { + } else if (error == (int) DB_TOO_BIG_RECORD) { - return(HA_ERR_TO_BIG_ROW); + return(HA_ERR_TO_BIG_ROW); - } else if (error == (int) DB_CORRUPTION) { + } else if (error == (int) DB_CORRUPTION) { - return(HA_ERR_CRASHED); - } else if (error == (int) DB_NO_SAVEPOINT) { + return(HA_ERR_CRASHED); + } else if (error == (int) DB_NO_SAVEPOINT) { - return(HA_ERR_NO_SAVEPOINT); - } else if (error == (int) DB_LOCK_TABLE_FULL) { + return(HA_ERR_NO_SAVEPOINT); + } else if (error == (int) DB_LOCK_TABLE_FULL) { - return(HA_ERR_LOCK_TABLE_FULL); - } else { - return(-1); // Unknown error - } + return(HA_ERR_LOCK_TABLE_FULL); + } else { + return(-1); // Unknown error + } } /***************************************************************** @@ -587,21 +583,21 @@ extern "C" void innobase_mysql_print_thd( /*=====================*/ - FILE* f, /* in: output stream */ - void* input_thd, /* in: pointer to a MySQL THD object */ + FILE* f, /* in: output stream */ + void* input_thd, /* in: pointer to a MySQL THD object */ uint max_query_len) /* in: max query length to print, or 0 to use the default max length */ { const THD* thd; - const Security_context *sctx; + const Security_context *sctx; const char* s; - thd = (const THD*) input_thd; - /* We probably want to have original user as part of debug output. */ - sctx = &thd->main_security_ctx; + thd = (const THD*) input_thd; + /* We probably want to have original user as part of debug output. */ + sctx = &thd->main_security_ctx; - fprintf(f, "MySQL thread id %lu, query id %lu", + fprintf(f, "MySQL thread id %lu, query id %lu", thd->thread_id, (ulong) thd->query_id); if (sctx->host) { putc(' ', f); @@ -613,10 +609,10 @@ innobase_mysql_print_thd( fputs(sctx->ip, f); } - if (sctx->user) { + if (sctx->user) { putc(' ', f); fputs(sctx->user, f); - } + } if ((s = thd->proc_info)) { putc(' ', f); @@ -635,9 +631,8 @@ innobase_mysql_print_thd( /* Points to buf or dyn_str. */ char* str = buf; - - if (max_query_len == 0) - { + + if (max_query_len == 0) { /* ADDITIONAL SAFETY: the default is to print at most 300 chars to reduce the probability of a seg fault if there is a race in @@ -646,23 +641,21 @@ innobase_mysql_print_thd( safe */ max_query_len = 300; } - + len = min(thd->query_length, max_query_len); - if (len > (sizeof(buf) - 1)) - { + if (len > (sizeof(buf) - 1)) { dyn_str = my_malloc(len + 1, MYF(0)); str = dyn_str; } - /* Use strmake to reduce the timeframe for a race, - compared to fwrite() */ + /* Use strmake to reduce the timeframe for a race, + compared to fwrite() */ len = (uint) (strmake(str, s, len) - str); putc('\n', f); fwrite(str, 1, len, f); - if (dyn_str) - { + if (dyn_str) { my_free(dyn_str, MYF(0)); } } @@ -764,10 +757,10 @@ innobase_mysql_tmpfile(void) if (fd2 < 0) { DBUG_PRINT("error",("Got error %d on dup",fd2)); my_errno=errno; - my_error(EE_OUT_OF_FILERESOURCES, - MYF(ME_BELL+ME_WAITTANG), - filename, my_errno); - } + my_error(EE_OUT_OF_FILERESOURCES, + MYF(ME_BELL+ME_WAITTANG), + filename, my_errno); + } my_close(fd, MYF(MY_WME)); } return(fd2); @@ -788,24 +781,24 @@ check_trx_exists( ut_ad(thd == current_thd); - trx = (trx_t*) thd->ha_data[innobase_hton.slot]; + trx = (trx_t*) thd->ha_data[innobase_hton.slot]; if (trx == NULL) { - DBUG_ASSERT(thd != NULL); + DBUG_ASSERT(thd != NULL); trx = trx_allocate_for_mysql(); trx->mysql_thd = thd; trx->mysql_query_str = &(thd->query); - trx->active_trans = 0; + trx->active_trans = 0; /* Update the info whether we should skip XA steps that eat CPU time */ trx->support_xa = (ibool)(thd->variables.innodb_support_xa); - thd->ha_data[innobase_hton.slot] = trx; + thd->ha_data[innobase_hton.slot] = trx; } else { if (trx->magic_n != TRX_MAGIC_N) { - mem_analyze_corruption((byte*)trx); + mem_analyze_corruption(trx); ut_a(0); } @@ -833,15 +826,14 @@ Construct ha_innobase handler. */ ha_innobase::ha_innobase(TABLE_SHARE *table_arg) :handler(&innobase_hton, table_arg), int_table_flags(HA_REC_NOT_IN_SEQ | - HA_NULL_IN_KEY | - HA_CAN_INDEX_BLOBS | - HA_CAN_SQL_HANDLER | - HA_NOT_EXACT_COUNT | - HA_PRIMARY_KEY_ALLOW_RANDOM_ACCESS | - HA_PRIMARY_KEY_IN_READ_INDEX | - HA_CAN_GEOMETRY | - HA_TABLE_SCAN_ON_INDEX), - last_dup_key((uint) -1), + HA_NULL_IN_KEY | + HA_CAN_INDEX_BLOBS | + HA_CAN_SQL_HANDLER | + HA_NOT_EXACT_COUNT | + HA_PRIMARY_KEY_ALLOW_RANDOM_ACCESS | + HA_PRIMARY_KEY_IN_READ_INDEX | + HA_CAN_GEOMETRY | + HA_TABLE_SCAN_ON_INDEX), start_of_scan(0), num_write_row(0) {} @@ -883,8 +875,8 @@ innobase_register_stmt( /*===================*/ THD* thd) /* in: MySQL thd (connection) object */ { - /* Register the statement */ - trans_register_ha(thd, FALSE, &innobase_hton); + /* Register the statement */ + trans_register_ha(thd, FALSE, &innobase_hton); } /************************************************************************* @@ -905,11 +897,11 @@ innobase_register_trx_and_stmt( innobase_register_stmt(thd); - if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { + if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { - /* No autocommit mode, register for a transaction */ - trans_register_ha(thd, TRUE, &innobase_hton); - } + /* No autocommit mode, register for a transaction */ + trans_register_ha(thd, TRUE, &innobase_hton); + } } /* BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB @@ -989,7 +981,7 @@ innobase_query_caching_of_table_permitted( name */ uint full_name_len, /* in: length of the full name, i.e. len(dbname) + len(tablename) + 1 */ - ulonglong *unused) /* unused for this engine */ + ulonglong *unused) /* unused for this engine */ { ibool is_autocommit; trx_t* trx; @@ -1000,16 +992,21 @@ innobase_query_caching_of_table_permitted( if (thd->variables.tx_isolation == ISO_SERIALIZABLE) { /* In the SERIALIZABLE mode we add LOCK IN SHARE MODE to every plain SELECT if AUTOCOMMIT is not on. */ - + return((my_bool)FALSE); } - trx = check_trx_exists(thd); + trx = check_trx_exists(thd); if (trx->has_search_latch) { ut_print_timestamp(stderr); sql_print_error("The calling thread is holding the adaptive " "search, latch though calling " "innobase_query_caching_of_table_permitted."); + + mutex_enter_noninline(&kernel_mutex); + trx_print(stderr, trx, 1024); + mutex_exit_noninline(&kernel_mutex); + ut_error; } innobase_release_stat_resources(trx); @@ -1043,7 +1040,7 @@ innobase_query_caching_of_table_permitted( return((my_bool)TRUE); } - + /* Normalize the table name to InnoDB format */ memcpy(norm_name, full_name, full_name_len); @@ -1057,11 +1054,11 @@ innobase_query_caching_of_table_permitted( /* The call of row_search_.. will start a new transaction if it is not yet started */ - if (trx->active_trans == 0) { + if (trx->active_trans == 0) { - innobase_register_trx_and_stmt(thd); - trx->active_trans = 1; - } + innobase_register_trx_and_stmt(thd); + trx->active_trans = 1; + } if (row_search_check_if_query_cache_permitted(trx, norm_name)) { @@ -1137,7 +1134,7 @@ trx_is_interrupted( } /************************************************************************** -Obtain a pointer to the MySQL THD object, as in current_thd(). This +Obtain a pointer to the MySQL THD object, as in current_thd(). This definition must match the one in sql/ha_innodb.cc! */ extern "C" void* @@ -1159,58 +1156,58 @@ void ha_innobase::init_table_handle_for_HANDLER(void) /*============================================*/ { - row_prebuilt_t* prebuilt; + row_prebuilt_t* prebuilt; - /* If current thd does not yet have a trx struct, create one. - If the current handle does not yet have a prebuilt struct, create - one. Update the trx pointers in the prebuilt struct. Normally - this operation is done in external_lock. */ + /* If current thd does not yet have a trx struct, create one. + If the current handle does not yet have a prebuilt struct, create + one. Update the trx pointers in the prebuilt struct. Normally + this operation is done in external_lock. */ - update_thd(current_thd); + update_thd(current_thd); - /* Initialize the prebuilt struct much like it would be inited in - external_lock */ + /* Initialize the prebuilt struct much like it would be inited in + external_lock */ - prebuilt = (row_prebuilt_t*)innobase_prebuilt; + prebuilt = (row_prebuilt_t*)innobase_prebuilt; innobase_release_stat_resources(prebuilt->trx); - /* If the transaction is not started yet, start it */ + /* If the transaction is not started yet, start it */ - trx_start_if_not_started_noninline(prebuilt->trx); + trx_start_if_not_started_noninline(prebuilt->trx); - /* Assign a read view if the transaction does not have it yet */ + /* Assign a read view if the transaction does not have it yet */ - trx_assign_read_view(prebuilt->trx); + trx_assign_read_view(prebuilt->trx); /* Set the MySQL flag to mark that there is an active transaction */ - if (prebuilt->trx->active_trans == 0) { + if (prebuilt->trx->active_trans == 0) { - innobase_register_trx_and_stmt(current_thd); + innobase_register_trx_and_stmt(current_thd); - prebuilt->trx->active_trans = 1; - } + prebuilt->trx->active_trans = 1; + } - /* We did the necessary inits in this function, no need to repeat them - in row_search_for_mysql */ + /* We did the necessary inits in this function, no need to repeat them + in row_search_for_mysql */ - prebuilt->sql_stat_start = FALSE; + prebuilt->sql_stat_start = FALSE; - /* We let HANDLER always to do the reads as consistent reads, even - if the trx isolation level would have been specified as SERIALIZABLE */ + /* We let HANDLER always to do the reads as consistent reads, even + if the trx isolation level would have been specified as SERIALIZABLE */ - prebuilt->select_lock_type = LOCK_NONE; - prebuilt->stored_select_lock_type = LOCK_NONE; + prebuilt->select_lock_type = LOCK_NONE; + prebuilt->stored_select_lock_type = LOCK_NONE; - /* Always fetch all columns in the index record */ + /* Always fetch all columns in the index record */ - prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS; + prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS; - /* We want always to fetch all columns in the whole row? Or do + /* We want always to fetch all columns in the whole row? Or do we???? */ - prebuilt->read_just_key = FALSE; + prebuilt->read_just_key = FALSE; prebuilt->used_in_HANDLER = TRUE; @@ -1228,12 +1225,12 @@ innobase_init(void) static char current_dir[3]; /* Set if using current lib */ int err; bool ret; - char *default_path; + char *default_path; - DBUG_ENTER("innobase_init"); + DBUG_ENTER("innobase_init"); - if (have_innodb != SHOW_OPTION_YES) - goto error; + if (have_innodb != SHOW_OPTION_YES) + goto error; ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); @@ -1256,7 +1253,7 @@ innobase_init(void) } } - os_innodb_umask = (ulint)my_umask; + os_innodb_umask = (ulint)my_umask; /* First calculate the default path for innodb_data_home_dir etc., in case the user has not given any value. @@ -1268,20 +1265,20 @@ innobase_init(void) default_path = mysql_real_data_home; fil_path_to_mysql_datadir = mysql_real_data_home; } else { - /* It's better to use current lib, to keep paths short */ - current_dir[0] = FN_CURLIB; - current_dir[1] = FN_LIBCHAR; - current_dir[2] = 0; - default_path = current_dir; + /* It's better to use current lib, to keep paths short */ + current_dir[0] = FN_CURLIB; + current_dir[1] = FN_LIBCHAR; + current_dir[2] = 0; + default_path = current_dir; } ut_a(default_path); if (specialflag & SPECIAL_NO_PRIOR) { - srv_set_thread_priorities = FALSE; + srv_set_thread_priorities = FALSE; } else { - srv_set_thread_priorities = TRUE; - srv_query_thread_priority = QUERY_PRIOR; + srv_set_thread_priorities = TRUE; + srv_query_thread_priority = QUERY_PRIOR; } /* Set InnoDB initialization parameters according to the values @@ -1295,11 +1292,11 @@ innobase_init(void) default_path); /* Set default InnoDB data file size to 10 MB and let it be - auto-extending. Thus users can use InnoDB in >= 4.0 without having + auto-extending. Thus users can use InnoDB in >= 4.0 without having to specify any startup options. */ if (!innobase_data_file_path) { - innobase_data_file_path = (char*) "ibdata1:10M:autoextend"; + innobase_data_file_path = (char*) "ibdata1:10M:autoextend"; } /* Since InnoDB edits the argument in the next call, we make another @@ -1317,22 +1314,22 @@ innobase_init(void) &srv_auto_extend_last_data_file, &srv_last_file_size_max); if (ret == FALSE) { - sql_print_error( + sql_print_error( "InnoDB: syntax error in innodb_data_file_path"); - my_free(internal_innobase_data_file_path, + my_free(internal_innobase_data_file_path, MYF(MY_ALLOW_ZERO_PTR)); - goto error; + goto error; } /* -------------- Log files ---------------------------*/ /* The default dir for log files is the datadir of MySQL */ - + if (!innobase_log_group_home_dir) { - innobase_log_group_home_dir = default_path; + innobase_log_group_home_dir = default_path; } -#ifdef UNIV_LOG_ARCHIVE +#ifdef UNIV_LOG_ARCHIVE /* Since innodb_log_arch_dir has no relevance under MySQL, starting from 4.0.6 we always set it the same as innodb_log_group_home_dir: */ @@ -1350,9 +1347,9 @@ innobase_init(void) sql_print_error("syntax error in innodb_log_group_home_dir, or a " "wrong number of mirrored log groups"); - my_free(internal_innobase_data_file_path, + my_free(internal_innobase_data_file_path, MYF(MY_ALLOW_ZERO_PTR)); - goto error; + goto error; } /* --------------------------------------------------*/ @@ -1369,25 +1366,25 @@ innobase_init(void) srv_log_buffer_size = (ulint) innobase_log_buffer_size; srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit; - /* We set srv_pool_size here in units of 1 kB. InnoDB internally - changes the value so that it becomes the number of database pages. */ - - if (innobase_buffer_pool_awe_mem_mb == 0) { - /* Careful here: we first convert the signed long int to ulint - and only after that divide */ - - srv_pool_size = ((ulint) innobase_buffer_pool_size) / 1024; - } else { - srv_use_awe = TRUE; - srv_pool_size = (ulint) - (1024 * innobase_buffer_pool_awe_mem_mb); - srv_awe_window_size = (ulint) innobase_buffer_pool_size; - - /* Note that what the user specified as - innodb_buffer_pool_size is actually the AWE memory window - size in this case, and the real buffer pool size is - determined by .._awe_mem_mb. */ - } + /* We set srv_pool_size here in units of 1 kB. InnoDB internally + changes the value so that it becomes the number of database pages. */ + + if (innobase_buffer_pool_awe_mem_mb == 0) { + /* Careful here: we first convert the signed long int to ulint + and only after that divide */ + + srv_pool_size = ((ulint) innobase_buffer_pool_size) / 1024; + } else { + srv_use_awe = TRUE; + srv_pool_size = (ulint) + (1024 * innobase_buffer_pool_awe_mem_mb); + srv_awe_window_size = (ulint) innobase_buffer_pool_size; + + /* Note that what the user specified as + innodb_buffer_pool_size is actually the AWE memory window + size in this case, and the real buffer pool size is + determined by .._awe_mem_mb. */ + } srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size; @@ -1401,9 +1398,9 @@ innobase_init(void) os_use_large_pages = (ibool) innobase_use_large_pages; os_large_page_size = (ulint) innobase_large_page_size; - + srv_file_per_table = (ibool) innobase_file_per_table; - srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog; + srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog; srv_max_n_open_files = (ulint) innobase_open_files; srv_innodb_status = (ibool) innobase_create_status_file; @@ -1417,6 +1414,7 @@ innobase_init(void) ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL == my_charset_latin1.number); + ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number); /* Store the latin1_swedish_ci character ordering table to InnoDB. For non-latin1_swedish_ci charsets we use the MySQL comparison functions, @@ -1428,7 +1426,7 @@ innobase_init(void) memcpy(srv_latin1_ordering, my_charset_latin1.sort_order, 256); /* Since we in this module access directly the fields of a trx - struct, and due to different headers and flags it might happen that + struct, and due to different headers and flags it might happen that mutex_t has a different size in this module and in InnoDB modules, we check at run time that the size is the same in these compilation modules. */ @@ -1438,18 +1436,18 @@ innobase_init(void) err = innobase_start_or_create_for_mysql(); if (err != DB_SUCCESS) { - my_free(internal_innobase_data_file_path, + my_free(internal_innobase_data_file_path, MYF(MY_ALLOW_ZERO_PTR)); - goto error; + goto error; } (void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0, - (hash_get_key) innobase_get_key, 0, 0); - pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST); - pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST); - pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST); - pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST); - pthread_cond_init(&commit_cond, NULL); + (hash_get_key) innobase_get_key, 0, 0); + pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST); + pthread_cond_init(&commit_cond, NULL); innodb_inited= 1; /* If this is a replication slave and we needed to do a crash recovery, @@ -1460,7 +1458,7 @@ innobase_init(void) THIS DOES NOT WORK CURRENTLY because replication seems to initialize glob_mi also after innobase_init. */ - + /* if (trx_sys_mysql_master_log_pos != -1) { ut_memcpy(glob_mi.log_file_name, trx_sys_mysql_master_log_name, 1 + ut_strlen(trx_sys_mysql_master_log_name)); @@ -1469,8 +1467,8 @@ innobase_init(void) */ DBUG_RETURN(FALSE); error: - have_innodb= SHOW_OPTION_DISABLED; // If we couldn't use handler - DBUG_RETURN(TRUE); + have_innodb= SHOW_OPTION_DISABLED; // If we couldn't use handler + DBUG_RETURN(TRUE); } /*********************************************************************** @@ -1485,29 +1483,29 @@ innobase_end(ha_panic_function type) DBUG_ENTER("innobase_end"); -#ifdef __NETWARE__ /* some special cleanup for NetWare */ +#ifdef __NETWARE__ /* some special cleanup for NetWare */ if (nw_panic) { set_panic_flag_for_netware(); } #endif if (innodb_inited) { - srv_fast_shutdown = (ulint) innobase_fast_shutdown; - innodb_inited = 0; - if (innobase_shutdown_for_mysql() != DB_SUCCESS) { - err = 1; + srv_fast_shutdown = (ulint) innobase_fast_shutdown; + innodb_inited = 0; + if (innobase_shutdown_for_mysql() != DB_SUCCESS) { + err = 1; } - hash_free(&innobase_open_tables); - my_free(internal_innobase_data_file_path, + hash_free(&innobase_open_tables); + my_free(internal_innobase_data_file_path, MYF(MY_ALLOW_ZERO_PTR)); - pthread_mutex_destroy(&innobase_share_mutex); - pthread_mutex_destroy(&prepare_commit_mutex); - pthread_mutex_destroy(&commit_threads_m); - pthread_mutex_destroy(&commit_cond_m); - pthread_cond_destroy(&commit_cond); + pthread_mutex_destroy(&innobase_share_mutex); + pthread_mutex_destroy(&prepare_commit_mutex); + pthread_mutex_destroy(&commit_threads_m); + pthread_mutex_destroy(&commit_cond_m); + pthread_cond_destroy(&commit_cond); } - DBUG_RETURN(err); + DBUG_RETURN(err); } /******************************************************************** @@ -1519,13 +1517,13 @@ innobase_flush_logs(void) /*=====================*/ /* out: TRUE if error */ { - bool result = 0; + bool result = 0; - DBUG_ENTER("innobase_flush_logs"); + DBUG_ENTER("innobase_flush_logs"); log_buffer_flush_to_disk(); - DBUG_RETURN(result); + DBUG_RETURN(result); } /********************************************************************* @@ -1536,22 +1534,22 @@ innobase_commit_low( /*================*/ trx_t* trx) /* in: transaction handle */ { - if (trx->conc_state == TRX_NOT_STARTED) { + if (trx->conc_state == TRX_NOT_STARTED) { - return; - } + return; + } #ifdef HAVE_REPLICATION - THD *thd=current_thd; + THD *thd=current_thd; - if (thd && thd->slave_thread) { - /* Update the replication position info inside InnoDB */ + if (thd && thd->slave_thread) { + /* Update the replication position info inside InnoDB */ - trx->mysql_master_log_file_name - = active_mi->rli.group_master_log_name; - trx->mysql_master_log_pos = ((ib_longlong) - active_mi->rli.future_group_master_log_pos); - } + trx->mysql_master_log_file_name + = active_mi->rli.group_master_log_name; + trx->mysql_master_log_pos = ((ib_longlong) + active_mi->rli.future_group_master_log_pos); + } #endif /* HAVE_REPLICATION */ trx_commit_for_mysql(trx); @@ -1572,7 +1570,7 @@ innobase_start_trx_and_assign_read_view( { trx_t* trx; - DBUG_ENTER("innobase_start_trx_and_assign_read_view"); + DBUG_ENTER("innobase_start_trx_and_assign_read_view"); /* Create a new trx struct for thd, if it does not yet have one */ @@ -1594,12 +1592,12 @@ innobase_start_trx_and_assign_read_view( /* Set the MySQL flag to mark that there is an active transaction */ - if (trx->active_trans == 0) { + if (trx->active_trans == 0) { - innobase_register_trx_and_stmt(current_thd); + innobase_register_trx_and_stmt(current_thd); - trx->active_trans = 1; - } + trx->active_trans = 1; + } DBUG_RETURN(0); } @@ -1614,13 +1612,13 @@ innobase_commit( /* out: 0 */ THD* thd, /* in: MySQL thread handle of the user for whom the transaction should be committed */ - bool all) /* in: TRUE - commit transaction - FALSE - the current SQL statement ended */ + bool all) /* in: TRUE - commit transaction + FALSE - the current SQL statement ended */ { trx_t* trx; - DBUG_ENTER("innobase_commit"); - DBUG_PRINT("trans", ("ending transaction")); + DBUG_ENTER("innobase_commit"); + DBUG_PRINT("trans", ("ending transaction")); trx = check_trx_exists(thd); @@ -1631,11 +1629,11 @@ innobase_commit( reserve the kernel mutex, we have to release the search system latch first to obey the latching order. */ - if (trx->has_search_latch) { - trx_search_latch_release_if_reserved(trx); - } - - /* The flag trx->active_trans is set to 1 in + if (trx->has_search_latch) { + trx_search_latch_release_if_reserved(trx); + } + + /* The flag trx->active_trans is set to 1 in 1. ::external_lock(), 2. ::start_stmt(), @@ -1650,65 +1648,66 @@ innobase_commit( For the time being, we play safe and do the cleanup though there should be nothing to clean up. */ - if (trx->active_trans == 0 - && trx->conc_state != TRX_NOT_STARTED) { - - sql_print_error("trx->active_trans == 0, but trx->conc_state != " - "TRX_NOT_STARTED"); + if (trx->active_trans == 0 + && trx->conc_state != TRX_NOT_STARTED) { + + sql_print_error("trx->active_trans == 0, but" + " trx->conc_state != TRX_NOT_STARTED"); } - if (all - || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { - - /* We were instructed to commit the whole transaction, or + if (all + || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + + /* We were instructed to commit the whole transaction, or this is an SQL statement end and autocommit is on */ - /* We need current binlog position for ibbackup to work. - Note, the position is current because of prepare_commit_mutex */ + /* We need current binlog position for ibbackup to work. + Note, the position is current because of + prepare_commit_mutex */ retry: - if (srv_commit_concurrency > 0) - { - pthread_mutex_lock(&commit_cond_m); - commit_threads++; - if (commit_threads > srv_commit_concurrency) - { - commit_threads--; - pthread_cond_wait(&commit_cond, &commit_cond_m); - pthread_mutex_unlock(&commit_cond_m); - goto retry; - } - else - pthread_mutex_unlock(&commit_cond_m); - } - - trx->mysql_log_file_name = mysql_bin_log.get_log_fname(); - trx->mysql_log_offset = - (ib_longlong)mysql_bin_log.get_log_file()->pos_in_file; + if (srv_commit_concurrency > 0) { + pthread_mutex_lock(&commit_cond_m); + commit_threads++; + + if (commit_threads > srv_commit_concurrency) { + commit_threads--; + pthread_cond_wait(&commit_cond, + &commit_cond_m); + pthread_mutex_unlock(&commit_cond_m); + goto retry; + } + else { + pthread_mutex_unlock(&commit_cond_m); + } + } + + trx->mysql_log_file_name = mysql_bin_log.get_log_fname(); + trx->mysql_log_offset = + (ib_longlong)mysql_bin_log.get_log_file()->pos_in_file; innobase_commit_low(trx); - if (srv_commit_concurrency > 0) - { - pthread_mutex_lock(&commit_cond_m); - commit_threads--; - pthread_cond_signal(&commit_cond); - pthread_mutex_unlock(&commit_cond_m); - } - - if (trx->active_trans == 2) { - - pthread_mutex_unlock(&prepare_commit_mutex); - } - - trx->active_trans = 0; - + if (srv_commit_concurrency > 0) { + pthread_mutex_lock(&commit_cond_m); + commit_threads--; + pthread_cond_signal(&commit_cond); + pthread_mutex_unlock(&commit_cond_m); + } + + if (trx->active_trans == 2) { + + pthread_mutex_unlock(&prepare_commit_mutex); + } + + trx->active_trans = 0; + } else { - /* We just mark the SQL statement ended and do not do a + /* We just mark the SQL statement ended and do not do a transaction commit */ if (trx->auto_inc_lock) { /* If we had reserved the auto-inc lock for some table in this SQL statement we release it now */ - + row_unlock_table_autoinc_for_mysql(trx); } /* Store the current undo_no of the transaction so that we @@ -1720,11 +1719,11 @@ retry: /* Tell the InnoDB server that there might be work for utility threads: */ - if (trx->declared_to_be_inside_innodb) { - /* Release our possible ticket in the FIFO */ + if (trx->declared_to_be_inside_innodb) { + /* Release our possible ticket in the FIFO */ - srv_conc_force_exit_innodb(trx); - } + srv_conc_force_exit_innodb(trx); + } srv_active_wake_master_thread(); DBUG_RETURN(0); @@ -1746,12 +1745,12 @@ InnoDB's group commit capability. */ int innobase_report_binlog_offset_and_commit( /*=====================================*/ - /* out: 0 */ - THD* thd, /* in: user thread */ - void* trx_handle, /* in: InnoDB trx handle */ - char* log_file_name, /* in: latest binlog file name */ - my_off_t end_offset) /* in: the offset in the binlog file - up to which we wrote */ + /* out: 0 */ + THD* thd, /* in: user thread */ + void* trx_handle, /* in: InnoDB trx handle */ + char* log_file_name, /* in: latest binlog file name */ + my_off_t end_offset) /* in: the offset in the binlog file + up to which we wrote */ { trx_t* trx; @@ -1763,23 +1762,23 @@ innobase_report_binlog_offset_and_commit( trx->mysql_log_offset = (ib_longlong)end_offset; #ifdef HAVE_REPLICATION - if (thd->variables.sync_replication) { - /* Let us store the binlog file name and the position, so that - we know how long to wait for the binlog to the replicated to - the slave in synchronous replication. */ + if (thd->variables.sync_replication) { + /* Let us store the binlog file name and the position, so that + we know how long to wait for the binlog to the replicated to + the slave in synchronous replication. */ - if (trx->repl_wait_binlog_name == NULL) { + if (trx->repl_wait_binlog_name == NULL) { - trx->repl_wait_binlog_name = - (char*)mem_alloc_noninline(FN_REFLEN + 100); - } + trx->repl_wait_binlog_name = + (char*)mem_alloc_noninline(FN_REFLEN + 100); + } - ut_a(strlen(log_file_name) < FN_REFLEN + 100); + ut_a(strlen(log_file_name) < FN_REFLEN + 100); - strcpy(trx->repl_wait_binlog_name, log_file_name); + strcpy(trx->repl_wait_binlog_name, log_file_name); - trx->repl_wait_binlog_pos = (ib_longlong)end_offset; - } + trx->repl_wait_binlog_pos = (ib_longlong)end_offset; + } #endif /* HAVE_REPLICATION */ trx->flush_log_later = TRUE; @@ -1797,26 +1796,26 @@ This function stores the binlog offset and flushes logs. */ void innobase_store_binlog_offset_and_flush_log( /*=======================================*/ - char *binlog_name, /* in: binlog name */ - longlong offset) /* in: binlog offset */ + char* binlog_name, /* in: binlog name */ + longlong offset) /* in: binlog offset */ { mtr_t mtr; assert(binlog_name != NULL); /* Start a mini-transaction */ - mtr_start_noninline(&mtr); + mtr_start_noninline(&mtr); /* Update the latest MySQL binlog name and offset info - in trx sys header */ + in trx sys header */ - trx_sys_update_mysql_binlog_offset( - binlog_name, - offset, - TRX_SYS_MYSQL_LOG_INFO, &mtr); + trx_sys_update_mysql_binlog_offset( + binlog_name, + offset, + TRX_SYS_MYSQL_LOG_INFO, &mtr); - /* Commits the mini-transaction */ - mtr_commit(&mtr); + /* Commits the mini-transaction */ + mtr_commit(&mtr); /* Synchronous flush of the log buffer to disk */ log_buffer_flush_to_disk(); @@ -1830,106 +1829,107 @@ transaction. Flushes the InnoDB log files to disk if required. */ int innobase_commit_complete( /*=====================*/ - /* out: 0 */ - THD* thd) /* in: user thread */ + /* out: 0 */ + THD* thd) /* in: user thread */ { trx_t* trx; - trx = (trx_t*) thd->ha_data[innobase_hton.slot]; + trx = (trx_t*) thd->ha_data[innobase_hton.slot]; - if (trx && trx->active_trans) { + if (trx && trx->active_trans) { - trx->active_trans = 0; + trx->active_trans = 0; - if (srv_flush_log_at_trx_commit == 0) { + if (srv_flush_log_at_trx_commit == 0) { - return(0); - } + return(0); + } - trx_commit_complete_for_mysql(trx); - } + trx_commit_complete_for_mysql(trx); + } #ifdef HAVE_REPLICATION - if (thd->variables.sync_replication - && trx->repl_wait_binlog_name - && innobase_repl_state != 0) { + if (thd->variables.sync_replication + && trx->repl_wait_binlog_name + && innobase_repl_state != 0) { struct timespec abstime; int cmp; int ret; - /* In synchronous replication, let us wait until the MySQL - replication has sent the relevant binlog segment to the - replication slave. */ + /* In synchronous replication, let us wait until the MySQL + replication has sent the relevant binlog segment to the + replication slave. */ - pthread_mutex_lock(&innobase_repl_cond_mutex); + pthread_mutex_lock(&innobase_repl_cond_mutex); try_again: - if (innobase_repl_state == 0) { + if (innobase_repl_state == 0) { - pthread_mutex_unlock(&innobase_repl_cond_mutex); + pthread_mutex_unlock(&innobase_repl_cond_mutex); - return(0); - } + return(0); + } - cmp = strcmp(innobase_repl_file_name, - trx->repl_wait_binlog_name); - if (cmp > 0 - || (cmp == 0 && innobase_repl_pos - >= (my_off_t)trx->repl_wait_binlog_pos)) { - /* We have already sent the relevant binlog to the - slave: no need to wait here */ + cmp = strcmp(innobase_repl_file_name, + trx->repl_wait_binlog_name); + if (cmp > 0 + || (cmp == 0 && innobase_repl_pos + >= (my_off_t)trx->repl_wait_binlog_pos)) { + /* We have already sent the relevant binlog to the + slave: no need to wait here */ - pthread_mutex_unlock(&innobase_repl_cond_mutex); + pthread_mutex_unlock(&innobase_repl_cond_mutex); -/* printf("Binlog now sent\n"); */ +/* printf("Binlog now sent\n"); */ - return(0); - } + return(0); + } - /* Let us update the info about the minimum binlog position - of waiting threads in the innobase_repl_... variables */ + /* Let us update the info about the minimum binlog position + of waiting threads in the innobase_repl_... variables */ - if (innobase_repl_wait_file_name_inited != 0) { - cmp = strcmp(trx->repl_wait_binlog_name, - innobase_repl_wait_file_name); - if (cmp < 0 - || (cmp == 0 && (my_off_t)trx->repl_wait_binlog_pos - <= innobase_repl_wait_pos)) { - /* This thd has an even lower position, let - us update the minimum info */ + if (innobase_repl_wait_file_name_inited != 0) { + cmp = strcmp(trx->repl_wait_binlog_name, + innobase_repl_wait_file_name); + if (cmp < 0 + || (cmp == 0 + && (my_off_t)trx->repl_wait_binlog_pos + <= innobase_repl_wait_pos)) { + /* This thd has an even lower position, let + us update the minimum info */ - strcpy(innobase_repl_wait_file_name, - trx->repl_wait_binlog_name); + strcpy(innobase_repl_wait_file_name, + trx->repl_wait_binlog_name); - innobase_repl_wait_pos = - trx->repl_wait_binlog_pos; - } - } else { - strcpy(innobase_repl_wait_file_name, - trx->repl_wait_binlog_name); + innobase_repl_wait_pos = + trx->repl_wait_binlog_pos; + } + } else { + strcpy(innobase_repl_wait_file_name, + trx->repl_wait_binlog_name); - innobase_repl_wait_pos = trx->repl_wait_binlog_pos; + innobase_repl_wait_pos = trx->repl_wait_binlog_pos; - innobase_repl_wait_file_name_inited = 1; - } - set_timespec(abstime, thd->variables.sync_replication_timeout); + innobase_repl_wait_file_name_inited = 1; + } + set_timespec(abstime, thd->variables.sync_replication_timeout); - /* Let us suspend this thread to wait on the condition; - when replication has progressed far enough, we will release - these waiting threads. The following call - pthread_cond_timedwait also atomically unlocks - innobase_repl_cond_mutex. */ + /* Let us suspend this thread to wait on the condition; + when replication has progressed far enough, we will release + these waiting threads. The following call + pthread_cond_timedwait also atomically unlocks + innobase_repl_cond_mutex. */ - innobase_repl_n_wait_threads++; + innobase_repl_n_wait_threads++; -/* printf("Waiting for binlog to be sent\n"); */ +/* printf("Waiting for binlog to be sent\n"); */ - ret = pthread_cond_timedwait(&innobase_repl_cond, - &innobase_repl_cond_mutex, &abstime); - innobase_repl_n_wait_threads--; + ret = pthread_cond_timedwait(&innobase_repl_cond, + &innobase_repl_cond_mutex, &abstime); + innobase_repl_n_wait_threads--; - if (ret != 0) { - ut_print_timestamp(stderr); + if (ret != 0) { + ut_print_timestamp(stderr); sql_print_error("MySQL synchronous replication was " "not able to send the binlog to the " @@ -1949,15 +1949,15 @@ try_again: trx->repl_wait_binlog_name, (ulong) trx->repl_wait_binlog_pos); - innobase_repl_state = 0; + innobase_repl_state = 0; - pthread_mutex_unlock(&innobase_repl_cond_mutex); + pthread_mutex_unlock(&innobase_repl_cond_mutex); - return(0); - } + return(0); + } - goto try_again; - } + goto try_again; + } #endif // HAVE_REPLICATION return(0); } @@ -1972,56 +1972,56 @@ function is used in a replication master. */ int innobase_repl_report_sent_binlog( /*=============================*/ - /* out: 0 */ - THD* thd, /* in: thread doing the binlog communication to - the slave */ - char* log_file_name, /* in: binlog file name */ - my_off_t end_offset) /* in: the offset in the binlog file up to - which we sent the contents to the slave */ + /* out: 0 */ + THD* thd, /* in: thread doing the binlog communication to + the slave */ + char* log_file_name, /* in: binlog file name */ + my_off_t end_offset) /* in: the offset in the binlog file up to + which we sent the contents to the slave */ { - int cmp; - ibool can_release_threads = 0; + int cmp; + ibool can_release_threads = 0; if (!innodb_inited) { - + return 0; } - /* If synchronous replication is not switched on, or this thd is - sending binlog to a slave where we do not need synchronous replication, - then return immediately */ + /* If synchronous replication is not switched on, or this thd is + sending binlog to a slave where we do not need synchronous replication, + then return immediately */ - if (thd->server_id != thd->variables.sync_replication_slave_id) { + if (thd->server_id != thd->variables.sync_replication_slave_id) { - /* Do nothing */ + /* Do nothing */ - return(0); - } + return(0); + } - pthread_mutex_lock(&innobase_repl_cond_mutex); + pthread_mutex_lock(&innobase_repl_cond_mutex); - if (innobase_repl_state == 0) { + if (innobase_repl_state == 0) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); sql_print_warning("Switching MySQL synchronous replication on " "again at binlog file %s, position %lu", log_file_name, (ulong) end_offset); - innobase_repl_state = 1; - } + innobase_repl_state = 1; + } - /* The position should increase monotonically, since just one thread - is sending the binlog to the slave for which we want synchronous - replication. Let us check this, and print an error to the .err log - if that is not the case. */ + /* The position should increase monotonically, since just one thread + is sending the binlog to the slave for which we want synchronous + replication. Let us check this, and print an error to the .err log + if that is not the case. */ - if (innobase_repl_file_name_inited) { - cmp = strcmp(log_file_name, innobase_repl_file_name); + if (innobase_repl_file_name_inited) { + cmp = strcmp(log_file_name, innobase_repl_file_name); - if (cmp < 0 - || (cmp == 0 && end_offset < innobase_repl_pos)) { + if (cmp < 0 + || (cmp == 0 && end_offset < innobase_repl_pos)) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); sql_print_error("MySQL synchronous replication has " "sent binlog to the slave up to file " "%s, position %lu, but now MySQL " @@ -2030,38 +2030,38 @@ innobase_repl_report_sent_binlog( innobase_repl_file_name, (ulong) innobase_repl_pos, log_file_name, (ulong) end_offset); - } - } + } + } - strcpy(innobase_repl_file_name, log_file_name); - innobase_repl_pos = end_offset; - innobase_repl_file_name_inited = 1; + strcpy(innobase_repl_file_name, log_file_name); + innobase_repl_pos = end_offset; + innobase_repl_file_name_inited = 1; - if (innobase_repl_n_wait_threads > 0) { - /* Let us check if some of the waiting threads doing a trx - commit can now proceed */ + if (innobase_repl_n_wait_threads > 0) { + /* Let us check if some of the waiting threads doing a trx + commit can now proceed */ - cmp = strcmp(innobase_repl_file_name, - innobase_repl_wait_file_name); - if (cmp > 0 - || (cmp == 0 && innobase_repl_pos - >= innobase_repl_wait_pos)) { + cmp = strcmp(innobase_repl_file_name, + innobase_repl_wait_file_name); + if (cmp > 0 + || (cmp == 0 && innobase_repl_pos + >= innobase_repl_wait_pos)) { - /* Yes, at least one waiting thread can now proceed: - let us release all waiting threads with a broadcast */ + /* Yes, at least one waiting thread can now proceed: + let us release all waiting threads with a broadcast */ - can_release_threads = 1; + can_release_threads = 1; - innobase_repl_wait_file_name_inited = 0; - } - } + innobase_repl_wait_file_name_inited = 0; + } + } - pthread_mutex_unlock(&innobase_repl_cond_mutex); + pthread_mutex_unlock(&innobase_repl_cond_mutex); - if (can_release_threads) { + if (can_release_threads) { - pthread_cond_broadcast(&innobase_repl_cond); - } + pthread_cond_broadcast(&innobase_repl_cond); + } return(0); } @@ -2076,8 +2076,8 @@ innobase_rollback( /* out: 0 or error number */ THD* thd, /* in: handle to the MySQL thread of the user whose transaction should be rolled back */ - bool all) /* in: TRUE - commit transaction - FALSE - the current SQL statement ended */ + bool all) /* in: TRUE - commit transaction + FALSE - the current SQL statement ended */ { int error = 0; trx_t* trx; @@ -2096,19 +2096,19 @@ innobase_rollback( innobase_release_stat_resources(trx); - if (trx->auto_inc_lock) { + if (trx->auto_inc_lock) { /* If we had reserved the auto-inc lock for some table (if we come here to roll back the latest SQL statement) we release it now before a possibly lengthy rollback */ - + row_unlock_table_autoinc_for_mysql(trx); } - if (all - || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + if (all + || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { error = trx_rollback_for_mysql(trx); - trx->active_trans = 0; + trx->active_trans = 0; } else { error = trx_rollback_last_sql_stat_for_mysql(trx); } @@ -2136,11 +2136,11 @@ innobase_rollback_trx( innobase_release_stat_resources(trx); - if (trx->auto_inc_lock) { + if (trx->auto_inc_lock) { /* If we had reserved the auto-inc lock for some table (if we come here to roll back the latest SQL statement) we release it now before a possibly lengthy rollback */ - + row_unlock_table_autoinc_for_mysql(trx); } @@ -2159,12 +2159,12 @@ innobase_rollback_to_savepoint( no savepoint with the given name */ THD* thd, /* in: handle to the MySQL thread of the user whose transaction should be rolled back */ - void *savepoint) /* in: savepoint data */ + void* savepoint) /* in: savepoint data */ { - ib_longlong mysql_binlog_cache_pos; - int error = 0; - trx_t* trx; - char name[64]; + ib_longlong mysql_binlog_cache_pos; + int error = 0; + trx_t* trx; + char name[64]; DBUG_ENTER("innobase_rollback_to_savepoint"); @@ -2176,11 +2176,11 @@ innobase_rollback_to_savepoint( innobase_release_stat_resources(trx); - /* TODO: use provided savepoint data area to store savepoint data */ + /* TODO: use provided savepoint data area to store savepoint data */ - longlong2str((ulint)savepoint, name, 36); + longlong2str((ulint)savepoint, name, 36); - error = (int) trx_rollback_to_savepoint_for_mysql(trx, name, + error = (int) trx_rollback_to_savepoint_for_mysql(trx, name, &mysql_binlog_cache_pos); DBUG_RETURN(convert_error_code_to_mysql(error, NULL)); } @@ -2195,19 +2195,19 @@ innobase_release_savepoint( no savepoint with the given name */ THD* thd, /* in: handle to the MySQL thread of the user whose transaction should be rolled back */ - void* savepoint) /* in: savepoint data */ + void* savepoint) /* in: savepoint data */ { - int error = 0; - trx_t* trx; - char name[64]; + int error = 0; + trx_t* trx; + char name[64]; DBUG_ENTER("innobase_release_savepoint"); trx = check_trx_exists(thd); - /* TODO: use provided savepoint data area to store savepoint data */ + /* TODO: use provided savepoint data area to store savepoint data */ - longlong2str((ulint)savepoint, name, 36); + longlong2str((ulint)savepoint, name, 36); error = (int) trx_release_savepoint_for_mysql(trx, name); @@ -2222,20 +2222,20 @@ innobase_savepoint( /*===============*/ /* out: always 0, that is, always succeeds */ THD* thd, /* in: handle to the MySQL thread */ - void* savepoint) /* in: savepoint data */ + void* savepoint) /* in: savepoint data */ { int error = 0; trx_t* trx; DBUG_ENTER("innobase_savepoint"); - /* - In the autocommit mode there is no sense to set a savepoint - (unless we are in sub-statement), so SQL layer ensures that - this method is never called in such situation. - */ - DBUG_ASSERT(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) || - thd->in_sub_stmt); + /* + In the autocommit mode there is no sense to set a savepoint + (unless we are in sub-statement), so SQL layer ensures that + this method is never called in such situation. + */ + DBUG_ASSERT(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) || + thd->in_sub_stmt); trx = check_trx_exists(thd); @@ -2245,14 +2245,14 @@ innobase_savepoint( innobase_release_stat_resources(trx); - /* cannot happen outside of transaction */ - DBUG_ASSERT(trx->active_trans); + /* cannot happen outside of transaction */ + DBUG_ASSERT(trx->active_trans); - /* TODO: use provided savepoint data area to store savepoint data */ - char name[64]; - longlong2str((ulint)savepoint,name,36); + /* TODO: use provided savepoint data area to store savepoint data */ + char name[64]; + longlong2str((ulint)savepoint,name,36); - error = (int) trx_savepoint_for_mysql(trx, name, (ib_longlong)0); + error = (int) trx_savepoint_for_mysql(trx, name, (ib_longlong)0); DBUG_RETURN(convert_error_code_to_mysql(error, NULL)); } @@ -2273,24 +2273,26 @@ innobase_close_connection( ut_a(trx); - if (trx->active_trans == 0 - && trx->conc_state != TRX_NOT_STARTED) { - - sql_print_error("trx->active_trans == 0, but trx->conc_state != " - "TRX_NOT_STARTED"); + if (trx->active_trans == 0 + && trx->conc_state != TRX_NOT_STARTED) { + + sql_print_error("trx->active_trans == 0, but" + " trx->conc_state != TRX_NOT_STARTED"); } if (trx->conc_state != TRX_NOT_STARTED && - global_system_variables.log_warnings) - sql_print_warning("MySQL is closing a connection that has an active " - "InnoDB transaction. %lu row modifications will " - "roll back.", - (ulong)trx->undo_no.low); + global_system_variables.log_warnings) { + sql_print_warning( + "MySQL is closing a connection that has an active " + "InnoDB transaction. %lu row modifications will " + "roll back.", + (ulong) trx->undo_no.low); + } innobase_rollback_trx(trx); - trx_free_for_mysql(trx); + trx_free_for_mysql(trx); return(0); } @@ -2310,7 +2312,7 @@ ha_innobase::get_row_type() const row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; if (prebuilt && prebuilt->table) { - if (prebuilt->table->comp) { + if (dict_table_is_comp(prebuilt->table)) { return(ROW_TYPE_COMPACT); } else { return(ROW_TYPE_REDUNDANT); @@ -2391,11 +2393,11 @@ ha_innobase::open( /*==============*/ /* out: 1 if error, 0 if success */ const char* name, /* in: table name */ - int mode, /* in: not used */ - uint test_if_locked) /* in: not used */ + int mode, /* in: not used */ + uint test_if_locked) /* in: not used */ { dict_table_t* ib_table; - char norm_name[1000]; + char norm_name[1000]; THD* thd; DBUG_ENTER("ha_innobase::open"); @@ -2424,20 +2426,21 @@ ha_innobase::open( table->s->reclength + table->s->max_key_length + MAX_REF_PARTS * 3; if (!(mysql_byte*) my_multi_malloc(MYF(MY_WME), - &upd_buff, upd_and_key_val_buff_len, - &key_val_buff, upd_and_key_val_buff_len, - NullS)) { - free_share(share); + &upd_buff, upd_and_key_val_buff_len, + &key_val_buff, upd_and_key_val_buff_len, + NullS)) { + free_share(share); - DBUG_RETURN(1); - } + DBUG_RETURN(1); + } /* Get pointer to a table object in InnoDB dictionary cache */ ib_table = dict_table_get_and_increment_handle_count( - norm_name, NULL); - if (NULL == ib_table) { - ut_print_timestamp(stderr); + norm_name, NULL); + + if (NULL == ib_table) { + ut_print_timestamp(stderr); sql_print_error("Cannot find table %s from the internal data " "dictionary\nof InnoDB though the .frm file " "for the table exists. Maybe you\nhave " @@ -2449,15 +2452,15 @@ ha_innobase::open( "http://www.innodb.com/ibman.html\n" "how you can resolve the problem.\n", norm_name); - free_share(share); - my_free((gptr) upd_buff, MYF(0)); - my_errno = ENOENT; + free_share(share); + my_free((gptr) upd_buff, MYF(0)); + my_errno = ENOENT; - DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); - } + DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); + } - if (ib_table->ibd_file_missing && !thd->tablespace_op) { - ut_print_timestamp(stderr); + if (ib_table->ibd_file_missing && !thd->tablespace_op) { + ut_print_timestamp(stderr); sql_print_error("MySQL is trying to open a table handle but " "the .ibd file for\ntable %s does not exist.\n" "Have you deleted the .ibd file from the " @@ -2467,13 +2470,13 @@ ha_innobase::open( "http://www.innodb.com/ibman.html\n" "how you can resolve the problem.\n", norm_name); - free_share(share); - my_free((gptr) upd_buff, MYF(0)); - my_errno = ENOENT; + free_share(share); + my_free((gptr) upd_buff, MYF(0)); + my_errno = ENOENT; dict_table_decrement_handle_count(ib_table); - DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); - } + DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); + } innobase_prebuilt = row_create_prebuilt(ib_table); @@ -2482,32 +2485,32 @@ ha_innobase::open( /* Looks like MySQL-3.23 sometimes has primary key number != 0 */ - primary_key = table->s->primary_key; + primary_key = table->s->primary_key; key_used_on_scan = primary_key; /* Allocate a buffer for a 'row reference'. A row reference is a string of bytes of length ref_length which uniquely specifies - a row in our table. Note that MySQL may also compare two row - references for equality by doing a simple memcmp on the strings - of length ref_length! */ + a row in our table. Note that MySQL may also compare two row + references for equality by doing a simple memcmp on the strings + of length ref_length! */ - if (!row_table_got_default_clust_index(ib_table)) { - if (primary_key >= MAX_KEY) { + if (!row_table_got_default_clust_index(ib_table)) { + if (primary_key >= MAX_KEY) { sql_print_error("Table %s has a primary key in InnoDB data " "dictionary, but not in MySQL!", name); } ((row_prebuilt_t*)innobase_prebuilt) ->clust_index_was_generated = FALSE; - /* MySQL allocates the buffer for ref. key_info->key_length + /* MySQL allocates the buffer for ref. key_info->key_length includes space for all key columns + one byte for each column that may be NULL. ref_length must be as exact as possible to save space, because all row reference buffers are allocated based on ref_length. */ - - ref_length = table->key_info[primary_key].key_length; + + ref_length = table->key_info[primary_key].key_length; } else { - if (primary_key != MAX_KEY) { + if (primary_key != MAX_KEY) { sql_print_error("Table %s has no primary key in InnoDB data " "dictionary, but has one in MySQL! If you " "created the table with a MySQL version < " @@ -2522,7 +2525,7 @@ ha_innobase::open( ((row_prebuilt_t*)innobase_prebuilt) ->clust_index_was_generated = TRUE; - ref_length = DATA_ROW_ID_LEN; + ref_length = DATA_ROW_ID_LEN; /* If we automatically created the clustered index, then MySQL does not know about it, and MySQL must NOT be aware @@ -2531,11 +2534,12 @@ ha_innobase::open( that key_used_on_scan is the undefined value MAX_KEY. The column is the row id in the automatical generation case, and it will never be updated anyway. */ - + if (key_used_on_scan != MAX_KEY) { - sql_print_warning("Table %s key_used_on_scan is %lu even " - "though there is no primary key inside " - "InnoDB.", name, (ulong) key_used_on_scan); + sql_print_warning( + "Table %s key_used_on_scan is %lu even " + "though there is no primary key inside " + "InnoDB.", name, (ulong) key_used_on_scan); } } @@ -2545,9 +2549,9 @@ ha_innobase::open( /* Init table lock structure */ thr_lock_data_init(&share->lock,&lock,(void*) 0); - info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); + info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); - DBUG_RETURN(0); + DBUG_RETURN(0); } uint @@ -2564,19 +2568,19 @@ ha_innobase::close(void) /*====================*/ /* out: 0 */ { - DBUG_ENTER("ha_innobase::close"); + DBUG_ENTER("ha_innobase::close"); row_prebuilt_free((row_prebuilt_t*) innobase_prebuilt); - my_free((gptr) upd_buff, MYF(0)); - free_share(share); + my_free((gptr) upd_buff, MYF(0)); + free_share(share); /* Tell InnoDB server that there might be work for utility threads: */ srv_active_wake_master_thread(); - DBUG_RETURN(0); + DBUG_RETURN(0); } /* The following accessor functions should really be inside MySQL code! */ @@ -2666,7 +2670,7 @@ innobase_mysql_cmp( { CHARSET_INFO* charset; enum_field_types mysql_tp; - int ret; + int ret; DBUG_ASSERT(a_length != UNIV_SQL_NULL); DBUG_ASSERT(b_length != UNIV_SQL_NULL); @@ -2675,14 +2679,14 @@ innobase_mysql_cmp( switch (mysql_tp) { - case MYSQL_TYPE_BIT: + case MYSQL_TYPE_BIT: case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_BLOB: case FIELD_TYPE_LONG_BLOB: - case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_VARCHAR: /* Use the charset number to pick the right charset struct for the comparison. Since the MySQL function get_charset may be slow before Bar removes the mutex operation there, we first @@ -2704,21 +2708,21 @@ innobase_mysql_cmp( } } - /* Starting from 4.1.3, we use strnncollsp() in comparisons of - non-latin1_swedish_ci strings. NOTE that the collation order - changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users - having indexes on such data need to rebuild their tables! */ + /* Starting from 4.1.3, we use strnncollsp() in comparisons of + non-latin1_swedish_ci strings. NOTE that the collation order + changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users + having indexes on such data need to rebuild their tables! */ - ret = charset->coll->strnncollsp(charset, - a, a_length, - b, b_length, 0); + ret = charset->coll->strnncollsp(charset, + a, a_length, + b, b_length, 0); if (ret < 0) { - return(-1); + return(-1); } else if (ret > 0) { - return(1); + return(1); } else { - return(0); - } + return(0); + } default: assert(0); } @@ -2759,7 +2763,7 @@ get_innobase_type_from_mysql_type( } if (field->real_type() == FIELD_TYPE_ENUM - || field->real_type() == FIELD_TYPE_SET) { + || field->real_type() == FIELD_TYPE_SET) { /* MySQL has field->type() a string type for these, but the data is actually internally stored as an unsigned integer @@ -2773,58 +2777,58 @@ get_innobase_type_from_mysql_type( } switch (field->type()) { - /* NOTE that we only allow string types in DATA_MYSQL - and DATA_VARMYSQL */ - case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */ - case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */ - if (field->binary()) { - return(DATA_BINARY); - } else if (strcmp( - field->charset()->name, - "latin1_swedish_ci") == 0) { - return(DATA_VARCHAR); - } else { - return(DATA_VARMYSQL); - } - case MYSQL_TYPE_BIT: - case MYSQL_TYPE_STRING: if (field->binary()) { - - return(DATA_FIXBINARY); - } else if (strcmp( - field->charset()->name, - "latin1_swedish_ci") == 0) { - return(DATA_CHAR); - } else { - return(DATA_MYSQL); - } - case FIELD_TYPE_NEWDECIMAL: - return(DATA_FIXBINARY); - case FIELD_TYPE_LONG: - case FIELD_TYPE_LONGLONG: - case FIELD_TYPE_TINY: - case FIELD_TYPE_SHORT: - case FIELD_TYPE_INT24: - case FIELD_TYPE_DATE: - case FIELD_TYPE_DATETIME: - case FIELD_TYPE_YEAR: - case FIELD_TYPE_NEWDATE: - case FIELD_TYPE_TIME: - case FIELD_TYPE_TIMESTAMP: - return(DATA_INT); - case FIELD_TYPE_FLOAT: - return(DATA_FLOAT); - case FIELD_TYPE_DOUBLE: - return(DATA_DOUBLE); - case FIELD_TYPE_DECIMAL: - return(DATA_DECIMAL); - case FIELD_TYPE_GEOMETRY: - case FIELD_TYPE_TINY_BLOB: - case FIELD_TYPE_MEDIUM_BLOB: - case FIELD_TYPE_BLOB: - case FIELD_TYPE_LONG_BLOB: - return(DATA_BLOB); - default: - assert(0); + /* NOTE that we only allow string types in DATA_MYSQL and + DATA_VARMYSQL */ + case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */ + case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */ + if (field->binary()) { + return(DATA_BINARY); + } else if (strcmp( + field->charset()->name, + "latin1_swedish_ci") == 0) { + return(DATA_VARCHAR); + } else { + return(DATA_VARMYSQL); + } + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_STRING: if (field->binary()) { + + return(DATA_FIXBINARY); + } else if (strcmp( + field->charset()->name, + "latin1_swedish_ci") == 0) { + return(DATA_CHAR); + } else { + return(DATA_MYSQL); + } + case FIELD_TYPE_NEWDECIMAL: + return(DATA_FIXBINARY); + case FIELD_TYPE_LONG: + case FIELD_TYPE_LONGLONG: + case FIELD_TYPE_TINY: + case FIELD_TYPE_SHORT: + case FIELD_TYPE_INT24: + case FIELD_TYPE_DATE: + case FIELD_TYPE_DATETIME: + case FIELD_TYPE_YEAR: + case FIELD_TYPE_NEWDATE: + case FIELD_TYPE_TIME: + case FIELD_TYPE_TIMESTAMP: + return(DATA_INT); + case FIELD_TYPE_FLOAT: + return(DATA_FLOAT); + case FIELD_TYPE_DOUBLE: + return(DATA_DOUBLE); + case FIELD_TYPE_DECIMAL: + return(DATA_DECIMAL); + case FIELD_TYPE_GEOMETRY: + case FIELD_TYPE_TINY_BLOB: + case FIELD_TYPE_MEDIUM_BLOB: + case FIELD_TYPE_BLOB: + case FIELD_TYPE_LONG_BLOB: + return(DATA_BLOB); + default: + assert(0); } return(0); @@ -2866,23 +2870,21 @@ uint ha_innobase::store_key_val_for_row( /*===============================*/ /* out: key value length as stored in buff */ - uint keynr, /* in: key number */ + uint keynr, /* in: key number */ char* buff, /* in/out: buffer for the key value (in MySQL format) */ uint buff_len,/* in: buffer length */ const mysql_byte* record)/* in: row in MySQL format */ { - KEY* key_info = table->key_info + keynr; - KEY_PART_INFO* key_part = key_info->key_part; - KEY_PART_INFO* end = key_part + key_info->key_parts; + KEY* key_info = table->key_info + keynr; + KEY_PART_INFO* key_part = key_info->key_part; + KEY_PART_INFO* end = key_part + key_info->key_parts; char* buff_start = buff; enum_field_types mysql_type; Field* field; - ulint blob_len; - byte* blob_data; ibool is_null; - DBUG_ENTER("store_key_val_for_row"); + DBUG_ENTER("store_key_val_for_row"); /* The format for storing a key field in MySQL is the following: @@ -2911,19 +2913,19 @@ ha_innobase::store_key_val_for_row( bzero(buff, buff_len); - for (; key_part != end; key_part++) { - is_null = FALSE; + for (; key_part != end; key_part++) { + is_null = FALSE; - if (key_part->null_bit) { - if (record[key_part->null_offset] + if (key_part->null_bit) { + if (record[key_part->null_offset] & key_part->null_bit) { *buff = 1; is_null = TRUE; - } else { + } else { *buff = 0; } buff++; - } + } field = key_part->field; mysql_type = field->type(); @@ -2934,49 +2936,54 @@ ha_innobase::store_key_val_for_row( ulint len; byte* data; ulint key_len; + ulint true_len; CHARSET_INFO* cs; int error=0; + key_len = key_part->length; + if (is_null) { - buff += key_part->length + 2; - + buff += key_len + 2; + continue; } + cs = field->charset(); lenlen = (ulint) (((Field_varstring*)field)->length_bytes); - data = row_mysql_read_true_varchar(&len, + data = row_mysql_read_true_varchar(&len, (byte*) (record + (ulint)get_field_offset(table, field)), lenlen); + true_len = len; + + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) data, + (const char *) data + len, + key_len / cs->mbmaxlen, + &error); + } + /* In a column prefix index, we may need to truncate the stored value: */ - - cs = key_part->field->charset(); - - if (cs->mbmaxlen > 1 && key_part->length > 0) { - key_len = (ulint) cs->cset->well_formed_len(cs, - (const char *) data, - (const char *) data + key_part->length, - key_part->length / cs->mbmaxlen, - &error); - } else { - key_len = key_part->length; - } - if (len > key_len) { - len = key_len; + if (true_len > key_len) { + true_len = key_len; } /* The length in a key value is always stored in 2 bytes */ - row_mysql_store_true_var_len((byte*)buff, len, 2); + row_mysql_store_true_var_len((byte*)buff, true_len, 2); buff += 2; - memcpy(buff, data, len); + memcpy(buff, data, true_len); /* Note that we always reserve the maximum possible length of the true VARCHAR in the key value, though @@ -2984,68 +2991,76 @@ ha_innobase::store_key_val_for_row( actual data. The rest of the space was reset to zero in the bzero() call above. */ - buff += key_part->length; + buff += key_len; } else if (mysql_type == FIELD_TYPE_TINY_BLOB - || mysql_type == FIELD_TYPE_MEDIUM_BLOB - || mysql_type == FIELD_TYPE_BLOB - || mysql_type == FIELD_TYPE_LONG_BLOB) { + || mysql_type == FIELD_TYPE_MEDIUM_BLOB + || mysql_type == FIELD_TYPE_BLOB + || mysql_type == FIELD_TYPE_LONG_BLOB) { CHARSET_INFO* cs; ulint key_len; ulint len; + ulint true_len; int error=0; + ulint blob_len; + byte* blob_data; ut_a(key_part->key_part_flag & HA_PART_KEY_SEG); - if (is_null) { - buff += key_part->length + 2; - + key_len = key_part->length; + + if (is_null) { + buff += key_len + 2; + continue; } - - blob_data = row_mysql_read_blob_ref(&blob_len, + + cs = field->charset(); + + blob_data = row_mysql_read_blob_ref(&blob_len, (byte*) (record + (ulint)get_field_offset(table, field)), (ulint) field->pack_length()); + true_len = blob_len; + ut_a(get_field_offset(table, field) - == key_part->offset); + == key_part->offset); + + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (blob_len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) blob_data, + (const char *) blob_data + + blob_len, + key_len / cs->mbmaxlen, + &error); + } /* All indexes on BLOB and TEXT are column prefix indexes, and we may need to truncate the data to be stored in the key value: */ - cs = key_part->field->charset(); - - if (cs->mbmaxlen > 1 && key_part->length > 0) { - key_len = (ulint) cs->cset->well_formed_len(cs, - (const char *) blob_data, - (const char *) blob_data - + key_part->length, - key_part->length / cs->mbmaxlen, - &error); - } else { - key_len = key_part->length; - } - - if (blob_len > key_len) { - blob_len = key_len; + if (true_len > key_len) { + true_len = key_len; } /* MySQL reserves 2 bytes for the length and the storage of the number is little-endian */ innobase_write_to_2_little_endian( - (byte*)buff, (ulint)blob_len); + (byte*)buff, true_len); buff += 2; - memcpy(buff, blob_data, blob_len); + memcpy(buff, blob_data, true_len); /* Note that we always reserve the maximum possible length of the BLOB prefix in the key value. */ - buff += key_part->length; + buff += key_len; } else { /* Here we handle all other data types except the true VARCHAR, BLOB and TEXT. Note that the column @@ -3053,48 +3068,67 @@ ha_innobase::store_key_val_for_row( index. */ CHARSET_INFO* cs; - ulint len; + ulint true_len; + ulint key_len; const mysql_byte* src_start; int error=0; + enum_field_types real_type; + + key_len = key_part->length; + + if (is_null) { + buff += key_len; - if (is_null) { - buff += key_part->length; - continue; } - /* In a column prefix index, we may need to truncate - the stored value: */ - - cs = key_part->field->charset(); src_start = record + key_part->offset; + real_type = field->real_type(); + true_len = key_len; - if (key_part->length > 0 && cs->mbmaxlen > 1) { - len = (ulint) cs->cset->well_formed_len(cs, - (const char *) src_start, - (const char *) src_start + key_part->length, - key_part->length / cs->mbmaxlen, - &error); - } else { - len = key_part->length; + /* Character set for the field is defined only + to fields whose type is string and real field + type is not enum or set. For these fields check + if character set is multi byte. */ + + if (real_type != FIELD_TYPE_ENUM + && real_type != FIELD_TYPE_SET + && ( mysql_type == MYSQL_TYPE_VAR_STRING + || mysql_type == MYSQL_TYPE_STRING)) { + + cs = field->charset(); + + /* For multi byte character sets we need to + calculate the true length of the key */ + + if (key_len > 0 && cs->mbmaxlen > 1) { + + true_len = (ulint) + cs->cset->well_formed_len(cs, + (const char *)src_start, + (const char *)src_start + + key_len, + key_len / cs->mbmaxlen, + &error); + } } - memcpy(buff, src_start, len); - buff+=len; + memcpy(buff, src_start, true_len); + buff += true_len; - /* Pad the unused space with spaces. Note that no - padding is ever needed for UCS-2 because in MySQL, - all UCS2 characters are 2 bytes, as MySQL does not + /* Pad the unused space with spaces. Note that no + padding is ever needed for UCS-2 because in MySQL, + all UCS2 characters are 2 bytes, as MySQL does not support surrogate pairs, which are needed to represent characters in the range U+10000 to U+10FFFF. */ - if (len < key_part->length) { - len = key_part->length - len; - memset(buff, ' ', len); - buff+=len; + if (true_len < key_len) { + ulint pad_len = key_len - true_len; + memset(buff, ' ', pad_len); + buff += pad_len; } } - } + } ut_a(buff <= buff_start + buff_len); @@ -3133,38 +3167,39 @@ build_template( use exclusive row level locks, for example, if the read is done in an UPDATE statement. */ - templ_type = ROW_MYSQL_WHOLE_ROW; + templ_type = ROW_MYSQL_WHOLE_ROW; } if (templ_type == ROW_MYSQL_REC_FIELDS) { - if (prebuilt->hint_need_to_fetch_extra_cols - == ROW_RETRIEVE_ALL_COLS) { + if (prebuilt->hint_need_to_fetch_extra_cols + == ROW_RETRIEVE_ALL_COLS) { - /* We know we must at least fetch all columns in the key, or - all columns in the table */ + /* We know we must at least fetch all columns in the + key, or all columns in the table */ - if (prebuilt->read_just_key) { - /* MySQL has instructed us that it is enough to - fetch the columns in the key; looks like MySQL - can set this flag also when there is only a - prefix of the column in the key: in that case we - retrieve the whole column from the clustered - index */ + if (prebuilt->read_just_key) { + /* MySQL has instructed us that it is enough + to fetch the columns in the key; looks like + MySQL can set this flag also when there is + only a prefix of the column in the key: in + that case we retrieve the whole column from + the clustered index */ - fetch_all_in_key = TRUE; - } else { - templ_type = ROW_MYSQL_WHOLE_ROW; + fetch_all_in_key = TRUE; + } else { + templ_type = ROW_MYSQL_WHOLE_ROW; + } + } else if (prebuilt->hint_need_to_fetch_extra_cols + == ROW_RETRIEVE_PRIMARY_KEY) { + /* We must at least fetch all primary key cols. Note + that if the clustered index was internally generated + by InnoDB on the row id (no primary key was + defined), then row_search_for_mysql() will always + retrieve the row id to a special buffer in the + prebuilt struct. */ + + fetch_primary_key_cols = TRUE; } - } else if (prebuilt->hint_need_to_fetch_extra_cols - == ROW_RETRIEVE_PRIMARY_KEY) { - /* We must at least fetch all primary key cols. Note that if - the clustered index was internally generated by InnoDB on the - row id (no primary key was defined), then - row_search_for_mysql() will always retrieve the row id to a - special buffer in the prebuilt struct. */ - - fetch_primary_key_cols = TRUE; - } } clust_index = dict_table_get_first_index_noninline(prebuilt->table); @@ -3222,15 +3257,15 @@ build_template( } if (table->file->ha_get_bit_in_read_set(i+1) || - table->file->ha_get_bit_in_write_set(i+1)) { + table->file->ha_get_bit_in_write_set(i+1)) { /* This field is needed in the query */ goto include_field; } if (fetch_primary_key_cols - && dict_table_col_in_clustered_key(index->table, - i)) { + && dict_table_col_in_clustered_key( + index->table, i)) { /* This field is needed in the query */ goto include_field; @@ -3281,9 +3316,9 @@ include_field: if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) { templ->mysql_length_bytes = (ulint) - (((Field_varstring*)field)->length_bytes); + (((Field_varstring*)field)->length_bytes); } - + templ->charset = dtype_get_charset_coll_noninline( index->table->cols[i].type.prtype); templ->mbminlen = index->table->cols[i].type.mbminlen; @@ -3307,7 +3342,7 @@ skip_field: templ = prebuilt->mysql_template + i; templ->rec_field_no = - (index->table->cols + templ->col_no)->clust_pos; + (index->table->cols + templ->col_no)->clust_pos; } } } @@ -3320,18 +3355,18 @@ int ha_innobase::write_row( /*===================*/ /* out: error code */ - mysql_byte* record) /* in: a row in MySQL format */ + mysql_byte* record) /* in: a row in MySQL format */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; - int error; + int error; longlong auto_inc; longlong dummy; - ibool auto_inc_used= FALSE; + ibool auto_inc_used= FALSE; - DBUG_ENTER("ha_innobase::write_row"); + DBUG_ENTER("ha_innobase::write_row"); if (prebuilt->trx != - (trx_t*) current_thd->ha_data[innobase_hton.slot]) { + (trx_t*) current_thd->ha_data[innobase_hton.slot]) { sql_print_error("The transaction object for the table handle is at " "%p, but for the current thread it is at %p", prebuilt->trx, @@ -3343,23 +3378,23 @@ ha_innobase::write_row( "InnoDB: Dump of 200 bytes around transaction.all: ", stderr); ut_print_buf(stderr, - ((byte*)(&(current_thd->ha_data[innobase_hton.slot]))) - 100, + ((byte*)(&(current_thd->ha_data[innobase_hton.slot]))) - 100, 200); putc('\n', stderr); ut_error; } - statistic_increment(current_thd->status_var.ha_write_count, - &LOCK_status); + statistic_increment(current_thd->status_var.ha_write_count, + &LOCK_status); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) + table->timestamp_field->set_time(); if ((user_thd->lex->sql_command == SQLCOM_ALTER_TABLE - || user_thd->lex->sql_command == SQLCOM_OPTIMIZE - || user_thd->lex->sql_command == SQLCOM_CREATE_INDEX - || user_thd->lex->sql_command == SQLCOM_DROP_INDEX) - && num_write_row >= 10000) { + || user_thd->lex->sql_command == SQLCOM_OPTIMIZE + || user_thd->lex->sql_command == SQLCOM_CREATE_INDEX + || user_thd->lex->sql_command == SQLCOM_DROP_INDEX) + && num_write_row >= 10000) { /* ALTER TABLE is COMMITted at every 10000 copied rows. The IX table lock for the original table has to be re-issued. As this method will be called on a temporary table where the @@ -3397,11 +3432,11 @@ no_commit: no need to re-acquire locks on it. */ /* Altering to InnoDB format */ - innobase_commit(user_thd, 1); + innobase_commit(user_thd, 1); /* Note that this transaction is still active. */ prebuilt->trx->active_trans = 1; /* We will need an IX lock on the destination table. */ - prebuilt->sql_stat_start = TRUE; + prebuilt->sql_stat_start = TRUE; } else { /* Ensure that there are no other table locks than LOCK_IX and LOCK_AUTO_INC on the destination table. */ @@ -3413,26 +3448,26 @@ no_commit: /* Commit the transaction. This will release the table locks, so they have to be acquired again. */ - innobase_commit(user_thd, 1); + innobase_commit(user_thd, 1); /* Note that this transaction is still active. */ prebuilt->trx->active_trans = 1; /* Re-acquire the table lock on the source table. */ row_lock_table_for_mysql(prebuilt, src_table, mode); /* We will need an IX lock on the destination table. */ - prebuilt->sql_stat_start = TRUE; + prebuilt->sql_stat_start = TRUE; } } num_write_row++; if (last_query_id != user_thd->query_id) { - prebuilt->sql_stat_start = TRUE; - last_query_id = user_thd->query_id; + prebuilt->sql_stat_start = TRUE; + last_query_id = user_thd->query_id; innobase_release_stat_resources(prebuilt->trx); } - if (table->next_number_field && record == table->record[0]) { + if (table->next_number_field && record == table->record[0]) { /* This is the case where the table has an auto-increment column */ @@ -3442,7 +3477,7 @@ no_commit: if (0 == dict_table_autoinc_peek(prebuilt->table)) { /* This call initializes the counter */ - error = innobase_read_and_init_auto_inc(&dummy); + error = innobase_read_and_init_auto_inc(&dummy); if (error) { /* Deadlock or lock wait timeout */ @@ -3478,10 +3513,10 @@ no_commit: } /* We must use the handler code to update the auto-increment - value to be sure that we increment it correctly. */ + value to be sure that we increment it correctly. */ - update_auto_increment(); - auto_inc_used = 1; + update_auto_increment(); + auto_inc_used = 1; } @@ -3499,34 +3534,34 @@ no_commit: if (error == DB_SUCCESS && auto_inc_used) { - /* Fetch the value that was set in the autoincrement field */ + /* Fetch the value that was set in the autoincrement field */ - auto_inc = table->next_number_field->val_int(); + auto_inc = table->next_number_field->val_int(); - if (auto_inc != 0) { + if (auto_inc != 0) { /* This call will update the counter according to the value that was inserted in the table */ - dict_table_autoinc_update(prebuilt->table, auto_inc); - } - } + dict_table_autoinc_update(prebuilt->table, auto_inc); + } + } - /* A REPLACE command and LOAD DATA INFILE REPLACE handle a duplicate - key error themselves, and we must update the autoinc counter if we are - performing those statements. */ + /* A REPLACE command and LOAD DATA INFILE REPLACE handle a duplicate + key error themselves, and we must update the autoinc counter if we are + performing those statements. */ - if (error == DB_DUPLICATE_KEY && auto_inc_used - && (user_thd->lex->sql_command == SQLCOM_REPLACE - || user_thd->lex->sql_command == SQLCOM_REPLACE_SELECT - || (user_thd->lex->sql_command == SQLCOM_LOAD - && user_thd->lex->duplicates == DUP_REPLACE))) { + if (error == DB_DUPLICATE_KEY && auto_inc_used + && (user_thd->lex->sql_command == SQLCOM_REPLACE + || user_thd->lex->sql_command == SQLCOM_REPLACE_SELECT + || (user_thd->lex->sql_command == SQLCOM_LOAD + && user_thd->lex->duplicates == DUP_REPLACE))) { - auto_inc = table->next_number_field->val_int(); + auto_inc = table->next_number_field->val_int(); - if (auto_inc != 0) { - dict_table_autoinc_update(prebuilt->table, auto_inc); - } - } + if (auto_inc != 0) { + dict_table_autoinc_update(prebuilt->table, auto_inc); + } + } innodb_srv_conc_exit_innodb(prebuilt->trx); @@ -3537,7 +3572,7 @@ no_commit: func_exit: innobase_active_small(); - DBUG_RETURN(error); + DBUG_RETURN(error); } /************************************************************************** @@ -3549,8 +3584,8 @@ calc_row_difference( /*================*/ /* out: error number or 0 */ upd_t* uvect, /* in/out: update vector */ - mysql_byte* old_row, /* in: old row in MySQL format */ - mysql_byte* new_row, /* in: new row in MySQL format */ + mysql_byte* old_row, /* in: old row in MySQL format */ + mysql_byte* new_row, /* in: new row in MySQL format */ struct st_table* table, /* in: table in MySQL data dictionary */ mysql_byte* upd_buff, /* in: buffer to use */ @@ -3566,9 +3601,9 @@ calc_row_difference( ulint n_len; ulint col_pack_len; byte* new_mysql_row_col; - byte* o_ptr; - byte* n_ptr; - byte* buf; + byte* o_ptr; + byte* n_ptr; + byte* buf; upd_field_t* ufield; ulint col_type; ulint n_changed = 0; @@ -3592,7 +3627,7 @@ calc_row_difference( o_ptr = (byte*) old_row + get_field_offset(table, field); n_ptr = (byte*) new_row + get_field_offset(table, field); - + /* Use new_mysql_row_col and col_pack_len save the values */ new_mysql_row_col = n_ptr; @@ -3602,10 +3637,10 @@ calc_row_difference( n_len = col_pack_len; /* We use o_ptr and n_ptr to dig up the actual data for - comparison. */ + comparison. */ field_mysql_type = field->type(); - + col_type = prebuilt->table->cols[i].type.mtype; switch (col_type) { @@ -3623,16 +3658,16 @@ calc_row_difference( /* This is a >= 5.0.3 type true VARCHAR where the real payload data length is stored in 1 or 2 bytes */ - + o_ptr = row_mysql_read_true_varchar( - &o_len, o_ptr, - (ulint) - (((Field_varstring*)field)->length_bytes)); - + &o_len, o_ptr, + (ulint) + (((Field_varstring*)field)->length_bytes)); + n_ptr = row_mysql_read_true_varchar( - &n_len, n_ptr, - (ulint) - (((Field_varstring*)field)->length_bytes)); + &n_len, n_ptr, + (ulint) + (((Field_varstring*)field)->length_bytes)); } break; @@ -3657,7 +3692,7 @@ calc_row_difference( /* The field has changed */ ufield = uvect->fields + n_changed; - + /* Let us use a dummy dfield to make the conversion from the MySQL column format to the InnoDB format */ @@ -3665,12 +3700,12 @@ calc_row_difference( if (n_len != UNIV_SQL_NULL) { buf = row_mysql_store_col_in_innobase_format( - &dfield, - (byte*)buf, - TRUE, - new_mysql_row_col, - col_pack_len, - prebuilt->table->comp); + &dfield, + (byte*)buf, + TRUE, + new_mysql_row_col, + col_pack_len, + dict_table_is_comp(prebuilt->table)); ufield->new_val.data = dfield.data; ufield->new_val.len = dfield.len; } else { @@ -3704,8 +3739,8 @@ int ha_innobase::update_row( /*====================*/ /* out: error number or 0 */ - const mysql_byte* old_row,/* in: old row in MySQL format */ - mysql_byte* new_row)/* in: new row in MySQL format */ + const mysql_byte* old_row,/* in: old row in MySQL format */ + mysql_byte* new_row)/* in: new row in MySQL format */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; upd_t* uvect; @@ -3714,14 +3749,14 @@ ha_innobase::update_row( DBUG_ENTER("ha_innobase::update_row"); ut_ad(prebuilt->trx == - (trx_t*) current_thd->ha_data[innobase_hton.slot]); + (trx_t*) current_thd->ha_data[innobase_hton.slot]); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) + table->timestamp_field->set_time(); if (last_query_id != user_thd->query_id) { - prebuilt->sql_stat_start = TRUE; - last_query_id = user_thd->query_id; + prebuilt->sql_stat_start = TRUE; + last_query_id = user_thd->query_id; innobase_release_stat_resources(prebuilt->trx); } @@ -3775,11 +3810,11 @@ ha_innobase::delete_row( DBUG_ENTER("ha_innobase::delete_row"); ut_ad(prebuilt->trx == - (trx_t*) current_thd->ha_data[innobase_hton.slot]); + (trx_t*) current_thd->ha_data[innobase_hton.slot]); if (last_query_id != user_thd->query_id) { - prebuilt->sql_stat_start = TRUE; - last_query_id = user_thd->query_id; + prebuilt->sql_stat_start = TRUE; + last_query_id = user_thd->query_id; innobase_release_stat_resources(prebuilt->trx); } @@ -3809,7 +3844,7 @@ ha_innobase::delete_row( } /************************************************************************** -Removes a new lock set on a row, if it was not read optimistically. This can +Removes a new lock set on a row, if it was not read optimistically. This can be called after a row has been read in the processing of an UPDATE or a DELETE query, if the option innodb_locks_unsafe_for_binlog is set. */ @@ -3878,15 +3913,15 @@ int ha_innobase::index_init( /*====================*/ /* out: 0 or error number */ - uint keynr, /* in: key (index) number */ - bool sorted) /* in: 1 if result MUST be sorted according to index */ + uint keynr, /* in: key (index) number */ + bool sorted) /* in: 1 if result MUST be sorted according to index */ { - int error = 0; - DBUG_ENTER("index_init"); + int error = 0; + DBUG_ENTER("index_init"); error = change_active_index(keynr); - DBUG_RETURN(error); + DBUG_RETURN(error); } /********************************************************************** @@ -3896,10 +3931,10 @@ int ha_innobase::index_end(void) /*========================*/ { - int error = 0; - DBUG_ENTER("index_end"); - active_index=MAX_KEY; - DBUG_RETURN(error); + int error = 0; + DBUG_ENTER("index_end"); + active_index=MAX_KEY; + DBUG_RETURN(error); } /************************************************************************* @@ -3912,15 +3947,15 @@ convert_search_mode_to_innobase( enum ha_rkey_function find_flag) { switch (find_flag) { - case HA_READ_KEY_EXACT: return(PAGE_CUR_GE); - /* the above does not require the index to be UNIQUE */ - case HA_READ_KEY_OR_NEXT: return(PAGE_CUR_GE); + case HA_READ_KEY_EXACT: return(PAGE_CUR_GE); + /* the above does not require the index to be UNIQUE */ + case HA_READ_KEY_OR_NEXT: return(PAGE_CUR_GE); case HA_READ_KEY_OR_PREV: return(PAGE_CUR_LE); case HA_READ_AFTER_KEY: return(PAGE_CUR_G); case HA_READ_BEFORE_KEY: return(PAGE_CUR_L); case HA_READ_PREFIX: return(PAGE_CUR_GE); - case HA_READ_PREFIX_LAST: return(PAGE_CUR_LE); - case HA_READ_PREFIX_LAST_OR_PREV:return(PAGE_CUR_LE); + case HA_READ_PREFIX_LAST: return(PAGE_CUR_LE); + case HA_READ_PREFIX_LAST_OR_PREV:return(PAGE_CUR_LE); /* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always pass a complete-field prefix of a key value as the search tuple. I.e., it is not allowed that the last field would @@ -4001,7 +4036,7 @@ ha_innobase::index_read( or error number */ mysql_byte* buf, /* in/out: buffer for the returned row */ - const mysql_byte* key_ptr,/* in: key value; if this is NULL + const mysql_byte* key_ptr,/* in: key value; if this is NULL we position the cursor at the start or end of index; this can also contain an InnoDB row id, in @@ -4016,21 +4051,21 @@ ha_innobase::index_read( row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; ulint mode; dict_index_t* index; - ulint match_mode = 0; - int error; + ulint match_mode = 0; + int error; ulint ret; - DBUG_ENTER("index_read"); + DBUG_ENTER("index_read"); ut_ad(prebuilt->trx == - (trx_t*) current_thd->ha_data[innobase_hton.slot]); + (trx_t*) current_thd->ha_data[innobase_hton.slot]); - statistic_increment(current_thd->status_var.ha_read_key_count, - &LOCK_status); + statistic_increment(current_thd->status_var.ha_read_key_count, + &LOCK_status); if (last_query_id != user_thd->query_id) { - prebuilt->sql_stat_start = TRUE; - last_query_id = user_thd->query_id; + prebuilt->sql_stat_start = TRUE; + last_query_id = user_thd->query_id; innobase_release_stat_resources(prebuilt->trx); } @@ -4038,7 +4073,7 @@ ha_innobase::index_read( index = prebuilt->index; /* Note that if the index for which the search template is built is not - necessarily prebuilt->index, but can also be the clustered index */ + necessarily prebuilt->index, but can also be the clustered index */ if (prebuilt->sql_stat_start) { build_template(prebuilt, user_thd, table, @@ -4046,7 +4081,7 @@ ha_innobase::index_read( } if (key_ptr) { - /* Convert the search key value to InnoDB format into + /* Convert the search key value to InnoDB format into prebuilt->search_tuple */ row_sel_convert_mysql_key_to_innobase(prebuilt->search_tuple, @@ -4059,7 +4094,7 @@ ha_innobase::index_read( /* We position the cursor to the last or the first entry in the index */ - dtuple_set_n_fields(prebuilt->search_tuple, 0); + dtuple_set_n_fields(prebuilt->search_tuple, 0); } mode = convert_search_mode_to_innobase(find_flag); @@ -4108,15 +4143,15 @@ row with the current key value or prefix. */ int ha_innobase::index_read_last( /*=========================*/ - /* out: 0, HA_ERR_KEY_NOT_FOUND, or an + /* out: 0, HA_ERR_KEY_NOT_FOUND, or an error code */ - mysql_byte* buf, /* out: fetched row */ - const mysql_byte* key_ptr, /* in: key value, or a prefix of a full + mysql_byte* buf, /* out: fetched row */ + const mysql_byte* key_ptr, /* in: key value, or a prefix of a full key value */ - uint key_len) /* in: length of the key val or prefix + uint key_len) /* in: length of the key val or prefix in bytes */ { - return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST)); + return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST)); } /************************************************************************ @@ -4126,19 +4161,19 @@ int ha_innobase::change_active_index( /*=============================*/ /* out: 0 or error code */ - uint keynr) /* in: use this index; MAX_KEY means always clustered + uint keynr) /* in: use this index; MAX_KEY means always clustered index, even if it was internally generated by InnoDB */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; KEY* key=0; statistic_increment(current_thd->status_var.ha_read_key_count, - &LOCK_status); + &LOCK_status); DBUG_ENTER("change_active_index"); ut_ad(user_thd == current_thd); ut_ad(prebuilt->trx == - (trx_t*) current_thd->ha_data[innobase_hton.slot]); + (trx_t*) current_thd->ha_data[innobase_hton.slot]); active_index = keynr; @@ -4146,19 +4181,20 @@ ha_innobase::change_active_index( key = table->key_info + active_index; prebuilt->index = dict_table_get_index_noninline( - prebuilt->table, - key->name); - } else { + prebuilt->table, key->name); + } else { prebuilt->index = dict_table_get_first_index_noninline( prebuilt->table); } if (!prebuilt->index) { - sql_print_error("Innodb could not find key n:o %u with name %s " - "from dict cache for table %s", - keynr, key ? key->name : "NULL", - prebuilt->table->name); - DBUG_RETURN(1); + sql_print_error( + "Innodb could not find key n:o %u with name %s " + "from dict cache for table %s", + keynr, key ? key->name : "NULL", + prebuilt->table->name); + + DBUG_RETURN(1); } assert(prebuilt->search_tuple != 0); @@ -4190,7 +4226,7 @@ ha_innobase::index_read_idx( /* out: error number or 0 */ mysql_byte* buf, /* in/out: buffer for the returned row */ - uint keynr, /* in: use this index */ + uint keynr, /* in: use this index */ const mysql_byte* key, /* in: key value; if this is NULL we position the cursor at the start or end of index */ @@ -4214,9 +4250,9 @@ ha_innobase::general_fetch( /*=======================*/ /* out: 0, HA_ERR_END_OF_FILE, or error number */ - mysql_byte* buf, /* in/out: buffer for next row in MySQL + mysql_byte* buf, /* in/out: buffer for next row in MySQL format */ - uint direction, /* in: ROW_SEL_NEXT or ROW_SEL_PREV */ + uint direction, /* in: ROW_SEL_NEXT or ROW_SEL_PREV */ uint match_mode) /* in: 0, ROW_SEL_EXACT, or ROW_SEL_EXACT_PREFIX */ { @@ -4227,7 +4263,7 @@ ha_innobase::general_fetch( DBUG_ENTER("general_fetch"); ut_ad(prebuilt->trx == - (trx_t*) current_thd->ha_data[innobase_hton.slot]); + (trx_t*) current_thd->ha_data[innobase_hton.slot]); innodb_srv_conc_enter_innodb(prebuilt->trx); @@ -4263,11 +4299,11 @@ ha_innobase::index_next( /*====================*/ /* out: 0, HA_ERR_END_OF_FILE, or error number */ - mysql_byte* buf) /* in/out: buffer for next row in MySQL + mysql_byte* buf) /* in/out: buffer for next row in MySQL format */ { - statistic_increment(current_thd->status_var.ha_read_next_count, - &LOCK_status); + statistic_increment(current_thd->status_var.ha_read_next_count, + &LOCK_status); return(general_fetch(buf, ROW_SEL_NEXT, 0)); } @@ -4280,12 +4316,12 @@ ha_innobase::index_next_same( /*=========================*/ /* out: 0, HA_ERR_END_OF_FILE, or error number */ - mysql_byte* buf, /* in/out: buffer for the row */ + mysql_byte* buf, /* in/out: buffer for the row */ const mysql_byte* key, /* in: key value */ - uint keylen) /* in: key value length */ + uint keylen) /* in: key value length */ { - statistic_increment(current_thd->status_var.ha_read_next_count, - &LOCK_status); + statistic_increment(current_thd->status_var.ha_read_next_count, + &LOCK_status); return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode)); } @@ -4299,7 +4335,7 @@ ha_innobase::index_prev( /*====================*/ /* out: 0, HA_ERR_END_OF_FILE, or error number */ - mysql_byte* buf) /* in/out: buffer for previous row in MySQL + mysql_byte* buf) /* in/out: buffer for previous row in MySQL format */ { return(general_fetch(buf, ROW_SEL_PREV, 0)); @@ -4318,19 +4354,19 @@ ha_innobase::index_first( { int error; - DBUG_ENTER("index_first"); - statistic_increment(current_thd->status_var.ha_read_first_count, - &LOCK_status); + DBUG_ENTER("index_first"); + statistic_increment(current_thd->status_var.ha_read_first_count, + &LOCK_status); - error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY); + error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY); - /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ + /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ - if (error == HA_ERR_KEY_NOT_FOUND) { - error = HA_ERR_END_OF_FILE; - } + if (error == HA_ERR_KEY_NOT_FOUND) { + error = HA_ERR_END_OF_FILE; + } - DBUG_RETURN(error); + DBUG_RETURN(error); } /************************************************************************ @@ -4345,19 +4381,19 @@ ha_innobase::index_last( { int error; - DBUG_ENTER("index_last"); - statistic_increment(current_thd->status_var.ha_read_last_count, - &LOCK_status); + DBUG_ENTER("index_last"); + statistic_increment(current_thd->status_var.ha_read_last_count, + &LOCK_status); - error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY); + error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY); - /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ + /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ - if (error == HA_ERR_KEY_NOT_FOUND) { - error = HA_ERR_END_OF_FILE; - } + if (error == HA_ERR_KEY_NOT_FOUND) { + error = HA_ERR_END_OF_FILE; + } - DBUG_RETURN(error); + DBUG_RETURN(error); } /******************************************************************** @@ -4389,9 +4425,9 @@ ha_innobase::rnd_init( try_semi_consistent_read(0); } - start_of_scan = 1; + start_of_scan = 1; - return(err); + return(err); } /********************************************************************* @@ -4418,11 +4454,11 @@ ha_innobase::rnd_next( { int error; - DBUG_ENTER("rnd_next"); - statistic_increment(current_thd->status_var.ha_read_rnd_next_count, - &LOCK_status); + DBUG_ENTER("rnd_next"); + statistic_increment(current_thd->status_var.ha_read_rnd_next_count, + &LOCK_status); - if (start_of_scan) { + if (start_of_scan) { error = index_first(buf); if (error == HA_ERR_KEY_NOT_FOUND) { error = HA_ERR_END_OF_FILE; @@ -4432,7 +4468,7 @@ ha_innobase::rnd_next( error = general_fetch(buf, ROW_SEL_NEXT, 0); } - DBUG_RETURN(error); + DBUG_RETURN(error); } /************************************************************************** @@ -4443,7 +4479,7 @@ ha_innobase::rnd_pos( /*=================*/ /* out: 0, HA_ERR_KEY_NOT_FOUND, or error code */ - mysql_byte* buf, /* in/out: buffer for the row */ + mysql_byte* buf, /* in/out: buffer for the row */ mysql_byte* pos) /* in: primary key value of the row in the MySQL format, or the row id if the clustered index was internally generated by InnoDB; @@ -4457,10 +4493,10 @@ ha_innobase::rnd_pos( DBUG_DUMP("key", (char*) pos, ref_length); statistic_increment(current_thd->status_var.ha_read_rnd_count, - &LOCK_status); + &LOCK_status); ut_ad(prebuilt->trx == - (trx_t*) current_thd->ha_data[innobase_hton.slot]); + (trx_t*) current_thd->ha_data[innobase_hton.slot]); if (prebuilt->clust_index_was_generated) { /* No primary key was defined for the table and we @@ -4474,12 +4510,12 @@ ha_innobase::rnd_pos( } if (error) { - DBUG_PRINT("error", ("Got error: %ld", error)); + DBUG_PRINT("error", ("Got error: %ld", error)); DBUG_RETURN(error); } /* Note that we assume the length of the row reference is fixed - for the table, and it is == ref_length */ + for the table, and it is == ref_length */ error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT); @@ -4489,7 +4525,7 @@ ha_innobase::rnd_pos( change_active_index(keynr); - DBUG_RETURN(error); + DBUG_RETURN(error); } /************************************************************************* @@ -4510,7 +4546,7 @@ ha_innobase::position( uint len; ut_ad(prebuilt->trx == - (trx_t*) current_thd->ha_data[innobase_hton.slot]); + (trx_t*) current_thd->ha_data[innobase_hton.slot]); if (prebuilt->clust_index_was_generated) { /* No primary key was defined for the table and we @@ -4528,10 +4564,10 @@ ha_innobase::position( /* We assume that the 'ref' value len is always fixed for the same table. */ - + if (len != ref_length) { sql_print_error("Stored ref len is %lu, but table ref len is %lu", - (ulong) len, (ulong) ref_length); + (ulong) len, (ulong) ref_length); } } @@ -4553,30 +4589,30 @@ create_table_def( an .ibd file for it (no .ibd extension in the path, though); otherwise this is NULL */ - ibool comp) /* in: TRUE=compact record format */ + ulint flags) /* in: table flags */ { Field* field; dict_table_t* table; ulint n_cols; - int error; - ulint col_type; + int error; + ulint col_type; ulint col_len; - ulint nulls_allowed; + ulint nulls_allowed; ulint unsigned_type; ulint binary_type; ulint long_true_varchar; ulint charset_no; - ulint i; + ulint i; - DBUG_ENTER("create_table_def"); - DBUG_PRINT("enter", ("table_name: %s", table_name)); + DBUG_ENTER("create_table_def"); + DBUG_PRINT("enter", ("table_name: %s", table_name)); n_cols = form->s->fields; /* We pass 0 as the space id, and determine at a lower level the space id where to store the table */ - table = dict_mem_table_create(table_name, 0, n_cols, comp); + table = dict_mem_table_create(table_name, 0, n_cols, flags); if (path_of_temp_table) { table->dir_path_of_temp_table = @@ -4600,7 +4636,7 @@ create_table_def( binary_type = 0; } - charset_no = 0; + charset_no = 0; if (dtype_is_string_type(col_type)) { @@ -4619,7 +4655,7 @@ create_table_def( for a true VARCHAR. Let us subtract that, so that the InnoDB column length in the InnoDB data dictionary is the real maximum byte length of the actual data. */ - + long_true_varchar = 0; if (field->type() == MYSQL_TYPE_VARCHAR) { @@ -4631,15 +4667,15 @@ create_table_def( } dict_mem_table_add_col(table, - (char*) field->field_name, - col_type, - dtype_form_prtype( - (ulint)field->type() - | nulls_allowed | unsigned_type - | binary_type | long_true_varchar, - charset_no), - col_len, - 0); + (char*) field->field_name, + col_type, + dtype_form_prtype( + (ulint)field->type() + | nulls_allowed | unsigned_type + | binary_type | long_true_varchar, + charset_no), + col_len, + 0); } error = row_create_table_for_mysql(table, trx); @@ -4663,7 +4699,7 @@ create_index( { Field* field; dict_index_t* index; - int error; + int error; ulint n_fields; KEY* key; KEY_PART_INFO* key_part; @@ -4671,19 +4707,19 @@ create_index( ulint col_type; ulint prefix_len; ulint is_unsigned; - ulint i; - ulint j; + ulint i; + ulint j; ulint* field_lengths; - - DBUG_ENTER("create_index"); + + DBUG_ENTER("create_index"); key = form->key_info + key_num; - n_fields = key->key_parts; + n_fields = key->key_parts; - ind_type = 0; + ind_type = 0; - if (key_num == form->s->primary_key) { + if (key_num == form->s->primary_key) { ind_type = ind_type | DICT_CLUSTERED; } @@ -4699,7 +4735,7 @@ create_index( field_lengths = (ulint*) my_malloc(sizeof(ulint) * n_fields, MYF(MY_FAE)); - + for (i = 0; i < n_fields; i++) { key_part = key->key_part + i; @@ -4708,7 +4744,7 @@ create_index( bytes of the column to the index field.) The flag does not seem to be properly set by MySQL. Let us fall back on testing the length of the key part versus the column. */ - + field = NULL; for (j = 0; j < form->s->fields; j++) { @@ -4729,39 +4765,36 @@ create_index( &is_unsigned, key_part->field); if (DATA_BLOB == col_type - || (key_part->length < field->pack_length() - && field->type() != MYSQL_TYPE_VARCHAR) - || (field->type() == MYSQL_TYPE_VARCHAR - && key_part->length < field->pack_length() - - ((Field_varstring*)field)->length_bytes)) { + || (key_part->length < field->pack_length() + && field->type() != MYSQL_TYPE_VARCHAR) + || (field->type() == MYSQL_TYPE_VARCHAR + && key_part->length < field->pack_length() + - ((Field_varstring*)field)->length_bytes)) { - prefix_len = key_part->length; + prefix_len = key_part->length; if (col_type == DATA_INT - || col_type == DATA_FLOAT - || col_type == DATA_DOUBLE - || col_type == DATA_DECIMAL) { - sql_print_error("MySQL is trying to create a column " - "prefix index field, on an " - "inappropriate data type. Table " - "name %s, column name %s.", - table_name, - key_part->field->field_name); - - prefix_len = 0; + || col_type == DATA_FLOAT + || col_type == DATA_DOUBLE + || col_type == DATA_DECIMAL) { + sql_print_error( + "MySQL is trying to create a column " + "prefix index field, on an " + "inappropriate data type. Table " + "name %s, column name %s.", + table_name, + key_part->field->field_name); + + prefix_len = 0; } } else { - prefix_len = 0; + prefix_len = 0; } field_lengths[i] = key_part->length; - /* We assume all fields should be sorted in ascending - order, hence the '0': */ - dict_mem_index_add_field(index, - (char*) key_part->field->field_name, - 0, prefix_len); + (char*) key_part->field->field_name, prefix_len); } /* Even though we've defined max_supported_key_part_length, we @@ -4772,7 +4805,7 @@ create_index( error = convert_error_code_to_mysql(error, NULL); my_free((gptr) field_lengths, MYF(0)); - + DBUG_RETURN(error); } @@ -4787,14 +4820,13 @@ create_clustered_index_when_no_primary( const char* table_name) /* in: table name */ { dict_index_t* index; - int error; + int error; /* We pass 0 as the space id, and determine at a lower level the space id where to store the table */ index = dict_mem_index_create((char*) table_name, - (char*) "GEN_CLUST_INDEX", - 0, DICT_CLUSTERED, 0); + (char*) "GEN_CLUST_INDEX", 0, DICT_CLUSTERED, 0); error = row_create_index_for_mysql(index, trx, NULL); error = convert_error_code_to_mysql(error, NULL); @@ -4825,9 +4857,10 @@ ha_innobase::create( char name2[FN_REFLEN]; char norm_name[FN_REFLEN]; THD *thd= current_thd; - ib_longlong auto_inc_value; + ib_longlong auto_inc_value; + ulint flags; - DBUG_ENTER("ha_innobase::create"); + DBUG_ENTER("ha_innobase::create"); DBUG_ASSERT(thd != NULL); @@ -4835,21 +4868,21 @@ ha_innobase::create( /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020, but we play safe here */ - DBUG_RETURN(HA_ERR_TO_BIG_ROW); - } + DBUG_RETURN(HA_ERR_TO_BIG_ROW); + } /* Get the transaction associated with the current thd, or create one if not yet created */ - + parent_trx = check_trx_exists(current_thd); /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ - trx_search_latch_release_if_reserved(parent_trx); - + trx_search_latch_release_if_reserved(parent_trx); + trx = trx_allocate_for_mysql(); - + trx->mysql_thd = thd; trx->mysql_query_str = &((*thd).query); @@ -4879,18 +4912,24 @@ ha_innobase::create( /* Create the table definition in InnoDB */ + flags = 0; + + if (form->s->row_type != ROW_TYPE_REDUNDANT) { + flags |= DICT_TF_COMPACT; + } + error = create_table_def(trx, form, norm_name, create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL, - form->s->row_type != ROW_TYPE_REDUNDANT); + flags); - if (error) { + if (error) { goto cleanup; - } + } /* Look for a primary key */ primary_key_no= (form->s->primary_key != MAX_KEY ? - (int) form->s->primary_key : + (int) form->s->primary_key : -1); /* Our function row_get_mysql_key_number_for_index assumes @@ -4907,29 +4946,29 @@ ha_innobase::create( error = create_clustered_index_when_no_primary(trx, norm_name); - if (error) { + if (error) { goto cleanup; - } + } } if (primary_key_no != -1) { /* In InnoDB the clustered index must always be created first */ - if ((error = create_index(trx, form, norm_name, + if ((error = create_index(trx, form, norm_name, (uint) primary_key_no))) { goto cleanup; - } - } + } + } for (i = 0; i < form->s->keys; i++) { if (i != (uint) primary_key_no) { - if ((error = create_index(trx, form, norm_name, i))) { + if ((error = create_index(trx, form, norm_name, i))) { goto cleanup; - } - } - } + } + } + } if (current_thd->query != NULL) { LEX_STRING q; @@ -4939,7 +4978,7 @@ ha_innobase::create( current_thd->query_length, current_thd->charset())) { error = HA_ERR_OUT_OF_MEM; - + goto cleanup; } @@ -4954,7 +4993,7 @@ ha_innobase::create( } } - innobase_commit_low(trx); + innobase_commit_low(trx); row_mysql_unlock_data_dictionary(trx); @@ -4971,7 +5010,7 @@ ha_innobase::create( if ((create_info->used_fields & HA_CREATE_USED_AUTO) && (create_info->auto_increment_value != 0)) { - /* Query was ALTER TABLE...AUTO_INCREMENT = x; or + /* Query was ALTER TABLE...AUTO_INCREMENT = x; or CREATE TABLE ...AUTO_INCREMENT = x; Find out a table definition from the dictionary and get the current value of the auto increment field. Set a new value to the @@ -4987,15 +5026,15 @@ ha_innobase::create( srv_active_wake_master_thread(); - trx_free_for_mysql(trx); + trx_free_for_mysql(trx); DBUG_RETURN(0); cleanup: innobase_commit_low(trx); - + row_mysql_unlock_data_dictionary(trx); - + trx_free_for_mysql(trx); DBUG_RETURN(error); @@ -5015,11 +5054,11 @@ ha_innobase::discard_or_import_tablespace( trx_t* trx; int err; - DBUG_ENTER("ha_innobase::discard_or_import_tablespace"); + DBUG_ENTER("ha_innobase::discard_or_import_tablespace"); ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[innobase_hton.slot]); + (trx_t*) current_thd->ha_data[innobase_hton.slot]); dict_table = prebuilt->table; trx = prebuilt->trx; @@ -5092,20 +5131,20 @@ ha_innobase::delete_table( int error; trx_t* parent_trx; trx_t* trx; - THD *thd= current_thd; + THD *thd= current_thd; char norm_name[1000]; - DBUG_ENTER("ha_innobase::delete_table"); + DBUG_ENTER("ha_innobase::delete_table"); /* Get the transaction associated with the current thd, or create one if not yet created */ - + parent_trx = check_trx_exists(current_thd); /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ - trx_search_latch_release_if_reserved(parent_trx); + trx_search_latch_release_if_reserved(parent_trx); if (lower_case_table_names) { srv_lower_case_table_names = TRUE; @@ -5135,7 +5174,7 @@ ha_innobase::delete_table( normalize_table_name(norm_name, name); - /* Drop the table in InnoDB */ + /* Drop the table in InnoDB */ error = row_drop_table_for_mysql(norm_name, trx, thd->lex->sql_command == SQLCOM_DROP_DB); @@ -5151,9 +5190,9 @@ ha_innobase::delete_table( srv_active_wake_master_thread(); - innobase_commit_low(trx); + innobase_commit_low(trx); - trx_free_for_mysql(trx); + trx_free_for_mysql(trx); error = convert_error_code_to_mysql(error, NULL); @@ -5181,13 +5220,13 @@ innobase_drop_database( /* Get the transaction associated with the current thd, or create one if not yet created */ - + parent_trx = check_trx_exists(current_thd); /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ - trx_search_latch_release_if_reserved(parent_trx); + trx_search_latch_release_if_reserved(parent_trx); ptr = strend(path) - 2; @@ -5202,7 +5241,7 @@ innobase_drop_database( memcpy(namebuf, ptr, len); namebuf[len] = '/'; namebuf[len + 1] = '\0'; -#ifdef __WIN__ +#ifdef __WIN__ innobase_casedn_str(namebuf); #endif trx = trx_allocate_for_mysql(); @@ -5213,7 +5252,7 @@ innobase_drop_database( trx->check_foreigns = FALSE; } - error = row_drop_database_for_mysql(namebuf, trx); + error = row_drop_database_for_mysql(namebuf, trx); my_free(namebuf, MYF(0)); /* Flush the log to reduce probability that the .frm files and @@ -5227,9 +5266,9 @@ innobase_drop_database( srv_active_wake_master_thread(); - innobase_commit_low(trx); - trx_free_for_mysql(trx); -#ifdef NO_LONGER_INTERESTED_IN_DROP_DB_ERROR + innobase_commit_low(trx); + trx_free_for_mysql(trx); +#ifdef NO_LONGER_INTERESTED_IN_DROP_DB_ERROR error = convert_error_code_to_mysql(error, NULL); return(error); @@ -5256,17 +5295,17 @@ ha_innobase::rename_table( char norm_from[1000]; char norm_to[1000]; - DBUG_ENTER("ha_innobase::rename_table"); + DBUG_ENTER("ha_innobase::rename_table"); /* Get the transaction associated with the current thd, or create one if not yet created */ - + parent_trx = check_trx_exists(current_thd); /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ - trx_search_latch_release_if_reserved(parent_trx); + trx_search_latch_release_if_reserved(parent_trx); if (lower_case_table_names) { srv_lower_case_table_names = TRUE; @@ -5291,9 +5330,9 @@ ha_innobase::rename_table( normalize_table_name(norm_from, from); normalize_table_name(norm_to, to); - /* Rename the table in InnoDB */ + /* Rename the table in InnoDB */ - error = row_rename_table_for_mysql(norm_from, norm_to, trx); + error = row_rename_table_for_mysql(norm_from, norm_to, trx); /* Flush the log to reduce probability that the .frm files and the InnoDB data dictionary get out-of-sync if the user runs @@ -5306,8 +5345,8 @@ ha_innobase::rename_table( srv_active_wake_master_thread(); - innobase_commit_low(trx); - trx_free_for_mysql(trx); + innobase_commit_low(trx); + trx_free_for_mysql(trx); error = convert_error_code_to_mysql(error, NULL); @@ -5322,30 +5361,30 @@ ha_innobase::records_in_range( /*==========================*/ /* out: estimated number of rows */ - uint keynr, /* in: index number */ - key_range *min_key, /* in: start key value of the - range, may also be 0 */ + uint keynr, /* in: index number */ + key_range *min_key, /* in: start key value of the + range, may also be 0 */ key_range *max_key) /* in: range end key val, may - also be 0 */ + also be 0 */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; KEY* key; dict_index_t* index; - mysql_byte* key_val_buff2 = (mysql_byte*) my_malloc( + mysql_byte* key_val_buff2 = (mysql_byte*) my_malloc( table->s->reclength - + table->s->max_key_length + 100, + + table->s->max_key_length + 100, MYF(MY_FAE)); ulint buff2_len = table->s->reclength - + table->s->max_key_length + 100; + + table->s->max_key_length + 100; dtuple_t* range_start; dtuple_t* range_end; ib_longlong n_rows; ulint mode1; ulint mode2; - void* heap1; - void* heap2; + void* heap1; + void* heap2; - DBUG_ENTER("records_in_range"); + DBUG_ENTER("records_in_range"); prebuilt->trx->op_info = (char*)"estimating records in index range"; @@ -5361,17 +5400,17 @@ ha_innobase::records_in_range( index = dict_table_get_index_noninline(prebuilt->table, key->name); range_start = dtuple_create_for_mysql(&heap1, key->key_parts); - dict_index_copy_types(range_start, index, key->key_parts); + dict_index_copy_types(range_start, index, key->key_parts); range_end = dtuple_create_for_mysql(&heap2, key->key_parts); - dict_index_copy_types(range_end, index, key->key_parts); + dict_index_copy_types(range_end, index, key->key_parts); row_sel_convert_mysql_key_to_innobase( range_start, (byte*) key_val_buff, (ulint)upd_and_key_val_buff_len, index, (byte*) (min_key ? min_key->key : - (const mysql_byte*) 0), + (const mysql_byte*) 0), (ulint) (min_key ? min_key->length : 0), prebuilt->trx); @@ -5379,21 +5418,21 @@ ha_innobase::records_in_range( range_end, (byte*) key_val_buff2, buff2_len, index, (byte*) (max_key ? max_key->key : - (const mysql_byte*) 0), + (const mysql_byte*) 0), (ulint) (max_key ? max_key->length : 0), prebuilt->trx); mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag : - HA_READ_KEY_EXACT); + HA_READ_KEY_EXACT); mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag : - HA_READ_KEY_EXACT); + HA_READ_KEY_EXACT); n_rows = btr_estimate_n_rows_in_range(index, range_start, mode1, range_end, mode2); dtuple_free_for_mysql(heap1); dtuple_free_for_mysql(heap2); - my_free((gptr) key_val_buff2, MYF(0)); + my_free((gptr) key_val_buff2, MYF(0)); prebuilt->trx->op_info = (char*)""; @@ -5404,7 +5443,7 @@ ha_innobase::records_in_range( Add 1 to the value to make sure MySQL does not make the assumption! */ if (n_rows == 0) { - n_rows = 1; + n_rows = 1; } DBUG_RETURN((ha_rows) n_rows); @@ -5424,7 +5463,7 @@ ha_innobase::estimate_rows_upper_bound(void) ulonglong estimate; ulonglong local_data_file_length; - DBUG_ENTER("estimate_rows_upper_bound"); + DBUG_ENTER("estimate_rows_upper_bound"); /* We do not know if MySQL can call this function before calling external_lock(). To be safe, update the thd of the current table @@ -5433,7 +5472,7 @@ ha_innobase::estimate_rows_upper_bound(void) update_thd(current_thd); prebuilt->trx->op_info = (char*) - "calculating upper bound for table rows"; + "calculating upper bound for table rows"; /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ @@ -5443,7 +5482,7 @@ ha_innobase::estimate_rows_upper_bound(void) index = dict_table_get_first_index_noninline(prebuilt->table); local_data_file_length = ((ulonglong) index->stat_n_leaf_pages) - * UNIV_PAGE_SIZE; + * UNIV_PAGE_SIZE; /* Calculate a minimum length for a clustered index record and from that an upper bound for the number of rows. Since we only calculate @@ -5474,7 +5513,7 @@ ha_innobase::scan_time() searches, we pretend that a sequential read takes the same time as a random disk read, that is, we do not divide the following by 10, which would be physically realistic. */ - + return((double) (prebuilt->table->stat_clustered_index_size)); } @@ -5486,16 +5525,16 @@ double ha_innobase::read_time( /*===================*/ /* out: estimated time measured in disk seeks */ - uint index, /* in: key number */ + uint index, /* in: key number */ uint ranges, /* in: how many ranges */ ha_rows rows) /* in: estimated number of rows in the ranges */ { ha_rows total_rows; - double time_for_scan; - + double time_for_scan; + if (index != table->s->primary_key) { - /* Not clustered */ - return(handler::read_time(index, ranges, rows)); + /* Not clustered */ + return(handler::read_time(index, ranges, rows)); } if (rows <= 2) { @@ -5510,7 +5549,7 @@ ha_innobase::read_time( if ((total_rows = estimate_rows_upper_bound()) < rows) { - return(time_for_scan); + return(time_for_scan); } return(ranges + (double) rows / (double) total_rows * time_for_scan); @@ -5533,18 +5572,18 @@ ha_innobase::info( ulong j; ulong i; char path[FN_REFLEN]; - os_file_stat_t stat_info; + os_file_stat_t stat_info; - DBUG_ENTER("info"); + DBUG_ENTER("info"); - /* If we are forcing recovery at a high level, we will suppress + /* If we are forcing recovery at a high level, we will suppress statistics calculation on tables, because that may crash the server if an index is badly corrupted. */ - if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { + if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { - DBUG_VOID_RETURN; - } + DBUG_VOID_RETURN; + } /* We do not know if MySQL can call this function before calling external_lock(). To be safe, update the thd of the current table @@ -5559,39 +5598,37 @@ ha_innobase::info( trx_search_latch_release_if_reserved(prebuilt->trx); - ib_table = prebuilt->table; + ib_table = prebuilt->table; - if (flag & HA_STATUS_TIME) { - /* In sql_show we call with this flag: update then statistics - so that they are up-to-date */ + if (flag & HA_STATUS_TIME) { + /* In sql_show we call with this flag: update then statistics + so that they are up-to-date */ - prebuilt->trx->op_info = (char*)"updating table statistics"; + prebuilt->trx->op_info = (char*)"updating table statistics"; - dict_update_statistics(ib_table); + dict_update_statistics(ib_table); prebuilt->trx->op_info = (char*) - "returning various info to MySQL"; + "returning various info to MySQL"; if (ib_table->space != 0) { my_snprintf(path, sizeof(path), "%s/%s%s", - mysql_data_home, ib_table->name, - ".ibd"); + mysql_data_home, ib_table->name, ".ibd"); unpack_filename(path,path); } else { - my_snprintf(path, sizeof(path), "%s/%s%s", - mysql_data_home, ib_table->name, - reg_ext); - + my_snprintf(path, sizeof(path), "%s/%s%s", + mysql_data_home, ib_table->name, reg_ext); + unpack_filename(path,path); } - /* Note that we do not know the access time of the table, + /* Note that we do not know the access time of the table, nor the CHECK TABLE time, nor the UPDATE or INSERT time. */ if (os_file_get_status(path,&stat_info)) { create_time = stat_info.ctime; } - } + } if (flag & HA_STATUS_VARIABLE) { n_rows = ib_table->stat_n_rows; @@ -5617,23 +5654,23 @@ ha_innobase::info( n_rows++; } - records = (ha_rows)n_rows; - deleted = 0; - data_file_length = ((ulonglong) + records = (ha_rows)n_rows; + deleted = 0; + data_file_length = ((ulonglong) ib_table->stat_clustered_index_size) - * UNIV_PAGE_SIZE; - index_file_length = ((ulonglong) + * UNIV_PAGE_SIZE; + index_file_length = ((ulonglong) ib_table->stat_sum_of_other_index_sizes) - * UNIV_PAGE_SIZE; - delete_length = 0; - check_time = 0; + * UNIV_PAGE_SIZE; + delete_length = 0; + check_time = 0; - if (records == 0) { - mean_rec_length = 0; - } else { - mean_rec_length = (ulong) (data_file_length / records); - } - } + if (records == 0) { + mean_rec_length = 0; + } else { + mean_rec_length = (ulong) (data_file_length / records); + } + } if (flag & HA_STATUS_CONST) { index = dict_table_get_first_index_noninline(ib_table); @@ -5659,7 +5696,7 @@ ha_innobase::info( for (j = 0; j < table->key_info[i].key_parts; j++) { if (j + 1 > index->n_uniq) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); sql_print_error("Index %s of %s has " "%lu columns unique " "inside InnoDB, but " @@ -5675,7 +5712,7 @@ ha_innobase::info( ib_table->name, (unsigned long) index->n_uniq, j + 1); - break; + break; } if (index->stat_n_diff_key_vals[j + 1] == 0) { @@ -5683,7 +5720,7 @@ ha_innobase::info( rec_per_key = records; } else { rec_per_key = (ha_rows)(records / - index->stat_n_diff_key_vals[j + 1]); + index->stat_n_diff_key_vals[j + 1]); } /* Since MySQL seems to favor table scans @@ -5697,7 +5734,7 @@ ha_innobase::info( rec_per_key = 1; } - table->key_info[i].rec_per_key[j]= + table->key_info[i].rec_per_key[j]= rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 : rec_per_key; } @@ -5706,13 +5743,12 @@ ha_innobase::info( } } - if (flag & HA_STATUS_ERRKEY) { + if (flag & HA_STATUS_ERRKEY) { ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N); errkey = (unsigned int) row_get_mysql_key_number_for_index( - (dict_index_t*) - trx_get_error_info(prebuilt->trx)); - } + (dict_index_t*) trx_get_error_info(prebuilt->trx)); + } if (flag & HA_STATUS_AUTO && table->found_next_number_field) { longlong auto_inc; @@ -5724,7 +5760,7 @@ ha_innobase::info( the auto-inc counter, and the second call is guaranteed to succeed. */ - ret = innobase_read_and_init_auto_inc(&auto_inc); + ret = innobase_read_and_init_auto_inc(&auto_inc); if (ret != 0) { ret = innobase_read_and_init_auto_inc(&auto_inc); @@ -5737,13 +5773,13 @@ ha_innobase::info( auto_inc = 0; } } - + auto_increment_value = auto_inc; } prebuilt->trx->op_info = (char*)""; - DBUG_VOID_RETURN; + DBUG_VOID_RETURN; } /************************************************************************** @@ -5752,7 +5788,7 @@ each index tree. This does NOT calculate exact statistics on the table. */ int ha_innobase::analyze( -/*=================*/ +/*=================*/ /* out: returns always 0 (success) */ THD* thd, /* in: connection thread handle */ HA_CHECK_OPT* check_opt) /* in: currently ignored */ @@ -5773,7 +5809,7 @@ ha_innobase::optimize( THD* thd, /* in: connection thread handle */ HA_CHECK_OPT* check_opt) /* in: currently ignored */ { - return(HA_ADMIN_TRY_ALTER); + return(HA_ADMIN_TRY_ALTER); } /*********************************************************************** @@ -5786,8 +5822,8 @@ ha_innobase::check( /*===============*/ /* out: HA_ADMIN_CORRUPT or HA_ADMIN_OK */ - THD* thd, /* in: user thread handle */ - HA_CHECK_OPT* check_opt) /* in: check options, currently + THD* thd, /* in: user thread handle */ + HA_CHECK_OPT* check_opt) /* in: check options, currently ignored */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; @@ -5795,7 +5831,7 @@ ha_innobase::check( ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[innobase_hton.slot]); + (trx_t*) current_thd->ha_data[innobase_hton.slot]); if (prebuilt->mysql_template == NULL) { /* Build the template; we will use a dummy template @@ -5810,7 +5846,7 @@ ha_innobase::check( return(HA_ADMIN_OK); } - return(HA_ADMIN_CORRUPT); + return(HA_ADMIN_CORRUPT); } /***************************************************************** @@ -5823,11 +5859,12 @@ ha_innobase::update_table_comment( /*==============================*/ /* out: table comment + InnoDB free space + info on foreign keys */ - const char* comment)/* in: table comment defined by user */ + const char* comment)/* in: table comment defined by user */ { uint length = (uint) strlen(comment); char* str; row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; + long flen; /* We do not know if MySQL can call this function before calling external_lock(). To be safe, update the thd of the current table @@ -5847,46 +5884,46 @@ ha_innobase::update_table_comment( trx_search_latch_release_if_reserved(prebuilt->trx); str = NULL; - if (FILE* file = os_file_create_tmpfile()) { - long flen; + /* output the data to a temporary file */ - /* output the data to a temporary file */ - fprintf(file, "InnoDB free: %lu kB", - (ulong) fsp_get_available_space_in_free_extents( - prebuilt->table->space)); + mutex_enter_noninline(&srv_dict_tmpfile_mutex); + rewind(srv_dict_tmpfile); - dict_print_info_on_foreign_keys(FALSE, file, + fprintf(srv_dict_tmpfile, "InnoDB free: %lu kB", + (ulong) fsp_get_available_space_in_free_extents( + prebuilt->table->space)); + + dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile, prebuilt->trx, prebuilt->table); - flen = ftell(file); - if (flen < 0) { - flen = 0; - } else if (length + flen + 3 > 64000) { - flen = 64000 - 3 - length; - } + flen = ftell(srv_dict_tmpfile); + if (flen < 0) { + flen = 0; + } else if (length + flen + 3 > 64000) { + flen = 64000 - 3 - length; + } - /* allocate buffer for the full string, and - read the contents of the temporary file */ + /* allocate buffer for the full string, and + read the contents of the temporary file */ - str = my_malloc(length + flen + 3, MYF(0)); + str = my_malloc(length + flen + 3, MYF(0)); - if (str) { - char* pos = str + length; - if (length) { - memcpy(str, comment, length); - *pos++ = ';'; - *pos++ = ' '; - } - rewind(file); - flen = (uint) fread(pos, 1, flen, file); - pos[flen] = 0; + if (str) { + char* pos = str + length; + if (length) { + memcpy(str, comment, length); + *pos++ = ';'; + *pos++ = ' '; } - - fclose(file); + rewind(srv_dict_tmpfile); + flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile); + pos[flen] = 0; } - prebuilt->trx->op_info = (char*)""; + mutex_exit_noninline(&srv_dict_tmpfile_mutex); + + prebuilt->trx->op_info = (char*)""; - return(str ? str : (char*) comment); + return(str ? str : (char*) comment); } /*********************************************************************** @@ -5901,6 +5938,7 @@ ha_innobase::get_foreign_key_create_info(void) { row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; char* str = 0; + long flen; ut_a(prebuilt != NULL); @@ -5910,52 +5948,47 @@ ha_innobase::get_foreign_key_create_info(void) update_thd(current_thd); - if (FILE* file = os_file_create_tmpfile()) { - long flen; + prebuilt->trx->op_info = (char*)"getting info on foreign keys"; - prebuilt->trx->op_info = (char*)"getting info on foreign keys"; + /* In case MySQL calls this in the middle of a SELECT query, + release possible adaptive hash latch to avoid + deadlocks of threads */ - /* In case MySQL calls this in the middle of a SELECT query, - release possible adaptive hash latch to avoid - deadlocks of threads */ + trx_search_latch_release_if_reserved(prebuilt->trx); - trx_search_latch_release_if_reserved(prebuilt->trx); + mutex_enter_noninline(&srv_dict_tmpfile_mutex); + rewind(srv_dict_tmpfile); - /* output the data to a temporary file */ - dict_print_info_on_foreign_keys(TRUE, file, + /* output the data to a temporary file */ + dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile, prebuilt->trx, prebuilt->table); - prebuilt->trx->op_info = (char*)""; - - flen = ftell(file); - if (flen < 0) { - flen = 0; - } else if (flen > 64000 - 1) { - flen = 64000 - 1; - } + prebuilt->trx->op_info = (char*)""; - /* allocate buffer for the string, and - read the contents of the temporary file */ + flen = ftell(srv_dict_tmpfile); + if (flen < 0) { + flen = 0; + } else if (flen > 64000 - 1) { + flen = 64000 - 1; + } - str = my_malloc(flen + 1, MYF(0)); + /* allocate buffer for the string, and + read the contents of the temporary file */ - if (str) { - rewind(file); - flen = (uint) fread(str, 1, flen, file); - str[flen] = 0; - } + str = my_malloc(flen + 1, MYF(0)); - fclose(file); - } else { - /* unable to create temporary file */ - str = my_strdup( -"/* Error: cannot display foreign key constraints */", MYF(0)); + if (str) { + rewind(srv_dict_tmpfile); + flen = (uint) fread(str, 1, flen, srv_dict_tmpfile); + str[flen] = 0; } - return(str); + mutex_exit_noninline(&srv_dict_tmpfile_mutex); + + return(str); } -int +int ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list) { dict_foreign_t* foreign; @@ -5969,85 +6002,80 @@ ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list) mutex_enter_noninline(&(dict_sys->mutex)); foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list); - while (foreign != NULL) - { - uint i; - FOREIGN_KEY_INFO f_key_info; - LEX_STRING *name= 0; - const char *tmp_buff; - - tmp_buff= foreign->id; - i= 0; - while (tmp_buff[i] != '/') - i++; - tmp_buff+= i + 1; - f_key_info.forein_id= make_lex_string(thd, 0, tmp_buff, - (uint) strlen(tmp_buff), 1); - tmp_buff= foreign->referenced_table_name; - i= 0; - while (tmp_buff[i] != '/') - i++; - f_key_info.referenced_db= make_lex_string(thd, 0, - tmp_buff, i, 1); - tmp_buff+= i + 1; - f_key_info.referenced_table= make_lex_string(thd, 0, tmp_buff, - (uint) strlen(tmp_buff), 1); - - for (i= 0;;) - { - tmp_buff= foreign->foreign_col_names[i]; - name= make_lex_string(thd, name, tmp_buff, (uint) strlen(tmp_buff), 1); - f_key_info.foreign_fields.push_back(name); - tmp_buff= foreign->referenced_col_names[i]; - name= make_lex_string(thd, name, tmp_buff, (uint) strlen(tmp_buff), 1); - f_key_info.referenced_fields.push_back(name); - if (++i >= foreign->n_fields) - break; - } - - ulong length= 0; - if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) - { - length=17; - tmp_buff= "ON DELETE CASCADE"; - } - else if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) - { - length=18; - tmp_buff= "ON DELETE SET NULL"; - } - else if (foreign->type == DICT_FOREIGN_ON_DELETE_NO_ACTION) - { - length=19; - tmp_buff= "ON DELETE NO ACTION"; - } - else if (foreign->type == DICT_FOREIGN_ON_UPDATE_CASCADE) - { - length=17; - tmp_buff= "ON UPDATE CASCADE"; - } - else if (foreign->type == DICT_FOREIGN_ON_UPDATE_SET_NULL) - { - length=18; - tmp_buff= "ON UPDATE SET NULL"; - } - else if (foreign->type == DICT_FOREIGN_ON_UPDATE_NO_ACTION) - { - length=19; - tmp_buff= "ON UPDATE NO ACTION"; - } - f_key_info.constraint_method= make_lex_string(thd, - f_key_info.constraint_method, - tmp_buff, length, 1); - - FOREIGN_KEY_INFO *pf_key_info= ((FOREIGN_KEY_INFO *) - thd->memdup((gptr) &f_key_info, - sizeof(FOREIGN_KEY_INFO))); - f_key_list->push_back(pf_key_info); - foreign = UT_LIST_GET_NEXT(foreign_list, foreign); + while (foreign != NULL) { + uint i; + FOREIGN_KEY_INFO f_key_info; + LEX_STRING *name= 0; + const char *tmp_buff; + + tmp_buff= foreign->id; + i= 0; + while (tmp_buff[i] != '/') + i++; + tmp_buff+= i + 1; + f_key_info.forein_id= make_lex_string(thd, 0, tmp_buff, + (uint) strlen(tmp_buff), 1); + tmp_buff= foreign->referenced_table_name; + i= 0; + while (tmp_buff[i] != '/') + i++; + f_key_info.referenced_db= make_lex_string(thd, 0, + tmp_buff, i, 1); + tmp_buff+= i + 1; + f_key_info.referenced_table= make_lex_string(thd, 0, tmp_buff, + (uint) strlen(tmp_buff), 1); + + for (i= 0;;) { + tmp_buff= foreign->foreign_col_names[i]; + name= make_lex_string(thd, name, tmp_buff, + (uint) strlen(tmp_buff), 1); + f_key_info.foreign_fields.push_back(name); + tmp_buff= foreign->referenced_col_names[i]; + name= make_lex_string(thd, name, tmp_buff, + (uint) strlen(tmp_buff), 1); + f_key_info.referenced_fields.push_back(name); + if (++i >= foreign->n_fields) + break; + } + + ulong length= 0; + if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) { + length=17; + tmp_buff= "ON DELETE CASCADE"; + } + else if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) { + length=18; + tmp_buff= "ON DELETE SET NULL"; + } + else if (foreign->type == DICT_FOREIGN_ON_DELETE_NO_ACTION) { + length=19; + tmp_buff= "ON DELETE NO ACTION"; + } + else if (foreign->type == DICT_FOREIGN_ON_UPDATE_CASCADE) { + length=17; + tmp_buff= "ON UPDATE CASCADE"; + } + else if (foreign->type == DICT_FOREIGN_ON_UPDATE_SET_NULL) { + length=18; + tmp_buff= "ON UPDATE SET NULL"; + } + else if (foreign->type == DICT_FOREIGN_ON_UPDATE_NO_ACTION) { + length=19; + tmp_buff= "ON UPDATE NO ACTION"; + } + f_key_info.constraint_method= make_lex_string(thd, + f_key_info.constraint_method, + tmp_buff, length, 1); + + FOREIGN_KEY_INFO *pf_key_info= ((FOREIGN_KEY_INFO *) + thd->memdup((gptr) &f_key_info, + sizeof(FOREIGN_KEY_INFO))); + f_key_list->push_back(pf_key_info); + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); } mutex_exit_noninline(&(dict_sys->mutex)); prebuilt->trx->op_info = (char*)""; + DBUG_RETURN(0); } @@ -6063,7 +6091,7 @@ ha_innobase::can_switch_engines(void) row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; bool can_switch; - DBUG_ENTER("ha_innobase::can_switch_engines"); + DBUG_ENTER("ha_innobase::can_switch_engines"); prebuilt->trx->op_info = "determining if there are foreign key constraints"; row_mysql_lock_data_dictionary(prebuilt->trx); @@ -6105,7 +6133,7 @@ non-NULL. */ void ha_innobase::free_foreign_key_create_info( /*======================================*/ - char* str) /* in, own: create info string to free */ + char* str) /* in, own: create info string to free */ { if (str) { my_free(str, MYF(0)); @@ -6120,7 +6148,7 @@ ha_innobase::extra( /*===============*/ /* out: 0 or error number */ enum ha_extra_function operation) - /* in: HA_EXTRA_RETRIEVE_ALL_COLS or some + /* in: HA_EXTRA_RETRIEVE_ALL_COLS or some other flag */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; @@ -6130,38 +6158,38 @@ ha_innobase::extra( obsolete! */ switch (operation) { - case HA_EXTRA_FLUSH: - if (prebuilt->blob_heap) { - row_mysql_prebuilt_free_blob_heap(prebuilt); - } - break; - case HA_EXTRA_RESET: - if (prebuilt->blob_heap) { - row_mysql_prebuilt_free_blob_heap(prebuilt); - } - prebuilt->keep_other_fields_on_keyread = 0; - prebuilt->read_just_key = 0; - break; - case HA_EXTRA_RESET_STATE: - prebuilt->keep_other_fields_on_keyread = 0; - prebuilt->read_just_key = 0; - break; + case HA_EXTRA_FLUSH: + if (prebuilt->blob_heap) { + row_mysql_prebuilt_free_blob_heap(prebuilt); + } + break; + case HA_EXTRA_RESET: + if (prebuilt->blob_heap) { + row_mysql_prebuilt_free_blob_heap(prebuilt); + } + prebuilt->keep_other_fields_on_keyread = 0; + prebuilt->read_just_key = 0; + break; + case HA_EXTRA_RESET_STATE: + prebuilt->keep_other_fields_on_keyread = 0; + prebuilt->read_just_key = 0; + break; case HA_EXTRA_NO_KEYREAD: - prebuilt->read_just_key = 0; - break; - case HA_EXTRA_RETRIEVE_ALL_COLS: + prebuilt->read_just_key = 0; + break; + case HA_EXTRA_RETRIEVE_ALL_COLS: prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS; break; - case HA_EXTRA_RETRIEVE_PRIMARY_KEY: + case HA_EXTRA_RETRIEVE_PRIMARY_KEY: if (prebuilt->hint_need_to_fetch_extra_cols == 0) { prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_PRIMARY_KEY; } break; - case HA_EXTRA_KEYREAD: - prebuilt->read_just_key = 1; - break; + case HA_EXTRA_KEYREAD: + prebuilt->read_just_key = 1; + break; case HA_EXTRA_KEYREAD_PRESERVE_FIELDS: prebuilt->keep_other_fields_on_keyread = 1; break; @@ -6187,9 +6215,9 @@ procedure. */ int ha_innobase::start_stmt( /*====================*/ - /* out: 0 or error code */ - THD* thd, /* in: handle to the user thread */ - thr_lock_type lock_type) + /* out: 0 or error code */ + THD* thd, /* in: handle to the user thread */ + thr_lock_type lock_type) { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; trx_t* trx; @@ -6208,30 +6236,30 @@ ha_innobase::start_stmt( innobase_release_stat_resources(trx); if (trx->isolation_level <= TRX_ISO_READ_COMMITTED - && trx->global_read_view) { - /* At low transaction isolation levels we let + && trx->global_read_view) { + /* At low transaction isolation levels we let each consistent read set its own snapshot */ - read_view_close_for_mysql(trx); + read_view_close_for_mysql(trx); } prebuilt->sql_stat_start = TRUE; prebuilt->hint_need_to_fetch_extra_cols = 0; prebuilt->read_just_key = 0; - prebuilt->keep_other_fields_on_keyread = FALSE; + prebuilt->keep_other_fields_on_keyread = FALSE; if (!prebuilt->mysql_has_locked) { - /* This handle is for a temporary table created inside - this same LOCK TABLES; since MySQL does NOT call external_lock - in this case, we must use x-row locks inside InnoDB to be - prepared for an update of a row */ - - prebuilt->select_lock_type = LOCK_X; + /* This handle is for a temporary table created inside + this same LOCK TABLES; since MySQL does NOT call external_lock + in this case, we must use x-row locks inside InnoDB to be + prepared for an update of a row */ + + prebuilt->select_lock_type = LOCK_X; } else { if (trx->isolation_level != TRX_ISO_SERIALIZABLE - && thd->lex->sql_command == SQLCOM_SELECT - && lock_type == TL_READ) { - + && thd->lex->sql_command == SQLCOM_SELECT + && lock_type == TL_READ) { + /* For other than temporary tables, we obtain no lock for consistent read (plain SELECT). */ @@ -6241,8 +6269,8 @@ ha_innobase::start_stmt( select_lock_type value. The value of stored_select_lock_type was decided in: 1) ::store_lock(), - 2) ::external_lock(), - 3) ::init_table_handle_for_HANDLER(), and + 2) ::external_lock(), + 3) ::init_table_handle_for_HANDLER(), and 4) :.transactional_table_lock(). */ prebuilt->select_lock_type = @@ -6250,10 +6278,11 @@ ha_innobase::start_stmt( } if (prebuilt->stored_select_lock_type != LOCK_S - && prebuilt->stored_select_lock_type != LOCK_X) { - sql_print_error("stored_select_lock_type is %lu inside " - "::start_stmt()!", - prebuilt->stored_select_lock_type); + && prebuilt->stored_select_lock_type != LOCK_X) { + sql_print_error( + "stored_select_lock_type is %lu inside " + "::start_stmt()!", + prebuilt->stored_select_lock_type); /* Set the value to LOCK_X: this is just fault tolerance, we do not know what the correct value @@ -6266,11 +6295,11 @@ ha_innobase::start_stmt( trx->detailed_error[0] = '\0'; /* Set the MySQL flag to mark that there is an active transaction */ - if (trx->active_trans == 0) { + if (trx->active_trans == 0) { - innobase_register_trx_and_stmt(thd); - trx->active_trans = 1; - } else { + innobase_register_trx_and_stmt(thd); + trx->active_trans = 1; + } else { innobase_register_stmt(thd); } @@ -6292,9 +6321,9 @@ innobase_map_isolation_level( case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE); case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED); default: ut_a(0); return(0); - } + } } - + /********************************************************************** As MySQL will execute an external lock for every new table it uses when it starts to process an SQL statement (an exception is when MySQL calls @@ -6307,14 +6336,14 @@ the SQL statement in case of an error. */ int ha_innobase::external_lock( /*=======================*/ - /* out: 0 */ + /* out: 0 */ THD* thd, /* in: handle to the user thread */ - int lock_type) /* in: lock type */ + int lock_type) /* in: lock type */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; trx_t* trx; - DBUG_ENTER("ha_innobase::external_lock"); + DBUG_ENTER("ha_innobase::external_lock"); DBUG_PRINT("enter",("lock_type: %d", lock_type)); update_thd(thd); @@ -6339,14 +6368,14 @@ ha_innobase::external_lock( /* MySQL is setting a new table lock */ trx->detailed_error[0] = '\0'; - + /* Set the MySQL flag to mark that there is an active transaction */ - if (trx->active_trans == 0) { + if (trx->active_trans == 0) { - innobase_register_trx_and_stmt(thd); - trx->active_trans = 1; - } else if (trx->n_mysql_tables_in_use == 0) { + innobase_register_trx_and_stmt(thd); + trx->active_trans = 1; + } else if (trx->n_mysql_tables_in_use == 0) { innobase_register_stmt(thd); } @@ -6354,14 +6383,14 @@ ha_innobase::external_lock( prebuilt->mysql_has_locked = TRUE; if (trx->n_mysql_tables_in_use == 1) { - trx->isolation_level = innobase_map_isolation_level( + trx->isolation_level = innobase_map_isolation_level( (enum_tx_isolation) thd->variables.tx_isolation); } if (trx->isolation_level == TRX_ISO_SERIALIZABLE - && prebuilt->select_lock_type == LOCK_NONE - && (thd->options + && prebuilt->select_lock_type == LOCK_NONE + && (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { /* To get serializable execution, we let InnoDB @@ -6380,20 +6409,22 @@ ha_innobase::external_lock( TABLES if AUTOCOMMIT=1. It does not make much sense to acquire an InnoDB table lock if it is released immediately at the end of LOCK TABLES, and InnoDB's table locks in that case cause - VERY easily deadlocks. We do not set InnoDB table locks when - MySQL sets them at the start of a stored procedure call - (MySQL does have thd->in_lock_tables TRUE there). */ + VERY easily deadlocks. + + We do not set InnoDB table locks if user has not explicitly + requested a table lock. Note that thd->in_lock_tables + can be TRUE on some cases e.g. at the start of a stored + procedure call (SQLCOM_CALL). */ if (prebuilt->select_lock_type != LOCK_NONE) { if (thd->in_lock_tables && - thd->lex->sql_command != SQLCOM_CALL && - thd->variables.innodb_table_locks && - (thd->options & OPTION_NOT_AUTOCOMMIT)) { + thd->lex->sql_command == SQLCOM_LOCK_TABLES && + thd->variables.innodb_table_locks && + (thd->options & OPTION_NOT_AUTOCOMMIT)) { - ulint error; - error = row_lock_table_for_mysql(prebuilt, - NULL, 0); + ulint error = row_lock_table_for_mysql( + prebuilt, NULL, 0); if (error != DB_SUCCESS) { error = convert_error_code_to_mysql( @@ -6402,7 +6433,7 @@ ha_innobase::external_lock( } } - trx->mysql_n_tables_locked++; + trx->mysql_n_tables_locked++; } DBUG_RETURN(0); @@ -6418,9 +6449,9 @@ ha_innobase::external_lock( if (trx->n_mysql_tables_in_use == 0) { - trx->mysql_n_tables_locked = 0; + trx->mysql_n_tables_locked = 0; prebuilt->used_in_HANDLER = FALSE; - + /* Release a possible FIFO ticket and search latch. Since we may reserve the kernel mutex, we have to release the search system latch first to obey the latching order. */ @@ -6428,12 +6459,12 @@ ha_innobase::external_lock( innobase_release_stat_resources(trx); if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { - if (trx->active_trans != 0) { - innobase_commit(thd, TRUE); + if (trx->active_trans != 0) { + innobase_commit(thd, TRUE); } } else { if (trx->isolation_level <= TRX_ISO_READ_COMMITTED - && trx->global_read_view) { + && trx->global_read_view) { /* At low transaction isolation levels we let each consistent read set its own snapshot */ @@ -6453,14 +6484,14 @@ user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */ int ha_innobase::transactional_table_lock( /*==================================*/ - /* out: error code */ + /* out: error code */ THD* thd, /* in: handle to the user thread */ - int lock_type) /* in: lock type */ + int lock_type) /* in: lock type */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; trx_t* trx; - DBUG_ENTER("ha_innobase::transactional_table_lock"); + DBUG_ENTER("ha_innobase::transactional_table_lock"); DBUG_PRINT("enter",("lock_type: %d", lock_type)); /* We do not know if MySQL can call this function before calling @@ -6469,9 +6500,9 @@ ha_innobase::transactional_table_lock( update_thd(thd); - if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB error:\n" + if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB error:\n" "MySQL is trying to use a table handle but the .ibd file for\n" "table %s does not exist.\n" "Have you deleted the .ibd file from the database directory under\n" @@ -6497,8 +6528,8 @@ ha_innobase::transactional_table_lock( prebuilt->select_lock_type = LOCK_S; prebuilt->stored_select_lock_type = LOCK_S; } else { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB error:\n" + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB error:\n" "MySQL is trying to set transactional table lock with corrupted lock type\n" "to table %s, lock type %d does not exist.\n", prebuilt->table->name, lock_type); @@ -6508,11 +6539,11 @@ ha_innobase::transactional_table_lock( /* MySQL is setting a new transactional table lock */ /* Set the MySQL flag to mark that there is an active transaction */ - if (trx->active_trans == 0) { + if (trx->active_trans == 0) { - innobase_register_trx_and_stmt(thd); - trx->active_trans = 1; - } + innobase_register_trx_and_stmt(thd); + trx->active_trans = 1; + } if (thd->in_lock_tables && thd->variables.innodb_table_locks) { ulint error = DB_SUCCESS; @@ -6526,8 +6557,8 @@ ha_innobase::transactional_table_lock( if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { - /* Store the current undo_no of the transaction - so that we know where to roll back if we have + /* Store the current undo_no of the transaction + so that we know where to roll back if we have to roll back the next SQL statement */ trx_mark_sql_stat_end(trx); @@ -6542,11 +6573,13 @@ Here we export InnoDB status variables to MySQL. */ int innodb_export_status() -/*======================*/ +/*==================*/ { - if (innodb_inited) - srv_export_innodb_status(); - return 0; + if (innodb_inited) { + srv_export_innodb_status(); + } + + return 0; } /**************************************************************************** @@ -6565,11 +6598,11 @@ innodb_show_status( ulint trx_list_start = ULINT_UNDEFINED; ulint trx_list_end = ULINT_UNDEFINED; - DBUG_ENTER("innodb_show_status"); + DBUG_ENTER("innodb_show_status"); - if (have_innodb != SHOW_OPTION_YES) { - DBUG_RETURN(FALSE); - } + if (have_innodb != SHOW_OPTION_YES) { + DBUG_RETURN(FALSE); + } trx = check_trx_exists(thd); @@ -6601,11 +6634,10 @@ innodb_show_status( /* allocate buffer for the string, and read the contents of the temporary file */ - if (!(str = my_malloc(usable_len + 1, MYF(0)))) - { - mutex_exit_noninline(&srv_monitor_file_mutex); - DBUG_RETURN(TRUE); - } + if (!(str = my_malloc(usable_len + 1, MYF(0)))) { + mutex_exit_noninline(&srv_monitor_file_mutex); + DBUG_RETURN(TRUE); + } rewind(srv_monitor_file); if (flen < MAX_STATUS_SIZE) { @@ -6632,8 +6664,8 @@ innodb_show_status( bool result = FALSE; - if (stat_print(thd, innobase_hton.name, strlen(innobase_hton.name), - STRING_WITH_LEN(""), str, flen)) { + if (stat_print(thd, innobase_hton.name, strlen(innobase_hton.name), + STRING_WITH_LEN(""), str, flen)) { result= TRUE; } my_free(str, MYF(0)); @@ -6646,96 +6678,99 @@ Implements the SHOW MUTEX STATUS command. . */ bool innodb_mutex_show_status( -/*===============*/ - THD* thd, /* in: the MySQL query thread of the caller */ - stat_print_fn *stat_print) -{ - char buf1[IO_SIZE], buf2[IO_SIZE]; - mutex_t* mutex; - ulint rw_lock_count= 0; - ulint rw_lock_count_spin_loop= 0; - ulint rw_lock_count_spin_rounds= 0; - ulint rw_lock_count_os_wait= 0; - ulint rw_lock_count_os_yield= 0; - ulonglong rw_lock_wait_time= 0; - uint hton_name_len= strlen(innobase_hton.name), buf1len, buf2len; - DBUG_ENTER("innodb_mutex_show_status"); +/*=====================*/ + THD* thd, /* in: the MySQL query thread of the + caller */ + stat_print_fn* stat_print) +{ + char buf1[IO_SIZE], buf2[IO_SIZE]; + mutex_t* mutex; + ulint rw_lock_count= 0; + ulint rw_lock_count_spin_loop= 0; + ulint rw_lock_count_spin_rounds= 0; + ulint rw_lock_count_os_wait= 0; + ulint rw_lock_count_os_yield= 0; + ulonglong rw_lock_wait_time= 0; + uint hton_name_len= strlen(innobase_hton.name), buf1len, buf2len; + DBUG_ENTER("innodb_mutex_show_status"); #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_enter(&mutex_list_mutex); + mutex_enter(&mutex_list_mutex); #endif - mutex = UT_LIST_GET_FIRST(mutex_list); - - while ( mutex != NULL ) - { - if (mutex->mutex_type != 1) - { - if (mutex->count_using > 0) - { - buf1len= my_snprintf(buf1, sizeof(buf1), "%s:%s", - mutex->cmutex_name, mutex->cfile_name); - buf2len= my_snprintf(buf2, sizeof(buf2), - "count=%lu, spin_waits=%lu, spin_rounds=%lu, " - "os_waits=%lu, os_yields=%lu, os_wait_times=%lu", - mutex->count_using, mutex->count_spin_loop, - mutex->count_spin_rounds, - mutex->count_os_wait, mutex->count_os_yield, - mutex->lspent_time/1000); - if (stat_print(thd, innobase_hton.name, hton_name_len, - buf1, buf1len, buf2, buf2len)) - { + mutex = UT_LIST_GET_FIRST(mutex_list); + + while (mutex != NULL) { + if (mutex->mutex_type != 1) { + if (mutex->count_using > 0) { + buf1len= my_snprintf(buf1, sizeof(buf1), + "%s:%s", + mutex->cmutex_name, mutex->cfile_name); + buf2len= my_snprintf(buf2, sizeof(buf2), + "count=%lu, spin_waits=%lu," + " spin_rounds=%lu, " + "os_waits=%lu, os_yields=%lu," + " os_wait_times=%lu", + mutex->count_using, + mutex->count_spin_loop, + mutex->count_spin_rounds, + mutex->count_os_wait, + mutex->count_os_yield, + mutex->lspent_time/1000); + + if (stat_print(thd, innobase_hton.name, + hton_name_len, buf1, buf1len, + buf2, buf2len)) { #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_exit(&mutex_list_mutex); + mutex_exit(&mutex_list_mutex); #endif - DBUG_RETURN(1); - } - } - } - else - { - rw_lock_count += mutex->count_using; - rw_lock_count_spin_loop += mutex->count_spin_loop; - rw_lock_count_spin_rounds += mutex->count_spin_rounds; - rw_lock_count_os_wait += mutex->count_os_wait; - rw_lock_count_os_yield += mutex->count_os_yield; - rw_lock_wait_time += mutex->lspent_time; - } - - mutex = UT_LIST_GET_NEXT(list, mutex); - } + DBUG_RETURN(1); + } + } + } + else { + rw_lock_count += mutex->count_using; + rw_lock_count_spin_loop += mutex->count_spin_loop; + rw_lock_count_spin_rounds += mutex->count_spin_rounds; + rw_lock_count_os_wait += mutex->count_os_wait; + rw_lock_count_os_yield += mutex->count_os_yield; + rw_lock_wait_time += mutex->lspent_time; + } - buf2len= my_snprintf(buf2, sizeof(buf2), - "count=%lu, spin_waits=%lu, spin_rounds=%lu, " - "os_waits=%lu, os_yields=%lu, os_wait_times=%lu", - rw_lock_count, rw_lock_count_spin_loop, - rw_lock_count_spin_rounds, - rw_lock_count_os_wait, rw_lock_count_os_yield, - rw_lock_wait_time/1000); - - if (stat_print(thd, innobase_hton.name, hton_name_len, - STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) - { - DBUG_RETURN(1); - } + mutex = UT_LIST_GET_NEXT(list, mutex); + } + + buf2len= my_snprintf(buf2, sizeof(buf2), + "count=%lu, spin_waits=%lu, spin_rounds=%lu, " + "os_waits=%lu, os_yields=%lu, os_wait_times=%lu", + rw_lock_count, rw_lock_count_spin_loop, + rw_lock_count_spin_rounds, + rw_lock_count_os_wait, rw_lock_count_os_yield, + rw_lock_wait_time/1000); + + if (stat_print(thd, innobase_hton.name, hton_name_len, + STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) { + DBUG_RETURN(1); + } #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_exit(&mutex_list_mutex); + mutex_exit(&mutex_list_mutex); #endif - DBUG_RETURN(FALSE); + + DBUG_RETURN(FALSE); } bool innobase_show_status(THD* thd, stat_print_fn* stat_print, - enum ha_stat_type stat_type) -{ - switch (stat_type) { - case HA_ENGINE_STATUS: - return innodb_show_status(thd, stat_print); - case HA_ENGINE_MUTEX: - return innodb_mutex_show_status(thd, stat_print); - default: - return FALSE; - } + enum ha_stat_type stat_type) +{ + switch (stat_type) { + case HA_ENGINE_STATUS: + return innodb_show_status(thd, stat_print); + case HA_ENGINE_MUTEX: + return innodb_mutex_show_status(thd, stat_print); + default: + return FALSE; + } } @@ -6744,54 +6779,61 @@ bool innobase_show_status(THD* thd, stat_print_fn* stat_print, locking. ****************************************************************************/ -static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length, - my_bool not_used __attribute__((unused))) -{ - *length=share->table_name_length; - return (mysql_byte*) share->table_name; -} - -static INNOBASE_SHARE *get_share(const char *table_name) -{ - INNOBASE_SHARE *share; - pthread_mutex_lock(&innobase_share_mutex); - uint length=(uint) strlen(table_name); - if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables, - (mysql_byte*) table_name, - length))) - { - if ((share=(INNOBASE_SHARE *) my_malloc(sizeof(*share)+length+1, - MYF(MY_WME | MY_ZEROFILL)))) - { - share->table_name_length=length; - share->table_name=(char*) (share+1); - strmov(share->table_name,table_name); - if (my_hash_insert(&innobase_open_tables, (mysql_byte*) share)) - { - pthread_mutex_unlock(&innobase_share_mutex); - my_free((gptr) share,0); - return 0; - } - thr_lock_init(&share->lock); - pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST); - } - } - share->use_count++; - pthread_mutex_unlock(&innobase_share_mutex); - return share; +static mysql_byte* innobase_get_key(INNOBASE_SHARE* share, uint* length, + my_bool not_used __attribute__((unused))) +{ + *length=share->table_name_length; + + return (mysql_byte*) share->table_name; } -static void free_share(INNOBASE_SHARE *share) +static INNOBASE_SHARE* get_share(const char* table_name) { - pthread_mutex_lock(&innobase_share_mutex); - if (!--share->use_count) - { - hash_delete(&innobase_open_tables, (mysql_byte*) share); - thr_lock_delete(&share->lock); - pthread_mutex_destroy(&share->mutex); - my_free((gptr) share, MYF(0)); - } - pthread_mutex_unlock(&innobase_share_mutex); + INNOBASE_SHARE *share; + pthread_mutex_lock(&innobase_share_mutex); + uint length=(uint) strlen(table_name); + + if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables, + (mysql_byte*) table_name, + length))) { + + share = (INNOBASE_SHARE *) my_malloc(sizeof(*share)+length+1, + MYF(MY_FAE | MY_ZEROFILL)); + + share->table_name_length=length; + share->table_name=(char*) (share+1); + strmov(share->table_name,table_name); + + if (my_hash_insert(&innobase_open_tables, + (mysql_byte*) share)) { + pthread_mutex_unlock(&innobase_share_mutex); + my_free((gptr) share,0); + + return 0; + } + + thr_lock_init(&share->lock); + pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST); + } + + share->use_count++; + pthread_mutex_unlock(&innobase_share_mutex); + + return share; +} + +static void free_share(INNOBASE_SHARE* share) +{ + pthread_mutex_lock(&innobase_share_mutex); + + if (!--share->use_count) { + hash_delete(&innobase_open_tables, (mysql_byte*) share); + thr_lock_delete(&share->lock); + pthread_mutex_destroy(&share->mutex); + my_free((gptr) share, MYF(0)); + } + + pthread_mutex_unlock(&innobase_share_mutex); } /********************************************************************* @@ -6814,22 +6856,22 @@ ha_innobase::store_lock( pointer to the 'lock' field of current handle is stored next to this array */ - enum thr_lock_type lock_type) /* in: lock type to store in + enum thr_lock_type lock_type) /* in: lock type to store in 'lock'; this may also be TL_IGNORE */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; - /* NOTE: MySQL can call this function with lock 'type' TL_IGNORE! + /* NOTE: MySQL can call this function with lock 'type' TL_IGNORE! Be careful to ignore TL_IGNORE if we are going to do something with only 'real' locks! */ - if ((lock_type == TL_READ && thd->in_lock_tables) || - (lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) || - lock_type == TL_READ_WITH_SHARED_LOCKS || - lock_type == TL_READ_NO_INSERT || - (thd->lex->sql_command != SQLCOM_SELECT - && lock_type != TL_IGNORE)) { + if ((lock_type == TL_READ && thd->in_lock_tables) || + (lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) || + lock_type == TL_READ_WITH_SHARED_LOCKS || + lock_type == TL_READ_NO_INSERT || + (thd->lex->sql_command != SQLCOM_SELECT + && lock_type != TL_IGNORE)) { /* The OR cases above are in this order: 1) MySQL is doing LOCK TABLES ... READ LOCAL, or @@ -6849,10 +6891,10 @@ ha_innobase::store_lock( used. */ if (srv_locks_unsafe_for_binlog && - prebuilt->trx->isolation_level != TRX_ISO_SERIALIZABLE && - (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) && - (thd->lex->sql_command == SQLCOM_INSERT_SELECT || - thd->lex->sql_command == SQLCOM_UPDATE)) { + prebuilt->trx->isolation_level != TRX_ISO_SERIALIZABLE && + (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) && + (thd->lex->sql_command == SQLCOM_INSERT_SELECT || + thd->lex->sql_command == SQLCOM_UPDATE)) { /* In case we have innobase_locks_unsafe_for_binlog option set and isolation level of the transaction @@ -6875,7 +6917,7 @@ ha_innobase::store_lock( } else if (lock_type != TL_IGNORE) { - /* We set possible LOCK_X value in external_lock, not yet + /* We set possible LOCK_X value in external_lock, not yet here even if this would be SELECT ... FOR UPDATE */ prebuilt->select_lock_type = LOCK_NONE; @@ -6884,7 +6926,7 @@ ha_innobase::store_lock( if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { - /* Starting from 5.0.7, we weaken also the table locks + /* Starting from 5.0.7, we weaken also the table locks set at the start of a MySQL stored procedure call, just like we weaken the locks set at the start of an SQL statement. MySQL does set thd->in_lock_tables TRUE there, but in reality @@ -6907,38 +6949,48 @@ ha_innobase::store_lock( lock_type = TL_READ_NO_INSERT; } - /* If we are not doing a LOCK TABLE or DISCARD/IMPORT - TABLESPACE or TRUNCATE TABLE, then allow multiple writers */ + /* If we are not doing a LOCK TABLE, DISCARD/IMPORT + TABLESPACE or TRUNCATE TABLE then allow multiple + writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ + < TL_WRITE_CONCURRENT_INSERT. - if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && - lock_type <= TL_WRITE) - && (!thd->in_lock_tables - || thd->lex->sql_command == SQLCOM_CALL) - && !thd->tablespace_op - && thd->lex->sql_command != SQLCOM_TRUNCATE - && thd->lex->sql_command != SQLCOM_OPTIMIZE - && thd->lex->sql_command != SQLCOM_CREATE_TABLE) { + We especially allow multiple writers if MySQL is at the + start of a stored procedure call (SQLCOM_CALL) + (MySQL does have thd->in_lock_tables TRUE there). */ - lock_type = TL_WRITE_ALLOW_WRITE; - } + if ((lock_type >= TL_WRITE_CONCURRENT_INSERT + && lock_type <= TL_WRITE) + && (!thd->in_lock_tables + || thd->lex->sql_command == SQLCOM_CALL) + && !thd->tablespace_op + && thd->lex->sql_command != SQLCOM_TRUNCATE + && thd->lex->sql_command != SQLCOM_OPTIMIZE + && thd->lex->sql_command != SQLCOM_CREATE_TABLE) { + + lock_type = TL_WRITE_ALLOW_WRITE; + } /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ... MySQL would use the lock TL_READ_NO_INSERT on t2, and that would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts to t2. Convert the lock to a normal read lock to allow - concurrent inserts to t2. */ - + concurrent inserts to t2. + + We especially allow concurrent inserts if MySQL is at the + start of a stored procedure call (SQLCOM_CALL) + (MySQL does have thd->in_lock_tables TRUE there). */ + if (lock_type == TL_READ_NO_INSERT - && (!thd->in_lock_tables - || thd->lex->sql_command == SQLCOM_CALL)) { + && (!thd->in_lock_tables + || thd->lex->sql_command == SQLCOM_CALL)) { lock_type = TL_READ; } - - lock.type = lock_type; - } - *to++= &lock; + lock.type = lock_type; + } + + *to++= &lock; return(to); } @@ -6956,17 +7008,17 @@ ha_innobase::innobase_read_and_init_auto_inc( timeout */ longlong* ret) /* out: auto-inc value */ { - row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; - longlong auto_inc; + row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; + longlong auto_inc; ulint old_select_lock_type; ibool trx_was_not_started = FALSE; - int error; + int error; - ut_a(prebuilt); + ut_a(prebuilt); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[innobase_hton.slot]); + (trx_t*) current_thd->ha_data[innobase_hton.slot]); ut_a(prebuilt->table); - + if (prebuilt->trx->conc_state == TRX_NOT_STARTED) { trx_was_not_started = TRUE; } @@ -6981,7 +7033,7 @@ ha_innobase::innobase_read_and_init_auto_inc( if (auto_inc != 0) { /* Already initialized */ *ret = auto_inc; - + error = 0; goto func_exit_early; @@ -6993,21 +7045,21 @@ ha_innobase::innobase_read_and_init_auto_inc( error = convert_error_code_to_mysql(error, user_thd); goto func_exit_early; - } + } /* Check again if someone has initialized the counter meanwhile */ auto_inc = dict_table_autoinc_read(prebuilt->table); if (auto_inc != 0) { *ret = auto_inc; - + error = 0; goto func_exit_early; } - (void) extra(HA_EXTRA_KEYREAD); - index_init(table->s->next_number_index, 1); + (void) extra(HA_EXTRA_KEYREAD); + index_init(table->s->next_number_index, 1); /* Starting from 5.0.9, we use a consistent read to read the auto-inc column maximum value. This eliminates the spurious deadlocks caused @@ -7016,12 +7068,12 @@ ha_innobase::innobase_read_and_init_auto_inc( column, our consistent read will not return the largest value. We accept this flaw, since the deadlocks were a bigger trouble. */ - /* Fetch all the columns in the key */ - + /* Fetch all the columns in the key */ + prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS; old_select_lock_type = prebuilt->select_lock_type; - prebuilt->select_lock_type = LOCK_NONE; + prebuilt->select_lock_type = LOCK_NONE; /* Eliminate an InnoDB error print that happens when we try to SELECT from a table when no table has been locked in ::external_lock(). */ @@ -7030,9 +7082,9 @@ ha_innobase::innobase_read_and_init_auto_inc( error = index_last(table->record[1]); prebuilt->trx->n_mysql_tables_in_use--; - prebuilt->select_lock_type = old_select_lock_type; + prebuilt->select_lock_type = old_select_lock_type; - if (error) { + if (error) { if (error == HA_ERR_END_OF_FILE) { /* The table was empty, initialize to 1 */ auto_inc = 1; @@ -7042,25 +7094,25 @@ ha_innobase::innobase_read_and_init_auto_inc( /* This should not happen in a consistent read */ sql_print_error("Consistent read of auto-inc column " "returned %lu", (ulong) error); - auto_inc = -1; + auto_inc = -1; - goto func_exit; - } - } else { + goto func_exit; + } + } else { /* Initialize to max(col) + 1; we use 'found_next_number_field' below because MySQL in SHOW TABLE STATUS does not seem to set 'next_number_field'. The comment in table.h says that 'next_number_field' is set when it is 'active'. */ - auto_inc = (longlong) table->found_next_number_field-> - val_int_offset(table->s->rec_buff_length) + 1; - } + auto_inc = (longlong) table->found_next_number_field-> + val_int_offset(table->s->rec_buff_length) + 1; + } dict_table_autoinc_initialize(prebuilt->table, auto_inc); func_exit: - (void) extra(HA_EXTRA_NO_KEYREAD); + (void) extra(HA_EXTRA_NO_KEYREAD); index_end(); @@ -7079,7 +7131,7 @@ func_exit_early: innobase_commit_low(prebuilt->trx); } - return(error); + return(error); } /*********************************************************************** @@ -7091,23 +7143,23 @@ auto-inc counter. */ ulonglong ha_innobase::get_auto_increment() /*=============================*/ - /* out: auto-increment column value, -1 if error - (deadlock or lock wait timeout) */ + /* out: auto-increment column value, -1 if error + (deadlock or lock wait timeout) */ { - longlong nr; - int error; - + longlong nr; + int error; + error = innobase_read_and_init_auto_inc(&nr); if (error) { /* This should never happen in the current (5.0.6) code, since we call this function only after the counter has been initialized. */ - + ut_print_timestamp(stderr); sql_print_error("Error %lu in ::get_auto_increment()", (ulong) error); - return(~(ulonglong) 0); + return(~(ulonglong) 0); } return((ulonglong) nr); @@ -7120,7 +7172,7 @@ ha_innobase::reset_auto_increment(ulonglong value) DBUG_ENTER("ha_innobase::reset_auto_increment"); row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; - int error; + int error; error = row_lock_table_autoinc_for_mysql(prebuilt); @@ -7128,7 +7180,7 @@ ha_innobase::reset_auto_increment(ulonglong value) error = convert_error_code_to_mysql(error, user_thd); DBUG_RETURN(error); - } + } dict_table_autoinc_initialize(prebuilt->table, value); @@ -7139,7 +7191,7 @@ ha_innobase::reset_auto_increment(ulonglong value) bool ha_innobase::get_error_message(int error, String *buf) { - trx_t* trx = check_trx_exists(current_thd); + trx_t* trx = check_trx_exists(current_thd); buf->copy(trx->detailed_error, strlen(trx->detailed_error), system_charset_info); @@ -7169,7 +7221,7 @@ ha_innobase::cmp_ref( KEY_PART_INFO* key_part_end; uint len1; uint len2; - int result; + int result; if (prebuilt->clust_index_was_generated) { /* The 'ref' is an InnoDB row id */ @@ -7190,10 +7242,10 @@ ha_innobase::cmp_ref( mysql_type = field->type(); if (mysql_type == FIELD_TYPE_TINY_BLOB - || mysql_type == FIELD_TYPE_MEDIUM_BLOB - || mysql_type == FIELD_TYPE_BLOB - || mysql_type == FIELD_TYPE_LONG_BLOB) { - + || mysql_type == FIELD_TYPE_MEDIUM_BLOB + || mysql_type == FIELD_TYPE_BLOB + || mysql_type == FIELD_TYPE_LONG_BLOB) { + /* In the MySQL key value format, a column prefix of a BLOB is preceded by a 2-byte length field */ @@ -7203,8 +7255,8 @@ ha_innobase::cmp_ref( ref1 += 2; ref2 += 2; result = ((Field_blob*)field)->cmp( - (const char*)ref1, len1, - (const char*)ref2, len2); + (const char*)ref1, len1, + (const char*)ref2, len2); } else { result = field->key_cmp(ref1, ref2); } @@ -7230,10 +7282,10 @@ ha_innobase::get_mysql_bin_log_name() ulonglong ha_innobase::get_mysql_bin_log_pos() { - /* trx... is ib_longlong, which is a typedef for a 64-bit integer + /* trx... is ib_longlong, which is a typedef for a 64-bit integer (__int64 or longlong) so it's ok to cast it to ulonglong. */ - return(trx_sys_mysql_bin_log_pos); + return(trx_sys_mysql_bin_log_pos); } extern "C" { @@ -7255,7 +7307,7 @@ innobase_get_at_most_n_mbchars( ulint prefix_len, /* in: prefix length in bytes of the index (this has to be divided by mbmaxlen to get the number of CHARACTERS n in the prefix) */ - ulint data_len, /* in: length of the string in bytes */ + ulint data_len, /* in: length of the string in bytes */ const char* str) /* in: character string */ { ulint char_length; /* character length in bytes */ @@ -7299,7 +7351,7 @@ innobase_get_at_most_n_mbchars( str + data_len, (int) n_chars); if (char_length > data_len) { char_length = data_len; - } + } } else { if (data_len < prefix_len) { char_length = data_len; @@ -7314,15 +7366,15 @@ innobase_get_at_most_n_mbchars( extern "C" { /********************************************************************** -This function returns true if +This function returns true if 1) SQL-query in the current thread -is either REPLACE or LOAD DATA INFILE REPLACE. +is either REPLACE or LOAD DATA INFILE REPLACE. 2) SQL-query in the current thread is INSERT ON DUPLICATE KEY UPDATE. -NOTE that /mysql/innobase/row/row0ins.c must contain the +NOTE that /mysql/innobase/row/row0ins.c must contain the prototype for this function ! */ ibool @@ -7330,19 +7382,19 @@ innobase_query_is_update(void) /*==========================*/ { THD* thd; - + thd = (THD *)innobase_current_thd(); - + if (thd->lex->sql_command == SQLCOM_REPLACE || - thd->lex->sql_command == SQLCOM_REPLACE_SELECT || - (thd->lex->sql_command == SQLCOM_LOAD && - thd->lex->duplicates == DUP_REPLACE)) { + thd->lex->sql_command == SQLCOM_REPLACE_SELECT || + (thd->lex->sql_command == SQLCOM_LOAD && + thd->lex->duplicates == DUP_REPLACE)) { return(1); } if (thd->lex->sql_command == SQLCOM_INSERT && - thd->lex->duplicates == DUP_UPDATE) { + thd->lex->duplicates == DUP_UPDATE) { return(1); } @@ -7354,7 +7406,7 @@ innobase_query_is_update(void) /*********************************************************************** This function is used to prepare X/Open XA distributed transaction */ -int +int innobase_xa_prepare( /*================*/ /* out: 0 or error number */ @@ -7364,39 +7416,39 @@ innobase_xa_prepare( FALSE - the current SQL statement ended */ { int error = 0; - trx_t* trx = check_trx_exists(thd); + trx_t* trx = check_trx_exists(thd); - if (thd->lex->sql_command != SQLCOM_XA_PREPARE) { + if (thd->lex->sql_command != SQLCOM_XA_PREPARE) { - /* For ibbackup to work the order of transactions in binlog - and InnoDB must be the same. Consider the situation + /* For ibbackup to work the order of transactions in binlog + and InnoDB must be the same. Consider the situation - thread1> prepare; write to binlog; ... - <context switch> - thread2> prepare; write to binlog; commit - thread1> ... commit + thread1> prepare; write to binlog; ... + <context switch> + thread2> prepare; write to binlog; commit + thread1> ... commit - To ensure this will not happen we're taking the mutex on - prepare, and releasing it on commit. + To ensure this will not happen we're taking the mutex on + prepare, and releasing it on commit. - Note: only do it for normal commits, done via ha_commit_trans. - If 2pc protocol is executed by external transaction - coordinator, it will be just a regular MySQL client - executing XA PREPARE and XA COMMIT commands. - In this case we cannot know how many minutes or hours - will be between XA PREPARE and XA COMMIT, and we don't want - to block for undefined period of time. - */ - pthread_mutex_lock(&prepare_commit_mutex); - trx->active_trans = 2; - } + Note: only do it for normal commits, done via ha_commit_trans. + If 2pc protocol is executed by external transaction + coordinator, it will be just a regular MySQL client + executing XA PREPARE and XA COMMIT commands. + In this case we cannot know how many minutes or hours + will be between XA PREPARE and XA COMMIT, and we don't want + to block for undefined period of time. + */ + pthread_mutex_lock(&prepare_commit_mutex); + trx->active_trans = 2; + } if (!thd->variables.innodb_support_xa) { return(0); } - trx->xid=thd->transaction.xid_state.xid; + trx->xid=thd->transaction.xid_state.xid; /* Release a possible FIFO ticket and search latch. Since we will reserve the kernel mutex, we have to release the search system latch @@ -7411,16 +7463,16 @@ innobase_xa_prepare( } if (all - || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { - /* We were instructed to prepare the whole transaction, or - this is an SQL statement end and autocommit is on */ + /* We were instructed to prepare the whole transaction, or + this is an SQL statement end and autocommit is on */ - ut_ad(trx->active_trans); + ut_ad(trx->active_trans); error = (int) trx_prepare_for_mysql(trx); } else { - /* We just mark the SQL statement ended and do not do a + /* We just mark the SQL statement ended and do not do a transaction prepare */ if (trx->auto_inc_lock) { @@ -7441,18 +7493,18 @@ innobase_xa_prepare( srv_active_wake_master_thread(); - return error; + return error; } /*********************************************************************** This function is used to recover X/Open XA distributed transactions */ -int +int innobase_xa_recover( /*================*/ - /* out: number of prepared transactions + /* out: number of prepared transactions stored in xid_list */ - XID* xid_list, /* in/out: prepared transactions */ + XID* xid_list, /* in/out: prepared transactions */ uint len) /* in: number of slots in xid_list */ { if (len == 0 || xid_list == NULL) { @@ -7467,7 +7519,7 @@ innobase_xa_recover( This function is used to commit one X/Open XA distributed transaction which is in the prepared state */ -int +int innobase_commit_by_xid( /*===================*/ /* out: 0 or error number */ @@ -7479,7 +7531,7 @@ innobase_commit_by_xid( if (trx) { innobase_commit_low(trx); - + return(XA_OK); } else { return(XAER_NOTA); @@ -7490,7 +7542,7 @@ innobase_commit_by_xid( This function is used to rollback one X/Open XA distributed transaction which is in the prepared state */ -int +int innobase_rollback_by_xid( /*=====================*/ /* out: 0 or error number */ @@ -7510,7 +7562,7 @@ innobase_rollback_by_xid( /*********************************************************************** Create a consistent view for a cursor based on current transaction which is created if the corresponding MySQL thread still lacks one. -This consistent view is then used inside of MySQL when accessing records +This consistent view is then used inside of MySQL when accessing records using a cursor. */ void* @@ -7524,7 +7576,7 @@ innobase_create_cursor_view(void) /*********************************************************************** Close the given consistent cursor view of a transaction and restore -global read view to a transaction read view. Transaction is created if the +global read view to a transaction read view. Transaction is created if the corresponding MySQL thread still lacks one. */ void @@ -7537,8 +7589,8 @@ innobase_close_cursor_view( } /*********************************************************************** -Set the given consistent cursor view to a transaction which is created -if the corresponding MySQL thread still lacks one. If the given +Set the given consistent cursor view to a transaction which is created +if the corresponding MySQL thread still lacks one. If the given consistent cursor view is NULL global read view of a transaction is restored to a transaction read view. */ @@ -7547,27 +7599,33 @@ innobase_set_cursor_view( /*=====================*/ void* curview)/* in: Consistent cursor view to be set */ { - read_cursor_set_for_mysql(check_trx_exists(current_thd), + read_cursor_set_for_mysql(check_trx_exists(current_thd), (cursor_view_t*) curview); } -bool ha_innobase::check_if_incompatible_data(HA_CREATE_INFO *info, - uint table_changes) +bool ha_innobase::check_if_incompatible_data( + HA_CREATE_INFO* info, + uint table_changes) { - if (table_changes != IS_EQUAL_YES) - return COMPATIBLE_DATA_NO; - - /* Check that auto_increment value was not changed */ - if ((info->used_fields & HA_CREATE_USED_AUTO) && - info->auto_increment_value != 0) - return COMPATIBLE_DATA_NO; - - /* Check that row format didn't change */ - if ((info->used_fields & HA_CREATE_USED_AUTO) && - get_row_type() != info->row_type) - return COMPATIBLE_DATA_NO; + if (table_changes != IS_EQUAL_YES) { - return COMPATIBLE_DATA_YES; -} + return COMPATIBLE_DATA_NO; + } + + /* Check that auto_increment value was not changed */ + if ((info->used_fields & HA_CREATE_USED_AUTO) && + info->auto_increment_value != 0) { + return COMPATIBLE_DATA_NO; + } + + /* Check that row format didn't change */ + if ((info->used_fields & HA_CREATE_USED_AUTO) && + get_row_type() != info->row_type) { + + return COMPATIBLE_DATA_NO; + } + + return COMPATIBLE_DATA_YES; +} diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index b9e399509de..6bbe3a562d7 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -7,12 +7,12 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This file is based on ha_berkeley.h of MySQL distribution @@ -34,8 +34,8 @@ typedef struct st_innobase_share { my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name, - uint full_name_len, - ulonglong *unused); + uint full_name_len, + ulonglong *unused); /* The class defining a handle to an Innodb table */ class ha_innobase: public handler @@ -47,22 +47,20 @@ class ha_innobase: public handler THD* user_thd; /* the thread handle of the user currently using the handle; this is set in external_lock function */ - query_id_t last_query_id; /* the latest query id where the + query_id_t last_query_id; /* the latest query id where the handle was used */ - THR_LOCK_DATA lock; - INNOBASE_SHARE *share; - - gptr alloc_ptr; - byte* upd_buff; /* buffer used in updates */ - byte* key_val_buff; /* buffer used in converting - search key values from MySQL format - to Innodb format */ + THR_LOCK_DATA lock; + INNOBASE_SHARE *share; + + byte* upd_buff; /* buffer used in updates */ + byte* key_val_buff; /* buffer used in converting + search key values from MySQL format + to Innodb format */ ulong upd_and_key_val_buff_len; /* the length of each of the previous two buffers */ - ulong int_table_flags; - uint primary_key; - uint last_dup_key; + ulong int_table_flags; + uint primary_key; ulong start_of_scan; /* this is set to 1 when we are starting a table scan but have not yet fetched any row, else 0 */ @@ -70,10 +68,9 @@ class ha_innobase: public handler ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX, or undefined */ uint num_write_row; /* number of write_row() calls */ - ulong max_supported_row_length(const byte *buf); uint store_key_val_for_row(uint keynr, char* buff, uint buff_len, - const byte* record); + const byte* record); int update_thd(THD* thd); int change_active_index(uint keynr); int general_fetch(byte* buf, uint direction, uint match_mode); @@ -81,27 +78,27 @@ class ha_innobase: public handler /* Init values for the class: */ public: - ha_innobase(TABLE_SHARE *table_arg); - ~ha_innobase() {} + ha_innobase(TABLE_SHARE *table_arg); + ~ha_innobase() {} /* Get the row type from the storage engine. If this method returns ROW_TYPE_NOT_USED, the information in HA_CREATE_INFO should be used. */ enum row_type get_row_type() const; - const char* table_type() const { return("InnoDB");} + const char* table_type() const { return("InnoDB");} const char *index_type(uint key_number) { return "BTREE"; } - const char** bas_ext() const; - ulong table_flags() const { return int_table_flags; } + const char** bas_ext() const; + ulong table_flags() const { return int_table_flags; } ulong index_flags(uint idx, uint part, bool all_parts) const { return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE | - HA_KEYREAD_ONLY); + HA_KEYREAD_ONLY); } - uint max_supported_keys() const { return MAX_KEY; } + uint max_supported_keys() const { return MAX_KEY; } /* An InnoDB page must store >= 2 keys; a secondary key record must also contain the primary key value: @@ -109,116 +106,113 @@ class ha_innobase: public handler less than 1 / 4 of page size which is 16 kB; but currently MySQL does not work with keys whose size is > MAX_KEY_LENGTH */ - uint max_supported_key_length() const { return 3500; } - uint max_supported_key_part_length() const; + uint max_supported_key_length() const { return 3500; } + uint max_supported_key_part_length() const; const key_map *keys_to_use_for_scanning() { return &key_map_full; } - bool has_transactions() { return 1;} + bool has_transactions() { return 1;} - int open(const char *name, int mode, uint test_if_locked); - int close(void); - double scan_time(); + int open(const char *name, int mode, uint test_if_locked); + int close(void); + double scan_time(); double read_time(uint index, uint ranges, ha_rows rows); - int write_row(byte * buf); - int update_row(const byte * old_data, byte * new_data); - int delete_row(const byte * buf); + int write_row(byte * buf); + int update_row(const byte * old_data, byte * new_data); + int delete_row(const byte * buf); bool was_semi_consistent_read(); void try_semi_consistent_read(bool yes); void unlock_row(); - int index_init(uint index, bool sorted); - int index_end(); - int index_read(byte * buf, const byte * key, - uint key_len, enum ha_rkey_function find_flag); - int index_read_idx(byte * buf, uint index, const byte * key, + int index_init(uint index, bool sorted); + int index_end(); + int index_read(byte * buf, const byte * key, + uint key_len, enum ha_rkey_function find_flag); + int index_read_idx(byte * buf, uint index, const byte * key, uint key_len, enum ha_rkey_function find_flag); int index_read_last(byte * buf, const byte * key, uint key_len); - int index_next(byte * buf); - int index_next_same(byte * buf, const byte *key, uint keylen); - int index_prev(byte * buf); - int index_first(byte * buf); - int index_last(byte * buf); - - int rnd_init(bool scan); - int rnd_end(); - int rnd_next(byte *buf); - int rnd_pos(byte * buf, byte *pos); - - void position(const byte *record); - void info(uint); - int analyze(THD* thd,HA_CHECK_OPT* check_opt); - int optimize(THD* thd,HA_CHECK_OPT* check_opt); + int index_next(byte * buf); + int index_next_same(byte * buf, const byte *key, uint keylen); + int index_prev(byte * buf); + int index_first(byte * buf); + int index_last(byte * buf); + + int rnd_init(bool scan); + int rnd_end(); + int rnd_next(byte *buf); + int rnd_pos(byte * buf, byte *pos); + + void position(const byte *record); + void info(uint); + int analyze(THD* thd,HA_CHECK_OPT* check_opt); + int optimize(THD* thd,HA_CHECK_OPT* check_opt); int discard_or_import_tablespace(my_bool discard); - int extra(enum ha_extra_function operation); - int external_lock(THD *thd, int lock_type); + int extra(enum ha_extra_function operation); + int external_lock(THD *thd, int lock_type); int transactional_table_lock(THD *thd, int lock_type); - int start_stmt(THD *thd, thr_lock_type lock_type); - - int ha_retrieve_all_cols() - { - ha_set_all_bits_in_read_set(); - return extra(HA_EXTRA_RETRIEVE_ALL_COLS); - } - int ha_retrieve_all_pk() - { - ha_set_primary_key_in_read_set(); - return extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY); - } - void position(byte *record); - ha_rows records_in_range(uint inx, key_range *min_key, key_range + int start_stmt(THD *thd, thr_lock_type lock_type); + + int ha_retrieve_all_cols() + { + ha_set_all_bits_in_read_set(); + return extra(HA_EXTRA_RETRIEVE_ALL_COLS); + } + int ha_retrieve_all_pk() + { + ha_set_primary_key_in_read_set(); + return extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY); + } + void position(byte *record); + ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key); ha_rows estimate_rows_upper_bound(); - int create(const char *name, register TABLE *form, + int create(const char *name, register TABLE *form, HA_CREATE_INFO *create_info); int delete_all_rows(); - int delete_table(const char *name); + int delete_table(const char *name); int rename_table(const char* from, const char* to); int check(THD* thd, HA_CHECK_OPT* check_opt); - char* update_table_comment(const char* comment); + char* update_table_comment(const char* comment); char* get_foreign_key_create_info(); - int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list); + int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list); bool can_switch_engines(); - uint referenced_by_foreign_key(); - void free_foreign_key_create_info(char* str); - THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, - enum thr_lock_type lock_type); - void init_table_handle_for_HANDLER(); + uint referenced_by_foreign_key(); + void free_foreign_key_create_info(char* str); + THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, + enum thr_lock_type lock_type); + void init_table_handle_for_HANDLER(); ulonglong get_auto_increment(); int reset_auto_increment(ulonglong value); virtual bool get_error_message(int error, String *buf); - - uint8 table_cache_type() { return HA_CACHE_TBL_ASKTRANSACT; } - /* - ask handler about permission to cache table during query registration - */ - my_bool register_query_cache_table(THD *thd, char *table_key, + + uint8 table_cache_type() { return HA_CACHE_TBL_ASKTRANSACT; } + /* + ask handler about permission to cache table during query registration + */ + my_bool register_query_cache_table(THD *thd, char *table_key, uint key_length, qc_engine_callback *call_back, ulonglong *engine_data) - { - *call_back= innobase_query_caching_of_table_permitted; - *engine_data= 0; - return innobase_query_caching_of_table_permitted(thd, table_key, - key_length, - engine_data); - } - static char *get_mysql_bin_log_name(); - static ulonglong get_mysql_bin_log_pos(); - bool primary_key_is_clustered() { return true; } - int cmp_ref(const byte *ref1, const byte *ref2); + { + *call_back= innobase_query_caching_of_table_permitted; + *engine_data= 0; + return innobase_query_caching_of_table_permitted(thd, table_key, + key_length, + engine_data); + } + static char *get_mysql_bin_log_name(); + static ulonglong get_mysql_bin_log_pos(); + bool primary_key_is_clustered() { return true; } + int cmp_ref(const byte *ref1, const byte *ref2); bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); }; extern SHOW_VAR innodb_status_variables[]; -extern uint innobase_init_flags, innobase_lock_type; extern uint innobase_flush_log_at_trx_commit; -extern ulong innobase_cache_size, innobase_fast_shutdown; +extern ulong innobase_fast_shutdown; extern ulong innobase_large_page_size; -extern char *innobase_home, *innobase_tmpdir, *innobase_logdir; -extern long innobase_lock_scan_time; extern long innobase_mirrored_log_groups, innobase_log_files_in_group; extern longlong innobase_buffer_pool_size, innobase_log_file_size; extern long innobase_log_buffer_size; @@ -232,17 +226,18 @@ extern char *innobase_log_group_home_dir, *innobase_log_arch_dir; extern char *innobase_unix_file_flush_method; /* The following variables have to be my_bool for SHOW VARIABLES to work */ extern my_bool innobase_log_archive, - innobase_use_doublewrite, - innobase_use_checksums, - innobase_use_large_pages, - innobase_use_native_aio, - innobase_file_per_table, innobase_locks_unsafe_for_binlog, - innobase_create_status_file; -extern my_bool innobase_very_fast_shutdown; /* set this to 1 just before - calling innobase_end() if you want - InnoDB to shut down without - flushing the buffer pool: this - is equivalent to a 'crash' */ + innobase_use_doublewrite, + innobase_use_checksums, + innobase_use_large_pages, + innobase_use_native_aio, + innobase_file_per_table, innobase_locks_unsafe_for_binlog, + innobase_create_status_file; +extern my_bool innobase_very_fast_shutdown; /* set this to 1 just before + calling innobase_end() if + you want InnoDB to shut down + without flushing the buffer + pool: this is equivalent to + a 'crash' */ extern "C" { extern ulong srv_max_buf_pool_modified_pct; extern ulong srv_max_purge_lag; @@ -254,8 +249,6 @@ extern ulong srv_thread_concurrency; extern ulong srv_commit_concurrency; } -extern TYPELIB innobase_lock_typelib; - bool innobase_init(void); int innobase_end(ha_panic_function type); bool innobase_flush_logs(void); @@ -267,10 +260,10 @@ uint innobase_get_free_space(void); */ #if 0 int innobase_report_binlog_offset_and_commit( - THD* thd, + THD* thd, void* trx_handle, - char* log_file_name, - my_off_t end_offset); + char* log_file_name, + my_off_t end_offset); int innobase_commit_complete(void* trx_handle); void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset); #endif @@ -300,9 +293,9 @@ This function is used to recover X/Open XA distributed transactions */ int innobase_xa_recover( /*====================*/ - /* out: number of prepared transactions + /* out: number of prepared transactions stored in xid_list */ - XID* xid_list, /* in/out: prepared transactions */ + XID* xid_list, /* in/out: prepared transactions */ uint len); /* in: number of slots in xid_list */ /*********************************************************************** @@ -323,16 +316,13 @@ int innobase_rollback_by_xid( XID *xid); /* in : X/Open XA Transaction Identification */ -int innobase_xa_end(THD *thd); - - int innobase_repl_report_sent_binlog(THD *thd, char *log_file_name, - my_off_t end_offset); + my_off_t end_offset); /*********************************************************************** Create a consistent view for a cursor based on current transaction which is created if the corresponding MySQL thread still lacks one. -This consistent view is then used inside of MySQL when accessing records +This consistent view is then used inside of MySQL when accessing records using a cursor. */ void* @@ -342,7 +332,7 @@ innobase_create_cursor_view(void); /*********************************************************************** Close the given consistent cursor view of a transaction and restore -global read view to a transaction read view. Transaction is created if the +global read view to a transaction read view. Transaction is created if the corresponding MySQL thread still lacks one. */ void @@ -351,8 +341,8 @@ innobase_close_cursor_view( void* curview); /* in: Consistent read view to be closed */ /*********************************************************************** -Set the given consistent cursor view to a transaction which is created -if the corresponding MySQL thread still lacks one. If the given +Set the given consistent cursor view to a transaction which is created +if the corresponding MySQL thread still lacks one. If the given consistent cursor view is NULL global read view of a transaction is restored to a transaction read view. */ diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index c27fb73ff8d..4ece0e36b19 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/storage/innobase/btr/btr0btr.c @@ -5,7 +5,7 @@ The B-tree Created 6/2/1994 Heikki Tuuri *******************************************************/ - + #include "btr0btr.h" #ifdef UNIV_NONINL @@ -56,7 +56,7 @@ field. To the child page we can store node pointers or index records which are >= P in the alphabetical order, but < P1 if there is a next node pointer on the level, and P1 is its prefix. -If a node pointer with a prefix P points to a non-leaf child, +If a node pointer with a prefix P points to a non-leaf child, then the leftmost record in the child must have the same prefix P. If it points to a leaf node, the child is not required to contain any record with a prefix equal to P. The leaf case @@ -138,14 +138,14 @@ btr_root_get( ulint space; ulint root_page_no; page_t* root; - + space = dict_tree_get_space(tree); root_page_no = dict_tree_get_page(tree); root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr); ut_a((ibool)!!page_is_comp(root) == - UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp); - + dict_table_is_comp(UT_LIST_GET_FIRST(tree->tree_indexes)->table)); + return(root); } @@ -175,20 +175,20 @@ btr_get_prev_user_rec( return(prev_rec); } } - + page = buf_frame_align(rec); prev_page_no = btr_page_get_prev(page, mtr); space = buf_frame_get_space_id(page); - + if (prev_page_no != FIL_NULL) { prev_page = buf_page_get_with_no_latch(space, prev_page_no, mtr); /* The caller must already have a latch to the brother */ ut_ad((mtr_memo_contains(mtr, buf_block_align(prev_page), - MTR_MEMO_PAGE_S_FIX)) - || (mtr_memo_contains(mtr, buf_block_align(prev_page), - MTR_MEMO_PAGE_X_FIX))); + MTR_MEMO_PAGE_S_FIX)) + || (mtr_memo_contains(mtr, buf_block_align(prev_page), + MTR_MEMO_PAGE_X_FIX))); ut_a(page_is_comp(prev_page) == page_is_comp(page)); return(page_rec_get_prev(page_get_supremum_rec(prev_page))); @@ -223,20 +223,20 @@ btr_get_next_user_rec( return(next_rec); } } - + page = buf_frame_align(rec); next_page_no = btr_page_get_next(page, mtr); space = buf_frame_get_space_id(page); - + if (next_page_no != FIL_NULL) { next_page = buf_page_get_with_no_latch(space, next_page_no, mtr); /* The caller must already have a latch to the brother */ ut_ad((mtr_memo_contains(mtr, buf_block_align(next_page), - MTR_MEMO_PAGE_S_FIX)) - || (mtr_memo_contains(mtr, buf_block_align(next_page), - MTR_MEMO_PAGE_X_FIX))); + MTR_MEMO_PAGE_S_FIX)) + || (mtr_memo_contains(mtr, buf_block_align(next_page), + MTR_MEMO_PAGE_X_FIX))); ut_a(page_is_comp(next_page) == page_is_comp(page)); return(page_rec_get_next(page_get_infimum_rec(next_page))); @@ -257,11 +257,11 @@ btr_page_create( mtr_t* mtr) /* in: mtr */ { ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); page_create(page, mtr, - UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp); + dict_table_is_comp(UT_LIST_GET_FIRST(tree->tree_indexes)->table)); buf_block_align(page)->check_index_page_at_flush = TRUE; - + btr_page_set_index_id(page, tree->id, mtr); } @@ -281,7 +281,7 @@ btr_page_alloc_for_ibuf( page_t* new_page; root = btr_root_get(tree, mtr); - + node_addr = flst_get_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr); ut_a(node_addr.page != FIL_NULL); @@ -293,7 +293,7 @@ btr_page_alloc_for_ibuf( #endif /* UNIV_SYNC_DEBUG */ flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, - new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, + new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr)); @@ -328,7 +328,7 @@ btr_page_alloc( } root = btr_root_get(tree, mtr); - + if (level == 0) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; } else { @@ -338,7 +338,7 @@ btr_page_alloc( /* Parameter TRUE below states that the caller has made the reservation for free extents, and thus we know that a page can be allocated: */ - + new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no, file_direction, TRUE, mtr); if (new_page_no == FIL_NULL) { @@ -351,9 +351,9 @@ btr_page_alloc( #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(new_page, SYNC_TREE_NODE_NEW); #endif /* UNIV_SYNC_DEBUG */ - + return(new_page); -} +} /****************************************************************** Gets the number of pages in a B-tree. */ @@ -376,20 +376,20 @@ btr_get_size( mtr_s_lock(dict_tree_get_lock(index->tree), &mtr); root = btr_root_get(index->tree, &mtr); - + if (flag == BTR_N_LEAF_PAGES) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; - + fseg_n_reserved_pages(seg_header, &n, &mtr); - + } else if (flag == BTR_TOTAL_SIZE) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP; n = fseg_n_reserved_pages(seg_header, &dummy, &mtr); - + seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; - - n += fseg_n_reserved_pages(seg_header, &dummy, &mtr); + + n += fseg_n_reserved_pages(seg_header, &dummy, &mtr); } else { ut_error; } @@ -397,7 +397,7 @@ btr_get_size( mtr_commit(&mtr); return(n); -} +} /****************************************************************** Frees a page used in an ibuf tree. Puts the page to the free list of the @@ -407,17 +407,17 @@ void btr_page_free_for_ibuf( /*===================*/ dict_tree_t* tree, /* in: index tree */ - page_t* page, /* in: page to be freed, x-latched */ + page_t* page, /* in: page to be freed, x-latched */ mtr_t* mtr) /* in: mtr */ { page_t* root; ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); root = btr_root_get(tree, mtr); - + flst_add_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, - page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); + page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr)); @@ -432,7 +432,7 @@ void btr_page_free_low( /*==============*/ dict_tree_t* tree, /* in: index tree */ - page_t* page, /* in: page to be freed, x-latched */ + page_t* page, /* in: page to be freed, x-latched */ ulint level, /* in: page level */ mtr_t* mtr) /* in: mtr */ { @@ -442,12 +442,12 @@ btr_page_free_low( ulint page_no; ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); /* The page gets invalid for optimistic searches: increment the frame modify clock */ buf_frame_modify_clock_inc(page); - + if (tree->type & DICT_IBUF) { btr_page_free_for_ibuf(tree, page, mtr); @@ -456,7 +456,7 @@ btr_page_free_low( } root = btr_root_get(tree, mtr); - + if (level == 0) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; } else { @@ -465,9 +465,9 @@ btr_page_free_low( space = buf_frame_get_space_id(page); page_no = buf_frame_get_page_no(page); - + fseg_free_page(seg_header, space, page_no, mtr); -} +} /****************************************************************** Frees a file page used in an index tree. NOTE: cannot free field external @@ -477,17 +477,17 @@ void btr_page_free( /*==========*/ dict_tree_t* tree, /* in: index tree */ - page_t* page, /* in: page to be freed, x-latched */ + page_t* page, /* in: page to be freed, x-latched */ mtr_t* mtr) /* in: mtr */ { ulint level; ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); level = btr_page_get_level(page, mtr); - + btr_page_free_low(tree, page, level, mtr); -} +} /****************************************************************** Sets the child node file address in a node pointer. */ @@ -507,12 +507,12 @@ btr_node_ptr_set_child_page_no( ut_ad(0 < btr_page_get_level(buf_frame_align(rec), mtr)); ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec)); - /* The child address is in the last field */ + /* The child address is in the last field */ field = rec_get_nth_field(rec, offsets, rec_offs_n_fields(offsets) - 1, &len); ut_ad(len == 4); - + mlog_write_ulint(field, page_no, MLOG_4BYTES, mtr); } @@ -536,7 +536,7 @@ btr_node_ptr_get_child( page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); page = btr_page_get(space, page_no, RW_X_LATCH, mtr); - + return(page); } @@ -567,7 +567,7 @@ btr_page_get_father_for_rec( ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); ut_a(page_rec_is_user_rec(user_rec)); - + ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page)); heap = mem_heap_create(100); @@ -589,7 +589,7 @@ btr_page_get_father_for_rec( ULINT_UNDEFINED, &heap); if (btr_node_ptr_get_child_page_no(node_ptr, offsets) != - buf_frame_get_page_no(page)) { + buf_frame_get_page_no(page)) { rec_t* print_rec; fputs("InnoDB: Dump of the child page:\n", stderr); buf_page_print(buf_frame_align(page)); @@ -677,13 +677,13 @@ btr_create( buf_page_dbg_add_level(ibuf_hdr_frame, SYNC_TREE_NODE_NEW); #endif /* UNIV_SYNC_DEBUG */ ut_ad(buf_frame_get_page_no(ibuf_hdr_frame) - == IBUF_HEADER_PAGE_NO); + == IBUF_HEADER_PAGE_NO); /* Allocate then the next page to the segment: it will be the - tree root page */ + tree root page */ - page_no = fseg_alloc_free_page( + page_no = fseg_alloc_free_page( ibuf_hdr_frame + IBUF_HEADER - + IBUF_TREE_SEG_HEADER, IBUF_TREE_ROOT_PAGE_NO, + + IBUF_TREE_SEG_HEADER, IBUF_TREE_ROOT_PAGE_NO, FSP_UP, mtr); ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO); @@ -692,14 +692,14 @@ btr_create( frame = fseg_create(space, 0, PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr); } - + if (frame == NULL) { return(FIL_NULL); } page_no = buf_frame_get_page_no(frame); - + #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW); #endif /* UNIV_SYNC_DEBUG */ @@ -708,9 +708,9 @@ btr_create( /* It is an insert buffer tree: initialize the free list */ ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO); - + flst_init(frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr); - } else { + } else { /* It is a non-ibuf tree: create a file segment for leaf pages */ fseg_create(space, page_no, PAGE_HEADER + PAGE_BTR_SEG_LEAF, @@ -721,7 +721,7 @@ btr_create( buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW); #endif /* UNIV_SYNC_DEBUG */ } - + /* Create a new index page on the the allocated segment page */ page = page_create(frame, mtr, comp); buf_block_align(page)->check_index_page_at_flush = TRUE; @@ -731,7 +731,7 @@ btr_create( /* Set the level of the new index page */ btr_page_set_level(page, 0, mtr); - + /* Set the next node and previous node fields */ btr_page_set_next(page, FIL_NULL, mtr); btr_page_set_prev(page, FIL_NULL, mtr); @@ -739,7 +739,7 @@ btr_create( /* We reset the free bits for the page to allow creation of several trees in the same mtr, otherwise the latch on a bitmap page would prevent it because of the latching order */ - + ibuf_reset_free_bits_with_type(type, page); /* In the following assertion we test that two records of maximum @@ -765,10 +765,10 @@ btr_free_but_not_root( page_t* root; mtr_t mtr; -leaf_loop: +leaf_loop: mtr_start(&mtr); - - root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr); + + root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr); /* NOTE: page hash indexes are dropped when a page is freed inside fsp0fsp. */ @@ -783,8 +783,8 @@ leaf_loop: } top_loop: mtr_start(&mtr); - - root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr); + + root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr); finished = fseg_free_step_not_header( root + PAGE_HEADER + PAGE_BTR_SEG_TOP, &mtr); @@ -793,7 +793,7 @@ top_loop: if (!finished) { goto top_loop; - } + } } /**************************************************************** @@ -812,14 +812,14 @@ btr_free_root( root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr); - btr_search_drop_page_hash_index(root); -top_loop: + btr_search_drop_page_hash_index(root); +top_loop: finished = fseg_free_step( root + PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr); if (!finished) { goto top_loop; - } + } } /***************************************************************** @@ -845,8 +845,8 @@ btr_page_reorganize_low( ulint max_ins_size2; ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); - ut_ad(!!page_is_comp(page) == index->table->comp); + MTR_MEMO_PAGE_X_FIX)); + ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); data_size1 = page_get_data_size(page); max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1); @@ -872,7 +872,7 @@ btr_page_reorganize_low( page_create(page, mtr, page_is_comp(page)); buf_block_align(page)->check_index_page_at_flush = TRUE; - + /* Copy the records from the temporary space to the recreated page; do not copy the lock bits yet */ @@ -880,7 +880,7 @@ btr_page_reorganize_low( page_get_infimum_rec(new_page), index, mtr); /* Copy max trx id to recreated page */ page_set_max_trx_id(page, page_get_max_trx_id(new_page)); - + if (!recovery) { /* Update the record lock bitmaps */ lock_move_reorganize_page(page, new_page); @@ -892,7 +892,7 @@ btr_page_reorganize_low( if (data_size1 != data_size2 || max_ins_size1 != max_ins_size2) { buf_page_print(page); buf_page_print(new_page); - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: page old data size %lu new data size %lu\n" "InnoDB: Error: page old max ins size %lu new max ins size %lu\n" "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", @@ -955,7 +955,7 @@ btr_page_empty( mtr_t* mtr) /* in: mtr */ { ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); btr_search_drop_page_hash_index(page); /* Recreate the page: note that global data on page (possible @@ -990,10 +990,10 @@ btr_root_raise_and_insert( rec_t* rec; mem_heap_t* heap; dtuple_t* node_ptr; - ulint level; + ulint level; rec_t* node_ptr_rec; page_cur_t* page_cursor; - + root = btr_cur_get_page(cursor); tree = btr_cur_get_tree(cursor); @@ -1001,24 +1001,24 @@ btr_root_raise_and_insert( ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); ut_ad(mtr_memo_contains(mtr, buf_block_align(root), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); btr_search_drop_page_hash_index(root); /* Allocate a new page to the tree. Root splitting is done by first moving the root records to the new page, emptying the root, putting a node pointer to the new page, and then splitting the new page. */ - + new_page = btr_page_alloc(tree, 0, FSP_NO_DIR, btr_page_get_level(root, mtr), mtr); btr_page_create(new_page, tree, mtr); level = btr_page_get_level(root, mtr); - + /* Set the levels of the new index page and root page */ btr_page_set_level(new_page, level, mtr); btr_page_set_level(root, level + 1, mtr); - + /* Set the next node and previous node fields of new page */ btr_page_set_next(new_page, FIL_NULL, mtr); btr_page_set_prev(new_page, FIL_NULL, mtr); @@ -1031,7 +1031,7 @@ btr_root_raise_and_insert( perform a pessimistic update then we have stored the lock information of the record to be inserted on the infimum of the root page: we cannot discard the lock structs on the root page */ - + lock_update_root_raise(new_page, root); /* Create a memory heap where the node pointer is stored */ @@ -1039,17 +1039,17 @@ btr_root_raise_and_insert( rec = page_rec_get_next(page_get_infimum_rec(new_page)); new_page_no = buf_frame_get_page_no(new_page); - + /* Build the node pointer (= node key and page address) for the child */ node_ptr = dict_tree_build_node_ptr(tree, rec, new_page_no, heap, - level); + level); /* Reorganize the root to get free space */ btr_page_reorganize(root, cursor->index, mtr); page_cursor = btr_cur_get_page_cur(cursor); - + /* Insert node pointer to the root */ page_cur_set_before_first(root, page_cursor); @@ -1064,7 +1064,7 @@ btr_root_raise_and_insert( node of a level: */ btr_set_min_rec_mark(node_ptr_rec, page_is_comp(root), mtr); - + /* Free the memory heap */ mem_heap_free(heap); @@ -1078,10 +1078,10 @@ btr_root_raise_and_insert( /* Reposition the cursor to the child node */ page_cur_search(new_page, cursor->index, tuple, PAGE_CUR_LE, page_cursor); - + /* Split the child and insert tuple */ return(btr_page_split_and_insert(cursor, tuple, mtr)); -} +} /***************************************************************** Decides if the page should be split at the convergence point of inserts @@ -1105,22 +1105,22 @@ btr_page_get_split_rec_to_left( insert_point = btr_cur_get_rec(cursor); if (page_header_get_ptr(page, PAGE_LAST_INSERT) - == page_rec_get_next(insert_point)) { + == page_rec_get_next(insert_point)) { + + infimum = page_get_infimum_rec(page); - infimum = page_get_infimum_rec(page); - /* If the convergence is in the middle of a page, include also the record immediately before the new insert to the upper page. Otherwise, we could repeatedly move from page to page lots of records smaller than the convergence point. */ if (infimum != insert_point - && page_rec_get_next(infimum) != insert_point) { + && page_rec_get_next(infimum) != insert_point) { *split_rec = insert_point; } else { - *split_rec = page_rec_get_next(insert_point); - } + *split_rec = page_rec_get_next(insert_point); + } return(TRUE); } @@ -1162,7 +1162,7 @@ btr_page_get_split_rec_to_right( if (page_rec_is_supremum(next_rec)) { split_at_new: /* Split at the new record to insert */ - *split_rec = NULL; + *split_rec = NULL; } else { rec_t* next_next_rec = page_rec_get_next(next_rec); if (page_rec_is_supremum(next_next_rec)) { @@ -1176,7 +1176,7 @@ split_at_new: index, as they can do the necessary checks of the right search position just by looking at the records on this page. */ - + *split_rec = next_next_rec; } @@ -1199,7 +1199,7 @@ btr_page_get_sure_split_rec( upper half-page */ btr_cur_t* cursor, /* in: cursor at which insert should be made */ - dtuple_t* tuple) /* in: tuple to insert */ + dtuple_t* tuple) /* in: tuple to insert */ { page_t* page; ulint insert_size; @@ -1216,7 +1216,7 @@ btr_page_get_sure_split_rec( ulint* offsets; page = btr_cur_get_page(cursor); - + insert_size = rec_get_converted_size(cursor->index, tuple); free_space = page_get_free_space_of_empty(page_is_comp(page)); @@ -1263,15 +1263,15 @@ btr_page_get_sure_split_rec( } n++; - + if (incl_data + page_dir_calc_reserved_space(n) - >= total_space / 2) { + >= total_space / 2) { - if (incl_data + page_dir_calc_reserved_space(n) - <= free_space) { - /* The next record will be the first on - the right half page if it is not the - supremum record of page */ + if (incl_data + page_dir_calc_reserved_space(n) + <= free_space) { + /* The next record will be the first on + the right half page if it is not the + supremum record of page */ if (rec == ins_rec) { rec = NULL; @@ -1286,7 +1286,7 @@ btr_page_get_sure_split_rec( if (!page_rec_is_supremum(next_rec)) { rec = next_rec; } - } + } func_exit: if (UNIV_LIKELY_NULL(heap)) { @@ -1295,7 +1295,7 @@ func_exit: return(rec); } } -} +} /***************************************************************** Returns TRUE if the insert fits on the appropriate half-page with the @@ -1323,7 +1323,7 @@ btr_page_insert_fits( rec_t* rec; rec_t* end_rec; ulint* offs; - + page = btr_cur_get_page(cursor); ut_ad(!split_rec == !offsets); @@ -1339,11 +1339,11 @@ btr_page_insert_fits( total_data = page_get_data_size(page) + insert_size; total_n_recs = page_get_n_recs(page) + 1; - + /* We determine which records (from rec to end_rec, not including end_rec) will end up on the other half page from tuple when it is inserted. */ - + if (split_rec == NULL) { rec = page_rec_get_next(page_get_infimum_rec(page)); end_rec = page_rec_get_next(btr_cur_get_rec(cursor)); @@ -1351,14 +1351,14 @@ btr_page_insert_fits( } else if (cmp_dtuple_rec(tuple, split_rec, offsets) >= 0) { rec = page_rec_get_next(page_get_infimum_rec(page)); - end_rec = split_rec; + end_rec = split_rec; } else { rec = split_rec; end_rec = page_get_supremum_rec(page); } if (total_data + page_dir_calc_reserved_space(total_n_recs) - <= free_space) { + <= free_space) { /* Ok, there will be enough available space on the half page where the tuple is inserted */ @@ -1379,7 +1379,7 @@ btr_page_insert_fits( total_n_recs--; if (total_data + page_dir_calc_reserved_space(total_n_recs) - <= free_space) { + <= free_space) { /* Ok, there will be enough available space on the half page where the tuple is inserted */ @@ -1391,7 +1391,7 @@ btr_page_insert_fits( } return(FALSE); -} +} /*********************************************************** Inserts a data tuple to a tree on a non-leaf level. It is assumed @@ -1406,25 +1406,22 @@ btr_insert_on_non_leaf_level( mtr_t* mtr) /* in: mtr */ { big_rec_t* dummy_big_rec; - btr_cur_t cursor; + btr_cur_t cursor; ulint err; rec_t* rec; ut_ad(level > 0); - + /* In the following, choose just any index from the tree as the first parameter for btr_cur_search_to_nth_level. */ btr_cur_search_to_nth_level(UT_LIST_GET_FIRST(tree->tree_indexes), - level, tuple, PAGE_CUR_LE, - BTR_CONT_MODIFY_TREE, - &cursor, 0, mtr); + level, tuple, PAGE_CUR_LE, BTR_CONT_MODIFY_TREE, + &cursor, 0, mtr); err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG - | BTR_KEEP_SYS_FLAG - | BTR_NO_UNDO_LOG_FLAG, - &cursor, tuple, - &rec, &dummy_big_rec, NULL, mtr); + | BTR_KEEP_SYS_FLAG | BTR_NO_UNDO_LOG_FLAG, + &cursor, tuple, &rec, &dummy_big_rec, NULL, mtr); ut_a(err == DB_SUCCESS); } @@ -1455,12 +1452,12 @@ btr_attach_half_pages( ulint lower_page_no; ulint upper_page_no; dtuple_t* node_ptr_upper; - mem_heap_t* heap; + mem_heap_t* heap; ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains(mtr, buf_block_align(new_page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); ut_a(page_is_comp(page) == page_is_comp(new_page)); /* Create a memory heap where the data tuple is stored */ @@ -1477,7 +1474,7 @@ btr_attach_half_pages( /* Look from the tree for the node pointer to page */ node_ptr = btr_page_get_father_node_ptr(tree, page, mtr); - /* Replace the address of the old child node (= page) with the + /* Replace the address of the old child node (= page) with the address of the new lower half */ btr_node_ptr_set_child_page_no(node_ptr, @@ -1492,7 +1489,7 @@ btr_attach_half_pages( lower_page = page; upper_page = new_page; } - + /* Get the level of the split pages */ level = btr_page_get_level(page, mtr); @@ -1500,13 +1497,13 @@ btr_attach_half_pages( half */ node_ptr_upper = dict_tree_build_node_ptr(tree, split_rec, - upper_page_no, heap, level); + upper_page_no, heap, level); /* Insert it next to the pointer to the lower half. Note that this may generate recursion leading to a split on the higher level. */ btr_insert_on_non_leaf_level(tree, level + 1, node_ptr_upper, mtr); - + /* Free the memory heap */ mem_heap_free(heap); @@ -1515,9 +1512,9 @@ btr_attach_half_pages( prev_page_no = btr_page_get_prev(page, mtr); next_page_no = btr_page_get_next(page, mtr); space = buf_frame_get_space_id(page); - + /* Update page links of the level */ - + if (prev_page_no != FIL_NULL) { prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr); @@ -1533,7 +1530,7 @@ btr_attach_half_pages( btr_page_set_prev(next_page, upper_page_no, mtr); } - + btr_page_set_prev(lower_page, prev_page_no, mtr); btr_page_set_next(lower_page, upper_page_no, mtr); btr_page_set_level(lower_page, level, mtr); @@ -1590,7 +1587,7 @@ func_start: mem_heap_empty(heap); offsets = NULL; tree = btr_cur_get_tree(cursor); - + ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); #ifdef UNIV_SYNC_DEBUG @@ -1600,9 +1597,9 @@ func_start: page = btr_cur_get_page(cursor); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); ut_ad(page_get_n_recs(page) >= 2); - + page_no = buf_frame_get_page_no(page); /* 1. Decide the split record; split_rec == NULL means that the @@ -1613,7 +1610,7 @@ func_start: direction = FSP_UP; hint_page_no = page_no + 1; split_rec = btr_page_get_sure_split_rec(cursor, tuple); - + } else if (btr_page_get_split_rec_to_right(cursor, &split_rec)) { direction = FSP_UP; hint_page_no = page_no + 1; @@ -1631,7 +1628,7 @@ func_start: new_page = btr_page_alloc(tree, hint_page_no, direction, btr_page_get_level(page, mtr), mtr); btr_page_create(new_page, tree, mtr); - + /* 3. Calculate the first record on the upper half-page, and the first record (move_limit) on original page which ends up on the upper half */ @@ -1646,7 +1643,7 @@ func_start: cursor->index, tuple); move_limit = page_rec_get_next(btr_cur_get_rec(cursor)); } - + /* 4. Do first the modifications in the tree structure */ btr_attach_half_pages(tree, page, first_rec, new_page, direction, mtr); @@ -1670,7 +1667,7 @@ func_start: insert_will_fit = btr_page_insert_fits(cursor, NULL, NULL, tuple, heap); } - + if (insert_will_fit && (btr_page_get_level(page, mtr) == 0)) { mtr_memo_release(mtr, dict_tree_get_lock(tree), @@ -1737,7 +1734,7 @@ func_start: mem_heap_free(heap); return(rec); } - + /* 8. If insert did not fit, try page reorganization */ btr_page_reorganize(insert_page, cursor->index, mtr); @@ -1749,7 +1746,7 @@ func_start: if (rec == NULL) { /* The insert did not fit on the page: loop back to the start of the function for a new split */ - + /* We play safe and reset the free bits for new_page */ ibuf_reset_free_bits(cursor->index, new_page); @@ -1787,24 +1784,24 @@ btr_level_list_remove( dict_tree_t* tree __attribute__((unused)), /* in: index tree */ page_t* page, /* in: page to remove */ mtr_t* mtr) /* in: mtr */ -{ +{ ulint space; ulint prev_page_no; page_t* prev_page; ulint next_page_no; page_t* next_page; - + ut_ad(tree && page && mtr); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); /* Get the previous and next page numbers of page */ prev_page_no = btr_page_get_prev(page, mtr); next_page_no = btr_page_get_next(page, mtr); space = buf_frame_get_space_id(page); - + /* Update page links of the level */ - + if (prev_page_no != FIL_NULL) { prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr); @@ -1821,7 +1818,7 @@ btr_level_list_remove( btr_page_set_prev(next_page, prev_page_no, mtr); } } - + /******************************************************************** Writes the redo log record for setting an index record as the predefined minimum record. */ @@ -1906,7 +1903,7 @@ btr_node_ptr_delete( btr_cur_t cursor; ibool compressed; ulint err; - + ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); /* Delete node pointer on father page */ @@ -1945,33 +1942,33 @@ btr_lift_page_up( ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL); ut_ad(btr_page_get_next(page, mtr) == FIL_NULL); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); father_page = buf_frame_align( btr_page_get_father_node_ptr(tree, page, mtr)); - + page_level = btr_page_get_level(page, mtr); index = UT_LIST_GET_FIRST(tree->tree_indexes); btr_search_drop_page_hash_index(page); - + /* Make the father empty */ btr_page_empty(father_page, mtr); /* Move records to the father */ - page_copy_rec_list_end(father_page, page, page_get_infimum_rec(page), + page_copy_rec_list_end(father_page, page, page_get_infimum_rec(page), index, mtr); lock_update_copy_and_discard(father_page, page); btr_page_set_level(father_page, page_level, mtr); /* Free the file page */ - btr_page_free(tree, page, mtr); + btr_page_free(tree, page, mtr); /* We play safe and reset the free bits for the father */ ibuf_reset_free_bits(index, father_page); ut_ad(page_validate(father_page, index)); ut_ad(btr_check_node_ptr(tree, father_page, mtr)); -} +} /***************************************************************** Tries to merge the page first to the left immediate brother if such a @@ -2014,7 +2011,7 @@ btr_compress( page = btr_cur_get_page(cursor); tree = btr_cur_get_tree(cursor); comp = page_is_comp(page); - ut_a((ibool)!!comp == cursor->index->table->comp); + ut_a((ibool)!!comp == dict_table_is_comp(cursor->index->table)); ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); @@ -2054,7 +2051,7 @@ btr_compress( return; } - + n_recs = page_get_n_recs(page); data_size = page_get_data_size(page); ut_a(page_is_comp(merge_page) == comp); @@ -2071,7 +2068,7 @@ btr_compress( ut_ad(page_validate(merge_page, cursor->index)); max_ins_size = page_get_max_insert_size(merge_page, n_recs); - + if (data_size > max_ins_size) { /* We have to reorganize merge_page */ @@ -2103,7 +2100,7 @@ btr_compress( mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; *offsets_ = (sizeof offsets_) / sizeof *offsets_; - /* Replace the address of the old child node (= page) with the + /* Replace the address of the old child node (= page) with the address of the merge page to the right */ btr_node_ptr_set_child_page_no(node_ptr, @@ -2115,7 +2112,7 @@ btr_compress( } btr_node_ptr_delete(tree, merge_page, mtr); } - + /* Move records to the merge page */ if (is_left) { orig_pred = page_rec_get_prev( @@ -2136,14 +2133,14 @@ btr_compress( /* We have added new records to merge_page: update its free bits */ ibuf_update_free_bits_if_full(cursor->index, merge_page, UNIV_PAGE_SIZE, ULINT_UNDEFINED); - + ut_ad(page_validate(merge_page, cursor->index)); /* Free the file page */ - btr_page_free(tree, page, mtr); + btr_page_free(tree, page, mtr); ut_ad(btr_check_node_ptr(tree, merge_page, mtr)); -} +} /***************************************************************** Discards a page that is the only page on its level. */ @@ -2158,7 +2155,7 @@ btr_discard_only_page_on_level( rec_t* node_ptr; page_t* father_page; ulint page_level; - + ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL); ut_ad(btr_page_get_next(page, mtr) == FIL_NULL); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), @@ -2175,7 +2172,7 @@ btr_discard_only_page_on_level( btr_page_set_level(father_page, page_level, mtr); /* Free the file page */ - btr_page_free(tree, page, mtr); + btr_page_free(tree, page, mtr); if (buf_frame_get_page_no(father_page) == dict_tree_get_page(tree)) { /* The father is the root page */ @@ -2190,7 +2187,7 @@ btr_discard_only_page_on_level( btr_discard_only_page_on_level(tree, father_page, mtr); } -} +} /***************************************************************** Discards a page from a B-tree. This is used to remove the last record from @@ -2212,7 +2209,7 @@ btr_discard_page( ibool is_left; page_t* page; rec_t* node_ptr; - + page = btr_cur_get_page(cursor); tree = btr_cur_get_tree(cursor); @@ -2222,7 +2219,7 @@ btr_discard_page( ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); space = dict_tree_get_space(tree); - + /* Decide the page which will inherit the locks */ left_page_no = btr_page_get_prev(page, mtr); @@ -2244,7 +2241,7 @@ btr_discard_page( ut_a(page_is_comp(merge_page) == page_is_comp(page)); btr_search_drop_page_hash_index(page); - + if (left_page_no == FIL_NULL && btr_page_get_level(page, mtr) > 0) { /* We have to mark the leftmost node pointer on the right @@ -2255,8 +2252,8 @@ btr_discard_page( ut_ad(page_rec_is_user_rec(node_ptr)); btr_set_min_rec_mark(node_ptr, page_is_comp(merge_page), mtr); - } - + } + btr_node_ptr_delete(tree, page, mtr); /* Remove the page from the level list */ @@ -2266,14 +2263,14 @@ btr_discard_page( lock_update_discard(page_get_supremum_rec(merge_page), page); } else { lock_update_discard(page_rec_get_next( - page_get_infimum_rec(merge_page)), page); + page_get_infimum_rec(merge_page)), page); } /* Free the file page */ - btr_page_free(tree, page, mtr); + btr_page_free(tree, page, mtr); ut_ad(btr_check_node_ptr(tree, merge_page, mtr)); -} +} #ifdef UNIV_BTR_PRINT /***************************************************************** @@ -2297,7 +2294,7 @@ btr_print_size( } mtr_start(&mtr); - + root = btr_root_get(tree, &mtr); seg = root + PAGE_HEADER + PAGE_BTR_SEG_TOP; @@ -2313,7 +2310,7 @@ btr_print_size( fseg_print(seg, &mtr); } - mtr_commit(&mtr); + mtr_commit(&mtr); } /**************************************************************** @@ -2341,14 +2338,14 @@ btr_print_recursive( ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); fprintf(stderr, "NODE ON LEVEL %lu page number %lu\n", - (ulong) btr_page_get_level(page, mtr), - (ulong) buf_frame_get_page_no(page)); - + (ulong) btr_page_get_level(page, mtr), + (ulong) buf_frame_get_page_no(page)); + index = UT_LIST_GET_FIRST(tree->tree_indexes); page_print(page, index, width, width); - + n_recs = page_get_n_recs(page); - + page_cur_set_before_first(page, &cursor); page_cur_move_to_next(&cursor); @@ -2413,6 +2410,7 @@ btr_print_tree( } #endif /* UNIV_BTR_PRINT */ +#ifdef UNIV_DEBUG /**************************************************************** Checks that the node pointer to a page is appropriate. */ @@ -2436,19 +2434,19 @@ btr_check_node_ptr( } node_ptr = btr_page_get_father_node_ptr(tree, page, mtr); - + if (btr_page_get_level(page, mtr) == 0) { return(TRUE); } - + heap = mem_heap_create(256); - + node_ptr_tuple = dict_tree_build_node_ptr( tree, page_rec_get_next(page_get_infimum_rec(page)), 0, heap, btr_page_get_level(page, mtr)); - + ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr, rec_get_offsets(node_ptr, dict_tree_find_index(tree, node_ptr), @@ -2458,6 +2456,7 @@ btr_check_node_ptr( return(TRUE); } +#endif /* UNIV_DEBUG */ /**************************************************************** Display identification information for a record. */ @@ -2481,7 +2480,7 @@ the index. */ ibool btr_index_rec_validate( -/*====================*/ +/*===================*/ /* out: TRUE if ok */ rec_t* rec, /* in: index record */ dict_index_t* index, /* in: index */ @@ -2501,18 +2500,20 @@ btr_index_rec_validate( page = buf_frame_align(rec); if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) { - /* The insert buffer index tree can contain records from any - other index: we cannot check the number of fields or - their length */ + /* The insert buffer index tree can contain records from any + other index: we cannot check the number of fields or + their length */ - return(TRUE); + return(TRUE); } - if (UNIV_UNLIKELY((ibool)!!page_is_comp(page) != index->table->comp)) { + if (UNIV_UNLIKELY((ibool)!!page_is_comp(page) + != dict_table_is_comp(index->table))) { btr_index_rec_validate_report(page, rec, index); fprintf(stderr, "InnoDB: compact flag=%lu, should be %lu\n", (ulong) !!page_is_comp(page), - (ulong) index->table->comp); + (ulong) dict_table_is_comp(index->table)); + return(FALSE); } @@ -2546,12 +2547,12 @@ btr_index_rec_validate( their type is CHAR. */ if ((dict_index_get_nth_field(index, i)->prefix_len == 0 - && len != UNIV_SQL_NULL && fixed_size - && len != fixed_size) + && len != UNIV_SQL_NULL && fixed_size + && len != fixed_size) || (dict_index_get_nth_field(index, i)->prefix_len > 0 - && len != UNIV_SQL_NULL - && len > + && len != UNIV_SQL_NULL + && len > dict_index_get_nth_field(index, i)->prefix_len)) { btr_index_rec_validate_report(page, rec, index); @@ -2576,7 +2577,7 @@ btr_index_rec_validate( if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } - return(TRUE); + return(TRUE); } /**************************************************************** @@ -2590,9 +2591,9 @@ btr_index_page_validate( page_t* page, /* in: index page */ dict_index_t* index) /* in: index */ { - page_cur_t cur; + page_cur_t cur; ibool ret = TRUE; - + page_cur_set_before_first(page, &cur); page_cur_move_to_next(&cur); @@ -2610,7 +2611,7 @@ btr_index_page_validate( page_cur_move_to_next(&cur); } - return(ret); + return(ret); } /**************************************************************** @@ -2686,7 +2687,7 @@ btr_validate_level( mtr_start(&mtr); mtr_x_lock(dict_tree_get_lock(tree), &mtr); - + page = btr_root_get(tree, &mtr); space = buf_frame_get_space_id(page); @@ -2733,14 +2734,14 @@ loop: ret = FALSE; } } - + ut_a(btr_page_get_level(page, &mtr) == level); right_page_no = btr_page_get_next(page, &mtr); left_page_no = btr_page_get_prev(page, &mtr); ut_a((page_get_n_recs(page) > 0) - || ((level == 0) && + || ((level == 0) && (buf_frame_get_page_no(page) == dict_tree_get_page(tree)))); if (right_page_no != FIL_NULL) { @@ -2776,10 +2777,10 @@ loop: rec_print(stderr, rec, index); putc('\n', stderr); - ret = FALSE; - } + ret = FALSE; + } } - + if (level > 0 && left_page_no == FIL_NULL) { ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits( page_rec_get_next(page_get_infimum_rec(page)), @@ -2789,7 +2790,7 @@ loop: if (buf_frame_get_page_no(page) != dict_tree_get_page(tree)) { /* Check father node pointers */ - + node_ptr = btr_page_get_father_node_ptr(tree, page, &mtr); father_page = buf_frame_align(node_ptr); offsets = rec_get_offsets(node_ptr, index, @@ -2822,25 +2823,25 @@ loop: &mtr); rec_print(stderr, rec, index); putc('\n', stderr); - ret = FALSE; + ret = FALSE; - goto node_ptr_fails; + goto node_ptr_fails; } if (btr_page_get_level(page, &mtr) > 0) { offsets = rec_get_offsets(node_ptr, index, offsets, ULINT_UNDEFINED, &heap); - + node_ptr_tuple = dict_tree_build_node_ptr( tree, page_rec_get_next( page_get_infimum_rec(page)), 0, heap, - btr_page_get_level(page, &mtr)); + btr_page_get_level(page, &mtr)); if (cmp_dtuple_rec(node_ptr_tuple, node_ptr, offsets)) { - rec_t* first_rec = page_rec_get_next( + rec_t* first_rec = page_rec_get_next( page_get_infimum_rec(page)); btr_validate_report1(index, level, page); @@ -2855,9 +2856,9 @@ loop: fputs("InnoDB: first rec ", stderr); rec_print(stderr, first_rec, index); putc('\n', stderr); - ret = FALSE; + ret = FALSE; - goto node_ptr_fails; + goto node_ptr_fails; } } @@ -2897,9 +2898,9 @@ loop: } else { right_father_page = buf_frame_align( right_node_ptr); - + if (right_node_ptr != page_rec_get_next( - page_get_infimum_rec( + page_get_infimum_rec( right_father_page))) { ret = FALSE; fputs( @@ -2931,7 +2932,7 @@ loop: buf_page_print(page); buf_page_print(right_page); } - } + } } } @@ -2941,7 +2942,7 @@ node_ptr_fails: if (right_page_no != FIL_NULL) { ulint comp = page_is_comp(page); mtr_start(&mtr); - + page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr); ut_a(page_is_comp(page) == comp); diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index f81cce5b8e9..14e991bb3c6 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/storage/innobase/btr/btr0cur.c @@ -116,7 +116,7 @@ btr_rec_get_externally_stored_len( const ulint* offsets);/* in: array returned by rec_get_offsets() */ /*==================== B-TREE SEARCH =========================*/ - + /************************************************************************ Latches the leaf page or pages requested. */ static @@ -128,17 +128,17 @@ btr_cur_latch_leaves( ulint space, /* in: space id */ ulint page_no, /* in: page number of the leaf */ ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */ - btr_cur_t* cursor, /* in: cursor */ + btr_cur_t* cursor, /* in: cursor */ mtr_t* mtr) /* in: mtr */ { ulint left_page_no; ulint right_page_no; page_t* get_page; - + ut_ad(page && mtr); if (latch_mode == BTR_SEARCH_LEAF) { - + get_page = btr_page_get(space, page_no, RW_S_LATCH, mtr); ut_a(page_is_comp(get_page) == page_is_comp(page)); buf_block_align(get_page)->check_index_page_at_flush = TRUE; @@ -161,7 +161,7 @@ btr_cur_latch_leaves( buf_block_align(get_page)->check_index_page_at_flush = TRUE; } - + get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr); ut_a(page_is_comp(get_page) == page_is_comp(page)); buf_block_align(get_page)->check_index_page_at_flush = TRUE; @@ -261,7 +261,7 @@ btr_cur_search_to_nth_level( ulint up_match; ulint up_bytes; ulint low_match; - ulint low_bytes; + ulint low_bytes; ulint height; ulint savepoint; ulint rw_latch; @@ -289,7 +289,7 @@ btr_cur_search_to_nth_level( #ifdef UNIV_DEBUG cursor->up_match = ULINT_UNDEFINED; cursor->low_match = ULINT_UNDEFINED; -#endif +#endif insert_planned = latch_mode & BTR_INSERT; estimate = latch_mode & BTR_ESTIMATE; ignore_sec_unique = latch_mode & BTR_IGNORE_SEC_UNIQUE; @@ -297,7 +297,7 @@ btr_cur_search_to_nth_level( | BTR_IGNORE_SEC_UNIQUE); ut_ad(!insert_planned || (mode == PAGE_CUR_LE)); - + cursor->flag = BTR_CUR_BINARY; cursor->index = index; @@ -312,7 +312,7 @@ btr_cur_search_to_nth_level( #ifdef UNIV_SEARCH_PERF_STAT info->n_searches++; -#endif +#endif if (btr_search_latch.writer == RW_LOCK_NOT_LOCKED && latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ && !estimate @@ -320,7 +320,7 @@ btr_cur_search_to_nth_level( && mode != PAGE_CUR_LE_OR_EXTENDS #endif /* PAGE_CUR_LE_OR_EXTENDS */ && srv_use_adaptive_hash_indexes - && btr_search_guess_on_hash(index, info, tuple, mode, + && btr_search_guess_on_hash(index, info, tuple, mode, latch_mode, cursor, has_search_latch, mtr)) { @@ -334,7 +334,7 @@ btr_cur_search_to_nth_level( || mode != PAGE_CUR_LE); btr_cur_n_sea++; - return; + return; } #endif #endif @@ -354,7 +354,7 @@ btr_cur_search_to_nth_level( savepoint = mtr_set_savepoint(mtr); tree = index->tree; - + if (latch_mode == BTR_MODIFY_TREE) { mtr_x_lock(dict_tree_get_lock(tree), mtr); @@ -365,7 +365,7 @@ btr_cur_search_to_nth_level( } else { mtr_s_lock(dict_tree_get_lock(tree), mtr); } - + page_cursor = btr_cur_get_page_cur(cursor); space = dict_tree_get_space(tree); @@ -411,14 +411,14 @@ btr_cur_search_to_nth_level( if (insert_planned && ibuf_should_try(index, ignore_sec_unique)) { - + /* Try insert to the insert buffer if the page is not in the buffer pool */ buf_mode = BUF_GET_IF_IN_POOL; } } -retry_page_get: +retry_page_get: page = buf_page_get_gen(space, page_no, rw_latch, guess, buf_mode, __FILE__, __LINE__, @@ -451,8 +451,8 @@ retry_page_get: } buf_block_align(page)->check_index_page_at_flush = TRUE; - -#ifdef UNIV_SYNC_DEBUG + +#ifdef UNIV_SYNC_DEBUG if (rw_latch != RW_NO_LATCH) { buf_page_dbg_add_level(page, SYNC_TREE_NODE); } @@ -469,10 +469,10 @@ retry_page_get: #ifdef BTR_CUR_ADAPT if (page != guess) { info->root_guess = page; - } + } #endif } - + if (height == 0) { if (rw_latch == RW_NO_LATCH) { @@ -482,7 +482,7 @@ retry_page_get: } if ((latch_mode != BTR_MODIFY_TREE) - && (latch_mode != BTR_CONT_MODIFY_TREE)) { + && (latch_mode != BTR_CONT_MODIFY_TREE)) { /* Release the tree s-latch */ @@ -499,7 +499,7 @@ retry_page_get: &low_match, &low_bytes, page_cursor); if (estimate) { btr_cur_add_path_info(cursor, height, root_height); - } + } /* If this is the desired level, leave the loop */ @@ -513,7 +513,7 @@ retry_page_get: page = btr_page_get(space, page_no, RW_X_LATCH, mtr); ut_a((ibool)!!page_is_comp(page) - == index->table->comp); + == dict_table_is_comp(index->table)); } break; @@ -541,7 +541,7 @@ retry_page_get: cursor->up_match = up_match; cursor->up_bytes = up_bytes; -#ifdef BTR_CUR_ADAPT +#ifdef BTR_CUR_ADAPT if (srv_use_adaptive_hash_indexes) { btr_search_info_update(index, cursor); @@ -556,7 +556,7 @@ retry_page_get: } if (has_search_latch) { - + rw_lock_s_lock(&btr_search_latch); } } @@ -583,7 +583,7 @@ btr_cur_open_at_index_side( ulint root_height = 0; /* remove warning */ rec_t* node_ptr; ulint estimate; - ulint savepoint; + ulint savepoint; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; @@ -591,9 +591,9 @@ btr_cur_open_at_index_side( estimate = latch_mode & BTR_ESTIMATE; latch_mode = latch_mode & ~BTR_ESTIMATE; - + tree = index->tree; - + /* Store the position of the tree latch we push to mtr so that we know how to release it when we have latched the leaf node */ @@ -604,7 +604,7 @@ btr_cur_open_at_index_side( } else { mtr_s_lock(dict_tree_get_lock(tree), mtr); } - + page_cursor = btr_cur_get_page_cur(cursor); cursor->index = index; @@ -639,9 +639,9 @@ btr_cur_open_at_index_side( we had to scan far to find a record visible to the current transaction, that could starve others waiting for the tree latch. */ - + if ((latch_mode != BTR_MODIFY_TREE) - && (latch_mode != BTR_CONT_MODIFY_TREE)) { + && (latch_mode != BTR_CONT_MODIFY_TREE)) { /* Release the tree s-latch */ @@ -650,7 +650,7 @@ btr_cur_open_at_index_side( dict_tree_get_lock(tree)); } } - + if (from_left) { page_cur_set_before_first(page, page_cursor); } else { @@ -658,10 +658,10 @@ btr_cur_open_at_index_side( } if (height == 0) { - if (estimate) { - btr_cur_add_path_info(cursor, height, - root_height); - } + if (estimate) { + btr_cur_add_path_info(cursor, height, + root_height); + } break; } @@ -691,7 +691,7 @@ btr_cur_open_at_index_side( mem_heap_free(heap); } } - + /************************************************************************** Positions a cursor at a randomly chosen position within a B-tree. */ @@ -716,13 +716,13 @@ btr_cur_open_at_rnd_pos( *offsets_ = (sizeof offsets_) / sizeof *offsets_; tree = index->tree; - + if (latch_mode == BTR_MODIFY_TREE) { mtr_x_lock(dict_tree_get_lock(tree), mtr); } else { mtr_s_lock(dict_tree_get_lock(tree), mtr); } - + page_cursor = btr_cur_get_page_cur(cursor); cursor->index = index; @@ -730,7 +730,7 @@ btr_cur_open_at_rnd_pos( page_no = dict_tree_get_page(tree); height = ULINT_UNDEFINED; - + for (;;) { page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL, BUF_GET, @@ -750,7 +750,7 @@ btr_cur_open_at_rnd_pos( latch_mode, cursor, mtr); } - page_cur_open_on_rnd_user_rec(page, page_cursor); + page_cur_open_on_rnd_user_rec(page, page_cursor); if (height == 0) { @@ -771,7 +771,7 @@ btr_cur_open_at_rnd_pos( if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } -} +} /*==================== B-TREE INSERT =========================*/ @@ -798,7 +798,7 @@ btr_cur_insert_if_possible( rec_t* rec; ut_ad(dtuple_check_typed(tuple)); - + *reorg = FALSE; page = btr_cur_get_page(cursor); @@ -806,7 +806,7 @@ btr_cur_insert_if_possible( ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); page_cursor = btr_cur_get_page_cur(cursor); - + /* Now, try the insert */ rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index, mtr); @@ -855,9 +855,9 @@ btr_cur_ins_lock_and_undo( rec = btr_cur_get_rec(cursor); index = cursor->index; - + err = lock_rec_insert_check_and_lock(flags, rec, index, thr, inherit); - + if (err != DB_SUCCESS) { return(err); @@ -942,7 +942,7 @@ btr_cur_optimistic_insert( ibool inherit; ulint rec_size; ulint type; - ulint err; + ulint err; *big_rec = NULL; @@ -975,11 +975,11 @@ calculate_sizes_again: /* The record is so big that we have to store some fields externally on separate database pages */ - - big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0); + + big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0); if (big_rec_vec == NULL) { - + return(DB_TOO_BIG_RECORD); } @@ -991,38 +991,38 @@ calculate_sizes_again: for future updates of records. */ type = index->type; - + if ((type & DICT_CLUSTERED) - && (dict_tree_get_space_reserve(index->tree) + rec_size > max_size) - && (page_get_n_recs(page) >= 2) - && (0 == level) - && (btr_page_get_split_rec_to_right(cursor, &dummy_rec) - || btr_page_get_split_rec_to_left(cursor, &dummy_rec))) { + && (dict_tree_get_space_reserve(index->tree) + rec_size > max_size) + && (page_get_n_recs(page) >= 2) + && (0 == level) + && (btr_page_get_split_rec_to_right(cursor, &dummy_rec) + || btr_page_get_split_rec_to_left(cursor, &dummy_rec))) { - if (big_rec_vec) { + if (big_rec_vec) { dtuple_convert_back_big_rec(index, entry, big_rec_vec); } return(DB_FAIL); } - + if (!(((max_size >= rec_size) - && (max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT)) - || (page_get_max_insert_size(page, 1) >= rec_size) - || (page_get_n_recs(page) <= 1))) { + && (max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT)) + || (page_get_max_insert_size(page, 1) >= rec_size) + || (page_get_n_recs(page) <= 1))) { - if (big_rec_vec) { + if (big_rec_vec) { dtuple_convert_back_big_rec(index, entry, big_rec_vec); } return(DB_FAIL); } - /* Check locks and write to the undo log, if specified */ - err = btr_cur_ins_lock_and_undo(flags, cursor, entry, thr, &inherit); + /* Check locks and write to the undo log, if specified */ + err = btr_cur_ins_lock_and_undo(flags, cursor, entry, thr, &inherit); if (err != DB_SUCCESS) { - if (big_rec_vec) { + if (big_rec_vec) { dtuple_convert_back_big_rec(index, entry, big_rec_vec); } return(err); @@ -1041,7 +1041,7 @@ calculate_sizes_again: btr_page_reorganize(page, index, mtr); ut_ad(page_get_max_insert_size(page, 1) == max_size); - + reorg = TRUE; page_cur_search(page, index, entry, PAGE_CUR_LE, page_cursor); @@ -1076,7 +1076,7 @@ calculate_sizes_again: " rec %lu ind type %lu\n", buf_frame_get_page_no(page), max_size, rec_size + PAGE_DIR_SLOT_SIZE, type); -*/ +*/ if (!(type & DICT_CLUSTERED)) { /* We have added a record to page: update its free bits */ ibuf_update_free_bits_if_full(cursor->index, page, max_size, @@ -1123,7 +1123,7 @@ btr_cur_pessimistic_insert( ibool success; ulint n_extents = 0; ulint n_reserved; - + ut_ad(dtuple_check_typed(entry)); *big_rec = NULL; @@ -1158,7 +1158,7 @@ btr_cur_pessimistic_insert( return(err); } - if (!(flags & BTR_NO_UNDO_LOG_FLAG)) { + if (!(flags & BTR_NO_UNDO_LOG_FLAG)) { /* First reserve enough free space for the file segments of the index tree, so that the insert will not fail because of lack of space */ @@ -1180,13 +1180,13 @@ btr_cur_pessimistic_insert( /* The record is so big that we have to store some fields externally on separate database pages */ - - big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0); + + big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0); if (big_rec_vec == NULL) { - + if (n_extents > 0) { - fil_space_release_free_extents(index->space, + fil_space_release_free_extents(index->space, n_reserved); } return(DB_TOO_BIG_RECORD); @@ -1202,7 +1202,7 @@ btr_cur_pessimistic_insert( *rec = btr_page_split_and_insert(cursor, entry, mtr); } - btr_cur_position(index, page_rec_get_prev(*rec), cursor); + btr_cur_position(index, page_rec_get_prev(*rec), cursor); #ifdef BTR_CUR_ADAPT btr_search_update_hash_on_insert(cursor); @@ -1244,12 +1244,12 @@ btr_cur_upd_lock_and_undo( dict_index_t* index; rec_t* rec; ulint err; - + ut_ad(cursor && update && thr && roll_ptr); rec = btr_cur_get_rec(cursor); index = cursor->index; - + if (!(index->type & DICT_CLUSTERED)) { /* We do undo logging only when we update a clustered index record */ @@ -1304,7 +1304,7 @@ btr_cur_update_in_place_log( byte* log_ptr; page_t* page = ut_align_down(rec, UNIV_PAGE_SIZE); ut_ad(flags < 256); - ut_ad(!!page_is_comp(page) == index->table->comp); + ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); log_ptr = mlog_open_and_write_index(mtr, rec, index, page_is_comp(page) ? MLOG_COMP_REC_UPDATE_IN_PLACE @@ -1332,7 +1332,7 @@ btr_cur_update_in_place_log( log_ptr += 2; row_upd_index_write_log(update, log_ptr, mtr); -} +} /*************************************************************** Parses a redo log record of updating a record in-place. */ @@ -1360,7 +1360,7 @@ btr_cur_parse_update_in_place( return(NULL); } - + flags = mach_read_from_1(ptr); ptr++; @@ -1382,7 +1382,7 @@ btr_cur_parse_update_in_place( ut_a(rec_offset <= UNIV_PAGE_SIZE); heap = mem_heap_create(256); - + ptr = row_upd_index_parse(ptr, end_ptr, heap, &update); if (!ptr || !page) { @@ -1390,9 +1390,9 @@ btr_cur_parse_update_in_place( goto func_exit; } - ut_a((ibool)!!page_is_comp(page) == index->table->comp); + ut_a((ibool)!!page_is_comp(page) == dict_table_is_comp(index->table)); rec = page + rec_offset; - + /* We do not need to reserve btr_search_latch, as the page is only being recovered, and there cannot be a hash index to it. */ @@ -1443,7 +1443,7 @@ btr_cur_update_in_place( rec = btr_cur_get_rec(cursor); index = cursor->index; - ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); trx = thr_get_trx(thr); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); #ifdef UNIV_DEBUG @@ -1466,19 +1466,19 @@ btr_cur_update_in_place( block = buf_block_align(rec); ut_ad(!!page_is_comp(buf_block_get_frame(block)) - == index->table->comp); + == dict_table_is_comp(index->table)); if (block->is_hashed) { /* The function row_upd_changes_ord_field_binary works only if the update vector was built for a clustered index, we must NOT call it if index is secondary */ - if (!(index->type & DICT_CLUSTERED) - || row_upd_changes_ord_field_binary(NULL, index, update)) { + if (!(index->type & DICT_CLUSTERED) + || row_upd_changes_ord_field_binary(NULL, index, update)) { - /* Remove possible hash index pointer to this record */ - btr_search_update_hash_on_delete(cursor); - } + /* Remove possible hash index pointer to this record */ + btr_search_update_hash_on_delete(cursor); + } rw_lock_x_lock(&btr_search_latch); } @@ -1558,8 +1558,8 @@ btr_cur_optimistic_update( page = btr_cur_get_page(cursor); rec = btr_cur_get_rec(cursor); index = cursor->index; - ut_ad(!!page_rec_is_comp(rec) == index->table->comp); - + ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); + heap = mem_heap_create(1024); offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); @@ -1600,20 +1600,20 @@ btr_cur_optimistic_update( mem_heap_free(heap); return(DB_OVERFLOW); } - + page_cursor = btr_cur_get_page_cur(cursor); - + new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, NULL); old_rec_size = rec_offs_size(offsets); new_rec_size = rec_get_converted_size(index, new_entry); - + if (UNIV_UNLIKELY(new_rec_size >= page_get_free_space_of_empty( page_is_comp(page)) / 2)) { - mem_heap_free(heap); + mem_heap_free(heap); return(DB_OVERFLOW); } @@ -1633,14 +1633,14 @@ btr_cur_optimistic_update( } if (!(((max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT) - && (max_size >= new_rec_size)) - || (page_get_n_recs(page) <= 1))) { + && (max_size >= new_rec_size)) + || (page_get_n_recs(page) <= 1))) { /* There was not enough space, or it did not pay to reorganize: for simplicity, we decide what to do assuming a reorganization is needed, though it might not be necessary */ - mem_heap_free(heap); + mem_heap_free(heap); return(DB_OVERFLOW); } @@ -1654,8 +1654,8 @@ btr_cur_optimistic_update( return(err); } - - /* Ok, we may do the replacement. Store on the page infimum the + + /* Ok, we may do the replacement. Store on the page infimum the explicit locks on rec, before deleting rec (see the comment in .._pessimistic_update). */ @@ -1666,7 +1666,7 @@ btr_cur_optimistic_update( page_cur_delete_rec(page_cursor, index, offsets, mtr); page_cur_move_to_prev(page_cursor); - + trx = thr_get_trx(thr); if (!(flags & BTR_KEEP_SYS_FLAG)) { @@ -1693,9 +1693,9 @@ btr_cur_optimistic_update( lock_rec_restore_from_page_infimum(rec, page); - page_cur_move_to_next(page_cursor); + page_cur_move_to_next(page_cursor); - mem_heap_free(heap); + mem_heap_free(heap); return(DB_SUCCESS); } @@ -1717,24 +1717,24 @@ btr_cur_pess_upd_restore_supremum( page_t* prev_page; ulint space; ulint prev_page_no; - + page = buf_frame_align(rec); if (page_rec_get_next(page_get_infimum_rec(page)) != rec) { - /* Updated record is not the first user record on its page */ - + /* Updated record is not the first user record on its page */ + return; } space = buf_frame_get_space_id(page); prev_page_no = btr_page_get_prev(page, mtr); - + ut_ad(prev_page_no != FIL_NULL); prev_page = buf_page_get_with_no_latch(space, prev_page_no, mtr); /* We must already have an x-latch to prev_page! */ ut_ad(mtr_memo_contains(mtr, buf_block_align(prev_page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); lock_rec_reset_and_inherit_gap_locks(page_get_supremum_rec(prev_page), rec); @@ -1786,9 +1786,9 @@ btr_cur_pessimistic_update( ulint n_ext_vect; ulint reserve_flag; ulint* offsets = NULL; - + *big_rec = NULL; - + page = btr_cur_get_page(cursor); rec = btr_cur_get_rec(cursor); index = cursor->index; @@ -1827,7 +1827,7 @@ btr_cur_pessimistic_update( } else { reserve_flag = FSP_NORMAL; } - + success = fsp_reserve_free_extents(&n_reserved, index->space, n_extents, reserve_flag, mtr); @@ -1837,12 +1837,12 @@ btr_cur_pessimistic_update( return(err); } } - + heap = mem_heap_create(1024); offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); trx = thr_get_trx(thr); - + new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, @@ -1863,7 +1863,7 @@ btr_cur_pessimistic_update( update it back again. */ ut_a(big_rec_vec == NULL); - + btr_rec_free_updated_extern_fields(index, rec, offsets, update, TRUE, mtr); } @@ -1882,8 +1882,8 @@ btr_cur_pessimistic_update( ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2, REC_MAX_DATA_SIZE))) { - big_rec_vec = dtuple_convert_big_rec(index, new_entry, - ext_vect, n_ext_vect); + big_rec_vec = dtuple_convert_big_rec(index, new_entry, + ext_vect, n_ext_vect); if (big_rec_vec == NULL) { err = DB_TOO_BIG_RECORD; @@ -1921,7 +1921,7 @@ btr_cur_pessimistic_update( lock_rec_restore_from_page_infimum(rec, page); rec_set_field_extern_bits(rec, index, ext_vect, n_ext_vect, mtr); - + if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) { /* The new inserted record owns its possible externally stored fields */ @@ -2009,7 +2009,7 @@ btr_cur_del_mark_set_clust_rec_log( ut_ad(flags < 256); ut_ad(val <= 1); - ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); log_ptr = mlog_open_and_write_index(mtr, rec, index, page_rec_is_comp(rec) @@ -2056,13 +2056,14 @@ btr_cur_parse_del_mark_set_clust_rec( ulint offset; rec_t* rec; - ut_ad(!page || !!page_is_comp(page) == index->table->comp); + ut_ad(!page + || !!page_is_comp(page) == dict_table_is_comp(index->table)); if (end_ptr < ptr + 2) { return(NULL); } - + flags = mach_read_from_1(ptr); ptr++; val = mach_read_from_1(ptr); @@ -2087,7 +2088,7 @@ btr_cur_parse_del_mark_set_clust_rec( if (page) { rec = page + offset; - + if (!(flags & BTR_KEEP_SYS_FLAG)) { mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; @@ -2108,7 +2109,7 @@ btr_cur_parse_del_mark_set_clust_rec( rec_set_deleted_flag(rec, page_is_comp(page), val); } - + return(ptr); } @@ -2142,7 +2143,7 @@ btr_cur_del_mark_set_clust_rec( rec = btr_cur_get_rec(cursor); index = cursor->index; - ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); #ifdef UNIV_DEBUG @@ -2186,11 +2187,11 @@ btr_cur_del_mark_set_clust_rec( rec_set_deleted_flag(rec, rec_offs_comp(offsets), val); trx = thr_get_trx(thr); - + if (!(flags & BTR_KEEP_SYS_FLAG)) { row_upd_rec_sys_fields(rec, index, offsets, trx, roll_ptr); } - + if (block->is_hashed) { rw_lock_x_unlock(&btr_search_latch); } @@ -2256,7 +2257,7 @@ btr_cur_parse_del_mark_set_sec_rec( return(NULL); } - + val = mach_read_from_1(ptr); ptr++; @@ -2267,17 +2268,17 @@ btr_cur_parse_del_mark_set_sec_rec( if (page) { rec = page + offset; - + /* We do not need to reserve btr_search_latch, as the page is only being recovered, and there cannot be a hash index to it. */ rec_set_deleted_flag(rec, page_is_comp(page), val); } - + return(ptr); } - + /*************************************************************** Sets a secondary index record delete mark to TRUE or FALSE. */ @@ -2315,8 +2316,8 @@ btr_cur_del_mark_set_sec_rec( block = buf_block_align(rec); ut_ad(!!page_is_comp(buf_block_get_frame(block)) - == cursor->index->table->comp); - + == dict_table_is_comp(cursor->index->table)); + if (block->is_hashed) { rw_lock_x_lock(&btr_search_latch); } @@ -2375,7 +2376,7 @@ btr_cur_compress( MTR_MEMO_PAGE_X_FIX)); ut_ad(btr_page_get_level(btr_cur_get_page(cursor), mtr) == 0); - btr_compress(cursor, mtr); + btr_compress(cursor, mtr); } /***************************************************************** @@ -2441,7 +2442,7 @@ btr_cur_optimistic_delete( /* This is intended only for leaf page deletions */ page = btr_cur_get_page(cursor); - + ut_ad(btr_page_get_level(page, mtr) == 0); rec = btr_cur_get_rec(cursor); @@ -2513,7 +2514,7 @@ btr_cur_pessimistic_delete( ulint level; mem_heap_t* heap; ulint* offsets; - + page = btr_cur_get_page(cursor); tree = btr_cur_get_tree(cursor); @@ -2555,26 +2556,26 @@ btr_cur_pessimistic_delete( } if (UNIV_UNLIKELY(page_get_n_recs(page) < 2) - && UNIV_UNLIKELY(dict_tree_get_page(btr_cur_get_tree(cursor)) - != buf_frame_get_page_no(page))) { + && UNIV_UNLIKELY(dict_tree_get_page(btr_cur_get_tree(cursor)) + != buf_frame_get_page_no(page))) { /* If there is only one record, drop the whole page in btr_discard_page, if this is not the root page */ - + btr_discard_page(cursor, mtr); *err = DB_SUCCESS; ret = TRUE; - goto return_after_reservations; + goto return_after_reservations; } lock_update_delete(rec); level = btr_page_get_level(page, mtr); if (level > 0 - && UNIV_UNLIKELY(rec == page_rec_get_next( - page_get_infimum_rec(page)))) { + && UNIV_UNLIKELY(rec == page_rec_get_next( + page_get_infimum_rec(page)))) { rec_t* next_rec = page_rec_get_next(rec); @@ -2602,7 +2603,7 @@ btr_cur_pessimistic_delete( btr_insert_on_non_leaf_level(tree, level + 1, node_ptr, mtr); } - } + } btr_search_update_hash_on_delete(cursor); @@ -2612,7 +2613,7 @@ btr_cur_pessimistic_delete( ut_ad(btr_check_node_ptr(tree, page, mtr)); *err = DB_SUCCESS; - + return_after_reservations: mem_heap_free(heap); @@ -2661,7 +2662,7 @@ btr_cur_add_path_info( } rec = btr_cur_get_rec(cursor); - + slot = cursor->path_arr + (root_height - height); slot->nth_rec = page_rec_get_n_recs_before(rec); @@ -2687,8 +2688,8 @@ btr_estimate_n_rows_in_range( btr_path_t* slot1; btr_path_t* slot2; ibool diverged; - ibool diverged_lot; - ulint divergence_level; + ibool diverged_lot; + ulint divergence_level; ib_longlong n_rows; ulint i; mtr_t mtr; @@ -2698,7 +2699,7 @@ btr_estimate_n_rows_in_range( cursor.path_arr = path1; if (dtuple_get_n_fields(tuple1) > 0) { - + btr_cur_search_to_nth_level(index, 0, tuple1, mode1, BTR_SEARCH_LEAF | BTR_ESTIMATE, &cursor, 0, &mtr); @@ -2707,7 +2708,7 @@ btr_estimate_n_rows_in_range( BTR_SEARCH_LEAF | BTR_ESTIMATE, &cursor, &mtr); } - + mtr_commit(&mtr); mtr_start(&mtr); @@ -2715,7 +2716,7 @@ btr_estimate_n_rows_in_range( cursor.path_arr = path2; if (dtuple_get_n_fields(tuple2) > 0) { - + btr_cur_search_to_nth_level(index, 0, tuple2, mode2, BTR_SEARCH_LEAF | BTR_ESTIMATE, &cursor, 0, &mtr); @@ -2724,48 +2725,48 @@ btr_estimate_n_rows_in_range( BTR_SEARCH_LEAF | BTR_ESTIMATE, &cursor, &mtr); } - + mtr_commit(&mtr); /* We have the path information for the range in path1 and path2 */ n_rows = 1; - diverged = FALSE; /* This becomes true when the path is not - the same any more */ - diverged_lot = FALSE; /* This becomes true when the paths are - not the same or adjacent any more */ + diverged = FALSE; /* This becomes true when the path is not + the same any more */ + diverged_lot = FALSE; /* This becomes true when the paths are + not the same or adjacent any more */ divergence_level = 1000000; /* This is the level where paths diverged - a lot */ - for (i = 0; ; i++) { + a lot */ + for (i = 0; ; i++) { ut_ad(i < BTR_PATH_ARRAY_N_SLOTS); - + slot1 = path1 + i; slot2 = path2 + i; if (slot1->nth_rec == ULINT_UNDEFINED || slot2->nth_rec == ULINT_UNDEFINED) { - if (i > divergence_level + 1) { - /* In trees whose height is > 1 our algorithm - tends to underestimate: multiply the estimate - by 2: */ + if (i > divergence_level + 1) { + /* In trees whose height is > 1 our algorithm + tends to underestimate: multiply the estimate + by 2: */ - n_rows = n_rows * 2; - } + n_rows = n_rows * 2; + } /* Do not estimate the number of rows in the range - to over 1 / 2 of the estimated rows in the whole + to over 1 / 2 of the estimated rows in the whole table */ if (n_rows > index->table->stat_n_rows / 2) { - n_rows = index->table->stat_n_rows / 2; + n_rows = index->table->stat_n_rows / 2; /* If there are just 0 or 1 rows in the table, then we estimate all rows are in the range */ - - if (n_rows == 0) { - n_rows = index->table->stat_n_rows; - } + + if (n_rows == 0) { + n_rows = index->table->stat_n_rows; + } } return(n_rows); @@ -2779,7 +2780,7 @@ btr_estimate_n_rows_in_range( n_rows = slot2->nth_rec - slot1->nth_rec; if (n_rows > 1) { - diverged_lot = TRUE; + diverged_lot = TRUE; divergence_level = i; } } else { @@ -2791,28 +2792,28 @@ btr_estimate_n_rows_in_range( } else if (diverged && !diverged_lot) { - if (slot1->nth_rec < slot1->n_recs - || slot2->nth_rec > 1) { + if (slot1->nth_rec < slot1->n_recs + || slot2->nth_rec > 1) { - diverged_lot = TRUE; + diverged_lot = TRUE; divergence_level = i; n_rows = 0; - if (slot1->nth_rec < slot1->n_recs) { - n_rows += slot1->n_recs - - slot1->nth_rec; + if (slot1->nth_rec < slot1->n_recs) { + n_rows += slot1->n_recs + - slot1->nth_rec; } if (slot2->nth_rec > 1) { - n_rows += slot2->nth_rec - 1; + n_rows += slot2->nth_rec - 1; } - } + } } else if (diverged_lot) { n_rows = (n_rows * (slot1->n_recs + slot2->n_recs)) / 2; - } + } } } @@ -2855,13 +2856,13 @@ btr_estimate_number_of_different_key_vals( memset(n_diff, 0, (n_cols + 1) * sizeof(ib_longlong)); /* We sample some pages in the index to get an estimate */ - + for (i = 0; i < BTR_KEY_VAL_ESTIMATE_N_PAGES; i++) { rec_t* supremum; mtr_start(&mtr); btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr); - + /* Count the number of different key values for each prefix of the key on this index page. If the prefix does not determine the index record uniquely in te B-tree, then we subtract one @@ -2906,7 +2907,7 @@ btr_estimate_number_of_different_key_vals( total_external_size += btr_rec_get_externally_stored_len( rec, offsets_rec); - + rec = next_rec; /* Initialize offsets_rec for the next round and assign the old offsets_rec buffer to @@ -2917,7 +2918,7 @@ btr_estimate_number_of_different_key_vals( offsets_next_rec = offsets_tmp; } } - + if (n_cols == dict_index_get_n_unique_in_tree(index)) { @@ -2931,7 +2932,7 @@ btr_estimate_number_of_different_key_vals( in the table. */ if (btr_page_get_prev(page, &mtr) != FIL_NULL - || btr_page_get_next(page, &mtr) != FIL_NULL) { + || btr_page_get_next(page, &mtr) != FIL_NULL) { n_diff[n_cols]++; } @@ -2948,10 +2949,10 @@ btr_estimate_number_of_different_key_vals( /* If we saw k borders between different key values on BTR_KEY_VAL_ESTIMATE_N_PAGES leaf pages, we can estimate how many there will be in index->stat_n_leaf_pages */ - + /* We must take into account that our sample actually represents also the pages used for external storage of fields (those pages are - included in index->stat_n_leaf_pages) */ + included in index->stat_n_leaf_pages) */ for (j = 0; j <= n_cols; j++) { index->stat_n_diff_key_vals[j] = @@ -2960,9 +2961,9 @@ btr_estimate_number_of_different_key_vals( + BTR_KEY_VAL_ESTIMATE_N_PAGES - 1 + total_external_size + not_empty_flag) - / (BTR_KEY_VAL_ESTIMATE_N_PAGES - + total_external_size); - + / (BTR_KEY_VAL_ESTIMATE_N_PAGES + + total_external_size); + /* If the tree is small, smaller than < 10 * BTR_KEY_VAL_ESTIMATE_N_PAGES + total_external_size, then the above estimate is ok. For bigger trees it is common that we @@ -2977,10 +2978,10 @@ btr_estimate_number_of_different_key_vals( if (add_on > BTR_KEY_VAL_ESTIMATE_N_PAGES) { add_on = BTR_KEY_VAL_ESTIMATE_N_PAGES; } - + index->stat_n_diff_key_vals[j] += add_on; } - + mem_free(n_diff); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -3016,7 +3017,7 @@ btr_rec_get_externally_stored_len( data = rec_get_nth_field(rec, offsets, i, &local_len); local_len -= BTR_EXTERN_FIELD_REF_SIZE; - + extern_len = mach_read_from_4(data + local_len + BTR_EXTERN_LEN + 4); @@ -3045,7 +3046,7 @@ btr_cur_set_ownership_of_extern_field( ulint byte_val; data = rec_get_nth_field(rec, offsets, i, &local_len); - + ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); local_len -= BTR_EXTERN_FIELD_REF_SIZE; @@ -3057,7 +3058,7 @@ btr_cur_set_ownership_of_extern_field( } else { byte_val = byte_val | BTR_EXTERN_OWNER_FLAG; } - + mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val, MLOG_1BYTE, mtr); } @@ -3087,7 +3088,7 @@ btr_cur_mark_extern_inherited_fields( for (i = 0; i < n; i++) { if (rec_offs_nth_extern(offsets, i)) { - + /* Check it is not in updated fields */ is_updated = FALSE; @@ -3136,7 +3137,7 @@ btr_cur_mark_dtuple_inherited_extern( return; } - + for (i = 0; i < n_ext_vec; i++) { /* Check ext_vec[i] is in updated fields */ @@ -3154,14 +3155,14 @@ btr_cur_mark_dtuple_inherited_extern( data = (byte*) dfield_get_data(dfield); len = dfield_get_len(dfield); - + len -= BTR_EXTERN_FIELD_REF_SIZE; byte_val = mach_read_from_1(data + len + BTR_EXTERN_LEN); byte_val = byte_val | BTR_EXTERN_INHERITED_FLAG; - + mach_write_to_1(data + len + BTR_EXTERN_LEN, byte_val); } } @@ -3191,7 +3192,7 @@ btr_cur_unmark_extern_fields( btr_cur_set_ownership_of_extern_field(rec, offsets, i, TRUE, mtr); } - } + } } /*********************************************************************** @@ -3216,15 +3217,15 @@ btr_cur_unmark_dtuple_extern_fields( data = (byte*) dfield_get_data(dfield); len = dfield_get_len(dfield); - + len -= BTR_EXTERN_FIELD_REF_SIZE; byte_val = mach_read_from_1(data + len + BTR_EXTERN_LEN); byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG); - + mach_write_to_1(data + len + BTR_EXTERN_LEN, byte_val); - } + } } /*********************************************************************** @@ -3251,7 +3252,7 @@ btr_push_update_extern_fields( if (update) { n = upd_get_n_fields(update); - + for (i = 0; i < n; i++) { if (upd_get_nth_field(update, i)->extern_storage) { @@ -3268,7 +3269,7 @@ btr_push_update_extern_fields( for (i = 0; i < n; i++) { if (rec_offs_nth_extern(offsets, i)) { - + /* Check it is not in updated fields */ is_updated = FALSE; @@ -3287,7 +3288,7 @@ btr_push_update_extern_fields( n_pushed++; } } - } + } return(n_pushed); } @@ -3333,8 +3334,8 @@ btr_store_big_rec_extern_fields( big_rec_t* big_rec_vec, /* in: vector containing fields to be stored externally */ mtr_t* local_mtr __attribute__((unused))) /* in: mtr - containing the latch to rec and to the - tree */ + containing the latch to rec and to the + tree */ { byte* data; ulint local_len; @@ -3356,9 +3357,9 @@ btr_store_big_rec_extern_fields( ut_ad(mtr_memo_contains(local_mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)); ut_a(index->type & DICT_CLUSTERED); - + space_id = buf_frame_get_space_id(rec); - + /* We have to create a file segment to the tablespace for each field and put the pointer to the field in rec */ @@ -3382,7 +3383,7 @@ btr_store_big_rec_extern_fields( } else { hint_page_no = prev_page_no + 1; } - + page = btr_page_alloc(index->tree, hint_page_no, FSP_NO_DIR, 0, &mtr); if (page == NULL) { @@ -3392,6 +3393,9 @@ btr_store_big_rec_extern_fields( return(DB_OUT_OF_FILE_SPACE); } + mlog_write_ulint(page + FIL_PAGE_TYPE, + FIL_PAGE_TYPE_BLOB, MLOG_2BYTES, &mtr); + page_no = buf_frame_get_page_no(page); if (prev_page_no != FIL_NULL) { @@ -3403,7 +3407,7 @@ btr_store_big_rec_extern_fields( buf_page_dbg_add_level(prev_page, SYNC_EXTERN_STORAGE); #endif /* UNIV_SYNC_DEBUG */ - + mlog_write_ulint(prev_page + FIL_PAGE_DATA + BTR_BLOB_HDR_NEXT_PAGE_NO, page_no, MLOG_4BYTES, &mtr); @@ -3431,7 +3435,7 @@ btr_store_big_rec_extern_fields( mlog_write_ulint(page + FIL_PAGE_DATA + BTR_BLOB_HDR_NEXT_PAGE_NO, FIL_NULL, MLOG_4BYTES, &mtr); - + extern_len -= store_len; rec_page = buf_page_get(space_id, @@ -3457,7 +3461,7 @@ btr_store_big_rec_extern_fields( + BTR_EXTERN_PAGE_NO, page_no, MLOG_4BYTES, &mtr); - + mlog_write_ulint(data + local_len + BTR_EXTERN_OFFSET, FIL_PAGE_DATA, @@ -3504,9 +3508,9 @@ btr_free_externally_stored_field( ibool do_not_free_inherited,/* in: TRUE if called in a rollback and we do not want to free inherited fields */ - mtr_t* local_mtr __attribute__((unused))) /* in: mtr - containing the latch to data an an - X-latch to the index tree */ + mtr_t* local_mtr __attribute__((unused))) /* in: mtr + containing the latch to data an an + X-latch to the index tree */ { page_t* page; page_t* rec_page; @@ -3525,7 +3529,7 @@ btr_free_externally_stored_field( MTR_MEMO_PAGE_X_FIX)); ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); local_len -= BTR_EXTERN_FIELD_REF_SIZE; - + for (;;) { mtr_start(&mtr); @@ -3574,7 +3578,7 @@ btr_free_externally_stored_field( return; } - + page = buf_page_get(space_id, page_no, RW_X_LATCH, &mtr); #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_EXTERN_STORAGE); @@ -3637,7 +3641,7 @@ btr_rec_free_externally_stored_fields( MTR_MEMO_PAGE_X_FIX)); /* Free possible externally stored fields in the record */ - ut_ad(index->table->comp == !!rec_offs_comp(offsets)); + ut_ad(dict_table_is_comp(index->table) == !!rec_offs_comp(offsets)); n_fields = rec_offs_n_fields(offsets); for (i = 0; i < n_fields; i++) { @@ -3684,7 +3688,7 @@ btr_rec_free_updated_extern_fields( for (i = 0; i < n_fields; i++) { ufield = upd_get_nth_field(update, i); - + if (rec_offs_nth_extern(offsets, ufield->field_no)) { data = rec_get_nth_field(rec, offsets, @@ -3735,7 +3739,7 @@ btr_copy_externally_stored_field( /* Currently a BLOB cannot be bigger that 4 GB; we leave the 4 upper bytes in the length field unused */ - + extern_len = mach_read_from_4(data + local_len + BTR_EXTERN_LEN + 4); buf = mem_heap_alloc(heap, local_len + extern_len); @@ -3745,11 +3749,11 @@ btr_copy_externally_stored_field( if (extern_len == 0) { *len = copied_len; - + return(buf); } - for (;;) { + for (;;) { mtr_start(&mtr); page = buf_page_get(space_id, page_no, RW_S_LATCH, &mtr); @@ -3777,7 +3781,7 @@ btr_copy_externally_stored_field( ut_a(copied_len == local_len + extern_len); *len = copied_len; - + return(buf); } diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index 5dbbca0b17d..e3ba50a2d5b 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/innobase/btr/btr0pcur.c @@ -30,7 +30,7 @@ btr_pcur_create_for_mysql(void) pcur->btr_cur.index = NULL; btr_pcur_init(pcur); - + return(pcur); } @@ -53,7 +53,7 @@ btr_pcur_free_for_mysql( cursor->old_rec = NULL; cursor->old_n_fields = 0; cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; - + cursor->latch_mode = BTR_NO_LATCHES; cursor->pos_state = BTR_PCUR_NOT_POSITIONED; @@ -79,7 +79,7 @@ btr_pcur_store_position( dict_tree_t* tree; page_t* page; ulint offs; - + ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); @@ -92,9 +92,9 @@ btr_pcur_store_position( offs = ut_align_offset(rec, UNIV_PAGE_SIZE); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_S_FIX) - || mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_S_FIX) + || mtr_memo_contains(mtr, buf_block_align(page), + MTR_MEMO_PAGE_X_FIX)); ut_a(cursor->latch_mode != BTR_NO_LATCHES); if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) { @@ -115,7 +115,7 @@ btr_pcur_store_position( } return; - } + } if (page_rec_is_supremum_low(offs)) { @@ -138,7 +138,7 @@ btr_pcur_store_position( &cursor->old_rec_buf, &cursor->buf_size); - cursor->block_when_stored = buf_block_align(page); + cursor->block_when_stored = buf_block_align(page); cursor->modify_clock = buf_block_get_modify_clock( cursor->block_when_stored); } @@ -158,17 +158,17 @@ btr_pcur_copy_stored_position( mem_free(pcur_receive->old_rec_buf); } - ut_memcpy((byte*)pcur_receive, (byte*)pcur_donate, sizeof(btr_pcur_t)); + ut_memcpy(pcur_receive, pcur_donate, sizeof(btr_pcur_t)); if (pcur_donate->old_rec_buf) { pcur_receive->old_rec_buf = mem_alloc(pcur_donate->buf_size); - + ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf, pcur_donate->buf_size); pcur_receive->old_rec = pcur_receive->old_rec_buf + (pcur_donate->old_rec - pcur_donate->old_rec_buf); - } + } pcur_receive->old_n_fields = pcur_donate->old_n_fields; } @@ -195,7 +195,7 @@ btr_pcur_restore_position( whose ordering fields are identical to the ones of the original user record */ ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */ - btr_pcur_t* cursor, /* in: detached persistent cursor */ + btr_pcur_t* cursor, /* in: detached persistent cursor */ mtr_t* mtr) /* in: mtr */ { dict_tree_t* tree; @@ -206,21 +206,21 @@ btr_pcur_restore_position( mem_heap_t* heap; if (UNIV_UNLIKELY(cursor->old_stored != BTR_PCUR_OLD_STORED) - || UNIV_UNLIKELY(cursor->pos_state != BTR_PCUR_WAS_POSITIONED - && cursor->pos_state != BTR_PCUR_IS_POSITIONED)) { - ut_print_buf(stderr, (const byte*)cursor, sizeof(btr_pcur_t)); + || UNIV_UNLIKELY(cursor->pos_state != BTR_PCUR_WAS_POSITIONED + && cursor->pos_state != BTR_PCUR_IS_POSITIONED)) { + ut_print_buf(stderr, cursor, sizeof(btr_pcur_t)); if (cursor->trx_if_known) { trx_print(stderr, cursor->trx_if_known, 0); } - + ut_error; } if (UNIV_UNLIKELY(cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) { - /* In these cases we do not try an optimistic restoration, - but always do a search */ + /* In these cases we do not try an optimistic restoration, + but always do a search */ btr_cur_open_at_index_side( cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE, @@ -232,7 +232,7 @@ btr_pcur_restore_position( return(FALSE); } - + ut_a(cursor->old_rec); ut_a(cursor->old_n_fields); @@ -241,10 +241,10 @@ btr_pcur_restore_position( if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF) || UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) { /* Try optimistic restoration */ - + if (UNIV_LIKELY(buf_page_optimistic_get(latch_mode, - cursor->block_when_stored, page, - cursor->modify_clock, mtr))) { + cursor->block_when_stored, page, + cursor->modify_clock, mtr))) { cursor->pos_state = BTR_PCUR_IS_POSITIONED; #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_TREE_NODE); @@ -285,14 +285,14 @@ btr_pcur_restore_position( /* If optimistic restoration did not succeed, open the cursor anew */ heap = mem_heap_create(256); - + tree = btr_cur_get_tree(btr_pcur_get_btr_cur(cursor)); tuple = dict_tree_build_data_tuple(tree, cursor->old_rec, cursor->old_n_fields, heap); /* Save the old search mode of the cursor */ old_mode = cursor->search_mode; - + if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) { mode = PAGE_CUR_LE; } else if (cursor->rel_pos == BTR_PCUR_AFTER) { @@ -304,13 +304,13 @@ btr_pcur_restore_position( btr_pcur_open_with_no_init(btr_pcur_get_btr_cur(cursor)->index, tuple, mode, latch_mode, cursor, 0, mtr); - + /* Restore the old search mode */ cursor->search_mode = old_mode; if (cursor->rel_pos == BTR_PCUR_ON - && btr_pcur_is_on_user_rec(cursor, mtr) - && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), + && btr_pcur_is_on_user_rec(cursor, mtr) + && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), rec_get_offsets(btr_pcur_get_rec(cursor), btr_pcur_get_btr_cur(cursor)->index, NULL, ULINT_UNDEFINED, &heap))) { @@ -335,7 +335,7 @@ btr_pcur_restore_position( /* We have to store new position information, modify_clock etc., to the cursor because it can now be on a different page, the record under it may have been removed, etc. */ - + btr_pcur_store_position(cursor, mtr); return(FALSE); @@ -358,12 +358,12 @@ btr_pcur_release_leaf( ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor)); - + btr_leaf_page_release(page, cursor->latch_mode, mtr); - - cursor->latch_mode = BTR_NO_LATCHES; + + cursor->latch_mode = BTR_NO_LATCHES; cursor->pos_state = BTR_PCUR_WAS_POSITIONED; } @@ -386,25 +386,25 @@ btr_pcur_move_to_next_page( page_t* page; page_t* next_page; - ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - ut_ad(btr_pcur_is_after_last_on_page(cursor, mtr)); + ut_ad(btr_pcur_is_after_last_on_page(cursor, mtr)); cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; - + page = btr_pcur_get_page(cursor); next_page_no = btr_page_get_next(page, mtr); space = buf_frame_get_space_id(page); - ut_ad(next_page_no != FIL_NULL); + ut_ad(next_page_no != FIL_NULL); next_page = btr_page_get(space, next_page_no, cursor->latch_mode, mtr); ut_a(page_is_comp(next_page) == page_is_comp(page)); buf_block_align(next_page)->check_index_page_at_flush = TRUE; btr_leaf_page_release(page, cursor->latch_mode, mtr); - + page_cur_set_before_first(next_page, btr_pcur_get_page_cur(cursor)); page_check_dir(next_page); @@ -436,11 +436,11 @@ btr_pcur_move_backward_from_page( ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - ut_ad(btr_pcur_is_before_first_on_page(cursor, mtr)); - ut_ad(!btr_pcur_is_before_first_in_tree(cursor, mtr)); - + ut_ad(btr_pcur_is_before_first_on_page(cursor, mtr)); + ut_ad(!btr_pcur_is_before_first_in_tree(cursor, mtr)); + latch_mode = cursor->latch_mode; - + if (latch_mode == BTR_SEARCH_LEAF) { latch_mode2 = BTR_SEARCH_PREV; @@ -459,7 +459,7 @@ btr_pcur_move_backward_from_page( mtr_start(mtr); - btr_pcur_restore_position(latch_mode2, cursor, mtr); + btr_pcur_restore_position(latch_mode2, cursor, mtr); page = btr_pcur_get_page(cursor); @@ -467,7 +467,7 @@ btr_pcur_move_backward_from_page( space = buf_frame_get_space_id(page); if (btr_pcur_is_before_first_on_page(cursor, mtr) - && (prev_page_no != FIL_NULL)) { + && (prev_page_no != FIL_NULL)) { prev_page = btr_pcur_get_btr_cur(cursor)->left_page; @@ -476,11 +476,11 @@ btr_pcur_move_backward_from_page( page_cur_set_after_last(prev_page, btr_pcur_get_page_cur(cursor)); } else if (prev_page_no != FIL_NULL) { - + /* The repositioned cursor did not end on an infimum record on a page. Cursor repositioning acquired a latch also on the previous page, but we do not need the latch: release it. */ - + prev_page = btr_pcur_get_btr_cur(cursor)->left_page; btr_leaf_page_release(prev_page, latch_mode, mtr); @@ -506,7 +506,7 @@ btr_pcur_move_to_prev( { ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; if (btr_pcur_is_before_first_on_page(cursor, mtr)) { @@ -542,14 +542,14 @@ btr_pcur_open_on_user_rec( ulint mode, /* in: PAGE_CUR_L, ... */ ulint latch_mode, /* in: BTR_SEARCH_LEAF or BTR_MODIFY_LEAF */ - btr_pcur_t* cursor, /* in: memory buffer for persistent + btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */ mtr_t* mtr) /* in: mtr */ { btr_pcur_open(index, tuple, mode, latch_mode, cursor, mtr); if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) { - + if (btr_pcur_is_after_last_on_page(cursor, mtr)) { btr_pcur_move_to_next_user_rec(cursor, mtr); diff --git a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c index 7a4e92a672a..a2f571f11e9 100644 --- a/storage/innobase/btr/btr0sea.c +++ b/storage/innobase/btr/btr0sea.c @@ -103,7 +103,7 @@ btr_search_check_free_space_in_heap(void) table = btr_search_sys->hash_index; heap = table->heap; - + /* Note that we peek the value of heap->free_block without reserving the latch: this is ok, because we will not guarantee that there will be enough free space in the hash table. */ @@ -133,9 +133,9 @@ btr_search_sys_create( { /* We allocate the search latch from dynamic memory: see above at the global variable definition */ - + btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t)); - + rw_lock_create(&btr_search_latch); btr_search_sys = mem_alloc(sizeof(btr_search_sys_t)); @@ -169,10 +169,10 @@ btr_search_info_create( info->last_hash_succ = FALSE; - info->n_hash_succ = 0; - info->n_hash_fail = 0; - info->n_patt_succ = 0; - info->n_searches = 0; + info->n_hash_succ = 0; + info->n_hash_fail = 0; + info->n_patt_succ = 0; + info->n_searches = 0; /* Set some sensible values */ info->n_fields = 1; @@ -191,7 +191,7 @@ static void btr_search_info_update_hash( /*========================*/ - btr_search_t* info, /* in: search info */ + btr_search_t* info, /* in/out: search info */ btr_cur_t* cursor) /* in: cursor which was just positioned */ { dict_index_t* index; @@ -223,7 +223,7 @@ btr_search_info_update_hash( hash prefix */ if (info->n_fields >= n_unique && cursor->up_match >= n_unique) { - + info->n_hash_potential++; return; @@ -244,20 +244,20 @@ btr_search_info_update_hash( if ((info->side == BTR_SEARCH_LEFT_SIDE && cmp > 0) || (info->side == BTR_SEARCH_RIGHT_SIDE && cmp <= 0)) { - goto set_new_recomm; + goto set_new_recomm; } info->n_hash_potential++; return; - + set_new_recomm: /* We have to set a new recommendation; skip the hash analysis for a while to avoid unnecessary CPU time usage when there is no chance for success */ - + info->hash_analysis = 0; - + cmp = ut_pair_cmp(cursor->up_match, cursor->up_bytes, cursor->low_match, cursor->low_bytes); if (cmp == 0) { @@ -282,7 +282,7 @@ set_new_recomm: info->n_fields = cursor->low_match + 1; info->n_bytes = 0; - } else { + } else { info->n_fields = cursor->low_match; info->n_bytes = cursor->low_bytes + 1; } @@ -300,7 +300,7 @@ set_new_recomm: info->n_fields = cursor->up_match + 1; info->n_bytes = 0; - } else { + } else { info->n_fields = cursor->up_match; info->n_bytes = cursor->up_bytes + 1; } @@ -308,7 +308,7 @@ set_new_recomm: info->side = BTR_SEARCH_RIGHT_SIDE; } } - + /************************************************************************* Updates the block search info on hash successes. NOTE that info and block->n_hash_helps, n_fields, n_bytes, side are NOT protected by any @@ -337,19 +337,19 @@ btr_search_update_block_hash_info( ut_a(info->magic_n == BTR_SEARCH_MAGIC_N); if ((block->n_hash_helps > 0) - && (info->n_hash_potential > 0) - && (block->n_fields == info->n_fields) - && (block->n_bytes == info->n_bytes) - && (block->side == info->side)) { - + && (info->n_hash_potential > 0) + && (block->n_fields == info->n_fields) + && (block->n_bytes == info->n_bytes) + && (block->side == info->side)) { + if ((block->is_hashed) - && (block->curr_n_fields == info->n_fields) - && (block->curr_n_bytes == info->n_bytes) - && (block->curr_side == info->side)) { + && (block->curr_n_fields == info->n_fields) + && (block->curr_n_bytes == info->n_bytes) + && (block->curr_side == info->side)) { /* The search would presumably have succeeded using the hash index */ - + info->last_hash_succ = TRUE; } @@ -366,19 +366,19 @@ btr_search_update_block_hash_info( } if ((block->n_hash_helps > page_get_n_recs(block->frame) - / BTR_SEARCH_PAGE_BUILD_LIMIT) - && (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) { + / BTR_SEARCH_PAGE_BUILD_LIMIT) + && (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) { - if ((!block->is_hashed) - || (block->n_hash_helps + if ((!block->is_hashed) + || (block->n_hash_helps > 2 * page_get_n_recs(block->frame)) - || (block->n_fields != block->curr_n_fields) - || (block->n_bytes != block->curr_n_bytes) - || (block->side != block->curr_side)) { + || (block->n_fields != block->curr_n_fields) + || (block->n_bytes != block->curr_n_bytes) + || (block->side != block->curr_side)) { - /* Build a new hash index on the page */ + /* Build a new hash index on the page */ - return(TRUE); + return(TRUE); } } @@ -415,21 +415,21 @@ btr_search_update_hash_ref( ut_a(!block->is_hashed || block->index == cursor->index); if (block->is_hashed - && (info->n_hash_potential > 0) - && (block->curr_n_fields == info->n_fields) - && (block->curr_n_bytes == info->n_bytes) - && (block->curr_side == info->side)) { + && (info->n_hash_potential > 0) + && (block->curr_n_fields == info->n_fields) + && (block->curr_n_bytes == info->n_bytes) + && (block->curr_side == info->side)) { mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; *offsets_ = (sizeof offsets_) / sizeof *offsets_; - rec = btr_cur_get_rec(cursor); + rec = btr_cur_get_rec(cursor); + + if (!page_rec_is_user_rec(rec)) { - if (!page_rec_is_user_rec(rec)) { + return; + } - return; - } - tree_id = ((cursor->index)->tree)->id; fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_, ULINT_UNDEFINED, &heap), @@ -444,22 +444,22 @@ btr_search_update_hash_ref( ha_insert_for_fold(btr_search_sys->hash_index, fold, rec); } -} - +} + /************************************************************************* Updates the search info. */ void btr_search_info_update_slow( /*========================*/ - btr_search_t* info, /* in: search info */ + btr_search_t* info, /* in/out: search info */ btr_cur_t* cursor) /* in: cursor which was just positioned */ { buf_block_t* block; ibool build_index; ulint* params; ulint* params2; - + #ifdef UNIV_SYNC_DEBUG ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); @@ -480,7 +480,7 @@ btr_search_info_update_slow( btr_search_check_free_space_in_heap(); } - + if (cursor->flag == BTR_CUR_HASH_FAIL) { /* Update the hash node reference, if appropriate */ @@ -511,7 +511,7 @@ btr_search_info_update_slow( optimizations */ params2 = params + btr_search_this_is_zero; - + btr_search_build_page_hash_index(cursor->index, block->frame, params2[0], @@ -531,15 +531,15 @@ btr_search_check_guess( /*===================*/ /* out: TRUE if success */ btr_cur_t* cursor, /* in: guessed cursor position */ - ibool can_only_compare_to_cursor_rec, - /* in: if we do not have a latch on the page + ibool can_only_compare_to_cursor_rec, + /* in: if we do not have a latch on the page of cursor, but only a latch on - btr_search_latch, then ONLY the columns + btr_search_latch, then ONLY the columns of the record UNDER the cursor are protected, not the next or previous record in the chain: we cannot look at the next or previous record to check our guess! */ - dtuple_t* tuple, /* in: data tuple */ + dtuple_t* tuple, /* in: data tuple */ ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_GE */ mtr_t* mtr) /* in: mtr */ @@ -556,7 +556,7 @@ btr_search_check_guess( *offsets_ = (sizeof offsets_) / sizeof *offsets_; n_unique = dict_index_get_n_unique_in_tree(cursor->index); - + rec = btr_cur_get_rec(cursor); ut_ad(page_rec_is_user_rec(rec)); @@ -579,7 +579,7 @@ btr_search_check_guess( if (match >= n_unique) { success = TRUE; goto exit_func; - } + } } else if (mode == PAGE_CUR_LE) { if (cmp == -1) { goto exit_func; @@ -598,8 +598,8 @@ btr_search_check_guess( } if (can_only_compare_to_cursor_rec) { - /* Since we could not determine if our guess is right just by - looking at the record under the cursor, return FALSE */ + /* Since we could not determine if our guess is right just by + looking at the record under the cursor, return FALSE */ goto exit_func; } @@ -610,7 +610,7 @@ btr_search_check_guess( rec_t* prev_rec; ut_ad(!page_rec_is_infimum(rec)); - + prev_rec = page_rec_get_prev(rec); if (page_rec_is_infimum(prev_rec)) { @@ -635,7 +635,7 @@ btr_search_check_guess( rec_t* next_rec; ut_ad(!page_rec_is_supremum(rec)); - + next_rec = page_rec_get_next(rec); if (page_rec_is_supremum(next_rec)) { @@ -676,18 +676,18 @@ both have sensible values. */ ibool btr_search_guess_on_hash( /*=====================*/ - /* out: TRUE if succeeded */ + /* out: TRUE if succeeded */ dict_index_t* index, /* in: index */ btr_search_t* info, /* in: index search info */ dtuple_t* tuple, /* in: logical record */ ulint mode, /* in: PAGE_CUR_L, ... */ - ulint latch_mode, /* in: BTR_SEARCH_LEAF, ...; + ulint latch_mode, /* in: BTR_SEARCH_LEAF, ...; NOTE that only if has_search_latch is 0, we will have a latch set on the cursor page, otherwise we assume the caller uses his search latch to protect the record! */ - btr_cur_t* cursor, /* out: tree cursor */ + btr_cur_t* cursor, /* out: tree cursor */ ulint has_search_latch,/* in: latch mode the caller currently has on btr_search_latch: RW_S_LATCH, RW_X_LATCH, or 0 */ @@ -699,7 +699,7 @@ btr_search_guess_on_hash( ulint fold; ulint tuple_n_fields; dulint tree_id; - ibool can_only_compare_to_cursor_rec = TRUE; + ibool can_only_compare_to_cursor_rec = TRUE; #ifdef notdefined btr_cur_t cursor2; btr_pcur_t pcur; @@ -729,7 +729,7 @@ btr_search_guess_on_hash( if (UNIV_UNLIKELY(tuple_n_fields == cursor->n_fields) && (cursor->n_bytes > 0)) { - return(FALSE); + return(FALSE); } tree_id = (index->tree)->id; @@ -741,7 +741,7 @@ btr_search_guess_on_hash( cursor->fold = fold; cursor->flag = BTR_CUR_HASH; - + if (UNIV_LIKELY(!has_search_latch)) { rw_lock_s_lock(&btr_search_latch); } @@ -778,7 +778,7 @@ btr_search_guess_on_hash( if (UNIV_UNLIKELY(block->state == BUF_BLOCK_REMOVE_HASH)) { if (UNIV_LIKELY(!has_search_latch)) { - + btr_leaf_page_release(page, latch_mode, mtr); } @@ -798,29 +798,29 @@ btr_search_guess_on_hash( record to determine if our guess for the cursor position is right. */ if (UNIV_EXPECT(ut_dulint_cmp(tree_id, btr_page_get_index_id(page)), 0) - || !btr_search_check_guess(cursor, can_only_compare_to_cursor_rec, - tuple, mode, mtr)) { + || !btr_search_check_guess(cursor, + can_only_compare_to_cursor_rec, tuple, mode, mtr)) { if (UNIV_LIKELY(!has_search_latch)) { - btr_leaf_page_release(page, latch_mode, mtr); + btr_leaf_page_release(page, latch_mode, mtr); } goto failure; } if (UNIV_LIKELY(info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5)) { - + info->n_hash_potential++; } #ifdef notdefined /* These lines of code can be used in a debug version to check the correctness of the searched cursor position: */ - + info->last_hash_succ = FALSE; /* Currently, does not work if the following fails: */ ut_ad(!has_search_latch); - + btr_leaf_page_release(page, latch_mode, mtr); btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode, @@ -831,7 +831,7 @@ btr_search_guess_on_hash( /* If mode is PAGE_CUR_GE, then the binary search in the index tree may actually take us to the supremum of the previous page */ - + info->last_hash_succ = FALSE; btr_pcur_open_on_user_rec(index, tuple, mode, latch_mode, @@ -854,14 +854,14 @@ btr_search_guess_on_hash( && buf_block_peek_if_too_old(block)) { buf_page_make_young(page); - } + } /* Increment the page get statistics though we did not really fix the page: for user info only */ buf_pool->n_page_gets++; - return(TRUE); + return(TRUE); /*-------------------------------------------*/ failure_unlock: @@ -889,7 +889,8 @@ Drops a page hash index. */ void btr_search_drop_page_hash_index( /*============================*/ - page_t* page) /* in: index page, s- or x-latched */ + page_t* page) /* in: index page, s- or x-latched, or an index page + for which we know that block->buf_fix_count == 0 */ { hash_table_t* table; buf_block_t* block; @@ -904,18 +905,19 @@ btr_search_drop_page_hash_index( ulint* folds; ulint i; mem_heap_t* heap; + dict_index_t* index; ulint* offsets; #ifdef UNIV_SYNC_DEBUG ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - +retry: rw_lock_s_lock(&btr_search_latch); block = buf_block_align(page); - if (!block->is_hashed) { + if (UNIV_LIKELY(!block->is_hashed)) { rw_lock_s_unlock(&btr_search_latch); @@ -926,17 +928,22 @@ btr_search_drop_page_hash_index( #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED) - || rw_lock_own(&(block->lock), RW_LOCK_EX) - || (block->buf_fix_count == 0)); + || rw_lock_own(&(block->lock), RW_LOCK_EX) + || (block->buf_fix_count == 0)); #endif /* UNIV_SYNC_DEBUG */ n_fields = block->curr_n_fields; n_bytes = block->curr_n_bytes; + index = block->index; - ut_a(n_fields + n_bytes > 0); + /* NOTE: The fields of block must not be accessed after + releasing btr_search_latch, as the index page might only + be s-latched! */ rw_lock_s_unlock(&btr_search_latch); - + + ut_a(n_fields + n_bytes > 0); + n_recs = page_get_n_recs(page); /* Calculate and cache fold values into an array for fast deletion @@ -949,33 +956,21 @@ btr_search_drop_page_hash_index( rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); - if (!page_rec_is_supremum(rec)) { - ut_a(n_fields <= rec_get_n_fields(rec, block->index)); + tree_id = btr_page_get_index_id(page); - if (n_bytes > 0) { - ut_a(n_fields < rec_get_n_fields(rec, block->index)); - } - } + ut_a(0 == ut_dulint_cmp(tree_id, index->id)); - tree_id = btr_page_get_index_id(page); - prev_fold = 0; heap = NULL; offsets = NULL; - if (block->index == NULL) { - - mem_analyze_corruption((byte*)block); - - ut_a(block->index != NULL); - } - while (!page_rec_is_supremum(rec)) { /* FIXME: in a mixed tree, not all records may have enough ordering fields: */ - offsets = rec_get_offsets(rec, block->index, - offsets, n_fields + (n_bytes > 0), &heap); + offsets = rec_get_offsets(rec, index, offsets, + n_fields + (n_bytes > 0), &heap); + ut_a(rec_offs_n_fields(offsets) == n_fields + (n_bytes > 0)); fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id); if (fold == prev_fold && prev_fold != 0) { @@ -999,6 +994,26 @@ next_rec: rw_lock_x_lock(&btr_search_latch); + if (UNIV_UNLIKELY(!block->is_hashed)) { + /* Someone else has meanwhile dropped the hash index */ + + goto cleanup; + } + + ut_a(block->index == index); + + if (UNIV_UNLIKELY(block->curr_n_fields != n_fields) + || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) { + + /* Someone else has meanwhile built a new hash index on the + page, with different parameters */ + + rw_lock_x_unlock(&btr_search_latch); + + mem_free(folds); + goto retry; + } + for (i = 0; i < n_cached; i++) { ha_remove_all_nodes_to_page(table, folds[i], page); @@ -1006,8 +1021,20 @@ next_rec: block->is_hashed = FALSE; block->index = NULL; +cleanup: + if (UNIV_UNLIKELY(block->n_pointers)) { + /* Corruption */ + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: Corruption of adaptive hash index. After dropping\n" +"InnoDB: the hash index to a page of %s, still %lu hash nodes remain.\n", + index->name, (ulong) block->n_pointers); + rw_lock_x_unlock(&btr_search_latch); - rw_lock_x_unlock(&btr_search_latch); + btr_search_validate(); + } else { + rw_lock_x_unlock(&btr_search_latch); + } mem_free(folds); } @@ -1032,14 +1059,14 @@ btr_search_drop_page_hash_when_freed( return; } - + mtr_start(&mtr); /* We assume that if the caller has a latch on the page, then the caller has already dropped the hash index for the page, and we never get here. Therefore we can acquire the s-latch to the page without having to fear a deadlock. */ - + page = buf_page_get_gen(space, page_no, RW_S_LATCH, NULL, BUF_GET_IF_IN_POOL, __FILE__, __LINE__, &mtr); @@ -1098,10 +1125,10 @@ btr_search_build_page_hash_index( #endif /* UNIV_SYNC_DEBUG */ rw_lock_s_lock(&btr_search_latch); - + if (block->is_hashed && ((block->curr_n_fields != n_fields) - || (block->curr_n_bytes != n_bytes) - || (block->curr_side != side))) { + || (block->curr_n_bytes != n_bytes) + || (block->curr_side != side))) { rw_lock_s_unlock(&btr_search_latch); @@ -1118,15 +1145,15 @@ btr_search_build_page_hash_index( } /* Check that the values for hash index build are sensible */ - + if (n_fields + n_bytes == 0) { return; } if (dict_index_get_n_unique_in_tree(index) < n_fields - || (dict_index_get_n_unique_in_tree(index) == n_fields - && n_bytes > 0)) { + || (dict_index_get_n_unique_in_tree(index) == n_fields + && n_bytes > 0)) { return; } @@ -1164,20 +1191,20 @@ btr_search_build_page_hash_index( recs[n_cached] = rec; n_cached++; } - + for (;;) { next_rec = page_rec_get_next(rec); if (page_rec_is_supremum(next_rec)) { if (side == BTR_SEARCH_RIGHT_SIDE) { - + folds[n_cached] = fold; recs[n_cached] = rec; n_cached++; } - break; + break; } offsets = rec_get_offsets(next_rec, index, offsets, @@ -1209,21 +1236,21 @@ btr_search_build_page_hash_index( rw_lock_x_lock(&btr_search_latch); if (block->is_hashed && ((block->curr_n_fields != n_fields) - || (block->curr_n_bytes != n_bytes) - || (block->curr_side != side))) { + || (block->curr_n_bytes != n_bytes) + || (block->curr_side != side))) { goto exit_func; } - + block->is_hashed = TRUE; block->n_hash_helps = 0; - + block->curr_n_fields = n_fields; block->curr_n_bytes = n_bytes; block->curr_side = side; block->index = index; for (i = 0; i < n_cached; i++) { - + ha_insert_for_fold(table, folds[i], recs[i]); } @@ -1272,7 +1299,7 @@ btr_search_move_or_delete_hash_entries( ut_a(!block->is_hashed || block->index == index); rw_lock_s_lock(&btr_search_latch); - + if (new_block->is_hashed) { rw_lock_s_unlock(&btr_search_latch); @@ -1393,13 +1420,13 @@ btr_search_update_hash_node_on_insert( rw_lock_x_lock(&btr_search_latch); if ((cursor->flag == BTR_CUR_HASH) - && (cursor->n_fields == block->curr_n_fields) - && (cursor->n_bytes == block->curr_n_bytes) - && (block->curr_side == BTR_SEARCH_RIGHT_SIDE)) { + && (cursor->n_fields == block->curr_n_fields) + && (cursor->n_bytes == block->curr_n_bytes) + && (block->curr_side == BTR_SEARCH_RIGHT_SIDE)) { + + table = btr_search_sys->hash_index; - table = btr_search_sys->hash_index; - - ha_search_and_update_if_found(table, cursor->fold, rec, + ha_search_and_update_if_found(table, cursor->fold, rec, page_rec_get_next(rec)); rw_lock_x_unlock(&btr_search_latch); @@ -1421,7 +1448,7 @@ btr_search_update_hash_on_insert( and the new record has been inserted next to the cursor */ { - hash_table_t* table; + hash_table_t* table; buf_block_t* block; rec_t* rec; rec_t* ins_rec; @@ -1450,7 +1477,7 @@ btr_search_update_hash_on_insert( #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - + if (!block->is_hashed) { return; @@ -1494,10 +1521,10 @@ btr_search_update_hash_on_insert( goto check_next_rec; } - - if (fold != ins_fold) { - if (!locked) { + if (fold != ins_fold) { + + if (!locked) { rw_lock_x_lock(&btr_search_latch); @@ -1516,22 +1543,22 @@ check_next_rec: if (side == BTR_SEARCH_RIGHT_SIDE) { - if (!locked) { + if (!locked) { rw_lock_x_lock(&btr_search_latch); locked = TRUE; } - + ha_insert_for_fold(table, ins_fold, ins_rec); } goto function_exit; } - + if (ins_fold != next_fold) { - if (!locked) { - + if (!locked) { + rw_lock_x_lock(&btr_search_latch); locked = TRUE; @@ -1548,8 +1575,8 @@ check_next_rec: } else { ha_insert_for_fold(table, next_fold, next_rec); } - } - + } + function_exit: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -1573,14 +1600,29 @@ btr_search_validate(void) ulint n_page_dumps = 0; ibool ok = TRUE; ulint i; + ulint cell_count; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_; - + + /* How many cells to check before temporarily releasing + btr_search_latch. */ + ulint chunk_size = 10000; + rw_lock_x_lock(&btr_search_latch); - for (i = 0; i < hash_get_n_cells(btr_search_sys->hash_index); i++) { + cell_count = hash_get_n_cells(btr_search_sys->hash_index); + + for (i = 0; i < cell_count; i++) { + /* We release btr_search_latch every once in a while to + give other queries a chance to run. */ + if ((i != 0) && ((i % chunk_size) == 0)) { + rw_lock_x_unlock(&btr_search_latch); + os_thread_yield(); + rw_lock_x_lock(&btr_search_latch); + } + node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node; while (node != NULL) { @@ -1592,11 +1634,11 @@ btr_search_validate(void) + (block->curr_n_bytes > 0), &heap); if (!block->is_hashed - || node->fold != rec_fold((rec_t*)(node->data), - offsets, - block->curr_n_fields, - block->curr_n_bytes, - btr_page_get_index_id(page))) { + || node->fold != rec_fold((rec_t*)(node->data), + offsets, + block->curr_n_fields, + block->curr_n_bytes, + btr_page_get_index_id(page))) { ok = FALSE; ut_print_timestamp(stderr); @@ -1610,9 +1652,9 @@ btr_search_validate(void) (ulong) node->fold, (ulong) rec_fold((rec_t*)(node->data), offsets, - block->curr_n_fields, - block->curr_n_bytes, - btr_page_get_index_id(page))); + block->curr_n_fields, + block->curr_n_bytes, + btr_page_get_index_id(page))); fputs("InnoDB: Record ", stderr); rec_print_new(stderr, (rec_t*)node->data, @@ -1620,11 +1662,11 @@ btr_search_validate(void) fprintf(stderr, "\nInnoDB: on that page." "Page mem address %p, is hashed %lu, n fields %lu, n bytes %lu\n" "side %lu\n", - page, (ulong) block->is_hashed, - (ulong) block->curr_n_fields, - (ulong) block->curr_n_bytes, (ulong) block->curr_side); + page, (ulong) block->is_hashed, + (ulong) block->curr_n_fields, + (ulong) block->curr_n_bytes, (ulong) block->curr_side); - if (n_page_dumps < 20) { + if (n_page_dumps < 20) { buf_page_print(page); n_page_dumps++; } @@ -1633,10 +1675,21 @@ btr_search_validate(void) node = node->next; } } - - if (!ha_validate(btr_search_sys->hash_index)) { - ok = FALSE; + for (i = 0; i < cell_count; i += chunk_size) { + ulint end_index = ut_min(i + chunk_size - 1, cell_count - 1); + + /* We release btr_search_latch every once in a while to + give other queries a chance to run. */ + if (i != 0) { + rw_lock_x_unlock(&btr_search_latch); + os_thread_yield(); + rw_lock_x_lock(&btr_search_latch); + } + + if (!ha_validate(btr_search_sys->hash_index, i, end_index)) { + ok = FALSE; + } } rw_lock_x_unlock(&btr_search_latch); diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index 3a3b64dd51b..197b38149fe 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -1,14 +1,14 @@ /* Innobase relational database engine; Copyright (C) 2001 Innobase Oy - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License 2 as published by the Free Software Foundation in June 1991. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License 2 along with this program (in file COPYING); if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ @@ -42,7 +42,7 @@ Created 11/5/1995 Heikki Tuuri IMPLEMENTATION OF THE BUFFER POOL ================================= -Performance improvement: +Performance improvement: ------------------------ Thread scheduling in NT may be so slow that the OS wait mechanism should not be used even in waiting for disk reads to complete. @@ -239,33 +239,33 @@ to a file. Note that we must be careful to calculate the same value on ulint buf_calc_page_new_checksum( /*=======================*/ - /* out: checksum */ - byte* page) /* in: buffer page */ + /* out: checksum */ + byte* page) /* in: buffer page */ { - ulint checksum; + ulint checksum; - /* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x - ..._ARCH_LOG_NO, are written outside the buffer pool to the first - pages of data files, we have to skip them in the page checksum - calculation. + /* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x + ..._ARCH_LOG_NO, are written outside the buffer pool to the first + pages of data files, we have to skip them in the page checksum + calculation. We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the checksum is stored, and also the last 8 bytes of page because there we store the old formula checksum. */ - - checksum = ut_fold_binary(page + FIL_PAGE_OFFSET, + + checksum = ut_fold_binary(page + FIL_PAGE_OFFSET, FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET) - + ut_fold_binary(page + FIL_PAGE_DATA, - UNIV_PAGE_SIZE - FIL_PAGE_DATA - - FIL_PAGE_END_LSN_OLD_CHKSUM); - checksum = checksum & 0xFFFFFFFFUL; + + ut_fold_binary(page + FIL_PAGE_DATA, + UNIV_PAGE_SIZE - FIL_PAGE_DATA + - FIL_PAGE_END_LSN_OLD_CHKSUM); + checksum = checksum & 0xFFFFFFFFUL; - return(checksum); + return(checksum); } /************************************************************************ In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only looked at the first few bytes of the page. This calculates that old -checksum. +checksum. NOTE: we must first store the new formula checksum to FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum because this takes that field as an input! */ @@ -273,16 +273,16 @@ because this takes that field as an input! */ ulint buf_calc_page_old_checksum( /*=======================*/ - /* out: checksum */ - byte* page) /* in: buffer page */ + /* out: checksum */ + byte* page) /* in: buffer page */ { - ulint checksum; - - checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN); + ulint checksum; + + checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN); - checksum = checksum & 0xFFFFFFFFUL; + checksum = checksum & 0xFFFFFFFFUL; - return(checksum); + return(checksum); } /************************************************************************ @@ -302,11 +302,11 @@ buf_page_is_corrupted( dulint current_lsn; #endif if (mach_read_from_4(read_buf + FIL_PAGE_LSN + 4) - != mach_read_from_4(read_buf + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { + != mach_read_from_4(read_buf + UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { /* Stored log sequence numbers at the start and the end - of page do not match */ + of page do not match */ return(TRUE); } @@ -314,8 +314,8 @@ buf_page_is_corrupted( #ifndef UNIV_HOTBACKUP if (recv_lsn_checks_on && log_peek_lsn(¤t_lsn)) { if (ut_dulint_cmp(current_lsn, - mach_read_from_8(read_buf + FIL_PAGE_LSN)) - < 0) { + mach_read_from_8(read_buf + FIL_PAGE_LSN)) + < 0) { ut_print_timestamp(stderr); fprintf(stderr, @@ -324,53 +324,58 @@ buf_page_is_corrupted( "InnoDB: Your database may be corrupt or you may have copied the InnoDB\n" "InnoDB: tablespace but not the InnoDB log files. See\n" "http://dev.mysql.com/doc/mysql/en/backing-up.html for more information.\n", - (ulong) mach_read_from_4(read_buf + FIL_PAGE_OFFSET), - (ulong) ut_dulint_get_high( - mach_read_from_8(read_buf + FIL_PAGE_LSN)), - (ulong) ut_dulint_get_low( - mach_read_from_8(read_buf + FIL_PAGE_LSN)), - (ulong) ut_dulint_get_high(current_lsn), - (ulong) ut_dulint_get_low(current_lsn)); + (ulong) mach_read_from_4(read_buf + FIL_PAGE_OFFSET), + (ulong) ut_dulint_get_high( + mach_read_from_8(read_buf + FIL_PAGE_LSN)), + (ulong) ut_dulint_get_low( + mach_read_from_8(read_buf + FIL_PAGE_LSN)), + (ulong) ut_dulint_get_high(current_lsn), + (ulong) ut_dulint_get_low(current_lsn)); } } #endif - - /* If we use checksums validation, make additional check before returning - TRUE to ensure that the checksum is not equal to BUF_NO_CHECKSUM_MAGIC which - might be stored by InnoDB with checksums disabled. - Otherwise, skip checksum calculation and return FALSE */ - - if (srv_use_checksums) { - old_checksum = buf_calc_page_old_checksum(read_buf); - - old_checksum_field = mach_read_from_4(read_buf + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN_OLD_CHKSUM); - - /* There are 2 valid formulas for old_checksum_field: - 1. Very old versions of InnoDB only stored 8 byte lsn to the start - and the end of the page. - 2. Newer InnoDB versions store the old formula checksum there. */ - - if (old_checksum_field != mach_read_from_4(read_buf + FIL_PAGE_LSN) - && old_checksum_field != old_checksum - && old_checksum_field != BUF_NO_CHECKSUM_MAGIC) { - - return(TRUE); - } - - checksum = buf_calc_page_new_checksum(read_buf); - checksum_field = mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM); - - /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id - (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */ - - if (checksum_field != 0 && checksum_field != checksum - && checksum_field != BUF_NO_CHECKSUM_MAGIC) { - - return(TRUE); - } - } - + + /* If we use checksums validation, make additional check before + returning TRUE to ensure that the checksum is not equal to + BUF_NO_CHECKSUM_MAGIC which might be stored by InnoDB with checksums + disabled. Otherwise, skip checksum calculation and return FALSE */ + + if (srv_use_checksums) { + old_checksum = buf_calc_page_old_checksum(read_buf); + + old_checksum_field = mach_read_from_4(read_buf + UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM); + + /* There are 2 valid formulas for old_checksum_field: + + 1. Very old versions of InnoDB only stored 8 byte lsn to the + start and the end of the page. + + 2. Newer InnoDB versions store the old formula checksum + there. */ + + if (old_checksum_field != mach_read_from_4(read_buf + + FIL_PAGE_LSN) + && old_checksum_field != old_checksum + && old_checksum_field != BUF_NO_CHECKSUM_MAGIC) { + + return(TRUE); + } + + checksum = buf_calc_page_new_checksum(read_buf); + checksum_field = mach_read_from_4(read_buf + + FIL_PAGE_SPACE_OR_CHKSUM); + + /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id + (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */ + + if (checksum_field != 0 && checksum_field != checksum + && checksum_field != BUF_NO_CHECKSUM_MAGIC) { + + return(TRUE); + } + } + return(FALSE); } @@ -393,12 +398,12 @@ buf_page_print( fputs("InnoDB: End of page dump\n", stderr); checksum = srv_use_checksums ? - buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC; + buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC; old_checksum = srv_use_checksums ? - buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC; + buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC; ut_print_timestamp(stderr); - fprintf(stderr, + fprintf(stderr, " InnoDB: Page checksum %lu, prior-to-4.0.14-form checksum %lu\n" "InnoDB: stored checksum %lu, prior-to-4.0.14-form stored checksum %lu\n", (ulong) checksum, (ulong) old_checksum, @@ -417,18 +422,19 @@ buf_page_print( (ulong) mach_read_from_4(read_buf + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID)); if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) - == TRX_UNDO_INSERT) { - fprintf(stderr, + == TRX_UNDO_INSERT) { + fprintf(stderr, "InnoDB: Page may be an insert undo log page\n"); } else if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) - == TRX_UNDO_UPDATE) { - fprintf(stderr, + == TRX_UNDO_UPDATE) { + fprintf(stderr, "InnoDB: Page may be an update undo log page\n"); } - if (fil_page_get_type(read_buf) == FIL_PAGE_INDEX) { - fprintf(stderr, + switch (fil_page_get_type(read_buf)) { + case FIL_PAGE_INDEX: + fprintf(stderr, "InnoDB: Page may be an index page where index id is %lu %lu\n", (ulong) ut_dulint_get_high(btr_page_get_index_id(read_buf)), (ulong) ut_dulint_get_low(btr_page_get_index_id(read_buf))); @@ -438,19 +444,50 @@ buf_page_print( if (dict_sys != NULL) { - index = dict_index_find_on_id_low( + index = dict_index_find_on_id_low( btr_page_get_index_id(read_buf)); - if (index) { + if (index) { fputs("InnoDB: (", stderr); dict_index_name_print(stderr, NULL, index); fputs(")\n", stderr); } } - } else if (fil_page_get_type(read_buf) == FIL_PAGE_INODE) { + break; + case FIL_PAGE_INODE: fputs("InnoDB: Page may be an 'inode' page\n", stderr); - } else if (fil_page_get_type(read_buf) == FIL_PAGE_IBUF_FREE_LIST) { + break; + case FIL_PAGE_IBUF_FREE_LIST: fputs("InnoDB: Page may be an insert buffer free list page\n", stderr); + break; + case FIL_PAGE_TYPE_ALLOCATED: + fputs("InnoDB: Page may be a freshly allocated page\n", + stderr); + break; + case FIL_PAGE_IBUF_BITMAP: + fputs("InnoDB: Page may be an insert buffer bitmap page\n", + stderr); + break; + case FIL_PAGE_TYPE_SYS: + fputs("InnoDB: Page may be a system page\n", + stderr); + break; + case FIL_PAGE_TYPE_TRX_SYS: + fputs("InnoDB: Page may be a transaction system page\n", + stderr); + break; + case FIL_PAGE_TYPE_FSP_HDR: + fputs("InnoDB: Page may be a file space header page\n", + stderr); + break; + case FIL_PAGE_TYPE_XDES: + fputs("InnoDB: Page may be an extent descriptor page\n", + stderr); + break; + case FIL_PAGE_TYPE_BLOB: + fputs("InnoDB: Page may be a BLOB page\n", + stderr); + break; } } @@ -464,14 +501,19 @@ buf_block_init( byte* frame) /* in: pointer to buffer frame, or NULL if in the case of AWE there is no frame */ { + block->magic_n = 0; + block->state = BUF_BLOCK_NOT_USED; - + block->frame = frame; block->awe_info = NULL; + block->buf_fix_count = 0; + block->io_fix = 0; + block->modify_clock = ut_dulint_zero; - + block->file_page_was_freed = FALSE; block->check_index_page_at_flush = FALSE; @@ -513,12 +555,12 @@ buf_pool_init( byte* frame; ulint i; buf_block_t* block; - + ut_a(max_size == curr_size); ut_a(srv_use_awe || n_frames == max_size); - + if (n_frames > curr_size) { - fprintf(stderr, + fprintf(stderr, "InnoDB: AWE: Error: you must specify in my.cnf .._awe_mem_mb larger\n" "InnoDB: than .._buffer_pool_size. Now the former is %lu pages,\n" "InnoDB: the latter %lu pages.\n", (ulong) curr_size, (ulong) n_frames); @@ -542,18 +584,18 @@ buf_pool_init( buf_pool->frame_mem = os_awe_allocate_virtual_mem_window( UNIV_PAGE_SIZE * (n_frames + 1)); - + /* Allocate the physical memory for AWE and the AWE info array for buf_pool */ if ((curr_size % ((1024 * 1024) / UNIV_PAGE_SIZE)) != 0) { - fprintf(stderr, + fprintf(stderr, "InnoDB: AWE: Error: physical memory must be allocated in full megabytes.\n" -"InnoDB: Trying to allocate %lu database pages.\n", +"InnoDB: Trying to allocate %lu database pages.\n", (ulong) curr_size); - return(NULL); + return(NULL); } if (!os_awe_allocate_physical_mem(&(buf_pool->awe_info), @@ -605,7 +647,7 @@ buf_pool_init( } buf_pool->blocks_of_frames = ut_malloc(sizeof(void*) * n_frames); - + if (buf_pool->blocks_of_frames == NULL) { return(NULL); @@ -626,7 +668,7 @@ buf_pool_init( } else { frame = NULL; } - + buf_block_init(block, frame); if (srv_use_awe) { @@ -647,14 +689,14 @@ buf_pool_init( buf_pool->n_pages_written = 0; buf_pool->n_pages_created = 0; buf_pool->n_pages_awe_remapped = 0; - + buf_pool->n_page_gets = 0; buf_pool->n_page_gets_old = 0; buf_pool->n_pages_read_old = 0; buf_pool->n_pages_written_old = 0; buf_pool->n_pages_created_old = 0; buf_pool->n_pages_awe_remapped_old = 0; - + /* 2. Initialize flushing fields ---------------------------- */ UT_LIST_INIT(buf_pool->flush_list); @@ -669,7 +711,7 @@ buf_pool_init( buf_pool->ulint_clock = 1; buf_pool->freed_page_clock = 0; - + /* 3. Initialize LRU fields ---------------------------- */ UT_LIST_INIT(buf_pool->LRU); @@ -695,7 +737,7 @@ buf_pool_init( if (srv_use_awe) { /* Add to the list of blocks mapped to frames */ - + UT_LIST_ADD_LAST(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } @@ -708,15 +750,15 @@ buf_pool_init( mutex_exit(&(buf_pool->mutex)); if (srv_use_adaptive_hash_indexes) { - btr_search_sys_create( + btr_search_sys_create( curr_size * UNIV_PAGE_SIZE / sizeof(void*) / 64); } else { - /* Create only a small dummy system */ - btr_search_sys_create(1000); + /* Create only a small dummy system */ + btr_search_sys_create(1000); } return(buf_pool); -} +} /************************************************************************ Maps the page of block to a frame, if not mapped yet. Unmaps some page @@ -749,9 +791,9 @@ buf_awe_map_page_to_frame( bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped); - while (bck) { + while (bck) { if (bck->state == BUF_BLOCK_FILE_PAGE - && (bck->buf_fix_count != 0 || bck->io_fix != 0)) { + && (bck->buf_fix_count != 0 || bck->io_fix != 0)) { /* We have to skip this */ bck = UT_LIST_GET_PREV(awe_LRU_free_mapped, bck); @@ -770,7 +812,7 @@ buf_awe_map_page_to_frame( - buf_pool->frame_zero)) >> UNIV_PAGE_SIZE_SHIFT)) = block; - + bck->frame = NULL; UT_LIST_REMOVE(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, @@ -783,7 +825,7 @@ buf_awe_map_page_to_frame( } buf_pool->n_pages_awe_remapped++; - + return; } } @@ -822,7 +864,7 @@ buf_block_make_young( /*=================*/ buf_block_t* block) /* in: block to make younger */ { - if (buf_pool->freed_page_clock >= block->freed_page_clock + if (buf_pool->freed_page_clock >= block->freed_page_clock + 1 + (buf_pool->curr_size / 1024)) { /* There has been freeing activity in the LRU list: @@ -839,11 +881,11 @@ the buffer pool. */ void buf_page_make_young( -/*=================*/ +/*================*/ buf_frame_t* frame) /* in: buffer frame of a file page */ { buf_block_t* block; - + mutex_enter(&(buf_pool->mutex)); block = buf_block_align(frame); @@ -893,7 +935,7 @@ buf_frame_free( { buf_block_free(buf_block_align(frame)); } - + /************************************************************************ Returns the buffer control block if the page can be found in the buffer pool. NOTE that it is possible that the page is not yet read @@ -938,7 +980,7 @@ buf_reset_check_index_page_at_flush( if (block) { block->check_index_page_at_flush = FALSE; } - + mutex_exit(&(buf_pool->mutex)); } @@ -1074,14 +1116,14 @@ buf_page_get_gen( ulint fix_type; ibool success; ibool must_read; - + ut_ad(mtr); ut_ad((rw_latch == RW_S_LATCH) - || (rw_latch == RW_X_LATCH) - || (rw_latch == RW_NO_LATCH)); + || (rw_latch == RW_X_LATCH) + || (rw_latch == RW_NO_LATCH)); ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH)); ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL) - || (mode == BUF_GET_NO_LATCH) || (mode == BUF_GET_NOWAIT)); + || (mode == BUF_GET_NO_LATCH) || (mode == BUF_GET_NOWAIT)); #ifndef UNIV_LOG_DEBUG ut_ad(!ibuf_inside() || ibuf_page(space, offset)); #endif @@ -1090,7 +1132,7 @@ loop: mutex_enter_fast(&(buf_pool->mutex)); block = NULL; - + if (guess) { block = buf_block_align(guess); @@ -1130,7 +1172,7 @@ loop: ut_a(block->state == BUF_BLOCK_FILE_PAGE); must_read = FALSE; - + if (block->io_fix == BUF_IO_READ) { must_read = TRUE; @@ -1142,7 +1184,7 @@ loop: return(NULL); } - } + } /* If AWE is enabled and the page is not mapped to a frame, then map it */ @@ -1153,10 +1195,10 @@ loop: /* We set second parameter TRUE because the block is in the LRU list and we must put it to awe_LRU_free_mapped list once mapped to a frame */ - + buf_awe_map_page_to_frame(block, TRUE); } - + #ifdef UNIV_SYNC_DEBUG buf_block_buf_fix_inc_debug(block, file, line); #else @@ -1172,7 +1214,7 @@ loop: #ifdef UNIV_DEBUG_FILE_ACCESSES ut_a(block->file_page_was_freed == FALSE); -#endif +#endif mutex_exit(&(buf_pool->mutex)); #ifdef UNIV_DEBUG @@ -1203,7 +1245,7 @@ loop: block->buf_fix_count--; #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); -#endif +#endif mutex_exit(&(buf_pool->mutex)); return(NULL); @@ -1211,24 +1253,24 @@ loop: } else if (rw_latch == RW_NO_LATCH) { if (must_read) { - /* Let us wait until the read operation + /* Let us wait until the read operation completes */ - for (;;) { - mutex_enter(&(buf_pool->mutex)); + for (;;) { + mutex_enter(&(buf_pool->mutex)); + + if (block->io_fix == BUF_IO_READ) { - if (block->io_fix == BUF_IO_READ) { + mutex_exit(&(buf_pool->mutex)); - mutex_exit(&(buf_pool->mutex)); - - /* Sleep 20 milliseconds */ + /* Sleep 20 milliseconds */ - os_thread_sleep(20000); + os_thread_sleep(20000); } else { - - mutex_exit(&(buf_pool->mutex)); - break; + mutex_exit(&(buf_pool->mutex)); + + break; } } } @@ -1257,7 +1299,7 @@ loop: #ifdef UNIV_IBUF_DEBUG ut_a(ibuf_count_get(block->space, block->offset) == 0); #endif - return(block->frame); + return(block->frame); } /************************************************************************ @@ -1284,11 +1326,11 @@ buf_page_optimistic_get_func( ut_ad(mtr && block); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); - + mutex_enter(&(buf_pool->mutex)); /* If AWE is used, block may have a different frame now, e.g., NULL */ - + if (UNIV_UNLIKELY(block->state != BUF_BLOCK_FILE_PAGE) || UNIV_UNLIKELY(block->frame != guess)) { exit_func: @@ -1326,7 +1368,7 @@ buf_page_optimistic_get_func( if (UNIV_UNLIKELY(!success)) { mutex_enter(&(buf_pool->mutex)); - + block->buf_fix_count--; #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); @@ -1345,7 +1387,7 @@ buf_page_optimistic_get_func( } mutex_enter(&(buf_pool->mutex)); - + block->buf_fix_count--; #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); @@ -1406,20 +1448,20 @@ buf_page_get_known_nowait( ut_ad(mtr); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); - + mutex_enter(&(buf_pool->mutex)); block = buf_block_align(guess); if (block->state == BUF_BLOCK_REMOVE_HASH) { - /* Another thread is just freeing the block from the LRU list - of the buffer pool: do not try to access this page; this + /* Another thread is just freeing the block from the LRU list + of the buffer pool: do not try to access this page; this attempt to access the page can only come through the hash index because when the buffer block state is ..._REMOVE_HASH, we have already removed it from the page address hash table of the buffer pool. */ - mutex_exit(&(buf_pool->mutex)); + mutex_exit(&(buf_pool->mutex)); return(FALSE); } @@ -1448,14 +1490,14 @@ buf_page_get_known_nowait( file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } - + if (!success) { mutex_enter(&(buf_pool->mutex)); - + block->buf_fix_count--; #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); -#endif +#endif mutex_exit(&(buf_pool->mutex)); return(FALSE); @@ -1499,27 +1541,27 @@ buf_page_init_for_backup_restore( /* Set the state of the block */ block->magic_n = BUF_BLOCK_MAGIC_N; - block->state = BUF_BLOCK_FILE_PAGE; - block->space = space; - block->offset = offset; + block->state = BUF_BLOCK_FILE_PAGE; + block->space = space; + block->offset = offset; block->lock_hash_val = 0; block->lock_mutex = NULL; - + block->freed_page_clock = 0; block->newest_modification = ut_dulint_zero; block->oldest_modification = ut_dulint_zero; - + block->accessed = FALSE; - block->buf_fix_count = 0; + block->buf_fix_count = 0; block->io_fix = 0; block->n_hash_helps = 0; block->is_hashed = FALSE; - block->n_fields = 1; - block->n_bytes = 0; - block->side = BTR_SEARCH_LEFT_SIDE; + block->n_fields = 1; + block->n_bytes = 0; + block->side = BTR_SEARCH_LEFT_SIDE; block->file_page_was_freed = FALSE; } @@ -1543,31 +1585,31 @@ buf_page_init( /* Set the state of the block */ block->magic_n = BUF_BLOCK_MAGIC_N; - block->state = BUF_BLOCK_FILE_PAGE; - block->space = space; - block->offset = offset; + block->state = BUF_BLOCK_FILE_PAGE; + block->space = space; + block->offset = offset; block->check_index_page_at_flush = FALSE; block->index = NULL; - + block->lock_hash_val = lock_rec_hash(space, offset); block->lock_mutex = NULL; - + /* Insert into the hash table of file pages */ - if (buf_page_hash_get(space, offset)) { - fprintf(stderr, + if (buf_page_hash_get(space, offset)) { + fprintf(stderr, "InnoDB: Error: page %lu %lu already found from the hash table\n", (ulong) space, (ulong) offset); #ifdef UNIV_DEBUG - buf_print(); - buf_LRU_print(); - buf_validate(); - buf_LRU_validate(); + buf_print(); + buf_LRU_print(); + buf_validate(); + buf_LRU_validate(); #endif /* UNIV_DEBUG */ - ut_a(0); - } + ut_a(0); + } HASH_INSERT(buf_block_t, hash, buf_pool->page_hash, buf_page_address_fold(space, offset), block); @@ -1576,16 +1618,16 @@ buf_page_init( block->newest_modification = ut_dulint_zero; block->oldest_modification = ut_dulint_zero; - + block->accessed = FALSE; - block->buf_fix_count = 0; + block->buf_fix_count = 0; block->io_fix = 0; block->n_hash_helps = 0; block->is_hashed = FALSE; - block->n_fields = 1; - block->n_bytes = 0; - block->side = BTR_SEARCH_LEFT_SIDE; + block->n_fields = 1; + block->n_bytes = 0; + block->side = BTR_SEARCH_LEFT_SIDE; block->file_page_was_freed = FALSE; } @@ -1600,7 +1642,7 @@ Sets the io_fix flag to BUF_IO_READ and sets a non-recursive exclusive lock on the buffer frame. The io-handler must take care that the flag is cleared and the lock released later. This is one of the functions which perform the state transition NOT_USED => FILE_PAGE to a block (the other is -buf_page_create). */ +buf_page_create). */ buf_block_t* buf_page_init_for_read( @@ -1626,9 +1668,9 @@ buf_page_init_for_read( ut_ad(!ibuf_bitmap_page(offset)); ut_ad(ibuf_inside()); - + mtr_start(&mtr); - + if (!ibuf_page_low(space, offset, &mtr)) { mtr_commit(&mtr); @@ -1638,7 +1680,7 @@ buf_page_init_for_read( } else { ut_ad(mode == BUF_READ_ANY_PAGE); } - + block = buf_block_alloc(); ut_a(block); @@ -1651,7 +1693,7 @@ buf_page_init_for_read( } if (*err == DB_TABLESPACE_DELETED - || NULL != buf_page_hash_get(space, offset)) { + || NULL != buf_page_hash_get(space, offset)) { /* The page belongs to a space which has been deleted or is being deleted, or the page is already in buf_pool, return */ @@ -1668,26 +1710,26 @@ buf_page_init_for_read( } ut_ad(block); - + buf_page_init(space, offset, block); /* The block must be put to the LRU list, to the old blocks */ - buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */ - + buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */ + block->io_fix = BUF_IO_READ; buf_pool->n_pend_reads++; - + /* We set a pass-type x-lock on the frame because then the same thread which called for the read operation (and is running now at this point of code) can wait for the read to complete by waiting for the x-lock on the frame; if the x-lock were recursive, the same thread would illegally get the x-lock before the page read is completed. The x-lock is cleared by the io-handler thread. */ - + rw_lock_x_lock_gen(&(block->lock), BUF_IO_READ); - - mutex_exit(&(buf_pool->mutex)); + + mutex_exit(&(buf_pool->mutex)); if (mode == BUF_READ_IBUF_PAGES_ONLY) { @@ -1695,7 +1737,7 @@ buf_page_init_for_read( } return(block); -} +} /************************************************************************ Initializes a page to the buffer buf_pool. The page is usually not read @@ -1715,11 +1757,11 @@ buf_page_create( buf_frame_t* frame; buf_block_t* block; buf_block_t* free_block = NULL; - + ut_ad(mtr); free_block = buf_LRU_get_free_block(); - + mutex_enter(&(buf_pool->mutex)); block = buf_page_hash_get(space, offset); @@ -1750,12 +1792,12 @@ buf_page_create( #endif /* UNIV_DEBUG */ block = free_block; - + buf_page_init(space, offset, block); /* The block must be put to the LRU list */ buf_LRU_add_block(block, FALSE); - + #ifdef UNIV_SYNC_DEBUG buf_block_buf_fix_inc_debug(block, __FILE__, __LINE__); #else @@ -1764,7 +1806,7 @@ buf_page_create( mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX); block->accessed = TRUE; - + buf_pool->n_pages_created++; mutex_exit(&(buf_pool->mutex)); @@ -1779,6 +1821,10 @@ buf_page_create( frame = block->frame; + memset(frame + FIL_PAGE_PREV, 0xff, 4); + memset(frame + FIL_PAGE_NEXT, 0xff, 4); + mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED); + /* Reset to zero the file flush lsn field in the page; if the first page of an ibdata file is 'created' in this function into the buffer pool then we lose the original contents of the file flush lsn stamp. @@ -1811,7 +1857,7 @@ buf_page_io_complete( { ulint io_type; ulint read_page_no; - + ut_ad(block); ut_a(block->state == BUF_BLOCK_FILE_PAGE); @@ -1827,7 +1873,7 @@ buf_page_io_complete( + FIL_PAGE_OFFSET); if (read_page_no != 0 && !trx_doublewrite_page_inside(read_page_no) - && read_page_no != block->offset) { + && read_page_no != block->offset) { fprintf(stderr, "InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n", @@ -1837,16 +1883,16 @@ buf_page_io_complete( to the 4 first bytes of the page end lsn field */ if (buf_page_is_corrupted(block->frame)) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Database page corruption on disk or a failed\n" "InnoDB: file read of page %lu.\n", (ulong) block->offset); - + fputs( "InnoDB: You may have to recover from a backup.\n", stderr); buf_page_print(block->frame); - fprintf(stderr, + fprintf(stderr, "InnoDB: Database page corruption on disk or a failed\n" "InnoDB: file read of page %lu.\n", (ulong) block->offset); fputs( @@ -1864,13 +1910,13 @@ buf_page_io_complete( "InnoDB: See also " "http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n" "InnoDB: about forcing recovery.\n", stderr); - + if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { fputs( "InnoDB: Ending processing because of a corrupt database page.\n", stderr); - exit(1); - } + exit(1); + } } if (recv_recovery_is_on()) { @@ -1883,24 +1929,24 @@ buf_page_io_complete( block->space, block->offset, TRUE); } } - + #ifdef UNIV_IBUF_DEBUG ut_a(ibuf_count_get(block->space, block->offset) == 0); #endif mutex_enter(&(buf_pool->mutex)); - + /* Because this thread which does the unlocking is not the same that did the locking, we use a pass value != 0 in unlock, which simply removes the newest lock debug record, without checking the thread id. */ block->io_fix = 0; - + if (io_type == BUF_IO_READ) { /* NOTE that the call to ibuf may have moved the ownership of the x-latch to this OS thread: do not let this confuse you in - debugging! */ - + debugging! */ + ut_ad(buf_pool->n_pend_reads > 0); buf_pool->n_pend_reads--; buf_pool->n_pages_read++; @@ -1930,7 +1976,7 @@ buf_page_io_complete( } #endif /* UNIV_DEBUG */ } - + mutex_exit(&(buf_pool->mutex)); #ifdef UNIV_DEBUG @@ -1953,13 +1999,13 @@ buf_pool_invalidate(void) ibool freed; ut_ad(buf_all_freed()); - + freed = TRUE; while (freed) { freed = buf_LRU_search_and_free_block(100); } - + mutex_enter(&(buf_pool->mutex)); ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0); @@ -1984,7 +2030,7 @@ buf_validate(void) ulint n_flush = 0; ulint n_free = 0; ulint n_page = 0; - + ut_ad(buf_pool); mutex_enter(&(buf_pool->mutex)); @@ -2001,8 +2047,8 @@ buf_validate(void) #ifdef UNIV_IBUF_DEBUG ut_a((block->io_fix == BUF_IO_READ) - || ibuf_count_get(block->space, block->offset) - == 0); + || ibuf_count_get(block->space, block->offset) + == 0); #endif if (block->io_fix == BUF_IO_WRITE) { @@ -2025,18 +2071,18 @@ buf_validate(void) ut_a(rw_lock_is_locked(&(block->lock), RW_LOCK_EX)); } - + n_lru++; if (ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0) { n_flush++; - } - + } + } else if (block->state == BUF_BLOCK_NOT_USED) { n_free++; } - } + } if (n_lru + n_free > buf_pool->curr_size) { fprintf(stderr, "n LRU %lu, n free %lu\n", (ulong) n_lru, (ulong) n_free); @@ -2054,14 +2100,14 @@ buf_validate(void) ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush); ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush); ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush); - + mutex_exit(&(buf_pool->mutex)); ut_a(buf_LRU_validate()); ut_a(buf_flush_validate()); return(TRUE); -} +} /************************************************************************* Prints info of the buffer buf_pool data structure. */ @@ -2077,9 +2123,9 @@ buf_print(void) ulint j; dulint id; ulint n_found; - buf_frame_t* frame; + buf_frame_t* frame; dict_index_t* index; - + ut_ad(buf_pool); size = buf_pool->curr_size; @@ -2088,7 +2134,7 @@ buf_print(void) counts = mem_alloc(sizeof(ulint) * size); mutex_enter(&(buf_pool->mutex)); - + fprintf(stderr, "buf_pool size %lu\n" "database pages %lu\n" @@ -2109,7 +2155,7 @@ buf_print(void) (ulong) buf_pool->n_pages_written); /* Count the number of blocks belonging to each index in the buffer */ - + n_found = 0; for (i = 0; i < size; i++) { @@ -2147,8 +2193,8 @@ buf_print(void) fprintf(stderr, "Block count for index %lu in buffer is about %lu", - (ulong) ut_dulint_get_low(index_ids[i]), - (ulong) counts[i]); + (ulong) ut_dulint_get_low(index_ids[i]), + (ulong) counts[i]); if (index) { putc(' ', stderr); @@ -2157,12 +2203,12 @@ buf_print(void) putc('\n', stderr); } - + mem_free(index_ids); mem_free(counts); ut_a(buf_validate()); -} +} #endif /* UNIV_DEBUG */ /************************************************************************* @@ -2171,23 +2217,23 @@ Returns the number of latched pages in the buffer pool. */ ulint buf_get_latched_pages_number(void) { - buf_block_t* block; - ulint i; - ulint fixed_pages_number = 0; + buf_block_t* block; + ulint i; + ulint fixed_pages_number = 0; - mutex_enter(&(buf_pool->mutex)); + mutex_enter(&(buf_pool->mutex)); - for (i = 0; i < buf_pool->curr_size; i++) { + for (i = 0; i < buf_pool->curr_size; i++) { - block = buf_pool_get_nth_block(buf_pool, i); + block = buf_pool_get_nth_block(buf_pool, i); - if (((block->buf_fix_count != 0) || (block->io_fix != 0)) && - block->magic_n == BUF_BLOCK_MAGIC_N ) - fixed_pages_number++; - } + if (((block->buf_fix_count != 0) || (block->io_fix != 0)) && + block->magic_n == BUF_BLOCK_MAGIC_N ) + fixed_pages_number++; + } - mutex_exit(&(buf_pool->mutex)); - return fixed_pages_number; + mutex_exit(&(buf_pool->mutex)); + return fixed_pages_number; } /************************************************************************* @@ -2216,10 +2262,10 @@ buf_get_modified_ratio_pct(void) mutex_enter(&(buf_pool->mutex)); ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list)) - / (1 + UT_LIST_GET_LEN(buf_pool->LRU) - + UT_LIST_GET_LEN(buf_pool->free)); + / (1 + UT_LIST_GET_LEN(buf_pool->LRU) + + UT_LIST_GET_LEN(buf_pool->free)); - /* 1 + is there to avoid division by zero */ + /* 1 + is there to avoid division by zero */ mutex_exit(&(buf_pool->mutex)); @@ -2237,17 +2283,17 @@ buf_print_io( time_t current_time; double time_elapsed; ulint size; - + ut_ad(buf_pool); size = buf_pool->curr_size; mutex_enter(&(buf_pool->mutex)); - + if (srv_use_awe) { fprintf(stderr, "AWE: Buffer pool memory frames %lu\n", (ulong) buf_pool->n_frames); - + fprintf(stderr, "AWE: Database pages and free buffers mapped in frames %lu\n", (ulong) UT_LIST_GET_LEN(buf_pool->awe_LRU_free_mapped)); @@ -2294,13 +2340,12 @@ buf_print_io( - buf_pool->n_pages_awe_remapped_old) / time_elapsed); } - + if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) { fprintf(file, "Buffer pool hit rate %lu / 1000\n", - (ulong) (1000 - - ((1000 * - (buf_pool->n_pages_read - buf_pool->n_pages_read_old)) - / (buf_pool->n_page_gets - buf_pool->n_page_gets_old)))); + (ulong) (1000 - + ((1000 * (buf_pool->n_pages_read - buf_pool->n_pages_read_old)) + / (buf_pool->n_page_gets - buf_pool->n_page_gets_old)))); } else { fputs("No buffer pool page gets since the last printout\n", file); @@ -2322,12 +2367,12 @@ void buf_refresh_io_stats(void) /*======================*/ { - buf_pool->last_printout_time = time(NULL); + buf_pool->last_printout_time = time(NULL); buf_pool->n_page_gets_old = buf_pool->n_page_gets; buf_pool->n_pages_read_old = buf_pool->n_pages_read; buf_pool->n_pages_created_old = buf_pool->n_pages_created; buf_pool->n_pages_written_old = buf_pool->n_pages_written; - buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped; + buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped; } /************************************************************************* @@ -2339,7 +2384,7 @@ buf_all_freed(void) { buf_block_t* block; ulint i; - + ut_ad(buf_pool); mutex_enter(&(buf_pool->mutex)); @@ -2355,15 +2400,15 @@ buf_all_freed(void) fprintf(stderr, "Page %lu %lu still fixed or dirty\n", (ulong) block->space, (ulong) block->offset); - ut_error; + ut_error; } } - } + } mutex_exit(&(buf_pool->mutex)); return(TRUE); -} +} /************************************************************************* Checks that there currently are no pending i/o-operations for the buffer diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c index e39d1ae0a71..7b02e353b76 100644 --- a/storage/innobase/buf/buf0flu.c +++ b/storage/innobase/buf/buf0flu.c @@ -30,7 +30,7 @@ Created 11/11/1995 Heikki Tuuri flushed along with the original page. */ #define BUF_FLUSH_AREA ut_min(BUF_READ_AHEAD_AREA,\ - buf_pool->curr_size / 16) + buf_pool->curr_size / 16) /********************************************************************** Validates the flush list. */ @@ -55,10 +55,10 @@ buf_flush_insert_into_flush_list( ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL) - || (ut_dulint_cmp( - (UT_LIST_GET_FIRST(buf_pool->flush_list)) - ->oldest_modification, - block->oldest_modification) <= 0)); + || (ut_dulint_cmp( + (UT_LIST_GET_FIRST(buf_pool->flush_list)) + ->oldest_modification, + block->oldest_modification) <= 0)); UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, block); @@ -77,7 +77,7 @@ buf_flush_insert_sorted_into_flush_list( { buf_block_t* prev_b; buf_block_t* b; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -120,18 +120,18 @@ buf_flush_ready_for_replace( fprintf(stderr, " InnoDB: Error: buffer block state %lu in the LRU list!\n", (ulong)block->state); - ut_print_buf(stderr, (byte*)block, sizeof(buf_block_t)); + ut_print_buf(stderr, block, sizeof(buf_block_t)); return(FALSE); } if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0) - || (block->buf_fix_count != 0) - || (block->io_fix != 0)) { + || (block->buf_fix_count != 0) + || (block->io_fix != 0)) { return(FALSE); } - + return(TRUE); } @@ -152,13 +152,13 @@ buf_flush_ready_for_flush( ut_a(block->state == BUF_BLOCK_FILE_PAGE); if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0) - && (block->io_fix == 0)) { - if (flush_type != BUF_FLUSH_LRU) { + && (block->io_fix == 0)) { + if (flush_type != BUF_FLUSH_LRU) { return(TRUE); } else if (block->buf_fix_count == 0) { - + /* If we are flushing the LRU list, to avoid deadlocks we require the block not to be bufferfixed, and hence not latched. */ @@ -166,7 +166,7 @@ buf_flush_ready_for_flush( return(TRUE); } } - + return(FALSE); } @@ -205,7 +205,7 @@ buf_flush_write_complete( buf_pool->n_flush[block->flush_type]); */ if ((buf_pool->n_flush[block->flush_type] == 0) - && (buf_pool->init_flush[block->flush_type] == FALSE)) { + && (buf_pool->init_flush[block->flush_type] == FALSE)) { /* The running flush batch has ended */ @@ -235,7 +235,7 @@ buf_flush_buffered_writes(void) return; } - + mutex_enter(&(trx_doublewrite->mutex)); /* Write first to doublewrite buffer blocks. We use synchronous @@ -252,17 +252,17 @@ buf_flush_buffered_writes(void) for (i = 0; i < trx_doublewrite->first_free; i++) { block = trx_doublewrite->buf_block_arr[i]; - ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (mach_read_from_4(block->frame + FIL_PAGE_LSN + 4) - != mach_read_from_4(block->frame + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { - ut_print_timestamp(stderr); - fprintf(stderr, + != mach_read_from_4(block->frame + UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: ERROR: The page to be written seems corrupt!\n" "InnoDB: The lsn fields do not match! Noticed in the buffer pool\n" "InnoDB: before posting to the doublewrite buffer.\n"); - } + } if (block->check_index_page_at_flush && !page_simple_validate(block->frame)) { @@ -281,27 +281,27 @@ buf_flush_buffered_writes(void) } } - /* increment the doublewrite flushed pages counter */ - srv_dblwr_pages_written+= trx_doublewrite->first_free; - srv_dblwr_writes++; - + /* increment the doublewrite flushed pages counter */ + srv_dblwr_pages_written+= trx_doublewrite->first_free; + srv_dblwr_writes++; + if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { len = TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE; } else { len = trx_doublewrite->first_free * UNIV_PAGE_SIZE; } - + fil_io(OS_FILE_WRITE, TRUE, TRX_SYS_SPACE, trx_doublewrite->block1, 0, len, - (void*)trx_doublewrite->write_buf, NULL); - + (void*)trx_doublewrite->write_buf, NULL); + write_buf = trx_doublewrite->write_buf; - for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len; len2 += UNIV_PAGE_SIZE) { - if (mach_read_from_4(write_buf + len2 + FIL_PAGE_LSN + 4) - != mach_read_from_4(write_buf + len2 + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { + for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len; len2 += UNIV_PAGE_SIZE) { + if (mach_read_from_4(write_buf + len2 + FIL_PAGE_LSN + 4) + != mach_read_from_4(write_buf + len2 + UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: ERROR: The page to be written seems corrupt!\n" @@ -312,23 +312,23 @@ buf_flush_buffered_writes(void) if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { len = (trx_doublewrite->first_free - TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) * UNIV_PAGE_SIZE; - + fil_io(OS_FILE_WRITE, TRUE, TRX_SYS_SPACE, trx_doublewrite->block2, 0, len, - (void*)(trx_doublewrite->write_buf - + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE), + (void*)(trx_doublewrite->write_buf + + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE), NULL); write_buf = trx_doublewrite->write_buf + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE; for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len; len2 += UNIV_PAGE_SIZE) { - if (mach_read_from_4(write_buf + len2 - + FIL_PAGE_LSN + 4) - != mach_read_from_4(write_buf + len2 + if (mach_read_from_4(write_buf + len2 + + FIL_PAGE_LSN + 4) + != mach_read_from_4(write_buf + len2 + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: ERROR: The page to be written seems corrupt!\n" @@ -349,32 +349,33 @@ buf_flush_buffered_writes(void) block = trx_doublewrite->buf_block_arr[i]; if (mach_read_from_4(block->frame + FIL_PAGE_LSN + 4) - != mach_read_from_4(block->frame + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { - ut_print_timestamp(stderr); - fprintf(stderr, + != mach_read_from_4(block->frame + UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: ERROR: The page to be written seems corrupt!\n" "InnoDB: The lsn fields do not match! Noticed in the buffer pool\n" "InnoDB: after posting and flushing the doublewrite buffer.\n" "InnoDB: Page buf fix count %lu, io fix %lu, state %lu\n", - (ulong)block->buf_fix_count, (ulong)block->io_fix, - (ulong)block->state); - } + (ulong)block->buf_fix_count, + (ulong)block->io_fix, + (ulong)block->state); + } ut_a(block->state == BUF_BLOCK_FILE_PAGE); fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, - (void*)block->frame, (void*)block); + (void*)block->frame, (void*)block); } - + /* Wake possible simulated aio thread to actually post the writes to the operating system */ os_aio_simulated_wake_handler_threads(); /* Wait that all async writes to tablespaces have been posted to - the OS */ - + the OS */ + os_aio_wait_until_no_pending_writes(); /* Now we flush the data to disk (for example, with fsync) */ @@ -385,7 +386,7 @@ buf_flush_buffered_writes(void) trx_doublewrite->first_free = 0; - mutex_exit(&(trx_doublewrite->mutex)); + mutex_exit(&(trx_doublewrite->mutex)); } /************************************************************************ @@ -442,7 +443,7 @@ buf_flush_init_for_writing( dulint newest_lsn, /* in: newest modification lsn to the page */ ulint space, /* in: space id */ ulint page_no) /* in: page number */ -{ +{ /* Write the newest modification lsn to the page header and trailer */ mach_write_to_8(page + FIL_PAGE_LSN, newest_lsn); @@ -451,13 +452,13 @@ buf_flush_init_for_writing( /* Write the page number and the space id */ mach_write_to_4(page + FIL_PAGE_OFFSET, page_no); - mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space); + mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space); /* Store the new formula checksum */ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, srv_use_checksums ? - buf_calc_page_new_checksum(page) : BUF_NO_CHECKSUM_MAGIC); + buf_calc_page_new_checksum(page) : BUF_NO_CHECKSUM_MAGIC); /* We overwrite the first 4 bytes of the end lsn field to store the old formula checksum. Since it depends also on the field @@ -466,7 +467,7 @@ buf_flush_init_for_writing( mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, srv_use_checksums ? - buf_calc_page_old_checksum(page) : BUF_NO_CHECKSUM_MAGIC); + buf_calc_page_old_checksum(page) : BUF_NO_CHECKSUM_MAGIC); } /************************************************************************ @@ -500,13 +501,13 @@ buf_flush_write_block_low( #else /* Force the log to the disk before writing the modified block */ log_write_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS, TRUE); -#endif +#endif buf_flush_init_for_writing(block->frame, block->newest_modification, block->space, block->offset); if (!srv_use_doublewrite_buf || !trx_doublewrite) { fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, - (void*)block->frame, (void*)block); + (void*)block->frame, (void*)block); } else { buf_flush_post_to_doublewrite_buf(block); } @@ -529,7 +530,7 @@ buf_flush_try_page( { buf_block_t* block; ibool locked; - + ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST || flush_type == BUF_FLUSH_SINGLE_PAGE); @@ -540,8 +541,8 @@ buf_flush_try_page( ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); if (flush_type == BUF_FLUSH_LIST - && block && buf_flush_ready_for_flush(block, flush_type)) { - + && block && buf_flush_ready_for_flush(block, flush_type)) { + block->io_fix = BUF_IO_WRITE; /* If AWE is enabled and the page is not mapped to a frame, @@ -553,7 +554,7 @@ buf_flush_try_page( /* We set second parameter TRUE because the block is in the LRU list and we must put it to awe_LRU_free_mapped list once mapped to a frame */ - + buf_awe_map_page_to_frame(block, TRUE); } @@ -567,7 +568,7 @@ buf_flush_try_page( (buf_pool->n_flush[flush_type])++; locked = FALSE; - + /* If the simulated aio thread is not running, we must not wait for any latch, as we may end up in a deadlock: if buf_fix_count == 0, then we know we need not wait */ @@ -595,7 +596,7 @@ buf_flush_try_page( #endif /* UNIV_DEBUG */ buf_flush_write_block_low(block); - + return(1); } else if (flush_type == BUF_FLUSH_LRU && block @@ -620,7 +621,7 @@ buf_flush_try_page( /* We set second parameter TRUE because the block is in the LRU list and we must put it to awe_LRU_free_mapped list once mapped to a frame */ - + buf_awe_map_page_to_frame(block, TRUE); } @@ -638,7 +639,7 @@ buf_flush_try_page( /* Note that the s-latch is acquired before releasing the buf_pool mutex: this ensures that the latch is acquired immediately. */ - + mutex_exit(&(buf_pool->mutex)); buf_flush_write_block_low(block); @@ -647,7 +648,7 @@ buf_flush_try_page( } else if (flush_type == BUF_FLUSH_SINGLE_PAGE && block && buf_flush_ready_for_flush(block, flush_type)) { - + block->io_fix = BUF_IO_WRITE; /* If AWE is enabled and the page is not mapped to a frame, @@ -659,7 +660,7 @@ buf_flush_try_page( /* We set second parameter TRUE because the block is in the LRU list and we must put it to awe_LRU_free_mapped list once mapped to a frame */ - + buf_awe_map_page_to_frame(block, TRUE); } @@ -681,18 +682,18 @@ buf_flush_try_page( fprintf(stderr, "Flushing single page space %lu, page no %lu \n", (ulong) block->space, - (ulong) block->offset); + (ulong) block->offset); } #endif /* UNIV_DEBUG */ buf_flush_write_block_low(block); - + return(1); } else { mutex_exit(&(buf_pool->mutex)); return(0); - } + } } /*************************************************************** @@ -719,13 +720,13 @@ buf_flush_try_neighbors( if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) { /* If there is little space, it is better not to flush any block except from the end of the LRU list */ - + low = offset; high = offset + 1; } /* fprintf(stderr, "Flush area: low %lu high %lu\n", low, high); */ - + if (high > fil_space_get_size(space)) { high = fil_space_get_size(space); } @@ -738,12 +739,12 @@ buf_flush_try_neighbors( ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); if (block && flush_type == BUF_FLUSH_LRU && i != offset - && !block->old) { + && !block->old) { - /* We avoid flushing 'non-old' blocks in an LRU flush, - because the flushed blocks are soon freed */ + /* We avoid flushing 'non-old' blocks in an LRU flush, + because the flushed blocks are soon freed */ - continue; + continue; } if (block && buf_flush_ready_for_flush(block, flush_type) @@ -767,7 +768,7 @@ buf_flush_try_neighbors( mutex_enter(&(buf_pool->mutex)); } } - + mutex_exit(&(buf_pool->mutex)); return(count); @@ -798,64 +799,64 @@ buf_flush_batch( exceed min_n), otherwise ignored */ { buf_block_t* block; - ulint page_count = 0; + ulint page_count = 0; ulint old_page_count; ulint space; ulint offset; ibool found; - + ut_ad((flush_type == BUF_FLUSH_LRU) - || (flush_type == BUF_FLUSH_LIST)); + || (flush_type == BUF_FLUSH_LIST)); ut_ad((flush_type != BUF_FLUSH_LIST) || sync_thread_levels_empty_gen(TRUE)); mutex_enter(&(buf_pool->mutex)); if ((buf_pool->n_flush[flush_type] > 0) - || (buf_pool->init_flush[flush_type] == TRUE)) { + || (buf_pool->init_flush[flush_type] == TRUE)) { /* There is already a flush batch of the same type running */ - + mutex_exit(&(buf_pool->mutex)); return(ULINT_UNDEFINED); } (buf_pool->init_flush)[flush_type] = TRUE; - + for (;;) { /* If we have flushed enough, leave the loop */ if (page_count >= min_n) { break; } - + /* Start from the end of the list looking for a suitable block to be flushed. */ - - if (flush_type == BUF_FLUSH_LRU) { + + if (flush_type == BUF_FLUSH_LRU) { block = UT_LIST_GET_LAST(buf_pool->LRU); - } else { + } else { ut_ad(flush_type == BUF_FLUSH_LIST); block = UT_LIST_GET_LAST(buf_pool->flush_list); if (!block - || (ut_dulint_cmp(block->oldest_modification, - lsn_limit) >= 0)) { + || (ut_dulint_cmp(block->oldest_modification, + lsn_limit) >= 0)) { /* We have flushed enough */ break; } - } - - found = FALSE; - + } + + found = FALSE; + /* Note that after finding a single flushable page, we try to flush also all its neighbors, and after that start from the END of the LRU list or flush list again: the list may change during the flushing and we cannot safely preserve within this function a pointer to a block in the list! */ - while ((block != NULL) && !found) { + while ((block != NULL) && !found) { ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (buf_flush_ready_for_flush(block, flush_type)) { @@ -863,11 +864,11 @@ buf_flush_batch( found = TRUE; space = block->space; offset = block->offset; - + mutex_exit(&(buf_pool->mutex)); old_page_count = page_count; - + /* Try to flush also all the neighbors */ page_count += buf_flush_try_neighbors(space, offset, @@ -887,19 +888,19 @@ buf_flush_batch( block = UT_LIST_GET_PREV(flush_list, block); } - } + } - /* If we could not find anything to flush, leave the loop */ + /* If we could not find anything to flush, leave the loop */ - if (!found) { - break; - } + if (!found) { + break; + } } (buf_pool->init_flush)[flush_type] = FALSE; if ((buf_pool->n_flush[flush_type] == 0) - && (buf_pool->init_flush[flush_type] == FALSE)) { + && (buf_pool->init_flush[flush_type] == FALSE)) { /* The running flush batch has ended */ @@ -920,9 +921,9 @@ buf_flush_batch( (ulong) page_count); } #endif /* UNIV_DEBUG */ - - if (page_count != ULINT_UNDEFINED) - srv_buf_pool_flushed+= page_count; + + if (page_count != ULINT_UNDEFINED) + srv_buf_pool_flushed+= page_count; return(page_count); } @@ -936,9 +937,9 @@ buf_flush_wait_batch_end( ulint type) /* in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */ { ut_ad((type == BUF_FLUSH_LRU) || (type == BUF_FLUSH_LIST)); - + os_event_wait(buf_pool->no_flush[type]); -} +} /********************************************************************** Gives a recommendation of how many blocks should be flushed to establish @@ -954,7 +955,7 @@ buf_flush_LRU_recommendation(void) buf_block_t* block; ulint n_replaceable; ulint distance = 0; - + mutex_enter(&(buf_pool->mutex)); n_replaceable = UT_LIST_GET_LEN(buf_pool->free); @@ -962,26 +963,26 @@ buf_flush_LRU_recommendation(void) block = UT_LIST_GET_LAST(buf_pool->LRU); while ((block != NULL) - && (n_replaceable < BUF_FLUSH_FREE_BLOCK_MARGIN - + BUF_FLUSH_EXTRA_MARGIN) - && (distance < BUF_LRU_FREE_SEARCH_LEN)) { + && (n_replaceable < BUF_FLUSH_FREE_BLOCK_MARGIN + + BUF_FLUSH_EXTRA_MARGIN) + && (distance < BUF_LRU_FREE_SEARCH_LEN)) { if (buf_flush_ready_for_replace(block)) { n_replaceable++; } distance++; - + block = UT_LIST_GET_PREV(LRU, block); } - + mutex_exit(&(buf_pool->mutex)); if (n_replaceable >= BUF_FLUSH_FREE_BLOCK_MARGIN) { return(0); } - + return(BUF_FLUSH_FREE_BLOCK_MARGIN + BUF_FLUSH_EXTRA_MARGIN - n_replaceable); } @@ -991,7 +992,7 @@ Flushes pages from the end of the LRU list if there is too small a margin of replaceable pages there or in the free list. VERY IMPORTANT: this function is called also by threads which have locks on pages. To avoid deadlocks, we flush only pages such that the s-lock required for flushing can be acquired -immediately, without waiting. */ +immediately, without waiting. */ void buf_flush_free_margin(void) @@ -1001,15 +1002,15 @@ buf_flush_free_margin(void) ulint n_flushed; n_to_flush = buf_flush_LRU_recommendation(); - + if (n_to_flush > 0) { n_flushed = buf_flush_batch(BUF_FLUSH_LRU, n_to_flush, ut_dulint_zero); if (n_flushed == ULINT_UNDEFINED) { /* There was an LRU type flush batch already running; let us wait for it to end */ - - buf_flush_wait_batch_end(BUF_FLUSH_LRU); + + buf_flush_wait_batch_end(BUF_FLUSH_LRU); } } } @@ -1024,7 +1025,7 @@ buf_flush_validate_low(void) { buf_block_t* block; dulint om; - + UT_LIST_VALIDATE(flush_list, buf_block_t, buf_pool->flush_list); block = UT_LIST_GET_FIRST(buf_pool->flush_list); @@ -1033,7 +1034,7 @@ buf_flush_validate_low(void) om = block->oldest_modification; ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(ut_dulint_cmp(om, ut_dulint_zero) > 0); - + block = UT_LIST_GET_NEXT(flush_list, block); if (block) { @@ -1054,11 +1055,11 @@ buf_flush_validate(void) /* out: TRUE if ok */ { ibool ret; - + mutex_enter(&(buf_pool->mutex)); ret = buf_flush_validate_low(); - + mutex_exit(&(buf_pool->mutex)); return(ret); diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c index a0157da2d42..3b6c47a21e9 100644 --- a/storage/innobase/buf/buf0lru.c +++ b/storage/innobase/buf/buf0lru.c @@ -80,21 +80,21 @@ buf_LRU_invalidate_tablespace( scan_again: mutex_enter(&(buf_pool->mutex)); - + all_freed = TRUE; - + block = UT_LIST_GET_LAST(buf_pool->LRU); while (block != NULL) { - ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (block->space == id - && (block->buf_fix_count > 0 || block->io_fix != 0)) { + && (block->buf_fix_count > 0 || block->io_fix != 0)) { /* We cannot remove this page during this scan yet; maybe the system is currently reading it in, or flushing the modifications to the file */ - + all_freed = FALSE; goto next_page; @@ -106,12 +106,12 @@ scan_again: printf( "Dropping space %lu page %lu\n", (ulong) block->space, - (ulong) block->offset); + (ulong) block->offset); } #endif if (block->is_hashed) { page_no = block->offset; - + mutex_exit(&(buf_pool->mutex)); /* Note that the following call will acquire @@ -129,7 +129,7 @@ scan_again: blocks */ block->oldest_modification = ut_dulint_zero; - UT_LIST_REMOVE(flush_list, + UT_LIST_REMOVE(flush_list, buf_pool->flush_list, block); } @@ -142,11 +142,11 @@ next_page: } mutex_exit(&(buf_pool->mutex)); - + if (!all_freed) { os_thread_sleep(20000); - goto scan_again; + goto scan_again; } } @@ -193,7 +193,7 @@ ibool buf_LRU_search_and_free_block( /*==========================*/ /* out: TRUE if freed */ - ulint n_iterations) /* in: how many times this has been called + ulint n_iterations) /* in: how many times this has been called repeatedly without result: a high value means that we should search farther; if value is k < 10, then we only search k/10 * [number @@ -205,12 +205,12 @@ buf_LRU_search_and_free_block( ibool freed; mutex_enter(&(buf_pool->mutex)); - + freed = FALSE; block = UT_LIST_GET_LAST(buf_pool->LRU); while (block != NULL) { - ut_a(block->in_LRU_list); + ut_a(block->in_LRU_list); if (buf_flush_ready_for_replace(block)) { #ifdef UNIV_DEBUG @@ -218,7 +218,7 @@ buf_LRU_search_and_free_block( fprintf(stderr, "Putting space %lu page %lu to free list\n", (ulong) block->space, - (ulong) block->offset); + (ulong) block->offset); } #endif /* UNIV_DEBUG */ @@ -229,7 +229,7 @@ buf_LRU_search_and_free_block( /* Remove possible adaptive hash index built on the page; in the case of AWE the block may not have a frame at all */ - + if (block->frame) { btr_search_drop_page_hash_index(block->frame); } @@ -246,26 +246,26 @@ buf_LRU_search_and_free_block( distance++; if (!freed && n_iterations <= 10 - && distance > 100 + (n_iterations * buf_pool->curr_size) - / 10) { + && distance > 100 + (n_iterations * buf_pool->curr_size) + / 10) { buf_pool->LRU_flush_ended = 0; mutex_exit(&(buf_pool->mutex)); - + return(FALSE); } } if (buf_pool->LRU_flush_ended > 0) { buf_pool->LRU_flush_ended--; } - if (!freed) { + if (!freed) { buf_pool->LRU_flush_ended = 0; } mutex_exit(&(buf_pool->mutex)); - + return(freed); } - + /********************************************************************** Tries to remove LRU flushed blocks from the end of the LRU list and put them to the free list. This is beneficial for the efficiency of the insert buffer @@ -286,12 +286,12 @@ buf_LRU_try_free_flushed_blocks(void) mutex_exit(&(buf_pool->mutex)); buf_LRU_search_and_free_block(1); - + mutex_enter(&(buf_pool->mutex)); } mutex_exit(&(buf_pool->mutex)); -} +} /********************************************************************** Returns TRUE if less than 15 % of the buffer pool is available. This can be @@ -310,7 +310,7 @@ buf_LRU_buf_pool_running_out(void) if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 7) { - + ret = TRUE; } @@ -334,16 +334,16 @@ buf_LRU_get_free_block(void) buf_block_t* block = NULL; ibool freed; ulint n_iterations = 1; - ibool mon_value_was = FALSE; + ibool mon_value_was = FALSE; ibool started_monitor = FALSE; loop: mutex_enter(&(buf_pool->mutex)); if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 10) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); - fprintf(stderr, + fprintf(stderr, " InnoDB: ERROR: over 9 / 10 of the buffer pool is occupied by\n" "InnoDB: lock heaps or the adaptive hash index! Check that your\n" "InnoDB: transactions do not set too many row locks.\n" @@ -354,18 +354,18 @@ loop: (ulong)(buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE))); ut_error; - + } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) { if (!buf_lru_switched_on_innodb_mon) { - /* Over 80 % of the buffer pool is occupied by lock + /* Over 80 % of the buffer pool is occupied by lock heaps or the adaptive hash index. This may be a memory leak! */ - ut_print_timestamp(stderr); - fprintf(stderr, + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: WARNING: over 4 / 5 of the buffer pool is occupied by\n" "InnoDB: lock heaps or the adaptive hash index! Check that your\n" "InnoDB: transactions do not set too many row locks.\n" @@ -389,21 +389,21 @@ loop: buf_lru_switched_on_innodb_mon = FALSE; srv_print_innodb_monitor = FALSE; } - + /* If there is a block in the free list, take it */ if (UT_LIST_GET_LEN(buf_pool->free) > 0) { - + block = UT_LIST_GET_FIRST(buf_pool->free); ut_a(block->in_free_list); UT_LIST_REMOVE(free, buf_pool->free, block); block->in_free_list = FALSE; ut_a(block->state != BUF_BLOCK_FILE_PAGE); - ut_a(!block->in_LRU_list); + ut_a(!block->in_LRU_list); if (srv_use_awe) { if (block->frame) { /* Remove from the list of mapped pages */ - + UT_LIST_REMOVE(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } else { @@ -414,18 +414,18 @@ loop: buf_awe_map_page_to_frame(block, FALSE); } } - + block->state = BUF_BLOCK_READY_FOR_USE; mutex_exit(&(buf_pool->mutex)); if (started_monitor) { srv_print_innodb_monitor = mon_value_was; - } + } return(block); } - + /* If no block was in the free list, search from the end of the LRU list and try to free a block there */ @@ -456,7 +456,7 @@ loop: (ulong) fil_n_pending_log_flushes, (ulong) fil_n_pending_tablespace_flushes, (ulong) os_n_file_reads, (ulong) os_n_file_writes, - (ulong) os_n_fsyncs); + (ulong) os_n_fsyncs); mon_value_was = srv_print_innodb_monitor; started_monitor = TRUE; @@ -467,7 +467,7 @@ loop: /* No free block was found: try to flush the LRU list */ buf_flush_free_margin(); - ++srv_buf_pool_wait_free; + ++srv_buf_pool_wait_free; os_aio_simulated_wake_handler_threads(); @@ -492,8 +492,8 @@ loop: n_iterations++; - goto loop; -} + goto loop; +} /*********************************************************************** Moves the LRU_old pointer so that the length of the old blocks list @@ -519,9 +519,9 @@ buf_LRU_old_adjust_len(void) ut_a(buf_pool->LRU_old->in_LRU_list); /* Update the LRU_old pointer if necessary */ - + if (old_len < new_len - BUF_LRU_OLD_TOLERANCE) { - + buf_pool->LRU_old = UT_LIST_GET_PREV(LRU, buf_pool->LRU_old); (buf_pool->LRU_old)->old = TRUE; @@ -561,16 +561,16 @@ buf_LRU_old_init(void) while (block != NULL) { ut_a(block->state == BUF_BLOCK_FILE_PAGE); - ut_a(block->in_LRU_list); + ut_a(block->in_LRU_list); block->old = TRUE; block = UT_LIST_GET_NEXT(LRU, block); } buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU); buf_pool->LRU_old_len = UT_LIST_GET_LEN(buf_pool->LRU); - + buf_LRU_old_adjust_len(); -} +} /********************************************************************** Removes a block from the LRU list. */ @@ -585,7 +585,7 @@ buf_LRU_remove_block( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); #endif /* UNIV_SYNC_DEBUG */ - + ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->in_LRU_list); @@ -611,10 +611,10 @@ buf_LRU_remove_block( if (srv_use_awe && block->frame) { /* Remove from the list of mapped pages */ - + UT_LIST_REMOVE(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); - } + } /* If the LRU list is so short that LRU_old not defined, return */ if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) { @@ -624,7 +624,7 @@ buf_LRU_remove_block( return; } - ut_ad(buf_pool->LRU_old); + ut_ad(buf_pool->LRU_old); /* Update the LRU_old_len field if necessary */ if (block->old) { @@ -634,7 +634,7 @@ buf_LRU_remove_block( /* Adjust the length of the old block list if necessary */ buf_LRU_old_adjust_len(); -} +} /********************************************************************** Adds a block to the LRU list end. */ @@ -645,7 +645,7 @@ buf_LRU_add_block_to_end_low( buf_block_t* block) /* in: control block */ { buf_block_t* last_block; - + ut_ad(buf_pool); ut_ad(block); #ifdef UNIV_SYNC_DEBUG @@ -662,7 +662,7 @@ buf_LRU_add_block_to_end_low( block->LRU_position = last_block->LRU_position; } else { block->LRU_position = buf_pool_clock_tic(); - } + } ut_a(!block->in_LRU_list); UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block); @@ -670,11 +670,11 @@ buf_LRU_add_block_to_end_low( if (srv_use_awe && block->frame) { /* Add to the list of mapped pages */ - + UT_LIST_ADD_LAST(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } - + if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) { buf_pool->LRU_old_len++; @@ -695,7 +695,7 @@ buf_LRU_add_block_to_end_low( buf_LRU_old_init(); } -} +} /********************************************************************** Adds a block to the LRU list. */ @@ -710,7 +710,7 @@ buf_LRU_add_block_low( the start, regardless of this parameter */ { ulint cl; - + ut_ad(buf_pool); ut_ad(block); #ifdef UNIV_SYNC_DEBUG @@ -727,7 +727,7 @@ buf_LRU_add_block_low( /* Add to the list of mapped pages; for simplicity we always add to the start, even if the user would have set 'old' TRUE */ - + UT_LIST_ADD_FIRST(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } @@ -736,7 +736,7 @@ buf_LRU_add_block_low( UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, block); - block->LRU_position = cl; + block->LRU_position = cl; block->freed_page_clock = buf_pool->freed_page_clock; } else { UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU, buf_pool->LRU_old, @@ -765,8 +765,8 @@ buf_LRU_add_block_low( defined: init it */ buf_LRU_old_init(); - } -} + } +} /********************************************************************** Adds a block to the LRU list. */ @@ -820,25 +820,25 @@ buf_LRU_block_free_non_file_page( ut_ad(mutex_own(&(buf_pool->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_ad(block); - + ut_a((block->state == BUF_BLOCK_MEMORY) - || (block->state == BUF_BLOCK_READY_FOR_USE)); + || (block->state == BUF_BLOCK_READY_FOR_USE)); ut_a(block->n_pointers == 0); ut_a(!block->in_free_list); block->state = BUF_BLOCK_NOT_USED; -#ifdef UNIV_DEBUG +#ifdef UNIV_DEBUG /* Wipe contents of page to reveal possible stale pointers to it */ memset(block->frame, '\0', UNIV_PAGE_SIZE); -#endif +#endif UT_LIST_ADD_FIRST(free, buf_pool->free, block); block->in_free_list = TRUE; if (srv_use_awe && block->frame) { /* Add to the list of mapped pages */ - + UT_LIST_ADD_FIRST(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } @@ -859,7 +859,7 @@ buf_LRU_block_remove_hashed_page( ut_ad(mutex_own(&(buf_pool->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_ad(block); - + ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->io_fix == 0); ut_a(block->buf_fix_count == 0); @@ -870,31 +870,31 @@ buf_LRU_block_remove_hashed_page( buf_pool->freed_page_clock += 1; /* Note that if AWE is enabled the block may not have a frame at all */ - - buf_block_modify_clock_inc(block); - - if (block != buf_page_hash_get(block->space, block->offset)) { - fprintf(stderr, + + buf_block_modify_clock_inc(block); + + if (block != buf_page_hash_get(block->space, block->offset)) { + fprintf(stderr, "InnoDB: Error: page %lu %lu not found from the hash table\n", (ulong) block->space, (ulong) block->offset); - if (buf_page_hash_get(block->space, block->offset)) { - fprintf(stderr, + if (buf_page_hash_get(block->space, block->offset)) { + fprintf(stderr, "InnoDB: From hash table we find block %p of %lu %lu which is not %p\n", buf_page_hash_get(block->space, block->offset), - (ulong) buf_page_hash_get(block->space, block->offset)->space, - (ulong) buf_page_hash_get(block->space, block->offset)->offset, + (ulong) buf_page_hash_get(block->space, block->offset)->space, + (ulong) buf_page_hash_get(block->space, block->offset)->offset, block); - } + } #ifdef UNIV_DEBUG - buf_print(); - buf_LRU_print(); - buf_validate(); - buf_LRU_validate(); + buf_print(); + buf_LRU_print(); + buf_validate(); + buf_LRU_validate(); #endif - ut_a(0); - } + ut_a(0); + } HASH_DELETE(buf_block_t, hash, buf_pool->page_hash, buf_page_address_fold(block->space, block->offset), @@ -934,7 +934,7 @@ buf_LRU_validate(void) ulint old_len; ulint new_len; ulint LRU_pos; - + ut_ad(buf_pool); mutex_enter(&(buf_pool->mutex)); @@ -946,7 +946,7 @@ buf_LRU_validate(void) ut_a(old_len >= new_len - BUF_LRU_OLD_TOLERANCE); ut_a(old_len <= new_len + BUF_LRU_OLD_TOLERANCE); } - + UT_LIST_VALIDATE(LRU, buf_block_t, buf_pool->LRU); block = UT_LIST_GET_FIRST(buf_pool->LRU); @@ -979,7 +979,7 @@ buf_LRU_validate(void) if (buf_pool->LRU_old) { ut_a(buf_pool->LRU_old_len == old_len); - } + } UT_LIST_VALIDATE(free, buf_block_t, buf_pool->free); @@ -1005,7 +1005,7 @@ buf_LRU_print(void) buf_block_t* block; buf_frame_t* frame; ulint len; - + ut_ad(buf_pool); mutex_enter(&(buf_pool->mutex)); diff --git a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c index 813ca589907..d9864aae360 100644 --- a/storage/innobase/buf/buf0rea.c +++ b/storage/innobase/buf/buf0rea.c @@ -79,14 +79,14 @@ buf_read_page_low( wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER; mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER; - + if (trx_doublewrite && space == TRX_SYS_SPACE && ( (offset >= trx_doublewrite->block1 - && offset < trx_doublewrite->block1 - + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) - || (offset >= trx_doublewrite->block2 - && offset < trx_doublewrite->block2 - + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) { + && offset < trx_doublewrite->block1 + + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) + || (offset >= trx_doublewrite->block2 + && offset < trx_doublewrite->block2 + + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Warning: trying to read doublewrite buffer page %lu\n", @@ -112,9 +112,9 @@ buf_read_page_low( /* Trx sys header is so low in the latching order that we play safe and do not leave the i/o-completion to an asynchronous i/o-thread. Ibuf bitmap pages must always be read with - syncronous i/o, to make sure they do not get involved in - thread deadlocks. */ - + syncronous i/o, to make sure they do not get involved in + thread deadlocks. */ + sync = TRUE; } @@ -125,16 +125,16 @@ buf_read_page_low( block = buf_page_init_for_read(err, mode, space, tablespace_version, offset); if (block == NULL) { - + return(0); } #ifdef UNIV_DEBUG if (buf_debug_prints) { fprintf(stderr, - "Posting read request for page %lu, sync %lu\n", + "Posting read request for page %lu, sync %lu\n", (ulong) offset, - (ulong) sync); + (ulong) sync); } #endif @@ -151,9 +151,9 @@ buf_read_page_low( fil_read */ buf_page_io_complete(block); } - + return(1); -} +} /************************************************************************ Applies a random read-ahead in buf_pool if there are at least a threshold @@ -188,15 +188,15 @@ buf_read_ahead_random( ulint i; if (srv_startup_is_before_trx_rollback_phase) { - /* No read-ahead to avoid thread deadlocks */ - return(0); + /* No read-ahead to avoid thread deadlocks */ + return(0); } if (ibuf_bitmap_page(offset) || trx_sys_hdr_page(space, offset)) { /* If it is an ibuf bitmap page or trx sys hdr, we do - no read-ahead, as that could break the ibuf page access - order */ + no read-ahead, as that could break the ibuf page access + order */ return(0); } @@ -219,7 +219,7 @@ buf_read_ahead_random( /* Get the minimum LRU_position field value for an initial segment of the LRU list, to determine which blocks have recently been added to the start of the list. */ - + LRU_recent_limit = buf_LRU_get_recent_limit(); mutex_enter(&(buf_pool->mutex)); @@ -229,7 +229,7 @@ buf_read_ahead_random( mutex_exit(&(buf_pool->mutex)); return(0); - } + } /* Count how many blocks in the area have been recently accessed, that is, reside near the start of the LRU list. */ @@ -238,15 +238,15 @@ buf_read_ahead_random( block = buf_page_hash_get(space, i); if ((block) - && (block->LRU_position > LRU_recent_limit) - && block->accessed) { + && (block->LRU_position > LRU_recent_limit) + && block->accessed) { recent_blocks++; } } mutex_exit(&(buf_pool->mutex)); - + if (recent_blocks < BUF_READ_AHEAD_RANDOM_THRESHOLD) { /* Do nothing */ @@ -270,7 +270,7 @@ buf_read_ahead_random( if (!ibuf_bitmap_page(i)) { count += buf_read_page_low(&err, FALSE, ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, - space, tablespace_version, i); + space, tablespace_version, i); if (err == DB_TABLESPACE_DELETED) { ut_print_timestamp(stderr); fprintf(stderr, @@ -285,7 +285,7 @@ buf_read_ahead_random( /* In simulated aio we wake the aio handler threads only after queuing all aio requests, in native aio the following call does nothing: */ - + os_aio_simulated_wake_handler_threads(); #ifdef UNIV_DEBUG @@ -293,11 +293,11 @@ buf_read_ahead_random( fprintf(stderr, "Random read-ahead space %lu offset %lu pages %lu\n", (ulong) space, (ulong) offset, - (ulong) count); + (ulong) count); } #endif /* UNIV_DEBUG */ - ++srv_read_ahead_rnd; + ++srv_read_ahead_rnd; return(count); } @@ -330,9 +330,9 @@ buf_read_page( count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, tablespace_version, offset); - srv_buf_pool_reads+= count2; + srv_buf_pool_reads+= count2; if (err == DB_TABLESPACE_DELETED) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: trying to access tablespace %lu page no. %lu,\n" "InnoDB: but the tablespace does not exist or is just being dropped.\n", @@ -391,17 +391,17 @@ buf_read_ahead_linear( ulint low, high; ulint err; ulint i; - + if (srv_startup_is_before_trx_rollback_phase) { - /* No read-ahead to avoid thread deadlocks */ - return(0); + /* No read-ahead to avoid thread deadlocks */ + return(0); } if (ibuf_bitmap_page(offset) || trx_sys_hdr_page(space, offset)) { /* If it is an ibuf bitmap page or trx sys hdr, we do - no read-ahead, as that could break the ibuf page access - order */ + no read-ahead, as that could break the ibuf page access + order */ return(0); } @@ -437,7 +437,7 @@ buf_read_ahead_linear( mutex_exit(&(buf_pool->mutex)); return(0); - } + } /* Check that almost all pages in the area have been accessed; if offset == low, the accesses must be in a descending order, otherwise, @@ -453,14 +453,15 @@ buf_read_ahead_linear( for (i = low; i < high; i++) { block = buf_page_hash_get(space, i); - + if ((block == NULL) || !block->accessed) { /* Not accessed */ fail_count++; - } else if (pred_block && (ut_ulint_cmp(block->LRU_position, - pred_block->LRU_position) - != asc_or_desc)) { + } else if (pred_block + && (ut_ulint_cmp(block->LRU_position, + pred_block->LRU_position) + != asc_or_desc)) { /* Accesses not in the right order */ fail_count++; @@ -489,27 +490,27 @@ buf_read_ahead_linear( } frame = block->frame; - + /* Read the natural predecessor and successor page addresses from the page; NOTE that because the calling thread may have an x-latch on the page, we do not acquire an s-latch on the page, this is to prevent deadlocks. Even if we read values which are nonsense, the - algorithm will work. */ + algorithm will work. */ pred_offset = fil_page_get_prev(frame); succ_offset = fil_page_get_next(frame); mutex_exit(&(buf_pool->mutex)); - + if ((offset == low) && (succ_offset == offset + 1)) { - /* This is ok, we can continue */ - new_offset = pred_offset; + /* This is ok, we can continue */ + new_offset = pred_offset; } else if ((offset == high - 1) && (pred_offset == offset - 1)) { - /* This is ok, we can continue */ - new_offset = succ_offset; + /* This is ok, we can continue */ + new_offset = succ_offset; } else { /* Successor or predecessor not in the right order */ @@ -548,7 +549,7 @@ buf_read_ahead_linear( full read batch to be posted, we use special heuristics here */ os_aio_simulated_put_read_threads_to_sleep(); - + for (i = low; i < high; i++) { /* It is only sensible to do read-ahead in the non-sync aio mode: hence FALSE as the first parameter */ @@ -556,7 +557,7 @@ buf_read_ahead_linear( if (!ibuf_bitmap_page(i)) { count += buf_read_page_low(&err, FALSE, ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, - space, tablespace_version, i); + space, tablespace_version, i); if (err == DB_TABLESPACE_DELETED) { ut_print_timestamp(stderr); fprintf(stderr, @@ -571,7 +572,7 @@ buf_read_ahead_linear( /* In simulated aio we wake the aio handler threads only after queuing all aio requests, in native aio the following call does nothing: */ - + os_aio_simulated_wake_handler_threads(); /* Flush pages from the end of the LRU list if necessary */ @@ -585,7 +586,7 @@ buf_read_ahead_linear( } #endif /* UNIV_DEBUG */ - ++srv_read_ahead_seq; + ++srv_read_ahead_seq; return(count); } @@ -616,11 +617,11 @@ buf_read_ibuf_merge_pages( ut_ad(!ibuf_inside()); #ifdef UNIV_IBUF_DEBUG ut_a(n_stored < UNIV_PAGE_SIZE); -#endif +#endif while (buf_pool->n_pend_reads > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) { os_thread_sleep(500000); - } + } for (i = 0; i < n_stored; i++) { if ((i + 1 == n_stored) && sync) { @@ -639,7 +640,7 @@ buf_read_ibuf_merge_pages( page_nos[i], FALSE); } } - + os_aio_simulated_wake_handler_threads(); /* Flush pages from the end of the LRU list if necessary */ @@ -704,14 +705,14 @@ buf_read_recv_pages( if ((i + 1 == n_stored) && sync) { buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, - tablespace_version, page_nos[i]); + tablespace_version, page_nos[i]); } else { buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE - | OS_AIO_SIMULATED_WAKE_LATER, - space, tablespace_version, page_nos[i]); + | OS_AIO_SIMULATED_WAKE_LATER, + space, tablespace_version, page_nos[i]); } } - + os_aio_simulated_wake_handler_threads(); /* Flush pages from the end of the LRU list if necessary */ diff --git a/storage/innobase/data/data0data.c b/storage/innobase/data/data0data.c index 19304a7a8e1..b2c8408e901 100644 --- a/storage/innobase/data/data0data.c +++ b/storage/innobase/data/data0data.c @@ -18,24 +18,24 @@ Created 5/30/1994 Heikki Tuuri #include "dict0dict.h" #include "btr0cur.h" +#ifdef UNIV_DEBUG byte data_error; /* data pointers of tuple fields are initialized to point here for error checking */ -#ifdef UNIV_DEBUG ulint data_dummy; /* this is used to fool the compiler in dtuple_validate */ #endif /* UNIV_DEBUG */ /* Some non-inlined functions used in the MySQL interface: */ -void +void dfield_set_data_noninline( - dfield_t* field, /* in: field */ + dfield_t* field, /* in: field */ void* data, /* in: data */ ulint len) /* in: length or UNIV_SQL_NULL */ { dfield_set_data(field, data, len); } -void* +void* dfield_get_data_noninline( dfield_t* field) /* in: field */ { @@ -47,15 +47,15 @@ dfield_get_len_noninline( { return(dfield_get_len(field)); } -ulint +ulint dtuple_get_n_fields_noninline( - dtuple_t* tuple) /* in: tuple */ + dtuple_t* tuple) /* in: tuple */ { return(dtuple_get_n_fields(tuple)); } -dfield_t* +dfield_t* dtuple_get_nth_field_noninline( - dtuple_t* tuple, /* in: tuple */ + dtuple_t* tuple, /* in: tuple */ ulint n) /* in: index of field */ { return(dtuple_get_nth_field(tuple, n)); @@ -83,7 +83,7 @@ dfield_data_is_binary_equal( } if (0 != ut_memcmp(field->data, data, len)) { - + return(FALSE); } @@ -122,18 +122,18 @@ dtuple_datas_are_ordering_equal( return(FALSE); } - + for (i = 0; i < n_fields; i++) { field1 = dtuple_get_nth_field(tuple1, i); field2 = dtuple_get_nth_field(tuple2, i); if (0 != cmp_dfield_dfield(field1, field2)) { - + return(FALSE); - } + } } - + return(TRUE); } @@ -144,12 +144,12 @@ dtuple_t* dtuple_create_for_mysql( /*====================*/ /* out, own created dtuple */ - void** heap, /* out: created memory heap */ - ulint n_fields) /* in: number of fields */ + void** heap, /* out: created memory heap */ + ulint n_fields) /* in: number of fields */ { - *heap = (void*)mem_heap_create(500); - - return(dtuple_create(*((mem_heap_t**)heap), n_fields)); + *heap = (void*)mem_heap_create(500); + + return(dtuple_create(*((mem_heap_t**)heap), n_fields)); } /************************************************************************* @@ -160,12 +160,12 @@ dtuple_free_for_mysql( /*==================*/ void* heap) /* in: memory heap where tuple was created */ { - mem_heap_free((mem_heap_t*)heap); + mem_heap_free((mem_heap_t*)heap); } /************************************************************************* Sets number of fields used in a tuple. Normally this is set in -dtuple_create, but if you want later to set it smaller, you can use this. */ +dtuple_create, but if you want later to set it smaller, you can use this. */ void dtuple_set_n_fields( @@ -189,7 +189,7 @@ dfield_check_typed_no_assert( dfield_t* field) /* in: data field */ { if (dfield_get_type(field)->mtype > DATA_MYSQL - || dfield_get_type(field)->mtype < DATA_VARCHAR) { + || dfield_get_type(field)->mtype < DATA_VARCHAR) { fprintf(stderr, "InnoDB: Error: data field type %lu, len %lu\n", @@ -211,8 +211,8 @@ dtuple_check_typed_no_assert( dtuple_t* tuple) /* in: tuple */ { dfield_t* field; - ulint i; - + ulint i; + if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) { fprintf(stderr, "InnoDB: Error: index entry has %lu fields\n", @@ -247,7 +247,7 @@ dfield_check_typed( dfield_t* field) /* in: data field */ { if (dfield_get_type(field)->mtype > DATA_MYSQL - || dfield_get_type(field)->mtype < DATA_VARCHAR) { + || dfield_get_type(field)->mtype < DATA_VARCHAR) { fprintf(stderr, "InnoDB: Error: data field type %lu, len %lu\n", @@ -270,7 +270,7 @@ dtuple_check_typed( dtuple_t* tuple) /* in: tuple */ { dfield_t* field; - ulint i; + ulint i; for (i = 0; i < dtuple_get_n_fields(tuple); i++) { @@ -294,11 +294,11 @@ dtuple_validate( dtuple_t* tuple) /* in: tuple */ { dfield_t* field; - byte* data; - ulint n_fields; - ulint len; - ulint i; - ulint j; + byte* data; + ulint n_fields; + ulint len; + ulint i; + ulint j; ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); @@ -311,7 +311,7 @@ dtuple_validate( field = dtuple_get_nth_field(tuple, i); len = dfield_get_len(field); - + if (len != UNIV_SQL_NULL) { data = field->data; @@ -357,7 +357,7 @@ dfield_print( mtype = dtype_get_mtype(dfield_get_type(dfield)); if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) { - + for (i = 0; i < len; i++) { int c = *data++; putc(isprint(c) ? c : ' ', stderr); @@ -372,7 +372,7 @@ dfield_print( /***************************************************************** Pretty prints a dfield value according to its data type. Also the hex string -is printed if a string contains non-printable characters. */ +is printed if a string contains non-printable characters. */ void dfield_print_also_hex( @@ -399,7 +399,7 @@ dfield_print_also_hex( if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) { print_also_hex = FALSE; - + for (i = 0; i < len; i++) { int c = *data++; if (!isprint(c)) { @@ -415,9 +415,9 @@ dfield_print_also_hex( } fputs(" Hex: ", stderr); - + data = dfield_get_data(dfield); - + for (i = 0; i < len; i++) { fprintf(stderr, "%02lx", (ulint)*data); @@ -431,6 +431,22 @@ dfield_print_also_hex( } } +/***************************************************************** +Print a dfield value using ut_print_buf. */ + +void +dfield_print_raw( +/*=============*/ + FILE* f, /* in: output stream */ + dfield_t* dfield) /* in: dfield */ +{ + if (dfield->len != UNIV_SQL_NULL) { + ut_print_buf(f, dfield->data, dfield->len); + } else { + fputs(" SQL NULL", f); + } +} + /************************************************************** The following function prints the contents of a tuple. */ @@ -440,7 +456,6 @@ dtuple_print( FILE* f, /* in: output stream */ dtuple_t* tuple) /* in: tuple */ { - dfield_t* field; ulint n_fields; ulint i; @@ -451,13 +466,7 @@ dtuple_print( for (i = 0; i < n_fields; i++) { fprintf(f, " %lu:", (ulong) i); - field = dtuple_get_nth_field(tuple, i); - - if (field->len != UNIV_SQL_NULL) { - ut_print_buf(f, field->data, field->len); - } else { - fputs(" SQL NULL", f); - } + dfield_print_raw(f, dtuple_get_nth_field(tuple, i)); putc(';', f); } @@ -497,7 +506,7 @@ dtuple_convert_big_rec( ibool is_externally_stored; ulint i; ulint j; - + ut_a(dtuple_check_typed_no_assert(entry)); size = rec_get_converted_size(index, entry); @@ -525,9 +534,9 @@ dtuple_convert_big_rec( n_fields = 0; while (rec_get_converted_size(index, entry) - >= ut_min(page_get_free_space_of_empty( - index->table->comp) / 2, - REC_MAX_DATA_SIZE)) { + >= ut_min(page_get_free_space_of_empty( + dict_table_is_comp(index->table)) / 2, + REC_MAX_DATA_SIZE)) { longest = 0; for (i = dict_index_get_n_unique_in_tree(index); @@ -545,25 +554,27 @@ dtuple_convert_big_rec( } } } - + if (!is_externally_stored) { dfield = dtuple_get_nth_field(entry, i); if (dfield->len != UNIV_SQL_NULL && - dfield->len > longest) { + dfield->len > longest) { - longest = dfield->len; + longest = dfield->len; - longest_i = i; + longest_i = i; } } } - + /* We do not store externally fields which are smaller than DICT_MAX_INDEX_COL_LEN */ - ut_a(DICT_MAX_INDEX_COL_LEN > REC_1BYTE_OFFS_LIMIT); +#if DICT_MAX_INDEX_COL_LEN <= REC_1BYTE_OFFS_LIMIT +# error "DICT_MAX_INDEX_COL_LEN <= REC_1BYTE_OFFS_LIMIT" +#endif if (longest < BTR_EXTERN_FIELD_REF_SIZE + 10 + DICT_MAX_INDEX_COL_LEN) { @@ -589,7 +600,7 @@ dtuple_convert_big_rec( vector->fields[n_fields].field_no = longest_i; ut_a(dfield->len > DICT_MAX_INDEX_COL_LEN); - + vector->fields[n_fields].len = dfield->len - DICT_MAX_INDEX_COL_LEN; @@ -610,7 +621,7 @@ dtuple_convert_big_rec( + dfield->len - BTR_EXTERN_FIELD_REF_SIZE, 0, BTR_EXTERN_FIELD_REF_SIZE); n_fields++; - } + } vector->n_fields = n_fields; return(vector); @@ -630,10 +641,10 @@ dtuple_convert_back_big_rec( freed in this function */ { dfield_t* dfield; - ulint i; + ulint i; for (i = 0; i < vector->n_fields; i++) { - + dfield = dtuple_get_nth_field(entry, vector->fields[i].field_no); /* Copy data from big rec vector */ @@ -641,10 +652,10 @@ dtuple_convert_back_big_rec( ut_memcpy(((byte*)dfield->data) + dfield->len - BTR_EXTERN_FIELD_REF_SIZE, vector->fields[i].data, - vector->fields[i].len); + vector->fields[i].len); dfield->len = dfield->len + vector->fields[i].len - BTR_EXTERN_FIELD_REF_SIZE; - } + } mem_heap_free(vector->heap); } diff --git a/storage/innobase/data/data0type.c b/storage/innobase/data/data0type.c index d4264ad2926..3ac1139d952 100644 --- a/storage/innobase/data/data0type.c +++ b/storage/innobase/data/data0type.c @@ -30,7 +30,7 @@ innobase_get_at_most_n_mbchars( ulint prefix_len, /* in: prefix length in bytes of the index (this has to be divided by mbmaxlen to get the number of CHARACTERS n in the prefix) */ - ulint data_len, /* in: length of the string in bytes */ + ulint data_len, /* in: length of the string in bytes */ const char* str); /* in: character string */ /* At the database startup we store the default-charset collation number of @@ -41,7 +41,7 @@ charset-collation code for them. */ ulint data_mysql_default_charset_coll = 99999999; dtype_t dtype_binary_val = {DATA_BINARY, 0, 0, 0, 0, 0}; -dtype_t* dtype_binary = &dtype_binary_val; +dtype_t* dtype_binary = &dtype_binary_val; /************************************************************************* Determine how many bytes the first n characters of the given string occupy. @@ -97,9 +97,9 @@ dtype_is_string_type( /* out: TRUE if string type */ ulint mtype) /* in: InnoDB main data type code: DATA_CHAR, ... */ { - if (mtype <= DATA_BLOB - || mtype == DATA_MYSQL - || mtype == DATA_VARMYSQL) { + if (mtype <= DATA_BLOB + || mtype == DATA_MYSQL + || mtype == DATA_VARMYSQL) { return(TRUE); } @@ -119,9 +119,9 @@ dtype_is_binary_string_type( ulint mtype, /* in: main data type */ ulint prtype) /* in: precise type */ { - if ((mtype == DATA_FIXBINARY) - || (mtype == DATA_BINARY) - || (mtype == DATA_BLOB && (prtype & DATA_BINARY_TYPE))) { + if ((mtype == DATA_FIXBINARY) + || (mtype == DATA_BINARY) + || (mtype == DATA_BLOB && (prtype & DATA_BINARY_TYPE))) { return(TRUE); } @@ -143,8 +143,8 @@ dtype_is_non_binary_string_type( ulint prtype) /* in: precise type */ { if (dtype_is_string_type(mtype) == TRUE - && dtype_is_binary_string_type(mtype, prtype) == FALSE) { - + && dtype_is_binary_string_type(mtype, prtype) == FALSE) { + return(TRUE); } @@ -190,7 +190,7 @@ dtype_validate( { ut_a(type); ut_a((type->mtype >= DATA_VARCHAR) && (type->mtype <= DATA_MYSQL)); - + if (type->mtype == DATA_SYS) { ut_a((type->prtype & DATA_MYSQL_TYPE_MASK) < DATA_N_SYS_COLS); } @@ -211,7 +211,7 @@ dtype_print( ulint mtype; ulint prtype; ulint len; - + ut_a(type); mtype = type->mtype; @@ -233,7 +233,7 @@ dtype_print( } len = type->len; - + if ((type->mtype == DATA_SYS) || (type->mtype == DATA_VARCHAR) || (type->mtype == DATA_CHAR)) { @@ -252,7 +252,7 @@ dtype_print( } else if (prtype == DATA_ENGLISH) { fputs("DATA_ENGLISH", stderr); } else { - fprintf(stderr, "prtype %lu", (ulong) mtype); + fprintf(stderr, "prtype %lu", (ulong) prtype); } } diff --git a/storage/innobase/dict/dict0boot.c b/storage/innobase/dict/dict0boot.c index 18a707a1b93..9c98338e603 100644 --- a/storage/innobase/dict/dict0boot.c +++ b/storage/innobase/dict/dict0boot.c @@ -29,14 +29,14 @@ Gets a pointer to the dictionary header and x-latches its page. */ dict_hdr_t* dict_hdr_get( /*=========*/ - /* out: pointer to the dictionary header, + /* out: pointer to the dictionary header, page x-latched */ mtr_t* mtr) /* in: mtr */ { dict_hdr_t* header; ut_ad(mtr); - + header = DICT_HDR + buf_page_get(DICT_HDR_SPACE, DICT_HDR_PAGE_NO, RW_X_LATCH, mtr); #ifdef UNIV_SYNC_DEBUG @@ -59,21 +59,21 @@ dict_hdr_get_new_id( mtr_t mtr; ut_ad((type == DICT_HDR_TABLE_ID) || (type == DICT_HDR_INDEX_ID) - || (type == DICT_HDR_MIX_ID)); + || (type == DICT_HDR_MIX_ID)); mtr_start(&mtr); dict_hdr = dict_hdr_get(&mtr); - id = mtr_read_dulint(dict_hdr + type, &mtr); + id = mtr_read_dulint(dict_hdr + type, &mtr); id = ut_dulint_add(id, 1); - - mlog_write_dulint(dict_hdr + type, id, &mtr); + + mlog_write_dulint(dict_hdr + type, id, &mtr); mtr_commit(&mtr); return(id); -} +} /************************************************************************** Writes the current value of the row id counter to the dictionary header file @@ -96,11 +96,11 @@ dict_hdr_flush_row_id(void) mtr_start(&mtr); dict_hdr = dict_hdr_get(&mtr); - - mlog_write_dulint(dict_hdr + DICT_HDR_ROW_ID, id, &mtr); + + mlog_write_dulint(dict_hdr + DICT_HDR_ROW_ID, id, &mtr); mtr_commit(&mtr); -} +} /********************************************************************* Creates the file page for the dictionary header. This function is @@ -116,7 +116,7 @@ dict_hdr_create( ulint hdr_page_no; ulint root_page_no; page_t* page; - + ut_ad(mtr); /* Create the dictionary header file block in a new, allocated file @@ -125,7 +125,7 @@ dict_hdr_create( DICT_HDR + DICT_HDR_FSEG_HEADER, mtr); hdr_page_no = buf_frame_get_page_no(page); - + ut_a(DICT_HDR_PAGE_NO == hdr_page_no); dict_header = dict_hdr_get(mtr); @@ -147,7 +147,7 @@ dict_hdr_create( /* Create the B-tree roots for the clustered indexes of the basic system tables */ - /*--------------------------*/ + /*--------------------------*/ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, DICT_HDR_SPACE, DICT_TABLES_ID, FALSE, mtr); if (root_page_no == FIL_NULL) { @@ -157,7 +157,7 @@ dict_hdr_create( mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no, MLOG_4BYTES, mtr); - /*--------------------------*/ + /*--------------------------*/ root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE, DICT_TABLE_IDS_ID, FALSE, mtr); if (root_page_no == FIL_NULL) { @@ -167,7 +167,7 @@ dict_hdr_create( mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no, MLOG_4BYTES, mtr); - /*--------------------------*/ + /*--------------------------*/ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, DICT_HDR_SPACE, DICT_COLUMNS_ID, FALSE, mtr); if (root_page_no == FIL_NULL) { @@ -177,7 +177,7 @@ dict_hdr_create( mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no, MLOG_4BYTES, mtr); - /*--------------------------*/ + /*--------------------------*/ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, DICT_HDR_SPACE, DICT_INDEXES_ID, FALSE, mtr); if (root_page_no == FIL_NULL) { @@ -187,7 +187,7 @@ dict_hdr_create( mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no, MLOG_4BYTES, mtr); - /*--------------------------*/ + /*--------------------------*/ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, DICT_HDR_SPACE, DICT_FIELDS_ID, FALSE, mtr); if (root_page_no == FIL_NULL) { @@ -197,7 +197,7 @@ dict_hdr_create( mlog_write_ulint(dict_header + DICT_HDR_FIELDS, root_page_no, MLOG_4BYTES, mtr); - /*--------------------------*/ + /*--------------------------*/ return(TRUE); } @@ -217,12 +217,12 @@ dict_boot(void) ibool success; mtr_start(&mtr); - + /* Create the hash tables etc. */ dict_init(); mutex_enter(&(dict_sys->mutex)); - + /* Get the dictionary header */ dict_hdr = dict_hdr_get(&mtr); @@ -237,16 +237,15 @@ dict_boot(void) header. */ dict_sys->row_id = ut_dulint_add( - ut_dulint_align_up( - mtr_read_dulint(dict_hdr + DICT_HDR_ROW_ID, - &mtr), - DICT_HDR_ROW_ID_WRITE_MARGIN), - DICT_HDR_ROW_ID_WRITE_MARGIN); + ut_dulint_align_up( + mtr_read_dulint(dict_hdr + DICT_HDR_ROW_ID, &mtr), + DICT_HDR_ROW_ID_WRITE_MARGIN), + DICT_HDR_ROW_ID_WRITE_MARGIN); /* Insert into the dictionary cache the descriptions of the basic system tables */ /*-------------------------*/ - table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, FALSE); + table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0); dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0); dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0); @@ -258,14 +257,14 @@ dict_boot(void) dict_mem_table_add_col(table, "SPACE", DATA_INT, 0, 4, 0); table->id = DICT_TABLES_ID; - + dict_table_add_to_cache(table); dict_sys->sys_tables = table; - + index = dict_mem_index_create("SYS_TABLES", "CLUST_IND", DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 1); - dict_mem_index_add_field(index, "NAME", 0, 0); + dict_mem_index_add_field(index, "NAME", 0); index->id = DICT_TABLES_ID; @@ -275,14 +274,14 @@ dict_boot(void) /*-------------------------*/ index = dict_mem_index_create("SYS_TABLES", "ID_IND", DICT_HDR_SPACE, DICT_UNIQUE, 1); - dict_mem_index_add_field(index, "ID", 0, 0); + dict_mem_index_add_field(index, "ID", 0); index->id = DICT_TABLE_IDS_ID; success = dict_index_add_to_cache(table, index, mtr_read_ulint( dict_hdr + DICT_HDR_TABLE_IDS, MLOG_4BYTES, &mtr)); ut_a(success); /*-------------------------*/ - table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, FALSE); + table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0); dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY,0,0,0); dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0); @@ -291,7 +290,7 @@ dict_boot(void) dict_mem_table_add_col(table, "PRTYPE", DATA_INT, 0, 4, 0); dict_mem_table_add_col(table, "LEN", DATA_INT, 0, 4, 0); dict_mem_table_add_col(table, "PREC", DATA_INT, 0, 4, 0); - + table->id = DICT_COLUMNS_ID; dict_table_add_to_cache(table); @@ -300,15 +299,15 @@ dict_boot(void) index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND", DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2); - dict_mem_index_add_field(index, "TABLE_ID", 0, 0); - dict_mem_index_add_field(index, "POS", 0, 0); + dict_mem_index_add_field(index, "TABLE_ID", 0); + dict_mem_index_add_field(index, "POS", 0); index->id = DICT_COLUMNS_ID; success = dict_index_add_to_cache(table, index, mtr_read_ulint( dict_hdr + DICT_HDR_COLUMNS, MLOG_4BYTES, &mtr)); ut_a(success); /*-------------------------*/ - table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, FALSE); + table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0); dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY, 0,0,0); dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0); @@ -336,15 +335,15 @@ dict_boot(void) index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND", DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2); - dict_mem_index_add_field(index, "TABLE_ID", 0, 0); - dict_mem_index_add_field(index, "ID", 0, 0); + dict_mem_index_add_field(index, "TABLE_ID", 0); + dict_mem_index_add_field(index, "ID", 0); index->id = DICT_INDEXES_ID; success = dict_index_add_to_cache(table, index, mtr_read_ulint( dict_hdr + DICT_HDR_INDEXES, MLOG_4BYTES, &mtr)); ut_a(success); /*-------------------------*/ - table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, FALSE); + table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0); dict_mem_table_add_col(table, "INDEX_ID", DATA_BINARY, 0,0,0); dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0); @@ -357,8 +356,8 @@ dict_boot(void) index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND", DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2); - dict_mem_index_add_field(index, "INDEX_ID", 0, 0); - dict_mem_index_add_field(index, "POS", 0, 0); + dict_mem_index_add_field(index, "INDEX_ID", 0); + dict_mem_index_add_field(index, "POS", 0); index->id = DICT_FIELDS_ID; success = dict_index_add_to_cache(table, index, mtr_read_ulint( @@ -378,7 +377,7 @@ dict_boot(void) dict_load_sys_table(dict_sys->sys_columns); dict_load_sys_table(dict_sys->sys_indexes); dict_load_sys_table(dict_sys->sys_fields); - + mutex_exit(&(dict_sys->mutex)); } @@ -407,7 +406,7 @@ dict_create(void) dict_hdr_create(&mtr); mtr_commit(&mtr); - + dict_boot(); dict_insert_initial_data(); diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c index c7d6ffd2c22..6f0a81296ac 100644 --- a/storage/innobase/dict/dict0crea.c +++ b/storage/innobase/dict/dict0crea.c @@ -33,7 +33,7 @@ dtuple_t* dict_create_sys_tables_tuple( /*=========================*/ /* out: the tuple which should be inserted */ - dict_table_t* table, /* in: table */ + dict_table_t* table, /* in: table */ mem_heap_t* heap) /* in: memory heap from which the memory for the built tuple is allocated */ { @@ -45,7 +45,7 @@ dict_create_sys_tables_tuple( ut_ad(table && heap); sys_tables = dict_sys->sys_tables; - + entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS); /* 0: NAME -----------------------------*/ @@ -62,9 +62,13 @@ dict_create_sys_tables_tuple( /* 4: N_COLS ---------------------------*/ dfield = dtuple_get_nth_field(entry, 2); +#if DICT_TF_COMPACT != 1 +#error +#endif + ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, table->n_def - | ((ulint) table->comp << 31)); + | ((table->flags & DICT_TF_COMPACT) << 31)); dfield_set_data(dfield, ptr, 4); /* 5: TYPE -----------------------------*/ dfield = dtuple_get_nth_field(entry, 3); @@ -91,7 +95,7 @@ dict_create_sys_tables_tuple( /* 8: CLUSTER_NAME ---------------------*/ dfield = dtuple_get_nth_field(entry, 6); - if (table->type == DICT_TABLE_CLUSTER_MEMBER) { + if (table->type == DICT_TABLE_CLUSTER_MEMBER) { dfield_set_data(dfield, table->cluster_name, ut_strlen(table->cluster_name)); ut_error; /* Oracle-style clusters are not supported yet */ @@ -108,9 +112,9 @@ dict_create_sys_tables_tuple( /*----------------------------------*/ dict_table_copy_types(entry, sys_tables); - + return(entry); -} +} /********************************************************************* Based on a table object, this function builds the entry to be inserted @@ -120,7 +124,7 @@ dtuple_t* dict_create_sys_columns_tuple( /*==========================*/ /* out: the tuple which should be inserted */ - dict_table_t* table, /* in: table */ + dict_table_t* table, /* in: table */ ulint i, /* in: column number */ mem_heap_t* heap) /* in: memory heap from which the memory for the built tuple is allocated */ @@ -136,7 +140,7 @@ dict_create_sys_columns_tuple( column = dict_table_get_nth_col(table, i); sys_columns = dict_sys->sys_columns; - + entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS); /* 0: TABLE_ID -----------------------*/ @@ -190,7 +194,7 @@ dict_create_sys_columns_tuple( dict_table_copy_types(entry, sys_columns); return(entry); -} +} /******************************************************************* Builds a table definition to insert. */ @@ -236,7 +240,7 @@ dict_build_table_def_step( cluster_table = dict_table_get_low(table->cluster_name); if (cluster_table == NULL) { - + return(DB_CLUSTER_NOT_FOUND); } @@ -244,7 +248,7 @@ dict_build_table_def_step( table->space = cluster_table->space; table->mix_len = cluster_table->mix_len; - + table->mix_id = dict_hdr_get_new_id(DICT_HDR_MIX_ID); } @@ -256,7 +260,7 @@ dict_build_table_def_step( - page 2 is the first inode page, - page 3 will contain the root of the clustered index of the table we create here. */ - + table->space = 0; /* reset to zero for the call below */ if (table->dir_path_of_temp_table) { @@ -281,7 +285,7 @@ dict_build_table_def_step( mtr_start(&mtr); fsp_header_init(table->space, FIL_IBD_FILE_INITIAL_SIZE, &mtr); - + mtr_commit(&mtr); } @@ -306,7 +310,7 @@ dict_build_col_def_step( row = dict_create_sys_columns_tuple(node->table, node->col_no, node->heap); ins_node_set_new_row(node->col_def, row); - + return(DB_SUCCESS); } @@ -318,7 +322,7 @@ dtuple_t* dict_create_sys_indexes_tuple( /*==========================*/ /* out: the tuple which should be inserted */ - dict_index_t* index, /* in: index */ + dict_index_t* index, /* in: index */ mem_heap_t* heap) /* in: memory heap from which the memory for the built tuple is allocated */ { @@ -336,7 +340,7 @@ dict_create_sys_indexes_tuple( sys_indexes = dict_sys->sys_indexes; table = dict_table_get_low(index->table_name); - + entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS); /* 0: TABLE_ID -----------------------*/ @@ -400,7 +404,7 @@ dict_create_sys_indexes_tuple( dict_table_copy_types(entry, sys_indexes); return(entry); -} +} /********************************************************************* Based on an index object, this function builds the entry to be inserted @@ -410,7 +414,7 @@ dtuple_t* dict_create_sys_fields_tuple( /*=========================*/ /* out: the tuple which should be inserted */ - dict_index_t* index, /* in: index */ + dict_index_t* index, /* in: index */ ulint i, /* in: field number */ mem_heap_t* heap) /* in: memory heap from which the memory for the built tuple is allocated */ @@ -426,15 +430,15 @@ dict_create_sys_fields_tuple( ut_ad(index && heap); for (j = 0; j < index->n_fields; j++) { - if (dict_index_get_nth_field(index, j)->prefix_len > 0) { - index_contains_column_prefix_field = TRUE; + if (dict_index_get_nth_field(index, j)->prefix_len > 0) { + index_contains_column_prefix_field = TRUE; } } field = dict_index_get_nth_field(index, i); sys_fields = dict_sys->sys_fields; - + entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS); /* 0: INDEX_ID -----------------------*/ @@ -449,19 +453,19 @@ dict_create_sys_fields_tuple( dfield = dtuple_get_nth_field(entry, 1); ptr = mem_heap_alloc(heap, 4); - + if (index_contains_column_prefix_field) { /* If there are column prefix fields in the index, then we store the number of the field to the 2 HIGH bytes and the prefix length to the 2 low bytes, */ - mach_write_to_4(ptr, (i << 16) + field->prefix_len); + mach_write_to_4(ptr, (i << 16) + field->prefix_len); } else { - /* Else we store the number of the field to the 2 LOW bytes. + /* Else we store the number of the field to the 2 LOW bytes. This is to keep the storage format compatible with InnoDB versions < 4.0.14. */ - - mach_write_to_4(ptr, i); + + mach_write_to_4(ptr, i); } dfield_set_data(dfield, ptr, 4); @@ -473,9 +477,9 @@ dict_create_sys_fields_tuple( /*---------------------------------*/ dict_table_copy_types(entry, sys_fields); - + return(entry); -} +} /********************************************************************* Creates the tuple with which the index entry is searched for writing the index @@ -498,13 +502,13 @@ dict_create_search_tuple( search_tuple = dtuple_create(heap, 2); - field1 = dtuple_get_nth_field(tuple, 0); - field2 = dtuple_get_nth_field(search_tuple, 0); + field1 = dtuple_get_nth_field(tuple, 0); + field2 = dtuple_get_nth_field(search_tuple, 0); dfield_copy(field2, field1); - field1 = dtuple_get_nth_field(tuple, 1); - field2 = dtuple_get_nth_field(search_tuple, 1); + field1 = dtuple_get_nth_field(tuple, 1); + field2 = dtuple_get_nth_field(search_tuple, 1); dfield_copy(field2, field1); @@ -547,8 +551,8 @@ dict_build_index_def_step( node->table = table; ut_ad((UT_LIST_GET_LEN(table->indexes) > 0) - || (index->type & DICT_CLUSTERED)); - + || (index->type & DICT_CLUSTERED)); + index->id = dict_hdr_get_new_id(DICT_HDR_INDEX_ID); /* Inherit the space id from the table; we store all indexes of a @@ -577,7 +581,7 @@ dict_build_field_def_step( dtuple_t* row; index = node->index; - + row = dict_create_sys_fields_tuple(index, node->field_no, node->heap); ins_node_set_new_row(node->field_def, row); @@ -605,7 +609,7 @@ dict_create_index_tree_step( ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ - index = node->index; + index = node->index; table = node->table; sys_indexes = dict_sys->sys_indexes; @@ -626,7 +630,7 @@ dict_create_index_tree_step( mtr_start(&mtr); search_tuple = dict_create_search_tuple(node->ind_row, node->heap); - + btr_pcur_open(UT_LIST_GET_FIRST(sys_indexes->indexes), search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF, &pcur, &mtr); @@ -634,7 +638,7 @@ dict_create_index_tree_step( btr_pcur_move_to_next_user_rec(&pcur, &mtr); node->page_no = btr_create(index->type, index->space, index->id, - table->comp, &mtr); + dict_table_is_comp(table), &mtr); /* printf("Created a new index tree in space %lu root page %lu\n", index->space, index->page_no); */ @@ -666,16 +670,16 @@ dict_drop_index_tree( ulint space; byte* ptr; ulint len; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ - ut_a(!dict_sys->sys_indexes->comp); + ut_a(!dict_table_is_comp(dict_sys->sys_indexes)); ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len); ut_ad(len == 4); - + root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr); if (root_page_no == FIL_NULL) { @@ -706,7 +710,7 @@ dict_drop_index_tree( /* Then we free the root page in the same mini-transaction where we write FIL_NULL to the appropriate field in the SYS_INDEXES record: this mini-transaction marks the B-tree totally freed */ - + /* printf("Dropping index tree in space %lu root page %lu\n", space, root_page_no); */ btr_free_root(space, root_page_no, mtr); @@ -743,7 +747,7 @@ dict_truncate_index_tree( ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ - ut_a(!dict_sys->sys_indexes->comp); + ut_a(!dict_table_is_comp(dict_sys->sys_indexes)); ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len); ut_ad(len == 4); @@ -853,7 +857,7 @@ tab_create_graph_create( tab_node_t* node; node = mem_heap_alloc(heap, sizeof(tab_node_t)); - + node->common.type = QUE_NODE_CREATE_TABLE; node->table = table; @@ -862,9 +866,9 @@ tab_create_graph_create( node->heap = mem_heap_create(256); node->tab_def = ins_node_create(INS_DIRECT, dict_sys->sys_tables, - heap); + heap); node->tab_def->common.parent = node; - + node->col_def = ins_node_create(INS_DIRECT, dict_sys->sys_columns, heap); node->col_def->common.parent = node; @@ -899,7 +903,7 @@ ind_create_graph_create( node->heap = mem_heap_create(256); node->ind_def = ins_node_create(INS_DIRECT, - dict_sys->sys_indexes, heap); + dict_sys->sys_indexes, heap); node->ind_def->common.parent = node; node->field_def = ins_node_create(INS_DIRECT, @@ -931,7 +935,7 @@ dict_create_table_step( #endif /* UNIV_SYNC_DEBUG */ trx = thr_get_trx(thr); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_TABLE); @@ -950,7 +954,7 @@ dict_create_table_step( goto function_exit; } - + node->state = TABLE_BUILD_COL_DEF; node->col_no = 0; @@ -971,7 +975,7 @@ dict_create_table_step( } node->col_no++; - + thr->run_node = node->col_def; return(thr); @@ -985,7 +989,7 @@ dict_create_table_step( /* Table was correctly defined: do NOT commit the transaction (CREATE TABLE does NOT do an implicit commit of the current transaction) */ - + node->state = TABLE_ADD_TO_CACHE; /* thr->run_node = node->commit_node; @@ -1018,7 +1022,7 @@ function_exit: thr->run_node = que_node_get_parent(node); return(thr); -} +} /*************************************************************** Creates an index. This is a high-level function used in SQL execution @@ -1041,7 +1045,7 @@ dict_create_index_step( #endif /* UNIV_SYNC_DEBUG */ trx = thr_get_trx(thr); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX); @@ -1058,7 +1062,7 @@ dict_create_index_step( goto function_exit; } - + node->state = INDEX_BUILD_FIELD_DEF; node->field_no = 0; @@ -1079,7 +1083,7 @@ dict_create_index_step( } node->field_no++; - + thr->run_node = node->field_def; return(thr); @@ -1105,7 +1109,7 @@ dict_create_index_step( /* Index was correctly defined: do NOT commit the transaction (CREATE INDEX does NOT currently do an implicit commit of the current transaction) */ - + node->state = INDEX_ADD_TO_CACHE; /* thr->run_node = node->commit_node; @@ -1141,7 +1145,7 @@ function_exit: thr->run_node = que_node_get_parent(node); return(thr); -} +} /******************************************************************** Creates the foreign key constraints system tables inside InnoDB @@ -1159,29 +1163,29 @@ dict_create_or_check_foreign_constraint_tables(void) que_t* graph; ulint error; trx_t* trx; - const char* str; + const char* str; mutex_enter(&(dict_sys->mutex)); table1 = dict_table_get_low("SYS_FOREIGN"); table2 = dict_table_get_low("SYS_FOREIGN_COLS"); - + if (table1 && table2 - && UT_LIST_GET_LEN(table1->indexes) == 3 - && UT_LIST_GET_LEN(table2->indexes) == 1) { + && UT_LIST_GET_LEN(table1->indexes) == 3 + && UT_LIST_GET_LEN(table2->indexes) == 1) { - /* Foreign constraint system tables have already been - created, and they are ok */ + /* Foreign constraint system tables have already been + created, and they are ok */ mutex_exit(&(dict_sys->mutex)); - return(DB_SUCCESS); - } + return(DB_SUCCESS); + } mutex_exit(&(dict_sys->mutex)); trx = trx_allocate_for_mysql(); - + trx->op_info = "creating foreign key sys tables"; row_mysql_lock_data_dictionary(trx); @@ -1204,7 +1208,7 @@ dict_create_or_check_foreign_constraint_tables(void) /* NOTE: in dict_load_foreigns we use the fact that there are 2 secondary indexes on SYS_FOREIGN, and they are defined just like below */ - + /* NOTE: when designing InnoDB's foreign key support in 2001, we made an error and made the table names and the foreign key id of type 'CHAR' (internally, really a VARCHAR). We should have made the type @@ -1243,7 +1247,7 @@ dict_create_or_check_foreign_constraint_tables(void) if (error != DB_SUCCESS) { fprintf(stderr, "InnoDB: error %lu in creation\n", (ulong) error); - + ut_a(error == DB_OUT_OF_FILE_SPACE); fprintf(stderr, "InnoDB: creation failed\n"); @@ -1258,14 +1262,14 @@ dict_create_or_check_foreign_constraint_tables(void) } que_graph_free(graph); - + trx->op_info = ""; row_mysql_unlock_data_dictionary(trx); - trx_free_for_mysql(trx); + trx_free_for_mysql(trx); - if (error == DB_SUCCESS) { + if (error == DB_SUCCESS) { fprintf(stderr, "InnoDB: Foreign key constraint system tables created\n"); } @@ -1324,7 +1328,7 @@ dict_create_add_foreigns_to_dictionary( if (NULL == dict_table_get_low("SYS_FOREIGN")) { fprintf(stderr, - "InnoDB: table SYS_FOREIGN not found from internal data dictionary\n"); +"InnoDB: table SYS_FOREIGN not found from internal data dictionary\n"); return(DB_ERROR); } @@ -1432,12 +1436,12 @@ loop: "in front of the user-defined constraint name).\n", ef); fputs("Note that InnoDB's FOREIGN KEY system tables store\n" - "constraint names as case-insensitive, with the\n" - "MySQL standard latin1_swedish_ci collation. If you\n" - "create tables or databases whose names differ only in\n" - "the character case, then collisions in constraint\n" - "names can occur. Workaround: name your constraints\n" - "explicitly with unique names.\n", + "constraint names as case-insensitive, with the\n" + "MySQL standard latin1_swedish_ci collation. If you\n" + "create tables or databases whose names differ only in\n" + "the character case, then collisions in constraint\n" + "names can occur. Workaround: name your constraints\n" + "explicitly with unique names.\n", ef); mutex_exit(&dict_foreign_err_mutex); @@ -1446,7 +1450,7 @@ loop: } if (error != DB_SUCCESS) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Foreign key constraint creation failed:\n" "InnoDB: internal error number %lu\n", (ulong) error); @@ -1461,7 +1465,7 @@ loop: return(error); } - + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); goto loop; diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index fb95ffbd80c..720074a4911 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -132,7 +132,7 @@ dict_index_find_cols( /*=================*/ /* out: TRUE if success */ dict_table_t* table, /* in: table */ - dict_index_t* index); /* in: index */ + dict_index_t* index); /* in: index */ /*********************************************************************** Builds the internal dictionary cache representation for a clustered index, containing also system fields not defined by the user. */ @@ -144,7 +144,7 @@ dict_index_build_internal_clust( of the clustered index */ dict_table_t* table, /* in: table */ dict_index_t* index); /* in: user representation of a clustered - index */ + index */ /*********************************************************************** Builds the internal dictionary cache representation for a non-clustered index, containing also system fields not defined by the user. */ @@ -156,7 +156,7 @@ dict_index_build_internal_non_clust( of the non-clustered index */ dict_table_t* table, /* in: table */ dict_index_t* index); /* in: user representation of a non-clustered - index */ + index */ /************************************************************************** Removes a foreign constraint struct from the dictionary cache. */ static @@ -196,9 +196,10 @@ dict_foreign_free( /* Stream for storing detailed information about the latest foreign key and unique key errors */ FILE* dict_foreign_err_file = NULL; -mutex_t dict_foreign_err_mutex; /* mutex protecting the foreign +mutex_t dict_foreign_err_mutex; /* mutex protecting the foreign and unique error buffers */ - + +#ifndef UNIV_HOTBACKUP /********************************************************************** Makes all characters in a NUL-terminated UTF-8 string lower case. */ @@ -209,6 +210,7 @@ dict_casedn_str( { innobase_casedn_str(a); } +#endif /* !UNIV_HOTBACKUP */ /************************************************************************ Checks if the database name in two table names is the same. */ @@ -263,7 +265,7 @@ dict_get_db_name_len( ut_a(s); return(s - name); } - + /************************************************************************ Reserves the dictionary system mutex for MySQL. */ @@ -273,7 +275,7 @@ dict_mutex_enter_for_mysql(void) { mutex_enter(&(dict_sys->mutex)); } - + /************************************************************************ Releases the dictionary system mutex for MySQL. */ @@ -283,7 +285,7 @@ dict_mutex_exit_for_mysql(void) { mutex_exit(&(dict_sys->mutex)); } - + /************************************************************************ Decrements the count of open MySQL handles to a table. */ @@ -297,7 +299,7 @@ dict_table_decrement_handle_count( ut_a(table->n_mysql_handles_opened > 0); table->n_mysql_handles_opened--; - + mutex_exit(&(dict_sys->mutex)); } @@ -350,7 +352,7 @@ dict_table_get_index_noninline( { return(dict_table_get_index(table, name)); } - + /************************************************************************ Initializes the autoinc counter. It is not an error to initialize an already initialized counter. */ @@ -390,7 +392,7 @@ dict_table_autoinc_get( value = table->autoinc; table->autoinc = table->autoinc + 1; } - + mutex_exit(&(table->autoinc_mutex)); return(value); @@ -407,7 +409,7 @@ dict_table_autoinc_decrement( mutex_enter(&(table->autoinc_mutex)); table->autoinc = table->autoinc - 1; - + mutex_exit(&(table->autoinc_mutex)); } @@ -431,7 +433,7 @@ dict_table_autoinc_read( } else { value = table->autoinc; } - + mutex_exit(&(table->autoinc_mutex)); return(value); @@ -476,7 +478,7 @@ dict_table_autoinc_update( if (value >= table->autoinc) { table->autoinc = value + 1; } - } + } mutex_exit(&(table->autoinc_mutex)); } @@ -497,7 +499,7 @@ dict_index_get_nth_col_pos( dict_col_t* col; ulint pos; ulint n_fields; - + ut_ad(index); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); @@ -509,7 +511,7 @@ dict_index_get_nth_col_pos( } n_fields = dict_index_get_n_fields(index); - + for (pos = 0; pos < n_fields; pos++) { field = dict_index_get_nth_field(index, pos); @@ -537,7 +539,7 @@ dict_index_contains_col_or_prefix( dict_col_t* col; ulint pos; ulint n_fields; - + ut_ad(index); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); @@ -549,7 +551,7 @@ dict_index_contains_col_or_prefix( col = dict_table_get_nth_col(index->table, n); n_fields = dict_index_get_n_fields(index); - + for (pos = 0; pos < n_fields; pos++) { field = dict_index_get_nth_field(index, pos); @@ -582,21 +584,21 @@ dict_index_get_nth_field_pos( dict_field_t* field2; ulint n_fields; ulint pos; - + ut_ad(index); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); field2 = dict_index_get_nth_field(index2, n); n_fields = dict_index_get_n_fields(index); - + for (pos = 0; pos < n_fields; pos++) { field = dict_index_get_nth_field(index, pos); if (field->col == field2->col - && (field->prefix_len == 0 + && (field->prefix_len == 0 || (field->prefix_len >= field2->prefix_len - && field2->prefix_len != 0))) { + && field2->prefix_len != 0))) { return(pos); } @@ -616,7 +618,7 @@ dict_table_get_on_id( trx_t* trx) /* in: transaction handle */ { dict_table_t* table; - + if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0 || trx->dict_operation_lock_mode == RW_X_LATCH) { /* It is a system table which will always exist in the table @@ -634,7 +636,7 @@ dict_table_get_on_id( mutex_enter(&(dict_sys->mutex)); table = dict_table_get_on_id_low(table_id, trx); - + mutex_exit(&(dict_sys->mutex)); return(table); @@ -672,7 +674,7 @@ dict_table_col_in_clustered_key( dict_col_t* col; ulint pos; ulint n_fields; - + ut_ad(table); col = dict_table_get_nth_col(table, n); @@ -680,7 +682,7 @@ dict_table_col_in_clustered_key( index = dict_table_get_first_index(table); n_fields = dict_index_get_n_unique(index); - + for (pos = 0; pos < n_fields; pos++) { field = dict_index_get_nth_field(index, pos); @@ -745,17 +747,17 @@ dict_table_get( UT_NOT_USED(trx); mutex_enter(&(dict_sys->mutex)); - + table = dict_table_get_low(table_name); mutex_exit(&(dict_sys->mutex)); if (table != NULL) { - if (!table->stat_initialized) { + if (!table->stat_initialized) { dict_update_statistics(table); } } - + return(table); } @@ -775,22 +777,22 @@ dict_table_get_and_increment_handle_count( UT_NOT_USED(trx); mutex_enter(&(dict_sys->mutex)); - + table = dict_table_get_low(table_name); if (table != NULL) { - table->n_mysql_handles_opened++; + table->n_mysql_handles_opened++; } mutex_exit(&(dict_sys->mutex)); if (table != NULL) { - if (!table->stat_initialized && !table->ibd_file_missing) { + if (!table->stat_initialized && !table->ibd_file_missing) { dict_update_statistics(table); } } - + return(table); } @@ -805,7 +807,7 @@ dict_table_add_to_cache( ulint fold; ulint id_fold; ulint i; - + ut_ad(table); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); @@ -813,12 +815,12 @@ dict_table_add_to_cache( ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); ut_ad(table->cached == FALSE); - + fold = ut_fold_string(table->name); id_fold = ut_fold_dulint(table->id); - + table->cached = TRUE; - + /* NOTE: the system columns MUST be added in the following order (so that they can be indexed by the numerical value of DATA_ROW_ID, etc.) and as the last columns of the table memory object. @@ -847,7 +849,7 @@ dict_table_add_to_cache( #endif /* This check reminds that if a new system column is added to - the program, it should be dealt with here */ + the program, it should be dealt with here */ #if DATA_N_SYS_COLS != 4 #error "DATA_N_SYS_COLS != 4" #endif @@ -909,7 +911,7 @@ dict_index_find_on_id_low( { dict_table_t* table; dict_index_t* index; - + table = UT_LIST_GET_FIRST(dict_sys->table_LRU); while (table) { @@ -951,16 +953,16 @@ dict_table_rename_in_cache( char* old_name; ibool success; ulint i; - + ut_ad(table); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ old_size = mem_heap_get_size(table->heap); - + fold = ut_fold_string(new_name); - + /* Look for a table with the same name: error if such exists */ { dict_table_t* table2; @@ -969,7 +971,7 @@ dict_table_rename_in_cache( if (table2) { fprintf(stderr, "InnoDB: Error: dictionary cache already contains a table of name %s\n", - new_name); + new_name); return(FALSE); } } @@ -1018,7 +1020,7 @@ dict_table_rename_in_cache( while (index != NULL) { index->table_name = table->name; - + index = dict_table_get_next_index(index); } @@ -1030,7 +1032,7 @@ dict_table_rename_in_cache( constraints from the dictionary cache here. The foreign key constraints will be inherited to the new table from the system tables through a call of dict_load_foreigns. */ - + /* Remove the foreign constraints from the cache */ foreign = UT_LIST_GET_LAST(table->foreign_list); @@ -1046,14 +1048,14 @@ dict_table_rename_in_cache( while (foreign != NULL) { foreign->referenced_table = NULL; foreign->referenced_index = NULL; - + foreign = UT_LIST_GET_NEXT(referenced_list, foreign); } /* Make the list of referencing constraints empty */ UT_LIST_INIT(table->referenced_list); - + return(TRUE); } @@ -1085,10 +1087,10 @@ dict_table_rename_in_cache( old_id = mem_strdup(foreign->id); if (ut_strlen(foreign->id) > ut_strlen(old_name) - + ((sizeof dict_ibfk) - 1) - && 0 == ut_memcmp(foreign->id, old_name, - ut_strlen(old_name)) - && 0 == ut_memcmp( + + ((sizeof dict_ibfk) - 1) + && 0 == ut_memcmp(foreign->id, old_name, + ut_strlen(old_name)) + && 0 == ut_memcmp( foreign->id + ut_strlen(old_name), dict_ibfk, (sizeof dict_ibfk) - 1)) { @@ -1096,11 +1098,11 @@ dict_table_rename_in_cache( if (ut_strlen(table->name) > ut_strlen(old_name)) { foreign->id = mem_heap_alloc( - foreign->heap, + foreign->heap, ut_strlen(table->name) + ut_strlen(old_id) + 1); } - + /* Replace the prefix 'databasename/tablename' with the new names */ strcpy(foreign->id, table->name); @@ -1112,16 +1114,16 @@ dict_table_rename_in_cache( db_len = dict_get_db_name_len(table->name) + 1; if (dict_get_db_name_len(table->name) - > dict_get_db_name_len(foreign->id)) { + > dict_get_db_name_len(foreign->id)) { foreign->id = mem_heap_alloc( - foreign->heap, - db_len + ut_strlen(old_id) + 1); + foreign->heap, + db_len + ut_strlen(old_id) + 1); } /* Replace the database prefix in id with the one from table->name */ - + ut_memcpy(foreign->id, table->name, db_len); strcpy(foreign->id + db_len, @@ -1194,7 +1196,7 @@ dict_table_remove_from_cache( dict_index_t* index; ulint size; ulint i; - + ut_ad(table); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); @@ -1222,7 +1224,7 @@ dict_table_remove_from_cache( while (foreign != NULL) { foreign->referenced_table = NULL; foreign->referenced_index = NULL; - + foreign = UT_LIST_GET_NEXT(referenced_list, foreign); } @@ -1308,7 +1310,7 @@ dict_col_add_to_cache( ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - + fold = ut_fold_ulint_pair(ut_fold_string(table->name), ut_fold_string(col->name)); @@ -1318,7 +1320,7 @@ dict_col_add_to_cache( HASH_SEARCH(hash, dict_sys->col_hash, fold, col2, (ut_strcmp(col->name, col2->name) == 0) && (ut_strcmp((col2->table)->name, table->name) - == 0)); + == 0)); ut_a(col2 == NULL); } @@ -1341,7 +1343,7 @@ dict_col_remove_from_cache( ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - + fold = ut_fold_ulint_pair(ut_fold_string(table->name), ut_fold_string(col->name)); @@ -1366,7 +1368,7 @@ dict_col_reposition_in_cache( ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - + fold = ut_fold_ulint_pair(ut_fold_string(table->name), ut_fold_string(col->name)); @@ -1374,7 +1376,7 @@ dict_col_reposition_in_cache( fold = ut_fold_ulint_pair(ut_fold_string(new_name), ut_fold_string(col->name)); - + HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col); } @@ -1397,14 +1399,14 @@ dict_index_add_to_cache( ulint n_ord; ibool success; ulint i; - + ut_ad(index); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_ad(index->n_def == index->n_fields); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - + ut_ad(mem_heap_validate(index->heap)); { @@ -1418,7 +1420,7 @@ dict_index_add_to_cache( } ut_a(UT_LIST_GET_LEN(table->indexes) == 0 - || (index->type & DICT_CLUSTERED) == 0); + || (index->type & DICT_CLUSTERED) == 0); } success = dict_index_find_cols(table, index); @@ -1428,7 +1430,7 @@ dict_index_add_to_cache( return(FALSE); } - + /* Build the cache internal representation of the index, containing also the added system fields */ @@ -1439,15 +1441,15 @@ dict_index_add_to_cache( } new_index->search_info = btr_search_info_create(new_index->heap); - + /* Set the n_fields value in new_index to the actual defined number of fields in the cache internal representation */ new_index->n_fields = new_index->n_def; - + /* Add the new index as the last index for the table */ - UT_LIST_ADD_LAST(indexes, table->indexes, new_index); + UT_LIST_ADD_LAST(indexes, table->indexes, new_index); new_index->table = table; new_index->table_name = table->name; @@ -1468,7 +1470,7 @@ dict_index_add_to_cache( if (table->type == DICT_TABLE_CLUSTER_MEMBER) { /* The index tree is found from the cluster object */ - + cluster = dict_table_get_low(table->cluster_name); tree = dict_index_get_tree( @@ -1496,10 +1498,10 @@ dict_index_add_to_cache( new_index->stat_n_diff_key_vals[i] = 100; } } - + /* Add the index to the list of indexes stored in the tree */ - UT_LIST_ADD_LAST(tree_indexes, tree->tree_indexes, new_index); - + UT_LIST_ADD_LAST(tree_indexes, tree->tree_indexes, new_index); + /* If the dictionary cache grows too big, trim the table LRU list */ dict_sys->size += mem_heap_get_size(new_index->heap); @@ -1563,13 +1565,13 @@ dict_index_find_cols( /*=================*/ /* out: TRUE if success */ dict_table_t* table, /* in: table */ - dict_index_t* index) /* in: index */ + dict_index_t* index) /* in: index */ { dict_col_t* col; dict_field_t* field; ulint fold; ulint i; - + ut_ad(table && index); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); #ifdef UNIV_SYNC_DEBUG @@ -1580,15 +1582,15 @@ dict_index_find_cols( field = dict_index_get_nth_field(index, i); fold = ut_fold_ulint_pair(ut_fold_string(table->name), - ut_fold_string(field->name)); - + ut_fold_string(field->name)); + HASH_SEARCH(hash, dict_sys->col_hash, fold, col, (ut_strcmp(col->name, field->name) == 0) && (ut_strcmp((col->table)->name, table->name) - == 0)); + == 0)); if (col == NULL) { - return(FALSE); + return(FALSE); } else { field->col = col; } @@ -1596,7 +1598,7 @@ dict_index_find_cols( return(TRUE); } - + /*********************************************************************** Adds a column to index. */ @@ -1605,12 +1607,11 @@ dict_index_add_col( /*===============*/ dict_index_t* index, /* in: index */ dict_col_t* col, /* in: column */ - ulint order, /* in: order criterion */ ulint prefix_len) /* in: column prefix length */ { dict_field_t* field; - dict_mem_index_add_field(index, col->name, order, prefix_len); + dict_mem_index_add_field(index, col->name, prefix_len); field = dict_index_get_nth_field(index, index->n_def - 1); @@ -1632,17 +1633,6 @@ dict_index_add_col( if (!(dtype_get_prtype(&col->type) & DATA_NOT_NULL)) { index->n_nullable++; } - - if (index->n_def > 1) { - const dict_field_t* field2 = - dict_index_get_nth_field(index, index->n_def - 2); - field->fixed_offs = (!field2->fixed_len || - field2->fixed_offs == ULINT_UNDEFINED) - ? ULINT_UNDEFINED - : field2->fixed_len + field2->fixed_offs; - } else { - field->fixed_offs = 0; - } } /*********************************************************************** @@ -1658,14 +1648,13 @@ dict_index_copy( { dict_field_t* field; ulint i; - + /* Copy fields contained in index2 */ for (i = start; i < end; i++) { field = dict_index_get_nth_field(index2, i); - dict_index_add_col(index1, field->col, field->order, - field->prefix_len); + dict_index_add_col(index1, field->col, field->prefix_len); } } @@ -1732,7 +1721,7 @@ dict_index_build_internal_clust( of the clustered index */ dict_table_t* table, /* in: table */ dict_index_t* index) /* in: user representation of a clustered - index */ + index */ { dict_index_t* new_index; dict_field_t* field; @@ -1750,26 +1739,24 @@ dict_index_build_internal_clust( /* Create a new index object with certainly enough fields */ new_index = dict_mem_index_create(table->name, - index->name, - table->space, - index->type, - index->n_fields + table->n_cols); + index->name, table->space, index->type, + index->n_fields + table->n_cols); /* Copy other relevant data from the old index struct to the new struct: it inherits the values */ new_index->n_user_defined_cols = index->n_fields; - + new_index->id = index->id; if (table->type != DICT_TABLE_ORDINARY) { /* The index is mixed: copy common key prefix fields */ - + dict_index_copy(new_index, index, 0, table->mix_len); /* Add the mix id column */ dict_index_add_col(new_index, - dict_table_get_sys_col(table, DATA_MIX_ID), 0, 0); + dict_table_get_sys_col(table, DATA_MIX_ID), 0); /* Copy the rest of fields */ dict_index_copy(new_index, index, table->mix_len, @@ -1783,7 +1770,7 @@ dict_index_build_internal_clust( /* No fixed number of fields determines an entry uniquely */ new_index->n_uniq = ULINT_MAX; - + } else if (index->type & DICT_UNIQUE) { /* Only the fields defined so far are needed to identify the index entry uniquely */ @@ -1801,21 +1788,27 @@ dict_index_build_internal_clust( trx_id_pos = new_index->n_def; - ut_ad(DATA_ROW_ID == 0); - ut_ad(DATA_TRX_ID == 1); - ut_ad(DATA_ROLL_PTR == 2); +#if DATA_ROW_ID != 0 +# error "DATA_ROW_ID != 0" +#endif +#if DATA_TRX_ID != 1 +# error "DATA_TRX_ID != 1" +#endif +#if DATA_ROLL_PTR != 2 +# error "DATA_ROLL_PTR != 2" +#endif if (!(index->type & DICT_UNIQUE)) { dict_index_add_col(new_index, - dict_table_get_sys_col(table, DATA_ROW_ID), 0, 0); + dict_table_get_sys_col(table, DATA_ROW_ID), 0); trx_id_pos++; } dict_index_add_col(new_index, - dict_table_get_sys_col(table, DATA_TRX_ID), 0, 0); - + dict_table_get_sys_col(table, DATA_TRX_ID), 0); + dict_index_add_col(new_index, - dict_table_get_sys_col(table, DATA_ROLL_PTR), 0, 0); + dict_table_get_sys_col(table, DATA_ROLL_PTR), 0); for (i = 0; i < trx_id_pos; i++) { @@ -1829,7 +1822,7 @@ dict_index_build_internal_clust( } if (dict_index_get_nth_field(new_index, i)->prefix_len - > 0) { + > 0) { new_index->trx_id_offset = 0; break; @@ -1857,10 +1850,10 @@ dict_index_build_internal_clust( if (field->prefix_len == 0) { - field->col->aux = 0; + field->col->aux = 0; } } - + /* Add to new_index non-system columns of table not yet included there */ for (i = 0; i < table->n_cols - DATA_N_SYS_COLS; i++) { @@ -1869,7 +1862,7 @@ dict_index_build_internal_clust( ut_ad(col->type.mtype != DATA_SYS); if (col->aux == ULINT_UNDEFINED) { - dict_index_add_col(new_index, col, 0, 0); + dict_index_add_col(new_index, col, 0); } } @@ -1884,14 +1877,14 @@ dict_index_build_internal_clust( if (field->prefix_len == 0) { - field->col->clust_pos = i; + field->col->clust_pos = i; } } - + new_index->cached = TRUE; return(new_index); -} +} /*********************************************************************** Builds the internal dictionary cache representation for a non-clustered @@ -1904,7 +1897,7 @@ dict_index_build_internal_non_clust( of the non-clustered index */ dict_table_t* table, /* in: table */ dict_index_t* index) /* in: user representation of a non-clustered - index */ + index */ { dict_field_t* field; dict_index_t* new_index; @@ -1920,24 +1913,21 @@ dict_index_build_internal_non_clust( /* The clustered index should be the first in the list of indexes */ clust_index = UT_LIST_GET_FIRST(table->indexes); - + ut_ad(clust_index); ut_ad(clust_index->type & DICT_CLUSTERED); ut_ad(!(clust_index->type & DICT_UNIVERSAL)); /* Create a new index */ new_index = dict_mem_index_create(table->name, - index->name, - index->space, - index->type, - index->n_fields - + 1 + clust_index->n_uniq); + index->name, index->space, index->type, + index->n_fields + 1 + clust_index->n_uniq); /* Copy other relevant data from the old index struct to the new struct: it inherits the values */ new_index->n_user_defined_cols = index->n_fields; - + new_index->id = index->id; /* Copy fields from index to new_index */ @@ -1961,7 +1951,7 @@ dict_index_build_internal_non_clust( if (field->prefix_len == 0) { - field->col->aux = 0; + field->col->aux = 0; } } @@ -1973,8 +1963,8 @@ dict_index_build_internal_non_clust( field = dict_index_get_nth_field(clust_index, i); if (field->col->aux == ULINT_UNDEFINED) { - dict_index_add_col(new_index, field->col, 0, - field->prefix_len); + dict_index_add_col(new_index, field->col, + field->prefix_len); } } @@ -1992,7 +1982,7 @@ dict_index_build_internal_non_clust( new_index->cached = TRUE; return(new_index); -} +} /*====================== FOREIGN KEY PROCESSING ========================*/ @@ -2007,7 +1997,7 @@ dict_table_referenced_by_foreign_key( dict_table_t* table) /* in: InnoDB table */ { if (UT_LIST_GET_LEN(table->referenced_list) > 0) { - + return(TRUE); } @@ -2037,7 +2027,7 @@ dict_foreign_remove_from_cache( ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_a(foreign); - + if (foreign->referenced_table) { UT_LIST_REMOVE(referenced_list, foreign->referenced_table->referenced_list, foreign); @@ -2078,7 +2068,7 @@ dict_foreign_find( foreign = UT_LIST_GET_NEXT(foreign_list, foreign); } - + foreign = UT_LIST_GET_FIRST(table->referenced_list); while (foreign) { @@ -2091,7 +2081,7 @@ dict_foreign_find( } return(NULL); -} +} /************************************************************************* Tries to find an index whose first fields are the columns in the array, @@ -2104,14 +2094,17 @@ dict_foreign_find_index( dict_table_t* table, /* in: table */ const char** columns,/* in: array of column names */ ulint n_cols, /* in: number of columns */ - dict_index_t* types_idx)/* in: NULL or an index to whose types the - column types must match */ + dict_index_t* types_idx, /* in: NULL or an index to whose types the + column types must match */ + ibool check_charsets) /* in: whether to check charsets. + only has an effect if types_idx != + NULL. */ { #ifndef UNIV_HOTBACKUP dict_index_t* index; const char* col_name; ulint i; - + index = dict_table_get_first_index(table); while (index != NULL) { @@ -2124,21 +2117,22 @@ dict_foreign_find_index( ->prefix_len != 0) { /* We do not accept column prefix indexes here */ - + break; } if (0 != innobase_strcasecmp(columns[i], col_name)) { - break; + break; } if (types_idx && !cmp_types_are_equal( - dict_index_get_nth_type(index, i), - dict_index_get_nth_type(types_idx, i))) { + dict_index_get_nth_type(index, i), + dict_index_get_nth_type(types_idx, i), + check_charsets)) { - break; - } + break; + } } if (i == n_cols) { @@ -2157,6 +2151,7 @@ dict_foreign_find_index( InnoDB Hot Backup builds. Besides, this function should never be called in InnoDB Hot Backup. */ ut_error; + return(NULL); #endif /* UNIV_HOTBACKUP */ } @@ -2190,8 +2185,9 @@ dict_foreign_error_report( fputs(msg, file); fputs(" Constraint:\n", file); dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE); + putc('\n', file); if (fk->foreign_index) { - fputs("\nThe index in the foreign key in table is ", file); + fputs("The index in the foreign key in table is ", file); ut_print_name(file, NULL, fk->foreign_index->name); fputs( "\nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" @@ -2212,14 +2208,15 @@ dict_foreign_add_to_cache( /*======================*/ /* out: DB_SUCCESS or error code */ dict_foreign_t* foreign, /* in, own: foreign key constraint */ - ibool check_types) /* in: TRUE=check type compatibility */ + ibool check_charsets) /* in: TRUE=check charset + compatibility */ { dict_table_t* for_table; dict_table_t* ref_table; dict_foreign_t* for_in_cache = NULL; dict_index_t* index; ibool added_to_referenced_list= FALSE; - FILE* ef = dict_foreign_err_file; + FILE* ef = dict_foreign_err_file; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); @@ -2227,7 +2224,7 @@ dict_foreign_add_to_cache( for_table = dict_table_check_if_in_cache_low( foreign->foreign_table_name); - + ref_table = dict_table_check_if_in_cache_low( foreign->referenced_table_name); ut_a(for_table || ref_table); @@ -2248,16 +2245,10 @@ dict_foreign_add_to_cache( } if (for_in_cache->referenced_table == NULL && ref_table) { - dict_index_t* types_idx; - if (check_types) { - types_idx = for_in_cache->foreign_index; - } else { - types_idx = NULL; - } index = dict_foreign_find_index(ref_table, (const char**) for_in_cache->referenced_col_names, for_in_cache->n_fields, - types_idx); + for_in_cache->foreign_index, check_charsets); if (index == NULL) { dict_foreign_error_report(ef, for_in_cache, @@ -2269,7 +2260,7 @@ dict_foreign_add_to_cache( mem_heap_free(foreign->heap); } - return(DB_CANNOT_ADD_CONSTRAINT); + return(DB_CANNOT_ADD_CONSTRAINT); } for_in_cache->referenced_table = ref_table; @@ -2281,16 +2272,10 @@ dict_foreign_add_to_cache( } if (for_in_cache->foreign_table == NULL && for_table) { - dict_index_t* types_idx; - if (check_types) { - types_idx = for_in_cache->referenced_index; - } else { - types_idx = NULL; - } index = dict_foreign_find_index(for_table, (const char**) for_in_cache->foreign_col_names, for_in_cache->n_fields, - types_idx); + for_in_cache->referenced_index, check_charsets); if (index == NULL) { dict_foreign_error_report(ef, for_in_cache, @@ -2304,11 +2289,11 @@ dict_foreign_add_to_cache( ref_table->referenced_list, for_in_cache); } - + mem_heap_free(foreign->heap); } - return(DB_CANNOT_ADD_CONSTRAINT); + return(DB_CANNOT_ADD_CONSTRAINT); } for_in_cache->foreign_table = for_table; @@ -2381,15 +2366,15 @@ dict_accept( const char* old_ptr2; *success = FALSE; - + while (isspace(*ptr)) { ptr++; } old_ptr2 = ptr; - + ptr = dict_scan_to(ptr, string); - + if (*ptr == '\0' || old_ptr2 != ptr) { return(old_ptr); } @@ -2459,8 +2444,8 @@ dict_scan_id( } } else { while (!isspace(*ptr) && *ptr != '(' && *ptr != ')' - && (accept_also_dot || *ptr != '.') - && *ptr != ',' && *ptr != '\0') { + && (accept_also_dot || *ptr != '.') + && *ptr != ',' && *ptr != '\0') { ptr++; } @@ -2497,9 +2482,9 @@ dict_scan_id( b = (byte*)(*id); id_len = strlen((char*) b); - + if (id_len >= 3 && b[id_len - 1] == 0xA0 - && b[id_len - 2] == 0xC2) { + && b[id_len - 2] == 0xC2) { /* Strip the 2 last bytes */ @@ -2542,28 +2527,29 @@ dict_scan_col( *success = TRUE; *column = NULL; } else { - for (i = 0; i < dict_table_get_n_cols(table); i++) { + for (i = 0; i < dict_table_get_n_cols(table); i++) { col = dict_table_get_nth_col(table, i); if (0 == innobase_strcasecmp(col->name, *name)) { - /* Found */ + /* Found */ - *success = TRUE; - *column = col; - strcpy((char*) *name, col->name); + *success = TRUE; + *column = col; + strcpy((char*) *name, col->name); - break; + break; } } } - + return(ptr); #else /* UNIV_HOTBACKUP */ /* This function depends on MySQL code that is not included in InnoDB Hot Backup builds. Besides, this function should never be called in InnoDB Hot Backup. */ ut_error; + return(NULL); #endif /* UNIV_HOTBACKUP */ } @@ -2592,11 +2578,11 @@ dict_scan_table_name( *success = FALSE; *table = NULL; - - ptr = dict_scan_id(ptr, heap, &scan_name, FALSE); + + ptr = dict_scan_id(ptr, heap, &scan_name, FALSE); if (scan_name == NULL) { - + return(ptr); /* Syntax error */ } @@ -2669,6 +2655,7 @@ dict_scan_table_name( InnoDB Hot Backup builds. Besides, this function should never be called in InnoDB Hot Backup. */ ut_error; + return(NULL); #endif /* UNIV_HOTBACKUP */ } @@ -2684,7 +2671,7 @@ dict_skip_word( left in string or a syntax error */ { const char* start; - + *success = FALSE; ptr = dict_scan_id(ptr, NULL, &start, TRUE); @@ -2692,7 +2679,7 @@ dict_skip_word( if (start) { *success = TRUE; } - + return(ptr); } @@ -2714,8 +2701,8 @@ dict_strip_comments( char* str; const char* sptr; char* ptr; - /* unclosed quote character (0 if none) */ - char quote = 0; + /* unclosed quote character (0 if none) */ + char quote = 0; str = mem_alloc(strlen(sql_string) + 1); @@ -2743,15 +2730,15 @@ scan_more: /* Starting quote: remember the quote character. */ quote = *sptr; } else if (*sptr == '#' - || (sptr[0] == '-' && sptr[1] == '-' && - sptr[2] == ' ')) { + || (sptr[0] == '-' && sptr[1] == '-' && + sptr[2] == ' ')) { for (;;) { /* In Unix a newline is 0x0A while in Windows it is 0x0D followed by 0x0A */ if (*sptr == (char)0x0A - || *sptr == (char)0x0D - || *sptr == '\0') { + || *sptr == (char)0x0D + || *sptr == '\0') { goto scan_more; } @@ -2762,7 +2749,7 @@ scan_more: for (;;) { if (*sptr == '*' && *(sptr + 1) == '/') { - sptr += 2; + sptr += 2; goto scan_more; } @@ -2808,9 +2795,10 @@ dict_table_get_highest_foreign_id( while (foreign) { if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len - && 0 == ut_memcmp(foreign->id, table->name, len) - && 0 == ut_memcmp(foreign->id + len, - dict_ibfk, (sizeof dict_ibfk) - 1)) { + && 0 == ut_memcmp(foreign->id, table->name, len) + && 0 == ut_memcmp(foreign->id + len, + dict_ibfk, (sizeof dict_ibfk) - 1) + && foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') { /* It is of the >= 4.0.18 format */ id = strtoul(foreign->id + len + ((sizeof dict_ibfk) - 1), @@ -2884,7 +2872,7 @@ dict_create_foreign_constraints_low( ulint highest_id_so_far = 0; dict_index_t* index; dict_foreign_t* foreign; - const char* ptr = sql_string; + const char* ptr = sql_string; const char* start_of_latest_foreign = sql_string; FILE* ef = dict_foreign_err_file; const char* constraint_name; @@ -2900,7 +2888,7 @@ dict_create_foreign_constraints_low( dict_col_t* columns[500]; const char* column_names[500]; const char* referenced_table_name; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -2982,7 +2970,7 @@ loop: ut_a(success); if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') { - goto loop; + goto loop; } while (isspace(*ptr)) { @@ -3005,15 +2993,14 @@ loop: command, determine if there are any foreign keys, and if so, immediately reject the command if the table is a temporary one. For now, this kludge will work. */ - if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) - { + if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) { return DB_CANNOT_ADD_CONSTRAINT; } - + /**********************************************************/ /* The following call adds the foreign key constraints to the data dictionary system tables on disk */ - + error = dict_create_add_foreigns_to_dictionary( highest_id_so_far, table, trx); return(error); @@ -3021,14 +3008,14 @@ loop: start_of_latest_foreign = ptr; - ptr = dict_accept(ptr, "FOREIGN", &success); - + ptr = dict_accept(ptr, "FOREIGN", &success); + if (!success) { goto loop; } if (!isspace(*ptr)) { - goto loop; + goto loop; } ptr = dict_accept(ptr, "KEY", &success); @@ -3057,7 +3044,7 @@ loop: /* We do not flag a syntax error here because in an ALTER TABLE we may also have DROP FOREIGN KEY abc */ - goto loop; + goto loop; } } @@ -3079,13 +3066,13 @@ col_loop1: } i++; - + ptr = dict_accept(ptr, ",", &success); if (success) { goto col_loop1; } - + ptr = dict_accept(ptr, ")", &success); if (!success) { @@ -3097,7 +3084,7 @@ col_loop1: /* Try to find an index which contains the columns as the first fields and in the right order */ - index = dict_foreign_find_index(table, column_names, i, NULL); + index = dict_foreign_find_index(table, column_names, i, NULL, TRUE); if (!index) { mutex_enter(&dict_foreign_err_mutex); @@ -3126,7 +3113,7 @@ col_loop1: foreign = dict_mem_foreign_create(); if (constraint_name) { - ulint db_len; + ulint db_len; /* Catenate 'databasename/' to the constraint name specified by the user: we conceive the constraint as belonging to the @@ -3154,7 +3141,7 @@ col_loop1: foreign->foreign_col_names[i] = mem_heap_strdup(foreign->heap, columns[i]->name); } - + ptr = dict_scan_table_name(ptr, &referenced_table, name, &success, heap, &referenced_table_name); @@ -3173,7 +3160,7 @@ col_loop1: return(DB_CANNOT_ADD_CONSTRAINT); } - + ptr = dict_accept(ptr, "(", &success); if (!success) { @@ -3190,7 +3177,7 @@ col_loop2: ptr = dict_scan_col(ptr, &success, referenced_table, columns + i, heap, column_names + i); i++; - + if (!success) { dict_foreign_free(foreign); @@ -3209,12 +3196,12 @@ col_loop2: if (success) { goto col_loop2; } - + ptr = dict_accept(ptr, ")", &success); if (!success || foreign->n_fields != i) { dict_foreign_free(foreign); - + dict_foreign_report_syntax_err(name, start_of_latest_foreign, ptr); return(DB_CANNOT_ADD_CONSTRAINT); @@ -3222,7 +3209,7 @@ col_loop2: n_on_deletes = 0; n_on_updates = 0; - + scan_on_conditions: /* Loop here as long as we can find ON ... conditions */ @@ -3240,7 +3227,7 @@ scan_on_conditions: if (!success) { dict_foreign_free(foreign); - + dict_foreign_report_syntax_err(name, start_of_latest_foreign, ptr); return(DB_CANNOT_ADD_CONSTRAINT); @@ -3280,7 +3267,7 @@ scan_on_conditions: dict_foreign_free(foreign); dict_foreign_report_syntax_err(name, start_of_latest_foreign, ptr); - + return(DB_CANNOT_ADD_CONSTRAINT); } @@ -3337,13 +3324,13 @@ scan_on_conditions: } else { foreign->type |= DICT_FOREIGN_ON_UPDATE_SET_NULL; } - + goto scan_on_conditions; try_find_index: if (n_on_deletes > 1 || n_on_updates > 1) { /* It is an error to define more than 1 action */ - + dict_foreign_free(foreign); mutex_enter(&dict_foreign_err_mutex); @@ -3362,8 +3349,7 @@ try_find_index: if (referenced_table) { index = dict_foreign_find_index(referenced_table, - column_names, i, - foreign->foreign_index); + column_names, i, foreign->foreign_index, TRUE); if (!index) { dict_foreign_free(foreign); mutex_enter(&dict_foreign_err_mutex); @@ -3392,7 +3378,7 @@ try_find_index: foreign->referenced_table_name = mem_heap_strdup(foreign->heap, referenced_table_name); - + foreign->referenced_col_names = mem_heap_alloc(foreign->heap, i * sizeof(void*)); for (i = 0; i < foreign->n_fields; i++) { @@ -3401,7 +3387,7 @@ try_find_index: } /* We found an ok constraint definition: add to the lists */ - + UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign); if (referenced_table) { @@ -3453,7 +3439,7 @@ dict_create_foreign_constraints( mem_heap_free(heap); mem_free(str); - return(err); + return(err); } /************************************************************************** @@ -3481,7 +3467,7 @@ dict_foreign_parse_drop_constraints( const char* ptr; const char* id; FILE* ef = dict_foreign_err_file; - + *n = 0; *constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*)); @@ -3497,7 +3483,7 @@ loop: if (*ptr == '\0') { mem_free(str); - + return(DB_SUCCESS); } @@ -3505,14 +3491,14 @@ loop: if (!isspace(*ptr)) { - goto loop; + goto loop; } ptr = dict_accept(ptr, "FOREIGN", &success); - + if (!success) { - goto loop; + goto loop; } ptr = dict_accept(ptr, "KEY", &success); @@ -3532,20 +3518,20 @@ loop: ut_a(*n < 1000); (*constraints_to_drop)[*n] = id; (*n)++; - + /* Look for the given constraint id */ foreign = UT_LIST_GET_FIRST(table->foreign_list); while (foreign != NULL) { if (0 == strcmp(foreign->id, id) - || (strchr(foreign->id, '/') - && 0 == strcmp(id, + || (strchr(foreign->id, '/') + && 0 == strcmp(id, dict_remove_db_name(foreign->id)))) { /* Found */ break; } - + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); } @@ -3569,7 +3555,7 @@ loop: return(DB_CANNOT_DROP_CONSTRAINT); } - goto loop; + goto loop; syntax_error: mutex_enter(&dict_foreign_err_mutex); @@ -3606,7 +3592,7 @@ dict_index_get_if_in_cache( } mutex_enter(&(dict_sys->mutex)); - + table = UT_LIST_GET_FIRST(dict_sys->table_LRU); while (table) { @@ -3654,7 +3640,7 @@ dict_tree_create( tree->page = page_no; tree->id = index->id; - + UT_LIST_INIT(tree->tree_indexes); tree->magic_n = DICT_TREE_MAGIC_N; @@ -3696,16 +3682,16 @@ dict_tree_find_index_low( dict_table_t* table; dulint mix_id; ulint len; - + index = UT_LIST_GET_FIRST(tree->tree_indexes); ut_ad(index); table = index->table; - + if ((index->type & DICT_CLUSTERED) && UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) { /* Get the mix id of the record */ - ut_a(!table->comp); + ut_a(!dict_table_is_comp(table)); mix_id = mach_dulint_read_compressed( rec_get_nth_field_old(rec, table->mix_len, &len)); @@ -3733,9 +3719,9 @@ dict_tree_find_index( index */ { dict_index_t* index; - + index = dict_tree_find_index_low(tree, rec); - + return(index); } @@ -3756,7 +3742,7 @@ dict_tree_find_index_for_tuple( dulint mix_id; ut_ad(dtuple_check_typed(tuple)); - + if (UT_LIST_GET_LEN(tree->tree_indexes) == 1) { return(UT_LIST_GET_FIRST(tree->tree_indexes)); @@ -3801,7 +3787,7 @@ dict_is_mixed_table_rec( byte* mix_id_field; ulint len; - ut_ad(!table->comp); + ut_ad(!dict_table_is_comp(table)); mix_id_field = rec_get_nth_field_old(rec, table->mix_len, &len); @@ -3847,7 +3833,7 @@ dict_tree_build_node_ptr( pointer */ ulint page_no,/* in: page number to put in node pointer */ mem_heap_t* heap, /* in: memory heap where pointer created */ - ulint level) /* in: level of rec in tree: 0 means leaf + ulint level) /* in: level of rec in tree: 0 means leaf level */ { dtuple_t* tuple; @@ -3857,21 +3843,21 @@ dict_tree_build_node_ptr( ulint n_unique; ind = dict_tree_find_index_low(tree, rec); - + if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) { /* In a universal index tree, we take the whole record as the node pointer if the reord is on the leaf level, on non-leaf levels we remove the last field, which contains the page number of the child page */ - ut_a(!ind->table->comp); + ut_a(!dict_table_is_comp(ind->table)); n_unique = rec_get_n_fields_old(rec); if (level > 0) { - ut_a(n_unique > 1); - n_unique--; + ut_a(n_unique > 1); + n_unique--; } - } else { + } else { n_unique = dict_index_get_n_unique_in_tree(ind); } @@ -3882,15 +3868,15 @@ dict_tree_build_node_ptr( levels in the tree there may be identical node pointers with a different page number; therefore, we set the n_fields_cmp to one less: */ - + dtuple_set_n_fields_cmp(tuple, n_unique); dict_index_copy_types(tuple, ind, n_unique); - + buf = mem_heap_alloc(heap, 4); mach_write_to_4(buf, page_no); - + field = dtuple_get_nth_field(tuple, n_unique); dfield_set_data(field, buf, 4); @@ -3903,8 +3889,8 @@ dict_tree_build_node_ptr( ut_ad(dtuple_check_typed(tuple)); return(tuple); -} - +} + /************************************************************************** Copies an initial segment of a physical record, long enough to specify an index entry uniquely. */ @@ -3927,7 +3913,7 @@ dict_tree_copy_rec_order_prefix( index = dict_tree_find_index_low(tree, rec); if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) { - ut_a(!index->table->comp); + ut_a(!dict_table_is_comp(index->table)); n = rec_get_n_fields_old(rec); } else { n = dict_index_get_n_unique_in_tree(index); @@ -3954,9 +3940,10 @@ dict_tree_build_data_tuple( ind = dict_tree_find_index_low(tree, rec); - ut_ad(ind->table->comp || n_fields <= rec_get_n_fields_old(rec)); - - tuple = dtuple_create(heap, n_fields); + ut_ad(dict_table_is_comp(ind->table) + || n_fields <= rec_get_n_fields_old(rec)); + + tuple = dtuple_create(heap, n_fields); dict_index_copy_types(tuple, ind, n_fields); @@ -3965,8 +3952,8 @@ dict_tree_build_data_tuple( ut_ad(dtuple_check_typed(tuple)); return(tuple); -} - +} + /************************************************************************* Calculates the minimum record length in an index. */ @@ -3978,7 +3965,7 @@ dict_index_calc_min_rec_len( ulint sum = 0; ulint i; - if (UNIV_LIKELY(index->table->comp)) { + if (dict_table_is_comp(index->table)) { ulint nullable = 0; sum = REC_N_NEW_EXTRA_BYTES; for (i = 0; i < dict_index_get_n_fields(index); i++) { @@ -4023,8 +4010,8 @@ dict_update_statistics_low( /*=======================*/ dict_table_t* table, /* in: table */ ibool has_dict_mutex __attribute__((unused))) - /* in: TRUE if the caller has the - dictionary mutex */ + /* in: TRUE if the caller has the + dictionary mutex */ { dict_index_t* index; ulint size; @@ -4053,11 +4040,11 @@ dict_update_statistics_low( /* Find out the sizes of the indexes and how many different values for the key they approximately have */ - index = dict_table_get_first_index(table); + index = dict_table_get_first_index(table); if (index == NULL) { /* Table definition is corrupt */ - + return; } @@ -4076,7 +4063,7 @@ dict_update_statistics_low( } index->stat_n_leaf_pages = size; - + btr_estimate_number_of_different_key_vals(index); index = dict_table_get_next_index(index); @@ -4094,7 +4081,7 @@ dict_update_statistics_low( table->stat_initialized = TRUE; - table->stat_modified_counter = 0; + table->stat_modified_counter = 0; } /************************************************************************* @@ -4133,7 +4120,7 @@ dict_foreign_print_low( fprintf(stderr, " )\n" " REFERENCES %s (", foreign->referenced_table_name); - + for (i = 0; i < foreign->n_fields; i++) { fprintf(stderr, " %s", foreign->referenced_col_names[i]); } @@ -4169,7 +4156,7 @@ dict_table_print_by_name( table = dict_table_get_low(name); ut_a(table); - + dict_table_print_low(table); mutex_exit(&(dict_sys->mutex)); } @@ -4191,7 +4178,7 @@ dict_table_print_low( #endif /* UNIV_SYNC_DEBUG */ dict_update_statistics_low(table, TRUE); - + fprintf(stderr, "--------------------------------------\n" "TABLE: name %s, id %lu %lu, columns %lu, indexes %lu, appr.rows %lu\n" @@ -4200,7 +4187,7 @@ dict_table_print_low( (ulong) ut_dulint_get_high(table->id), (ulong) ut_dulint_get_low(table->id), (ulong) table->n_cols, - (ulong) UT_LIST_GET_LEN(table->indexes), + (ulong) UT_LIST_GET_LEN(table->indexes), (ulong) table->stat_n_rows); for (i = 0; i < table->n_cols - 1; i++) { @@ -4278,7 +4265,7 @@ dict_index_print_low( } fprintf(stderr, - " INDEX: name %s, id %lu %lu, fields %lu/%lu, type %lu\n" + " INDEX: name %s, id %lu %lu, fields %lu/%lu, uniq %lu, type %lu\n" " root page %lu, appr.key vals %lu," " leaf pages %lu, size pages %lu\n" " FIELDS: ", @@ -4286,12 +4273,14 @@ dict_index_print_low( (ulong) ut_dulint_get_high(tree->id), (ulong) ut_dulint_get_low(tree->id), (ulong) index->n_user_defined_cols, - (ulong) index->n_fields, (ulong) index->type, + (ulong) index->n_fields, + (ulong) index->n_uniq, + (ulong) index->type, (ulong) tree->page, (ulong) n_vals, (ulong) index->stat_n_leaf_pages, (ulong) index->stat_index_size); - + for (i = 0; i < index->n_fields; i++) { dict_field_print_low(dict_index_get_nth_field(index, i)); } @@ -4337,7 +4326,7 @@ dict_print_info_on_foreign_key_in_create_format( { const char* stripped_id; ulint i; - + if (strchr(foreign->id, '/')) { /* Strip the preceding database name from the constraint id */ stripped_id = foreign->id + 1 @@ -4347,14 +4336,14 @@ dict_print_info_on_foreign_key_in_create_format( } putc(',', file); - + if (add_newline) { /* SHOW CREATE TABLE wants constraints each printed nicely on its own line, while error messages want no newlines inserted. */ fputs("\n ", file); } - + fputs(" CONSTRAINT ", file); ut_print_name(file, trx, stripped_id); fputs(" FOREIGN KEY (", file); @@ -4363,7 +4352,7 @@ dict_print_info_on_foreign_key_in_create_format( ut_print_name(file, trx, foreign->foreign_col_names[i]); if (++i < foreign->n_fields) { fputs(", ", file); - } else { + } else { break; } } @@ -4406,7 +4395,7 @@ dict_print_info_on_foreign_key_in_create_format( if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) { fputs(" ON DELETE CASCADE", file); } - + if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) { fputs(" ON DELETE SET NULL", file); } @@ -4418,7 +4407,7 @@ dict_print_info_on_foreign_key_in_create_format( if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) { fputs(" ON UPDATE CASCADE", file); } - + if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) { fputs(" ON UPDATE SET NULL", file); } @@ -4489,7 +4478,7 @@ dict_print_info_on_foreign_keys( if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) { fputs(" ON DELETE CASCADE", file); } - + if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) { fputs(" ON DELETE SET NULL", file); } @@ -4501,7 +4490,7 @@ dict_print_info_on_foreign_keys( if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) { fputs(" ON UPDATE CASCADE", file); } - + if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) { fputs(" ON UPDATE SET NULL", file); } diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c index 9bafcf33553..09935c03288 100644 --- a/storage/innobase/dict/dict0load.c +++ b/storage/innobase/dict/dict0load.c @@ -47,18 +47,18 @@ dict_get_first_table_name_in_db( byte* field; ulint len; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ heap = mem_heap_create(1000); - + mtr_start(&mtr); sys_tables = dict_table_get_low("SYS_TABLES"); sys_index = UT_LIST_GET_FIRST(sys_tables->indexes); - ut_a(!sys_tables->comp); + ut_a(!dict_table_is_comp(sys_tables)); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); @@ -77,36 +77,36 @@ loop: btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); - + return(NULL); - } + } field = rec_get_nth_field_old(rec, 0, &len); if (len < strlen(name) - || ut_memcmp(name, field, strlen(name)) != 0) { + || ut_memcmp(name, field, strlen(name)) != 0) { /* Not found */ btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); - + return(NULL); } - if (!rec_get_deleted_flag(rec, sys_tables->comp)) { + if (!rec_get_deleted_flag(rec, 0)) { /* We found one */ - char* table_name = mem_strdupl((char*) field, len); - + char* table_name = mem_strdupl((char*) field, len); + btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); - + return(table_name); } - + btr_pcur_move_to_next_user_rec(&pcur, &mtr); goto loop; @@ -128,7 +128,7 @@ dict_print(void) byte* field; ulint len; mtr_t mtr; - + /* Enlarge the fatal semaphore wait timeout during the InnoDB table monitor printout */ @@ -155,7 +155,7 @@ loop: btr_pcur_close(&pcur); mtr_commit(&mtr); - + mutex_exit(&(dict_sys->mutex)); /* Restore the fatal semaphore wait timeout */ @@ -165,15 +165,15 @@ loop: mutex_exit(&kernel_mutex); return; - } + } field = rec_get_nth_field_old(rec, 0, &len); - if (!rec_get_deleted_flag(rec, sys_tables->comp)) { + if (!rec_get_deleted_flag(rec, 0)) { /* We found one */ - char* table_name = mem_strdupl((char*) field, len); + char* table_name = mem_strdupl((char*) field, len); btr_pcur_store_position(&pcur, &mtr); @@ -228,14 +228,14 @@ dict_check_tablespaces_and_store_max_id( ulint space_id; ulint max_space_id = 0; mtr_t mtr; - + mutex_enter(&(dict_sys->mutex)); mtr_start(&mtr); sys_tables = dict_table_get_low("SYS_TABLES"); sys_index = UT_LIST_GET_FIRST(sys_tables->indexes); - ut_a(!sys_tables->comp); + ut_a(!dict_table_is_comp(sys_tables)); btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr); @@ -249,40 +249,40 @@ loop: btr_pcur_close(&pcur); mtr_commit(&mtr); - + /* We must make the tablespace cache aware of the biggest known space id */ /* printf("Biggest space id in data dictionary %lu\n", - max_space_id); */ + max_space_id); */ fil_set_max_space_id_if_bigger(max_space_id); mutex_exit(&(dict_sys->mutex)); return; - } + } field = rec_get_nth_field_old(rec, 0, &len); - if (!rec_get_deleted_flag(rec, sys_tables->comp)) { + if (!rec_get_deleted_flag(rec, 0)) { /* We found one */ - char* name = mem_strdupl((char*) field, len); + char* name = mem_strdupl((char*) field, len); field = rec_get_nth_field_old(rec, 9, &len); ut_a(len == 4); - + space_id = mach_read_from_4(field); btr_pcur_store_position(&pcur, &mtr); mtr_commit(&mtr); - + if (space_id != 0 && in_crash_recovery) { /* Check that the tablespace (the .ibd file) really exists; print a warning to the .err log if not */ - + fil_space_for_table_exists_in_mem(space_id, name, FALSE, TRUE, TRUE); } @@ -334,7 +334,7 @@ dict_load_columns( ulint prec; ulint i; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -343,7 +343,7 @@ dict_load_columns( sys_columns = dict_table_get_low("SYS_COLUMNS"); sys_index = UT_LIST_GET_FIRST(sys_columns->indexes); - ut_a(!sys_columns->comp); + ut_a(!dict_table_is_comp(sys_columns)); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); @@ -356,13 +356,13 @@ dict_load_columns( btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); - for (i = 0; i < table->n_cols - DATA_N_SYS_COLS; i++) { + for (i = 0; i < table->n_cols - DATA_N_SYS_COLS; i++) { rec = btr_pcur_get_rec(&pcur); ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr)); - ut_a(!rec_get_deleted_flag(rec, sys_columns->comp)); + ut_a(!rec_get_deleted_flag(rec, 0)); field = rec_get_nth_field_old(rec, 0, &len); ut_ad(len == 8); @@ -385,13 +385,23 @@ dict_load_columns( field = rec_get_nth_field_old(rec, 6, &len); prtype = mach_read_from_4(field); - if (dtype_is_non_binary_string_type(mtype, prtype) - && dtype_get_charset_coll(prtype) == 0) { - /* This is a non-binary string type, and the table - was created with < 4.1.2. Use the default charset. */ + if (dtype_get_charset_coll(prtype) == 0 + && dtype_is_string_type(mtype)) { + /* The table was created with < 4.1.2. */ + + if (dtype_is_binary_string_type(mtype, prtype)) { + /* Use the binary collation for + string columns of binary type. */ + + prtype = dtype_form_prtype(prtype, + DATA_MYSQL_BINARY_CHARSET_COLL); + } else { + /* Use the default charset for + other than binary columns. */ - prtype = dtype_form_prtype(prtype, + prtype = dtype_form_prtype(prtype, data_mysql_default_charset_coll); + } } field = rec_get_nth_field_old(rec, 7, &len); @@ -407,7 +417,7 @@ dict_load_columns( dict_mem_table_add_col(table, name, mtype, prtype, col_len, prec); btr_pcur_move_to_next_user_rec(&pcur, &mtr); - } + } btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -455,7 +465,7 @@ dict_load_fields( byte* buf; ulint i; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -466,7 +476,7 @@ dict_load_fields( sys_fields = dict_table_get_low("SYS_FIELDS"); sys_index = UT_LIST_GET_FIRST(sys_fields->indexes); - ut_a(!sys_fields->comp); + ut_a(!dict_table_is_comp(sys_fields)); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); @@ -479,15 +489,15 @@ dict_load_fields( btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); - for (i = 0; i < index->n_fields; i++) { + for (i = 0; i < index->n_fields; i++) { rec = btr_pcur_get_rec(&pcur); ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr)); - if (rec_get_deleted_flag(rec, sys_fields->comp)) { + if (rec_get_deleted_flag(rec, 0)) { dict_load_report_deleted_index(table->name, i); } - + field = rec_get_nth_field_old(rec, 0, &len); ut_ad(len == 8); ut_a(ut_memcmp(buf, field, len) == 0); @@ -506,14 +516,14 @@ dict_load_fields( pos_and_prefix_len = mach_read_from_4(field); ut_a((pos_and_prefix_len & 0xFFFFUL) == i - || (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16)); + || (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16)); if ((i == 0 && pos_and_prefix_len > 0) - || (pos_and_prefix_len & 0xFFFF0000UL) > 0) { + || (pos_and_prefix_len & 0xFFFF0000UL) > 0) { - prefix_len = pos_and_prefix_len & 0xFFFFUL; + prefix_len = pos_and_prefix_len & 0xFFFFUL; } else { - prefix_len = 0; + prefix_len = 0; } ut_a(0 == ut_strcmp("COL_NAME", @@ -523,10 +533,10 @@ dict_load_fields( field = rec_get_nth_field_old(rec, 4, &len); dict_mem_index_add_field(index, - mem_heap_strdupl(heap, (char*) field, len), 0, prefix_len); + mem_heap_strdupl(heap, (char*) field, len), prefix_len); btr_pcur_move_to_next_user_rec(&pcur, &mtr); - } + } btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -563,23 +573,23 @@ dict_load_indexes( ibool is_sys_table; dulint id; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ if ((ut_dulint_get_high(table->id) == 0) - && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) { + && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) { is_sys_table = TRUE; } else { is_sys_table = FALSE; } - + mtr_start(&mtr); sys_indexes = dict_table_get_low("SYS_INDEXES"); sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes); - ut_a(!sys_indexes->comp); + ut_a(!dict_table_is_comp(sys_indexes)); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); @@ -592,14 +602,14 @@ dict_load_indexes( btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); - for (;;) { + for (;;) { if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { break; } rec = btr_pcur_get_rec(&pcur); - + field = rec_get_nth_field_old(rec, 0, &len); ut_ad(len == 8); @@ -607,7 +617,7 @@ dict_load_indexes( break; } - if (rec_get_deleted_flag(rec, table->comp)) { + if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) { dict_load_report_deleted_index(table->name, ULINT_UNDEFINED); @@ -658,7 +668,7 @@ dict_load_indexes( } if ((type & DICT_CLUSTERED) == 0 - && NULL == dict_table_get_first_index(table)) { + && NULL == dict_table_get_first_index(table)) { fprintf(stderr, "InnoDB: Error: trying to load index %s for table %s\n" @@ -670,27 +680,27 @@ dict_load_indexes( return(FALSE); } - + if (is_sys_table - && ((type & DICT_CLUSTERED) - || ((table == dict_sys->sys_tables) - && (name_len == (sizeof "ID_IND") - 1) - && (0 == ut_memcmp(name_buf, "ID_IND", + && ((type & DICT_CLUSTERED) + || ((table == dict_sys->sys_tables) + && (name_len == (sizeof "ID_IND") - 1) + && (0 == ut_memcmp(name_buf, "ID_IND", name_len))))) { /* The index was created in memory already at booting of the database server */ } else { - index = dict_mem_index_create(table->name, name_buf, + index = dict_mem_index_create(table->name, name_buf, space, type, n_fields); index->id = id; - + dict_load_fields(table, index, heap); dict_index_add_to_cache(table, index, page_no); } btr_pcur_move_to_next_user_rec(&pcur, &mtr); - } + } btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -729,20 +739,21 @@ dict_load_table( ulint len; ulint space; ulint n_cols; + ulint flags; ulint err; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ heap = mem_heap_create(1000); - + mtr_start(&mtr); sys_tables = dict_table_get_low("SYS_TABLES"); sys_index = UT_LIST_GET_FIRST(sys_tables->indexes); - ut_a(!sys_tables->comp); + ut_a(!dict_table_is_comp(sys_tables)); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); @@ -755,15 +766,15 @@ dict_load_table( rec = btr_pcur_get_rec(&pcur); if (!btr_pcur_is_on_user_rec(&pcur, &mtr) - || rec_get_deleted_flag(rec, sys_tables->comp)) { + || rec_get_deleted_flag(rec, 0)) { /* Not found */ btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); - + return(NULL); - } + } field = rec_get_nth_field_old(rec, 0, &len); @@ -772,14 +783,14 @@ dict_load_table( btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); - + return(NULL); } ut_a(0 == ut_strcmp("SPACE", dict_field_get_col( dict_index_get_nth_field(sys_index, 9))->name)); - + field = rec_get_nth_field_old(rec, 9, &len); space = mach_read_from_4(field); @@ -817,10 +828,15 @@ dict_load_table( field = rec_get_nth_field_old(rec, 4, &len); n_cols = mach_read_from_4(field); + flags = 0; + /* The high-order bit of N_COLS is the "compact format" flag. */ - table = dict_mem_table_create(name, space, - n_cols & ~0x80000000UL, - !!(n_cols & 0x80000000UL)); + if (n_cols & 0x80000000UL) { + flags |= DICT_TF_COMPACT; + } + + table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL, + flags); table->ibd_file_missing = ibd_file_missing; @@ -846,7 +862,7 @@ dict_load_table( } if ((table->type == DICT_TABLE_CLUSTER) - || (table->type == DICT_TABLE_CLUSTER_MEMBER)) { + || (table->type == DICT_TABLE_CLUSTER_MEMBER)) { field = rec_get_nth_field_old(rec, 7, &len); ut_a(len == 4); @@ -865,17 +881,17 @@ dict_load_table( dict_load_columns(table, heap); dict_table_add_to_cache(table); - + dict_load_indexes(table, heap); - + err = dict_load_foreigns(table->name, TRUE); /* if (err != DB_SUCCESS) { - - mutex_enter(&dict_foreign_err_mutex); - ut_print_timestamp(stderr); - + mutex_enter(&dict_foreign_err_mutex); + + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Error: could not make a foreign key definition to match\n" "InnoDB: the foreign key table or the referenced table!\n" @@ -883,7 +899,7 @@ dict_load_table( "InnoDB: and recreate the foreign key table or the referenced table.\n" "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n" "InnoDB: Latest foreign key error printout:\n%s\n", dict_foreign_err_buf); - + mutex_exit(&dict_foreign_err_mutex); } */ @@ -899,21 +915,21 @@ dict_table_t* dict_load_table_on_id( /*==================*/ /* out: table; NULL if table does not exist */ - dulint table_id) /* in: table id */ + dulint table_id) /* in: table id */ { byte id_buf[8]; btr_pcur_t pcur; - mem_heap_t* heap; + mem_heap_t* heap; dtuple_t* tuple; dfield_t* dfield; dict_index_t* sys_table_ids; dict_table_t* sys_tables; rec_t* rec; byte* field; - ulint len; + ulint len; dict_table_t* table; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -922,13 +938,13 @@ dict_load_table_on_id( the dictionary mutex, and therefore no deadlocks can occur with other dictionary operations. */ - mtr_start(&mtr); + mtr_start(&mtr); /*---------------------------------------------------*/ - /* Get the secondary index based on ID for table SYS_TABLES */ + /* Get the secondary index based on ID for table SYS_TABLES */ sys_tables = dict_sys->sys_tables; sys_table_ids = dict_table_get_next_index( dict_table_get_first_index(sys_tables)); - ut_a(!sys_tables->comp); + ut_a(!dict_table_is_comp(sys_tables)); heap = mem_heap_create(256); tuple = dtuple_create(heap, 1); @@ -936,22 +952,22 @@ dict_load_table_on_id( /* Write the table id in byte format to id_buf */ mach_write_to_8(id_buf, table_id); - + dfield_set_data(dfield, id_buf, 8); dict_index_copy_types(tuple, sys_table_ids, 1); btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); rec = btr_pcur_get_rec(&pcur); - + if (!btr_pcur_is_on_user_rec(&pcur, &mtr) - || rec_get_deleted_flag(rec, sys_tables->comp)) { + || rec_get_deleted_flag(rec, 0)) { /* Not found */ btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); - + return(NULL); } @@ -969,15 +985,15 @@ dict_load_table_on_id( btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); - + return(NULL); } - + /* Now we get the table name from the record */ field = rec_get_nth_field_old(rec, 1, &len); /* Load the table definition to memory */ table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len)); - + btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); @@ -1004,7 +1020,7 @@ dict_load_sys_table( heap = mem_heap_create(1000); dict_load_indexes(table, heap); - + mem_heap_free(heap); } @@ -1028,7 +1044,7 @@ dict_load_foreign_cols( ulint len; ulint i; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -1042,7 +1058,7 @@ dict_load_foreign_cols( sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS"); sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes); - ut_a(!sys_foreign_cols->comp); + ut_a(!dict_table_is_comp(sys_foreign_cols)); tuple = dtuple_create(foreign->heap, 1); dfield = dtuple_get_nth_field(tuple, 0); @@ -1052,12 +1068,12 @@ dict_load_foreign_cols( btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); - for (i = 0; i < foreign->n_fields; i++) { + for (i = 0; i < foreign->n_fields; i++) { rec = btr_pcur_get_rec(&pcur); ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr)); - ut_a(!rec_get_deleted_flag(rec, sys_foreign_cols->comp)); + ut_a(!rec_get_deleted_flag(rec, 0)); field = rec_get_nth_field_old(rec, 0, &len); ut_a(len == ut_strlen(id)); @@ -1069,14 +1085,14 @@ dict_load_foreign_cols( field = rec_get_nth_field_old(rec, 4, &len); foreign->foreign_col_names[i] = - mem_heap_strdupl(foreign->heap, (char*) field, len); + mem_heap_strdupl(foreign->heap, (char*) field, len); field = rec_get_nth_field_old(rec, 5, &len); foreign->referenced_col_names[i] = - mem_heap_strdupl(foreign->heap, (char*) field, len); + mem_heap_strdupl(foreign->heap, (char*) field, len); btr_pcur_move_to_next_user_rec(&pcur, &mtr); - } + } btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -1091,8 +1107,8 @@ dict_load_foreign( /* out: DB_SUCCESS or error code */ const char* id, /* in: foreign constraint id as a null-terminated string */ - ibool check_types)/* in: TRUE=check type compatibility */ -{ + ibool check_charsets)/* in: TRUE=check charset compatibility */ +{ dict_foreign_t* foreign; dict_table_t* sys_foreign; btr_pcur_t pcur; @@ -1104,18 +1120,18 @@ dict_load_foreign( byte* field; ulint len; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ heap2 = mem_heap_create(1000); - + mtr_start(&mtr); sys_foreign = dict_table_get_low("SYS_FOREIGN"); sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes); - ut_a(!sys_foreign->comp); + ut_a(!dict_table_is_comp(sys_foreign)); tuple = dtuple_create(heap2, 1); dfield = dtuple_get_nth_field(tuple, 0); @@ -1128,7 +1144,7 @@ dict_load_foreign( rec = btr_pcur_get_rec(&pcur); if (!btr_pcur_is_on_user_rec(&pcur, &mtr) - || rec_get_deleted_flag(rec, sys_foreign->comp)) { + || rec_get_deleted_flag(rec, 0)) { /* Not found */ fprintf(stderr, @@ -1138,9 +1154,9 @@ dict_load_foreign( btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap2); - + return(DB_ERROR); - } + } field = rec_get_nth_field_old(rec, 0, &len); @@ -1154,7 +1170,7 @@ dict_load_foreign( btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap2); - + return(DB_ERROR); } @@ -1162,7 +1178,7 @@ dict_load_foreign( with the constraint */ mem_heap_free(heap2); - + foreign = dict_mem_foreign_create(); foreign->n_fields = @@ -1171,19 +1187,19 @@ dict_load_foreign( ut_a(len == 4); /* We store the type to the bits 24-31 of n_fields */ - + foreign->type = foreign->n_fields >> 24; foreign->n_fields = foreign->n_fields & 0xFFFFFFUL; - + foreign->id = mem_heap_strdup(foreign->heap, id); field = rec_get_nth_field_old(rec, 3, &len); foreign->foreign_table_name = - mem_heap_strdupl(foreign->heap, (char*) field, len); + mem_heap_strdupl(foreign->heap, (char*) field, len); field = rec_get_nth_field_old(rec, 4, &len); foreign->referenced_table_name = - mem_heap_strdupl(foreign->heap, (char*) field, len); + mem_heap_strdupl(foreign->heap, (char*) field, len); btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -1204,7 +1220,7 @@ dict_load_foreign( a new foreign key constraint but loading one from the data dictionary. */ - return(dict_foreign_add_to_cache(foreign, check_types)); + return(dict_foreign_add_to_cache(foreign, check_charsets)); } /*************************************************************************** @@ -1219,21 +1235,22 @@ dict_load_foreigns( /*===============*/ /* out: DB_SUCCESS or error code */ const char* table_name, /* in: table name */ - ibool check_types) /* in: TRUE=check type compatibility */ + ibool check_charsets) /* in: TRUE=check charset + compatibility */ { btr_pcur_t pcur; - mem_heap_t* heap; + mem_heap_t* heap; dtuple_t* tuple; dfield_t* dfield; dict_index_t* sec_index; dict_table_t* sys_foreign; rec_t* rec; byte* field; - ulint len; + ulint len; char* id ; ulint err; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -1245,15 +1262,15 @@ dict_load_foreigns( fprintf(stderr, "InnoDB: Error: no foreign key system tables in the database\n"); - + return(DB_ERROR); } - ut_a(!sys_foreign->comp); - mtr_start(&mtr); + ut_a(!dict_table_is_comp(sys_foreign)); + mtr_start(&mtr); /* Get the secondary index based on FOR_NAME from table - SYS_FOREIGN */ + SYS_FOREIGN */ sec_index = dict_table_get_next_index( dict_table_get_first_index(sys_foreign)); @@ -1270,7 +1287,7 @@ start_load: BTR_SEARCH_LEAF, &pcur, &mtr); loop: rec = btr_pcur_get_rec(&pcur); - + if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { /* End of index */ @@ -1290,7 +1307,7 @@ loop: if (0 != cmp_data_data(dfield_get_type(dfield), dfield_get_data(dfield), dfield_get_len(dfield), field, len)) { - + goto load_next_index; } @@ -1303,8 +1320,8 @@ loop: goto next_rec; } - - if (rec_get_deleted_flag(rec, sys_foreign->comp)) { + + if (rec_get_deleted_flag(rec, 0)) { goto next_rec; } @@ -1312,14 +1329,14 @@ loop: /* Now we get a foreign key constraint id */ field = rec_get_nth_field_old(rec, 1, &len); id = mem_heap_strdupl(heap, (char*) field, len); - + btr_pcur_store_position(&pcur, &mtr); mtr_commit(&mtr); /* Load the foreign constraint definition to the dictionary cache */ - - err = dict_load_foreign(id, check_types); + + err = dict_load_foreign(id, check_charsets); if (err != DB_SUCCESS) { btr_pcur_close(&pcur); @@ -1340,12 +1357,12 @@ load_next_index: btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); - + sec_index = dict_table_get_next_index(sec_index); if (sec_index != NULL) { - mtr_start(&mtr); + mtr_start(&mtr); goto start_load; } diff --git a/storage/innobase/dict/dict0mem.c b/storage/innobase/dict/dict0mem.c index eec35310039..d9f0ad3d84e 100644 --- a/storage/innobase/dict/dict0mem.c +++ b/storage/innobase/dict/dict0mem.c @@ -36,13 +36,13 @@ dict_mem_table_create( ignored if the table is made a member of a cluster */ ulint n_cols, /* in: number of columns */ - ibool comp) /* in: TRUE=compact page format */ + ulint flags) /* in: table flags */ { dict_table_t* table; mem_heap_t* heap; - + ut_ad(name); - ut_ad(comp == FALSE || comp == TRUE); + ut_ad(!(flags & ~DICT_TF_COMPACT)); heap = mem_heap_create(DICT_HEAP_SIZE); @@ -51,24 +51,24 @@ dict_mem_table_create( table->heap = heap; table->type = DICT_TABLE_ORDINARY; + table->flags = flags; table->name = mem_heap_strdup(heap, name); table->dir_path_of_temp_table = NULL; table->space = space; table->ibd_file_missing = FALSE; table->tablespace_discarded = FALSE; - table->comp = comp; table->n_def = 0; table->n_cols = n_cols + DATA_N_SYS_COLS; table->mem_fix = 0; table->n_mysql_handles_opened = 0; table->n_foreign_key_checks_running = 0; - + table->cached = FALSE; - + table->mix_id = ut_dulint_zero; table->mix_len = 0; - + table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS) * sizeof(dict_col_t)); UT_LIST_INIT(table->indexes); @@ -86,14 +86,14 @@ dict_mem_table_create( table->stat_initialized = FALSE; table->stat_modified_counter = 0; - + mutex_create(&(table->autoinc_mutex)); mutex_set_level(&(table->autoinc_mutex), SYNC_DICT_AUTOINC_MUTEX); table->autoinc_inited = FALSE; table->magic_n = DICT_TABLE_MAGIC_N; - + return(table); } @@ -114,7 +114,7 @@ dict_mem_cluster_create( dict_table_t* cluster; /* Clustered tables cannot work with the compact record format. */ - cluster = dict_mem_table_create(name, space, n_cols, FALSE); + cluster = dict_mem_table_create(name, space, n_cols, 0); cluster->type = DICT_TABLE_CLUSTER; cluster->mix_len = mix_len; @@ -150,13 +150,13 @@ dict_mem_table_add_col( { dict_col_t* col; dtype_t* type; - + ut_ad(table && name); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - + table->n_def++; - col = dict_table_get_nth_col(table, table->n_def - 1); + col = dict_table_get_nth_col(table, table->n_def - 1); col->ind = table->n_def - 1; col->name = mem_heap_strdup(table->heap, name); @@ -164,7 +164,7 @@ dict_mem_table_add_col( col->ord_part = 0; col->clust_pos = ULINT_UNDEFINED; - + type = dict_col_get_type(col); dtype_set(type, mtype, prtype, len, prec); @@ -188,14 +188,14 @@ dict_mem_index_create( { dict_index_t* index; mem_heap_t* heap; - + ut_ad(table_name && index_name); heap = mem_heap_create(DICT_HEAP_SIZE); index = mem_heap_alloc(heap, sizeof(dict_index_t)); index->heap = heap; - + index->type = type; index->space = space; index->name = mem_heap_strdup(heap, index_name); @@ -261,24 +261,20 @@ dict_mem_index_add_field( /*=====================*/ dict_index_t* index, /* in: index */ const char* name, /* in: column name */ - ulint order, /* in: order criterion; 0 means an - ascending order */ ulint prefix_len) /* in: 0 or the column prefix length in a MySQL index like INDEX (textcol(25)) */ { dict_field_t* field; - + ut_ad(index && name); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - + index->n_def++; - field = dict_index_get_nth_field(index, index->n_def - 1); + field = dict_index_get_nth_field(index, index->n_def - 1); field->name = name; - field->order = order; - field->prefix_len = prefix_len; } diff --git a/storage/innobase/dyn/dyn0dyn.c b/storage/innobase/dyn/dyn0dyn.c index 0afe6eda856..bcf2fda2b08 100644 --- a/storage/innobase/dyn/dyn0dyn.c +++ b/storage/innobase/dyn/dyn0dyn.c @@ -31,7 +31,7 @@ dyn_array_add_block( UT_LIST_ADD_FIRST(list, arr->base, arr); arr->heap = mem_heap_create(sizeof(dyn_block_t)); - } + } block = dyn_array_get_last_block(arr); block->used = block->used | DYN_BLOCK_FULL_FLAG; diff --git a/storage/innobase/eval/eval0eval.c b/storage/innobase/eval/eval0eval.c index 5b2d1f857b1..79f889a39ee 100644 --- a/storage/innobase/eval/eval0eval.c +++ b/storage/innobase/eval/eval0eval.c @@ -17,7 +17,7 @@ Created 12/29/1997 Heikki Tuuri #include "row0sel.h" /* The RND function seed */ -ulint eval_rnd = 128367121; +ulint eval_rnd = 128367121; /* Dummy adress used when we should allocate a buffer of size 0 in the function below */ @@ -44,12 +44,12 @@ eval_node_alloc_val_buf( byte* data; ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL - || que_node_get_type(node) == QUE_NODE_FUNC); + || que_node_get_type(node) == QUE_NODE_FUNC); dfield = que_node_get_val(node); data = dfield_get_data(dfield); - + if (data && data != &eval_dummy) { mem_free(data); } @@ -81,15 +81,15 @@ eval_node_free_val_buf( byte* data; ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL - || que_node_get_type(node) == QUE_NODE_FUNC); + || que_node_get_type(node) == QUE_NODE_FUNC); dfield = que_node_get_val(node); data = dfield_get_data(dfield); - + if (que_node_get_val_buf_size(node) > 0) { ut_a(data); - + mem_free(data); } } @@ -108,7 +108,7 @@ eval_cmp( int res; ibool val; int func; - + ut_ad(que_node_get_type(cmp_node) == QUE_NODE_FUNC); arg1 = cmp_node->args; @@ -119,7 +119,7 @@ eval_cmp( val = TRUE; func = cmp_node->func; - + if (func == '=') { if (res != 0) { val = FALSE; @@ -142,7 +142,7 @@ eval_cmp( } } else { ut_ad(func == '>'); - + if (res != 1) { val = FALSE; } @@ -268,7 +268,7 @@ eval_aggregate( val = val + arg_val; } - + eval_node_set_int_val(node, val); } @@ -304,7 +304,7 @@ eval_predefined_2( if (func == PARS_PRINTF_TOKEN) { arg = arg1; - + while (arg) { dfield_print(que_node_get_val(arg)); @@ -312,16 +312,16 @@ eval_predefined_2( } putc('\n', stderr); - + } else if (func == PARS_ASSERT_TOKEN) { if (!eval_node_get_ibool_val(arg1)) { fputs("SQL assertion fails in a stored procedure!\n", stderr); } - + ut_a(eval_node_get_ibool_val(arg1)); - + /* This function, or more precisely, a debug procedure, returns no value */ @@ -332,7 +332,7 @@ eval_predefined_2( ut_ad(len2 >= len1); - if (len2 > len1) { + if (len2 > len1) { int_val = (lint)(len1 + (eval_rnd % (len2 - len1 + 1))); } else { @@ -383,7 +383,7 @@ eval_notfound( ut_ad(que_node_get_type(cursor) == QUE_NODE_SYMBOL); if (cursor->token_type == SYM_LIT) { - + ut_ad(ut_memcmp(dfield_get_data(que_node_get_val(cursor)), "SQL", 3) == 0); @@ -425,7 +425,7 @@ eval_substr( arg3 = que_node_get_next(arg2); str1 = dfield_get_data(que_node_get_val(arg1)); - + len1 = (ulint)eval_node_get_int_val(arg2); len2 = (ulint)eval_node_get_int_val(arg3); @@ -473,7 +473,7 @@ eval_replstr( ut_memcpy(str1 + len1, str2, len2); } - + /********************************************************************* Evaluates an instr-function node. */ static @@ -500,7 +500,7 @@ eval_instr( dfield1 = que_node_get_val(arg1); dfield2 = que_node_get_val(arg2); - + str1 = dfield_get_data(dfield1); str2 = dfield_get_data(dfield2); @@ -539,7 +539,7 @@ eval_instr( } } } - + int_val = 0; match_found: @@ -568,7 +568,7 @@ eval_binary_to_number( str1 = dfield_get_data(dfield); len1 = dfield_get_len(dfield); - if (len1 > 4) { + if (len1 > 4) { ut_error; } @@ -577,13 +577,13 @@ eval_binary_to_number( } else { int_val = 0; str2 = (byte*)&int_val; - + ut_memcpy(str2 + (4 - len1), str1, len1); } eval_node_copy_and_alloc_val(func_node, str2, 4); } - + /********************************************************************* Evaluates a predefined function node. */ static @@ -661,14 +661,14 @@ eval_to_binary( } arg2 = que_node_get_next(arg1); - + len1 = (ulint)eval_node_get_int_val(arg2); if (len1 > 4) { ut_error; } - + dfield = que_node_get_val(func_node); dfield_set_data(dfield, str1 + (4 - len1), len1); @@ -688,7 +688,7 @@ eval_predefined( int func; func = func_node->func; - + arg1 = func_node->args; if (func == PARS_LENGTH_TOKEN) { @@ -763,7 +763,7 @@ eval_predefined( return; } - eval_node_set_int_val(func_node, int_val); + eval_node_set_int_val(func_node, int_val); } /********************************************************************* @@ -791,7 +791,7 @@ eval_func( /* The functions are not defined for SQL null argument values, except for eval_cmp and notfound */ - + if ((dfield_get_len(que_node_get_val(arg)) == UNIV_SQL_NULL) && (class != PARS_FUNC_CMP) && (func != PARS_NOTFOUND_TOKEN) diff --git a/storage/innobase/eval/eval0proc.c b/storage/innobase/eval/eval0proc.c index 50676e4f3fc..dcbdc0da5fc 100644 --- a/storage/innobase/eval/eval0proc.c +++ b/storage/innobase/eval/eval0proc.c @@ -25,7 +25,7 @@ if_step( elsif_node_t* elsif_node; ut_ad(thr); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_IF); @@ -83,9 +83,9 @@ if_step( if (thr->run_node == NULL) { thr->run_node = que_node_get_parent(node); } - + return(thr); -} +} /************************************************************************** Performs an execution step of a while-statement node. */ @@ -99,7 +99,7 @@ while_step( while_node_t* node; ut_ad(thr); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_WHILE); @@ -121,7 +121,7 @@ while_step( } return(thr); -} +} /************************************************************************** Performs an execution step of an assignment statement node. */ @@ -135,7 +135,7 @@ assign_step( assign_node_t* node; ut_ad(thr); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_ASSIGNMENT); @@ -144,11 +144,11 @@ assign_step( eval_exp(node->val); eval_node_copy_val(node->var->alias, node->val); - + thr->run_node = que_node_get_parent(node); return(thr); -} +} /************************************************************************** Performs an execution step of a for-loop node. */ @@ -164,9 +164,9 @@ for_step( lint loop_var_value; ut_ad(thr); - + node = thr->run_node; - + ut_ad(que_node_get_type(node) == QUE_NODE_FOR); parent = que_node_get_parent(node); @@ -182,7 +182,7 @@ for_step( } /* Increment the value of loop_var */ - + loop_var_value = 1 + eval_node_get_int_val(node->loop_var); } else { /* Initialize the loop */ @@ -210,7 +210,7 @@ for_step( } return(thr); -} +} /************************************************************************** Performs an execution step of a return-statement node. */ @@ -225,9 +225,9 @@ return_step( que_node_t* parent; ut_ad(thr); - + node = thr->run_node; - + ut_ad(que_node_get_type(node) == QUE_NODE_RETURN); parent = node; diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index 20f522c1a60..7418420628e 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -27,7 +27,7 @@ Created 10/25/1995 Heikki Tuuri #include "mtr0log.h" #include "dict0dict.h" - + /* IMPLEMENTATION OF THE TABLESPACE MEMORY CACHE ============================================= @@ -69,7 +69,7 @@ books on database tuning to achieve more speed in i/o. Using raw disk certainly prevents the OS from fragmenting disk space, but it is not clear if it really adds speed. We measured on the Pentium 100 MHz + NT + NTFS file system + EIDE Conner disk only a negligible difference in speed when reading -from a file, versus reading from a raw disk. +from a file, versus reading from a raw disk. To have fast access to a tablespace or a log file, we put the data structures to a hash table. Each tablespace and log file is given an unique 32-bit @@ -90,7 +90,7 @@ directory, and we must set the base file path explicitly */ const char* fil_path_to_mysql_datadir = "."; /* The number of fsyncs done to the log */ -ulint fil_n_log_flushes = 0; +ulint fil_n_log_flushes = 0; ulint fil_n_pending_log_flushes = 0; ulint fil_n_pending_tablespace_flushes = 0; @@ -117,7 +117,7 @@ struct fil_node_struct { ulint n_pending_flushes; /* count of pending flushes on this file; closing of the file is not allowed if - this is > 0 */ + this is > 0 */ ib_longlong modification_counter;/* when we write to the file we increment this by one */ ib_longlong flush_counter;/* up to what modification_counter value @@ -165,7 +165,7 @@ struct fil_space_struct { ulint size; /* space size in pages; 0 if a single-table tablespace whose size we do not know yet; last incomplete megabytes in data files may be - ignored if space == 0 */ + ignored if space == 0 */ ulint n_reserved_extents; /* number of reserved free extents for ongoing operations like B-tree page split */ @@ -177,10 +177,15 @@ struct fil_space_struct { may need to access the ibuf bitmap page in the tablespade: dropping of the tablespace is forbidden if this is > 0 */ - hash_node_t hash; /* hash chain node */ + hash_node_t hash; /* hash chain node */ hash_node_t name_hash;/* hash chain the name_hash table */ rw_lock_t latch; /* latch protecting the file space storage allocation */ + UT_LIST_NODE_T(fil_space_t) unflushed_spaces; + /* list of spaces with at least one unflushed + file we have written to */ + ibool is_in_unflushed_spaces; /* TRUE if this space is + currently in the list above */ UT_LIST_NODE_T(fil_space_t) space_list; /* list of all spaces */ ibuf_data_t* ibuf_data; @@ -213,6 +218,12 @@ struct fil_system_struct { not put to this list: they are opened after the startup, and kept open until shutdown */ + UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces; + /* base node for the list of those + tablespaces whose files contain + unflushed writes; those spaces have + at least one file node where + modification_counter > flush_counter */ ulint n_open; /* number of files currently open */ ulint max_n_open; /* n_open is not allowed to exceed this */ @@ -389,6 +400,36 @@ fil_space_get_ibuf_data( return(space->ibuf_data); } +/************************************************************************** +Checks if all the file nodes in a space are flushed. The caller must hold +the fil_system mutex. */ +static +ibool +fil_space_is_flushed( +/*=================*/ + /* out: TRUE if all are flushed */ + fil_space_t* space) /* in: space */ +{ + fil_node_t* node; + +#ifdef UNIV_SYNC_DEBUG + ut_ad(mutex_own(&(fil_system->mutex))); +#endif /* UNIV_SYNC_DEBUG */ + + node = UT_LIST_GET_FIRST(space->chain); + + while (node) { + if (node->modification_counter > node->flush_counter) { + + return(FALSE); + } + + node = UT_LIST_GET_NEXT(chain, node); + } + + return(TRUE); +} + /*********************************************************************** Appends a new file to the chain of files of a space. File must be closed. */ @@ -426,7 +467,7 @@ fil_node_create( node->modification_counter = 0; node->flush_counter = 0; - + HASH_SEARCH(hash, system->spaces, id, space, space->id == id); if (!space) { @@ -450,7 +491,7 @@ fil_node_create( node->space = space; UT_LIST_ADD_LAST(chain, space->chain, node); - + mutex_exit(&(system->mutex)); } @@ -469,10 +510,12 @@ fil_node_open_file( ulint size_low; ulint size_high; ibool ret; + ibool success; +#ifndef UNIV_HOTBACKUP byte* buf2; byte* page; - ibool success; ulint space_id; +#endif /* !UNIV_HOTBACKUP */ #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(system->mutex))); @@ -505,24 +548,24 @@ fil_node_open_file( ut_a(0); } - ut_a(space->purpose != FIL_LOG); - ut_a(space->id != 0); - os_file_get_size(node->handle, &size_low, &size_high); size_bytes = (((ib_longlong)size_high) << 32) - + (ib_longlong)size_low; + + (ib_longlong)size_low; #ifdef UNIV_HOTBACKUP node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE); #else + ut_a(space->purpose != FIL_LOG); + ut_a(space->id != 0); + if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: the size of single-table tablespace file %s\n" "InnoDB: is only %lu %lu, should be at least %lu!\n", node->name, (ulong) size_high, (ulong) size_low, (ulong) (4 * UNIV_PAGE_SIZE)); - + ut_a(0); } @@ -538,22 +581,22 @@ fil_node_open_file( space_id = fsp_header_get_space_id(page); ut_free(buf2); - + /* Close the file now that we have read the space id from it */ os_file_close(node->handle); if (space_id == ULINT_UNDEFINED || space_id == 0) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: tablespace id %lu in file %s is not sensible\n", (ulong) space_id, node->name); - - ut_a(0); + + ut_a(0); } if (space_id != space->id) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: tablespace id is %lu in the data dictionary\n" "InnoDB: but in file %s it is %lu!\n", space->id, node->name, space_id); @@ -576,20 +619,20 @@ fil_node_open_file( unbuffered async I/O mode, though global variables may make os_file_create() to fall back to the normal file I/O mode. */ - if (space->purpose == FIL_LOG) { + if (space->purpose == FIL_LOG) { node->handle = os_file_create(node->name, OS_FILE_OPEN, OS_FILE_AIO, OS_LOG_FILE, &ret); } else if (node->is_raw_disk) { node->handle = os_file_create(node->name, - OS_FILE_OPEN_RAW, + OS_FILE_OPEN_RAW, OS_FILE_AIO, OS_DATA_FILE, &ret); } else { node->handle = os_file_create(node->name, OS_FILE_OPEN, OS_FILE_AIO, OS_DATA_FILE, &ret); } - + ut_a(ret); - + node->open = TRUE; system->n_open++; @@ -645,7 +688,7 @@ ibool fil_try_to_close_file_in_LRU( /*=========================*/ /* out: TRUE if success, FALSE if should retry - later; since i/o's generally complete in < + later; since i/o's generally complete in < 100 ms, and as InnoDB writes at most 128 pages from the buffer pool in a batch, and then immediately flushes the files, there is a good @@ -669,22 +712,22 @@ fil_try_to_close_file_in_LRU( while (node != NULL) { if (node->modification_counter == node->flush_counter - && node->n_pending_flushes == 0) { + && node->n_pending_flushes == 0) { fil_node_close_file(node, system); - + return(TRUE); } - + if (print_info && node->n_pending_flushes > 0) { fputs("InnoDB: cannot close file ", stderr); ut_print_filename(stderr, node->name); fprintf(stderr, ", because n_pending_flushes %lu\n", - (ulong) node->n_pending_flushes); + (ulong) node->n_pending_flushes); } if (print_info - && node->modification_counter != node->flush_counter) { + && node->modification_counter != node->flush_counter) { fputs("InnoDB: cannot close file ", stderr); ut_print_filename(stderr, node->name); fprintf(stderr, @@ -811,7 +854,7 @@ close_more: /* Flush tablespaces so that we can close modified files in the LRU list */ - fil_flush_file_spaces(FIL_TABLESPACE); + fil_flush_file_spaces(FIL_TABLESPACE); count++; @@ -841,11 +884,21 @@ fil_node_free( node->modification_counter = node->flush_counter; + if (space->is_in_unflushed_spaces + && fil_space_is_flushed(space)) { + + space->is_in_unflushed_spaces = FALSE; + + UT_LIST_REMOVE(unflushed_spaces, + system->unflushed_spaces, + space); + } + fil_node_close_file(node, system); } space->size -= node->size; - + UT_LIST_REMOVE(chain, space->chain, node); mem_free(node->name); @@ -873,7 +926,7 @@ fil_space_truncate_start( HASH_SEARCH(hash, system->spaces, id, space, space->id == id); ut_a(space); - + while (trunc_len > 0) { node = UT_LIST_GET_FIRST(space->chain); @@ -882,8 +935,8 @@ fil_space_truncate_start( trunc_len -= node->size * UNIV_PAGE_SIZE; fil_node_free(node, system, space); - } - + } + mutex_exit(&(system->mutex)); } @@ -900,7 +953,7 @@ fil_space_create( ulint purpose)/* in: FIL_TABLESPACE, or FIL_LOG if log */ { fil_system_t* system = fil_system; - fil_space_t* space; + fil_space_t* space; ulint namesake_id; try_again: /*printf( @@ -988,7 +1041,7 @@ try_again: space->size = 0; space->n_reserved_extents = 0; - + space->n_pending_flushes = 0; space->n_pending_ibuf_merges = 0; @@ -996,16 +1049,18 @@ try_again: space->magic_n = FIL_SPACE_MAGIC_N; space->ibuf_data = NULL; - + rw_lock_create(&(space->latch)); rw_lock_set_level(&(space->latch), SYNC_FSP); - + HASH_INSERT(fil_space_t, hash, system->spaces, id, space); HASH_INSERT(fil_space_t, name_hash, system->name_hash, ut_fold_string(name), space); + space->is_in_unflushed_spaces = FALSE; + UT_LIST_ADD_LAST(space_list, system->space_list, space); - + mutex_exit(&(system->mutex)); return(TRUE); @@ -1032,8 +1087,8 @@ fil_assign_new_space_id(void) id = system->max_assigned_id; if (id > (SRV_LOG_SPACE_FIRST_ID / 2) && (id % 1000000UL == 0)) { - ut_print_timestamp(stderr); - fprintf(stderr, + ut_print_timestamp(stderr); + fprintf(stderr, "InnoDB: Warning: you are running out of new single-table tablespace id's.\n" "InnoDB: Current counter is %lu and it must not exceed %lu!\n" "InnoDB: To reset the counter to zero you have to dump all your tables and\n" @@ -1042,8 +1097,8 @@ fil_assign_new_space_id(void) } if (id >= SRV_LOG_SPACE_FIRST_ID) { - ut_print_timestamp(stderr); - fprintf(stderr, + ut_print_timestamp(stderr); + fprintf(stderr, "InnoDB: You have run out of single-table tablespace id's!\n" "InnoDB: Current counter is %lu.\n" "InnoDB: To reset the counter to zero you have to dump all your tables and\n" @@ -1085,20 +1140,27 @@ fil_space_free( "InnoDB: it is not there.\n", (ulong) id); mutex_exit(&(system->mutex)); - + return(FALSE); } HASH_DELETE(fil_space_t, hash, system->spaces, id, space); HASH_SEARCH(name_hash, system->name_hash, ut_fold_string(space->name), - namespace, 0 == strcmp(space->name, namespace->name)); + namespace, 0 == strcmp(space->name, namespace->name)); ut_a(namespace); ut_a(space == namespace); HASH_DELETE(fil_space_t, name_hash, system->name_hash, ut_fold_string(space->name), space); + if (space->is_in_unflushed_spaces) { + space->is_in_unflushed_spaces = FALSE; + + UT_LIST_REMOVE(unflushed_spaces, system->unflushed_spaces, + space); + } + UT_LIST_REMOVE(space_list, system->space_list, space); ut_a(space->magic_n == FIL_SPACE_MAGIC_N); @@ -1110,8 +1172,8 @@ fil_space_free( fil_node_free(fil_node, system, space); fil_node = UT_LIST_GET_FIRST(space->chain); - } - + } + ut_a(0 == UT_LIST_GET_LEN(space->chain)); mutex_exit(&(system->mutex)); @@ -1157,7 +1219,7 @@ fil_space_get_size( /* out: space size, 0 if space not found */ ulint id) /* in: space id */ { - fil_system_t* system = fil_system; + fil_system_t* system = fil_system; fil_node_t* node; fil_space_t* space; ulint size; @@ -1190,7 +1252,7 @@ fil_space_get_size( } size = space->size; - + mutex_exit(&(system->mutex)); return(size); @@ -1213,7 +1275,7 @@ fil_check_adress_in_tablespace( } return(FALSE); -} +} /******************************************************************** Creates a the tablespace memory cache. */ @@ -1250,6 +1312,7 @@ fil_system_create( system->tablespace_version = 0; + UT_LIST_INIT(system->unflushed_spaces); UT_LIST_INIT(system->space_list); return(system); @@ -1266,7 +1329,7 @@ fil_init( ut_a(fil_system == NULL); /*printf("Initializing the tablespace cache with max %lu open files\n", - max_n_open); */ + max_n_open); */ fil_system = fil_system_create(FIL_SYSTEM_HASH_SIZE, max_n_open); } @@ -1305,8 +1368,8 @@ fil_open_log_and_system_tablespace_files(void) "InnoDB: tablespace files open for the whole time mysqld is running, and\n" "InnoDB: needs to open also some .ibd files if the file-per-table storage\n" "InnoDB: model is used. Current open files %lu, max allowed open files %lu.\n", - (ulong) system->n_open, - (ulong) system->max_n_open); + (ulong) system->n_open, + (ulong) system->max_n_open); } node = UT_LIST_GET_NEXT(chain, node); } @@ -1389,7 +1452,7 @@ fil_ibuf_init_at_db_start(void) space = UT_LIST_GET_FIRST(fil_system->space_list); ut_a(space); - ut_a(space->purpose == FIL_TABLESPACE); + ut_a(space->purpose == FIL_TABLESPACE); space->ibuf_data = ibuf_data_init_for_space(space->id); } @@ -1420,7 +1483,7 @@ fil_write_lsn_and_arch_no_to_file( fil_write(TRUE, space_id, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL); - return(DB_SUCCESS); + return(DB_SUCCESS); } /******************************************************************** @@ -1440,9 +1503,9 @@ fil_write_flushed_lsn_to_data_files( ulint err; mutex_enter(&(fil_system->mutex)); - + space = UT_LIST_GET_FIRST(fil_system->space_list); - + while (space) { /* We only write the lsn to all existing data files which have been open during the lifetime of the mysqld process; they are @@ -1451,7 +1514,7 @@ fil_write_flushed_lsn_to_data_files( always open. */ if (space->purpose == FIL_TABLESPACE - && space->id == 0) { + && space->id == 0) { sum_of_sizes = 0; node = UT_LIST_GET_FIRST(space->chain); @@ -1504,7 +1567,7 @@ fil_read_flushed_lsn_and_arch_log_no( buf2 = ut_malloc(2 * UNIV_PAGE_SIZE); /* Align the memory for a possible read from a raw device */ buf = ut_align(buf2, UNIV_PAGE_SIZE); - + os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE); flushed_lsn = mach_read_from_8(buf + FIL_PAGE_FILE_FLUSH_LSN); @@ -1552,7 +1615,7 @@ fil_inc_pending_ibuf_merges( { fil_system_t* system = fil_system; fil_space_t* space; - + mutex_enter(&(system->mutex)); HASH_SEARCH(hash, system->spaces, id, space, space->id == id); @@ -1581,12 +1644,12 @@ Decrements the count of pending insert buffer page merges. */ void fil_decr_pending_ibuf_merges( -/*========================*/ +/*=========================*/ ulint id) /* in: space id */ { fil_system_t* system = fil_system; fil_space_t* space; - + mutex_enter(&(system->mutex)); HASH_SEARCH(hash, system->spaces, id, space, space->id == id); @@ -1647,7 +1710,7 @@ fil_op_write_log( const char* name, /* in: table name in the familiar 'databasename/tablename' format, or the file path in the case of - MLOG_FILE_DELETE */ + MLOG_FILE_DELETE */ const char* new_name, /* in: if type is MLOG_FILE_RENAME, the new table name in the 'databasename/tablename' format */ @@ -1706,13 +1769,13 @@ datadir that we should use in replaying the file operations. */ byte* fil_op_log_parse_or_replay( /*=======================*/ - /* out: end of log record, or NULL if the + /* out: end of log record, or NULL if the record was not completely contained between ptr and end_ptr */ - byte* ptr, /* in: buffer containing the log record body, + byte* ptr, /* in: buffer containing the log record body, or an initial segment of it, if the record does not fir completely between ptr and end_ptr */ - byte* end_ptr, /* in: buffer end */ + byte* end_ptr, /* in: buffer end */ ulint type, /* in: the type of this log record */ ibool do_replay, /* in: TRUE if we want to replay the operation, and not just parse the log record */ @@ -1735,7 +1798,7 @@ fil_op_log_parse_or_replay( ptr += 2; if (end_ptr < ptr + name_len) { - + return(NULL); } @@ -1750,11 +1813,11 @@ fil_op_log_parse_or_replay( } new_name_len = mach_read_from_2(ptr); - + ptr += 2; if (end_ptr < ptr + new_name_len) { - + return(NULL); } @@ -1780,7 +1843,7 @@ fil_op_log_parse_or_replay( /* Let us try to perform the file operation, if sensible. Note that ibbackup has at this stage already read in all space id info to the fil0fil.c data structures. - + NOTE that our algorithm is not guaranteed to work correctly if there were renames of tables during the backup. See ibbackup code for more on the problem. */ @@ -1799,12 +1862,12 @@ fil_op_log_parse_or_replay( /* Create the database directory for the new name, if it does not exist yet */ fil_create_directory_for_tablename(new_name); - + /* Rename the table if there is not yet a tablespace with the same name */ if (fil_get_space_id_for_table(new_name) - == ULINT_UNDEFINED) { + == ULINT_UNDEFINED) { /* We do not care of the old name, that is why we pass NULL as the first argument */ ut_a(fil_rename_tablespace(NULL, space_id, @@ -1826,7 +1889,7 @@ fil_op_log_parse_or_replay( ut_a(space_id != 0); - ut_a(DB_SUCCESS == + ut_a(DB_SUCCESS == fil_create_new_single_table_tablespace( &space_id, name, FALSE, FIL_IBD_FILE_INITIAL_SIZE)); @@ -1905,9 +1968,9 @@ try_again: (ulong) id); mutex_exit(&(system->mutex)); - + return(FALSE); - } + } ut_a(space); ut_a(space->n_pending_ibuf_merges == 0); @@ -2010,7 +2073,7 @@ fil_discard_tablespace( fprintf(stderr, "InnoDB: Warning: cannot delete tablespace %lu in DISCARD TABLESPACE.\n" "InnoDB: But let us remove the insert buffer entries for this tablespace.\n", - (ulong) id); + (ulong) id); } /* Remove all insert buffer entries for the tablespace */ @@ -2034,9 +2097,9 @@ fil_rename_tablespace_in_mem( fil_system_t* system = fil_system; fil_space_t* space2; const char* old_name = space->name; - + HASH_SEARCH(name_hash, system->name_hash, ut_fold_string(old_name), - space2, 0 == strcmp(old_name, space2->name)); + space2, 0 == strcmp(old_name, space2->name)); if (space != space2) { fputs("InnoDB: Error: cannot find ", stderr); ut_print_filename(stderr, old_name); @@ -2046,12 +2109,12 @@ fil_rename_tablespace_in_mem( } HASH_SEARCH(name_hash, system->name_hash, ut_fold_string(path), - space2, 0 == strcmp(path, space2->name)); + space2, 0 == strcmp(path, space2->name)); if (space2 != NULL) { fputs("InnoDB: Error: ", stderr); ut_print_filename(stderr, path); fputs(" is already in tablespace memory cache\n", stderr); - + return(FALSE); } @@ -2123,11 +2186,11 @@ fil_rename_tablespace( fil_node_t* node; ulint count = 0; char* path; - ibool old_name_was_specified = TRUE; + ibool old_name_was_specified = TRUE; char* old_path; ut_a(id != 0); - + if (old_name == NULL) { old_name = "(name not specified)"; old_name_was_specified = FALSE; @@ -2236,7 +2299,7 @@ retry: mutex_exit(&(system->mutex)); -#ifndef UNIV_HOTBACKUP +#ifndef UNIV_HOTBACKUP if (success) { mtr_t mtr; @@ -2274,7 +2337,7 @@ fil_create_new_single_table_tablespace( tablespace file in pages, must be >= FIL_IBD_FILE_INITIAL_SIZE */ { - os_file_t file; + os_file_t file; ibool ret; ulint err; byte* buf2; @@ -2285,9 +2348,9 @@ fil_create_new_single_table_tablespace( ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE); path = fil_make_ibd_name(tablename, is_temp); - + file = os_file_create(path, OS_FILE_CREATE, OS_FILE_NORMAL, - OS_DATA_FILE, &ret); + OS_DATA_FILE, &ret); if (ret == FALSE) { ut_print_timestamp(stderr); fputs(" InnoDB: Error creating file ", stderr); @@ -2295,11 +2358,11 @@ fil_create_new_single_table_tablespace( fputs(".\n", stderr); /* The following call will print an error message */ - + err = os_file_get_last_error(TRUE); - + if (err == OS_FILE_ALREADY_EXISTS) { - fputs( + fputs( "InnoDB: The file already exists though the corresponding table did not\n" "InnoDB: exist in the InnoDB data dictionary. Have you moved InnoDB\n" "InnoDB: .ibd files around without using the SQL commands\n" @@ -2329,7 +2392,7 @@ fil_create_new_single_table_tablespace( page = ut_align(buf2, UNIV_PAGE_SIZE); ret = os_file_set_size(path, file, size * UNIV_PAGE_SIZE, 0); - + if (!ret) { ut_free(buf2); os_file_close(file); @@ -2367,7 +2430,7 @@ fil_create_new_single_table_tablespace( memset(page, '\0', UNIV_PAGE_SIZE); - fsp_header_write_space_id(page, *space_id); + fsp_header_write_space_id(page, *space_id); buf_flush_init_for_writing(page, ut_dulint_zero, *space_id, 0); @@ -2400,14 +2463,14 @@ fil_create_new_single_table_tablespace( } success = fil_space_create(path, *space_id, FIL_TABLESPACE); - + if (!success) { goto error_exit2; - } + } fil_node_create(path, size, *space_id, FALSE); -#ifndef UNIV_HOTBACKUP +#ifndef UNIV_HOTBACKUP { mtr_t mtr; @@ -2463,7 +2526,7 @@ fil_reset_too_high_lsns( ut_print_timestamp(stderr); - fputs( + fputs( " InnoDB: Error: trying to open a table, but could not\n" "InnoDB: open the tablespace file ", stderr); ut_print_filename(stderr, filepath); @@ -2497,17 +2560,17 @@ fil_reset_too_high_lsns( } space_id = fsp_header_get_space_id(page); - + ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Flush lsn in the tablespace file %lu to be imported\n" "InnoDB: is %lu %lu, which exceeds current system lsn %lu %lu.\n" "InnoDB: We reset the lsn's in the file ", - (ulong) space_id, - (ulong) ut_dulint_get_high(flush_lsn), - (ulong) ut_dulint_get_low(flush_lsn), - (ulong) ut_dulint_get_high(current_lsn), - (ulong) ut_dulint_get_low(current_lsn)); + (ulong) space_id, + (ulong) ut_dulint_get_high(flush_lsn), + (ulong) ut_dulint_get_low(flush_lsn), + (ulong) ut_dulint_get_high(current_lsn), + (ulong) ut_dulint_get_low(current_lsn)); ut_print_filename(stderr, filepath); fputs(".\n", stderr); @@ -2530,9 +2593,9 @@ fil_reset_too_high_lsns( space_id = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); page_no = mach_read_from_4(page + FIL_PAGE_OFFSET); - + buf_flush_init_for_writing(page, current_lsn, space_id, - page_no); + page_no); success = os_file_write(filepath, file, page, (ulint)(offset & 0xFFFFFFFFUL), (ulint)(offset >> 32), UNIV_PAGE_SIZE); @@ -2615,7 +2678,7 @@ fil_open_single_table_tablespace( ut_print_timestamp(stderr); - fputs( + fputs( " InnoDB: Error: trying to open a table, but could not\n" "InnoDB: open the tablespace file ", stderr); ut_print_filename(stderr, filepath); @@ -2657,7 +2720,7 @@ fil_open_single_table_tablespace( if (space_id != id) { ut_print_timestamp(stderr); - fputs( + fputs( " InnoDB: Error: tablespace id in file ", stderr); ut_print_filename(stderr, filepath); fprintf(stderr, " is %lu, but in the InnoDB\n" @@ -2737,13 +2800,14 @@ fil_load_single_table_tablespace( #ifdef UNIV_HOTBACKUP fil_space_t* space; #endif - filepath = mem_alloc(strlen(dbname) + strlen(filename) + filepath = mem_alloc(strlen(dbname) + strlen(filename) + strlen(fil_path_to_mysql_datadir) + 3); sprintf(filepath, "%s/%s/%s", fil_path_to_mysql_datadir, dbname, filename); srv_normalize_path_for_win(filepath); #ifdef __WIN__ +# ifndef UNIV_HOTBACKUP /* If lower_case_table_names is 0 or 2, then MySQL allows database directory names with upper case letters. On Windows, all table and database names in InnoDB are internally always in lower case. Put the @@ -2751,6 +2815,7 @@ fil_load_single_table_tablespace( internal data dictionary. */ dict_casedn_str(filepath); +# endif /* !UNIV_HOTBACKUP */ #endif file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success); @@ -2758,7 +2823,7 @@ fil_load_single_table_tablespace( /* The following call prints an error message */ os_file_get_last_error(TRUE); - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: could not open single-table tablespace file\n" "InnoDB: %s!\n" "InnoDB: We do not continue the crash recovery, because the table may become\n" @@ -2792,7 +2857,7 @@ fil_load_single_table_tablespace( /* The following call prints an error message */ os_file_get_last_error(TRUE); - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: could not measure the size of single-table tablespace file\n" "InnoDB: %s!\n" "InnoDB: We do not continue crash recovery, because the table will become\n" @@ -2830,7 +2895,7 @@ fil_load_single_table_tablespace( size = (((ib_longlong)size_high) << 32) + (ib_longlong)size_low; #ifndef UNIV_HOTBACKUP if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: the size of single-table tablespace file %s\n" "InnoDB: is only %lu %lu, should be at least %lu!", filepath, (ulong) size_high, @@ -2859,7 +2924,7 @@ fil_load_single_table_tablespace( #ifndef UNIV_HOTBACKUP if (space_id == ULINT_UNDEFINED || space_id == 0) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: tablespace id %lu in file %s is not sensible\n", (ulong) space_id, filepath); @@ -2969,7 +3034,7 @@ fil_file_readdir_next_file( return(ret); } - + fprintf(stderr, "InnoDB: Error: os_file_readdir_next_file() returned -1 in\n" "InnoDB: directory %s\n" @@ -3001,7 +3066,7 @@ fil_load_single_table_tablespaces(void) os_file_dir_t dbdir; os_file_stat_t dbinfo; os_file_stat_t fileinfo; - ulint err = DB_SUCCESS; + ulint err = DB_SUCCESS; /* The datadir of MySQL is always the default directory of mysqld */ @@ -3024,9 +3089,9 @@ fil_load_single_table_tablespaces(void) /* printf("Looking at %s in datadir\n", dbinfo.name); */ if (dbinfo.type == OS_FILE_TYPE_FILE - || dbinfo.type == OS_FILE_TYPE_UNKNOWN) { + || dbinfo.type == OS_FILE_TYPE_UNKNOWN) { - goto next_datadir_item; + goto next_datadir_item; } /* We found a symlink or a directory; try opening it to see @@ -3059,19 +3124,19 @@ fil_load_single_table_tablespaces(void) &fileinfo); while (ret == 0) { /* printf( -" Looking at file %s\n", fileinfo.name); */ + " Looking at file %s\n", fileinfo.name); */ - if (fileinfo.type == OS_FILE_TYPE_DIR) { + if (fileinfo.type == OS_FILE_TYPE_DIR) { - goto next_file_item; + goto next_file_item; } /* We found a symlink or a file */ if (strlen(fileinfo.name) > 4 - && 0 == strcmp(fileinfo.name + + && 0 == strcmp(fileinfo.name + strlen(fileinfo.name) - 4, ".ibd")) { - /* The name ends in .ibd; try opening + /* The name ends in .ibd; try opening the file */ fil_load_single_table_tablespace( dbinfo.name, fileinfo.name); @@ -3091,7 +3156,7 @@ next_file_item: err = DB_ERROR; } } - + next_datadir_item: ret = fil_file_readdir_next_file(&err, fil_path_to_mysql_datadir, @@ -3121,7 +3186,7 @@ void fil_print_orphaned_tablespaces(void) /*================================*/ { - fil_system_t* system = fil_system; + fil_system_t* system = fil_system; fil_space_t* space; mutex_enter(&(system->mutex)); @@ -3129,7 +3194,7 @@ fil_print_orphaned_tablespaces(void) space = UT_LIST_GET_FIRST(system->space_list); while (space) { - if (space->purpose == FIL_TABLESPACE && space->id != 0 + if (space->purpose == FIL_TABLESPACE && space->id != 0 && !space->mark) { fputs("InnoDB: Warning: tablespace ", stderr); ut_print_filename(stderr, space->name); @@ -3140,7 +3205,7 @@ fil_print_orphaned_tablespaces(void) space = UT_LIST_GET_NEXT(space_list, space); } - mutex_exit(&(system->mutex)); + mutex_exit(&(system->mutex)); } /*********************************************************************** @@ -3264,7 +3329,7 @@ fil_space_for_table_exists_in_mem( 0 == strcmp(namespace->name, path)); if (space && space == namespace) { /* Found */ - + if (mark_space) { space->mark = TRUE; } @@ -3276,16 +3341,16 @@ fil_space_for_table_exists_in_mem( } if (!print_error_if_does_not_exist) { - + mem_free(path); mutex_exit(&(system->mutex)); - + return(FALSE); } if (space == NULL) { if (namespace == NULL) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); ut_print_filename(stderr, name); fprintf(stderr, "\n" @@ -3297,7 +3362,7 @@ fil_space_for_table_exists_in_mem( "InnoDB: table still exists in the InnoDB internal data dictionary.\n", (ulong) id); } else { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); ut_print_filename(stderr, name); fprintf(stderr, "\n" @@ -3379,7 +3444,7 @@ fil_get_space_id_for_table( 0 == strcmp(namespace->name, path)); if (namespace) { id = namespace->id; - } + } mem_free(path); @@ -3428,11 +3493,11 @@ fil_extend_space_to_desired_size( *actual_size = space->size; - mutex_exit(&(system->mutex)); + mutex_exit(&(system->mutex)); return(TRUE); } - + node = UT_LIST_GET_LAST(space->chain); fil_node_prepare_for_io(node, system, space); @@ -3456,7 +3521,7 @@ fil_extend_space_to_desired_size( / (4096 * ((1024 * 1024) / UNIV_PAGE_SIZE)); offset_low = ((start_page_no - file_start_page_no) % (4096 * ((1024 * 1024) / UNIV_PAGE_SIZE))) - * UNIV_PAGE_SIZE; + * UNIV_PAGE_SIZE; #ifdef UNIV_HOTBACKUP success = os_file_write(node->name, node->handle, buf, offset_low, offset_high, @@ -3476,7 +3541,7 @@ fil_extend_space_to_desired_size( } else { /* Let us measure the size of the file to determine how much we were able to extend it */ - + n_pages = ((ulint) (os_file_get_size_as_iblonglong(node->handle) / UNIV_PAGE_SIZE)) - node->size; @@ -3496,6 +3561,7 @@ fil_extend_space_to_desired_size( *actual_size = space->size; +#ifndef UNIV_HOTBACKUP if (space_id == 0) { ulint pages_per_mb = (1024 * 1024) / UNIV_PAGE_SIZE; @@ -3505,11 +3571,12 @@ fil_extend_space_to_desired_size( srv_data_file_sizes[srv_n_data_files - 1] = (node->size / pages_per_mb) * pages_per_mb; } +#endif /* !UNIV_HOTBACKUP */ /* - printf("Extended %s to %lu, actual size %lu pages\n", space->name, - size_after_extend, *actual_size); */ - mutex_exit(&(system->mutex)); + printf("Extended %s to %lu, actual size %lu pages\n", space->name, + size_after_extend, *actual_size); */ + mutex_exit(&(system->mutex)); fil_flush(space_id); @@ -3527,7 +3594,7 @@ void fil_extend_tablespaces_to_stored_len(void) /*======================================*/ { - fil_system_t* system = fil_system; + fil_system_t* system = fil_system; fil_space_t* space; byte* buf; ulint actual_size; @@ -3542,11 +3609,11 @@ fil_extend_tablespaces_to_stored_len(void) space = UT_LIST_GET_FIRST(system->space_list); while (space) { - ut_a(space->purpose == FIL_TABLESPACE); + ut_a(space->purpose == FIL_TABLESPACE); mutex_exit(&(system->mutex)); /* no need to protect with a - mutex, because this is a single- - threaded operation */ + mutex, because this is a + single-threaded operation */ error = fil_read(TRUE, space->id, 0, 0, UNIV_PAGE_SIZE, buf, NULL); ut_a(error == DB_SUCCESS); @@ -3562,7 +3629,7 @@ fil_extend_tablespaces_to_stored_len(void) "InnoDB: size after extension %lu pages\n" "InnoDB: Check that you have free disk space and retry!\n", space->name, size_in_header, actual_size); - exit(1); + exit(1); } mutex_enter(&(system->mutex)); @@ -3607,7 +3674,7 @@ fil_space_reserve_free_extents( space->n_reserved_extents += n_to_reserve; success = TRUE; } - + mutex_exit(&(system->mutex)); return(success); @@ -3633,9 +3700,9 @@ fil_space_release_free_extents( ut_a(space); ut_a(space->n_reserved_extents >= n_reserved); - + space->n_reserved_extents -= n_reserved; - + mutex_exit(&(system->mutex)); } @@ -3657,11 +3724,11 @@ fil_space_get_n_reserved_extents( mutex_enter(&(system->mutex)); HASH_SEARCH(hash, system->spaces, id, space, space->id == id); - + ut_a(space); n = space->n_reserved_extents; - + mutex_exit(&(system->mutex)); return(n); @@ -3688,7 +3755,7 @@ fil_node_prepare_for_io( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(system->mutex))); #endif /* UNIV_SYNC_DEBUG */ - + if (system->n_open > system->max_n_open + 5) { ut_print_timestamp(stderr); fprintf(stderr, @@ -3705,7 +3772,7 @@ fil_node_prepare_for_io( } if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE - && space->id != 0) { + && space->id != 0) { /* The node is in the LRU list, remove it */ ut_a(UT_LIST_GET_LEN(system->LRU) > 0); @@ -3736,14 +3803,22 @@ fil_node_complete_io( #endif /* UNIV_SYNC_DEBUG */ ut_a(node->n_pending > 0); - + node->n_pending--; if (type == OS_FILE_WRITE) { system->modification_counter++; node->modification_counter = system->modification_counter; + + if (!node->space->is_in_unflushed_spaces) { + + node->space->is_in_unflushed_spaces = TRUE; + UT_LIST_ADD_FIRST(unflushed_spaces, + system->unflushed_spaces, + node->space); + } } - + if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE && node->space->id != 0) { /* The node must be put back to the LRU list */ @@ -3752,6 +3827,31 @@ fil_node_complete_io( } /************************************************************************ +Report information about an invalid page access. */ +static +void +fil_report_invalid_page_access( +/*===========================*/ + ulint block_offset, /* in: block offset */ + ulint space_id, /* in: space id */ + const char* space_name, /* in: space name */ + ulint byte_offset, /* in: byte offset */ + ulint len, /* in: I/O length */ + ulint type) /* in: I/O type */ +{ + fprintf(stderr, + "InnoDB: Error: trying to access page number %lu in space %lu,\n" + "InnoDB: space name %s,\n" + "InnoDB: which is outside the tablespace bounds.\n" + "InnoDB: Byte offset %lu, len %lu, i/o type %lu.\n" + "InnoDB: If you get this error at mysqld startup, please check that\n" + "InnoDB: your my.cnf matches the ibdata files that you have in the\n" + "InnoDB: MySQL server.\n", + (ulong) block_offset, (ulong) space_id, space_name, + (ulong) byte_offset, (ulong) len, (ulong) type); +} + +/************************************************************************ Reads or writes data. This operation is asynchronous (aio). */ ulint @@ -3793,13 +3893,13 @@ fil_io( ibool ret; ulint is_log; ulint wake_later; - + is_log = type & OS_FILE_LOG; type = type & ~OS_FILE_LOG; wake_later = type & OS_AIO_SIMULATED_WAKE_LATER; type = type & ~OS_AIO_SIMULATED_WAKE_LATER; - + ut_ad(byte_offset < UNIV_PAGE_SIZE); ut_ad(buf); ut_ad(len > 0); @@ -3825,17 +3925,17 @@ fil_io( mode = OS_AIO_NORMAL; } - if (type == OS_FILE_READ) { - srv_data_read+= len; - } else if (type == OS_FILE_WRITE) { - srv_data_written+= len; - } + if (type == OS_FILE_READ) { + srv_data_read+= len; + } else if (type == OS_FILE_WRITE) { + srv_data_written+= len; + } /* Reserve the fil_system mutex and make sure that we can open at least one file while holding it, if the file is not already open */ fil_mutex_enter_and_prepare_for_io(space_id); - + HASH_SEARCH(hash, system->spaces, space_id, space, space->id == space_id); if (!space) { @@ -3857,15 +3957,9 @@ fil_io( for (;;) { if (node == NULL) { - fprintf(stderr, - "InnoDB: Error: trying to access page number %lu in space %lu,\n" - "InnoDB: space name %s,\n" - "InnoDB: which is outside the tablespace bounds.\n" - "InnoDB: Byte offset %lu, len %lu, i/o type %lu\n", - (ulong) block_offset, (ulong) space_id, - space->name, (ulong) byte_offset, (ulong) len, - (ulong) type); - + fil_report_invalid_page_access(block_offset, space_id, + space->name, byte_offset, len, type); + ut_error; } @@ -3883,25 +3977,20 @@ fil_io( block_offset -= node->size; node = UT_LIST_GET_NEXT(chain, node); } - } - + } + /* Open file if closed */ fil_node_prepare_for_io(node, system, space); /* Check that at least the start offset is within the bounds of a single-table tablespace */ if (space->purpose == FIL_TABLESPACE && space->id != 0 - && node->size <= block_offset) { + && node->size <= block_offset) { - fprintf(stderr, - "InnoDB: Error: trying to access page number %lu in space %lu,\n" - "InnoDB: space name %s,\n" - "InnoDB: which is outside the tablespace bounds.\n" - "InnoDB: Byte offset %lu, len %lu, i/o type %lu\n", - (ulong) block_offset, (ulong) space_id, - space->name, (ulong) byte_offset, (ulong) len, - (ulong) type); - ut_a(0); + fil_report_invalid_page_access(block_offset, space_id, + space->name, byte_offset, len, type); + + ut_error; } /* Now we have made the changes in the data structures of system */ @@ -3914,7 +4003,7 @@ fil_io( + byte_offset; ut_a(node->size - block_offset >= - (byte_offset + len + (UNIV_PAGE_SIZE - 1)) / UNIV_PAGE_SIZE); + (byte_offset + len + (UNIV_PAGE_SIZE - 1)) / UNIV_PAGE_SIZE); /* Do aio */ @@ -3940,7 +4029,7 @@ fil_io( if (mode == OS_AIO_SYNC) { /* The i/o operation is already completed when we return from os_aio: */ - + mutex_enter(&(system->mutex)); fil_node_complete_io(node, system, type); @@ -4019,21 +4108,21 @@ void fil_aio_wait( /*=========*/ ulint segment) /* in: the number of the segment in the aio - array to wait for */ + array to wait for */ { fil_system_t* system = fil_system; - ibool ret; + ibool ret; fil_node_t* fil_node; void* message; ulint type; - + ut_ad(fil_validate()); if (os_aio_use_native_aio) { srv_set_io_thread_op_info(segment, "native aio handle"); #ifdef WIN_ASYNC_IO ret = os_aio_windows_handle(segment, 0, &fil_node, - &message, &type); + &message, &type); #elif defined(POSIX_ASYNC_IO) ret = os_aio_posix_handle(segment, &fil_node, &message); #else @@ -4044,9 +4133,9 @@ fil_aio_wait( srv_set_io_thread_op_info(segment, "simulated aio handle"); ret = os_aio_simulated_handle(segment, &fil_node, - &message, &type); + &message, &type); } - + ut_a(ret); srv_set_io_thread_op_info(segment, "complete io for fil node"); @@ -4091,7 +4180,7 @@ fil_flush( ib_longlong old_mod_counter; mutex_enter(&(system->mutex)); - + HASH_SEARCH(hash, system->spaces, space_id, space, space->id == space_id); if (!space || space->is_being_deleted) { @@ -4124,7 +4213,7 @@ fil_flush( goto skip_flush; } #endif -retry: +retry: if (node->n_pending_flushes > 0) { /* We want to avoid calling os_file_flush() on the file twice at the same time, because we do @@ -4154,7 +4243,7 @@ retry: /* fprintf(stderr, "Flushing to file %s\n", node->name); */ - os_file_flush(file); + os_file_flush(file); mutex_enter(&(system->mutex)); @@ -4162,6 +4251,16 @@ retry: skip_flush: if (node->flush_counter < old_mod_counter) { node->flush_counter = old_mod_counter; + + if (space->is_in_unflushed_spaces + && fil_space_is_flushed(space)) { + + space->is_in_unflushed_spaces = FALSE; + + UT_LIST_REMOVE(unflushed_spaces, + system->unflushed_spaces, + space); + } } if (space->purpose == FIL_TABLESPACE) { @@ -4172,7 +4271,7 @@ skip_flush: } node = UT_LIST_GET_NEXT(chain, node); - } + } space->n_pending_flushes--; @@ -4193,13 +4292,13 @@ fil_flush_file_spaces( mutex_enter(&(system->mutex)); - space = UT_LIST_GET_FIRST(system->space_list); + space = UT_LIST_GET_FIRST(system->unflushed_spaces); while (space) { if (space->purpose == purpose && !space->is_being_deleted) { - space->n_pending_flushes++; /* prevent dropping of the - space while we are + space->n_pending_flushes++; /* prevent dropping of + the space while we are flushing */ mutex_exit(&(system->mutex)); @@ -4209,9 +4308,9 @@ fil_flush_file_spaces( space->n_pending_flushes--; } - space = UT_LIST_GET_NEXT(space_list, space); + space = UT_LIST_GET_NEXT(unflushed_spaces, space); } - + mutex_exit(&(system->mutex)); } @@ -4222,13 +4321,13 @@ ibool fil_validate(void) /*==============*/ /* out: TRUE if ok */ -{ +{ fil_system_t* system = fil_system; fil_space_t* space; fil_node_t* fil_node; ulint n_open = 0; ulint i; - + mutex_enter(&(system->mutex)); /* Look for spaces in the hash table */ @@ -4236,9 +4335,9 @@ fil_validate(void) for (i = 0; i < hash_get_n_cells(system->spaces); i++) { space = HASH_GET_FIRST(system->spaces, i); - + while (space != NULL) { - UT_LIST_VALIDATE(chain, fil_node_t, space->chain); + UT_LIST_VALIDATE(chain, fil_node_t, space->chain); fil_node = UT_LIST_GET_FIRST(space->chain); @@ -4270,7 +4369,7 @@ fil_validate(void) fil_node = UT_LIST_GET_NEXT(LRU, fil_node); } - + mutex_exit(&(system->mutex)); return(TRUE); @@ -4313,13 +4412,13 @@ Sets the file page type. */ void fil_page_set_type( /*==============*/ - byte* page, /* in: file page */ + byte* page, /* in: file page */ ulint type) /* in: type */ { ut_ad(page); mach_write_to_2(page + FIL_PAGE_TYPE, type); -} +} /************************************************************************* Gets the file page type. */ @@ -4329,7 +4428,7 @@ fil_page_get_type( /*==============*/ /* out: type; NOTE that if the type has not been written to page, the return value not defined */ - byte* page) /* in: file page */ + byte* page) /* in: file page */ { ut_ad(page); diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c index ad4228f6797..43c7ba005cb 100644 --- a/storage/innobase/fsp/fsp0fsp.c +++ b/storage/innobase/fsp/fsp0fsp.c @@ -33,9 +33,9 @@ Created 11/29/1995 Heikki Tuuri /* The data structures in files are defined just as byte strings in C */ typedef byte fsp_header_t; -typedef byte xdes_t; +typedef byte xdes_t; -/* SPACE HEADER +/* SPACE HEADER ============ File space header data structure: this data structure is contained in the @@ -92,7 +92,7 @@ descriptor page, but used only in the first. */ #define FSP_FREE_ADD 4 /* this many free extents are added to the free list from above FSP_FREE_LIMIT at a time */ - + /* FILE SEGMENT INODE ================== @@ -142,7 +142,7 @@ typedef byte fseg_inode_t; single page */ #define FSEG_MAGIC_N_VALUE 97937874 - + #define FSEG_FILLFACTOR 8 /* If this value is x, then if the number of unused but reserved pages in a segment is less than @@ -152,7 +152,7 @@ typedef byte fseg_inode_t; be added to the segment in fseg_alloc_free_page. Otherwise, we use unused pages of the segment. */ - + #define FSEG_FRAG_LIMIT FSEG_FRAG_ARR_N_SLOTS /* If the segment has >= this many used pages, it may be expanded by @@ -166,7 +166,7 @@ typedef byte fseg_inode_t; list of the extent: at most FSEG_FREE_LIST_MAX_LEN many */ #define FSEG_FREE_LIST_MAX_LEN 4 - + /* EXTENT DESCRIPTOR ================= @@ -186,7 +186,7 @@ the extent are free and which contain old tuple version to clean. */ /* Descriptor bitmap of the pages in the extent */ /*-------------------------------------*/ - + #define XDES_BITS_PER_PAGE 2 /* How many bits are there per page */ #define XDES_FREE_BIT 0 /* Index of the bit which tells if the page is free */ @@ -208,7 +208,7 @@ definition rounds the number of bytes upward. */ /* Offset of the descriptor array on a descriptor page */ #define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE) - + /************************************************************************** Returns an extent to the free list of a space. */ static @@ -236,7 +236,7 @@ ulint fseg_n_reserved_pages_low( /*======================*/ /* out: number of reserved pages */ - fseg_inode_t* header, /* in: segment inode */ + fseg_inode_t* header, /* in: segment inode */ ulint* used, /* out: number of pages used (<= reserved) */ mtr_t* mtr); /* in: mtr handle */ /************************************************************************ @@ -290,7 +290,7 @@ fseg_alloc_free_page_low( /* out: the allocated page number, FIL_NULL if no page could be allocated */ ulint space, /* in: space */ - fseg_inode_t* seg_inode, /* in: segment inode */ + fseg_inode_t* seg_inode, /* in: segment inode */ ulint hint, /* in: hint of which page would be desirable */ byte direction, /* in: if the new page is needed because of an index page split, and records are @@ -354,17 +354,17 @@ xdes_get_bit( MTR_MEMO_PAGE_X_FIX)); ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT)); ut_ad(offset < FSP_EXTENT_SIZE); - + index = bit + XDES_BITS_PER_PAGE * offset; byte_index = index / 8; bit_index = index % 8; - + return(ut_bit_get_nth( mtr_read_ulint(descr + XDES_BITMAP + byte_index, MLOG_1BYTE, mtr), - bit_index)); -} + bit_index)); +} /************************************************************************** Sets a descriptor bit of a page. */ @@ -383,7 +383,7 @@ xdes_set_bit( ulint byte_index; ulint bit_index; ulint descr_byte; - + ut_ad(mtr_memo_contains(mtr, buf_block_align(descr), MTR_MEMO_PAGE_X_FIX)); ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT)); @@ -400,7 +400,7 @@ xdes_set_bit( mlog_write_ulint(descr + XDES_BITMAP + byte_index, descr_byte, MLOG_1BYTE, mtr); -} +} /************************************************************************** Looks for a descriptor bit having the desired value. Starts from hint @@ -419,7 +419,7 @@ xdes_find_bit( mtr_t* mtr) /* in: mtr */ { ulint i; - + ut_ad(descr && mtr); ut_ad(val <= TRUE); ut_ad(hint < FSP_EXTENT_SIZE); @@ -438,9 +438,9 @@ xdes_find_bit( return(i); } } - - return(ULINT_UNDEFINED); -} + + return(ULINT_UNDEFINED); +} /************************************************************************** Looks for a descriptor bit having the desired value. Scans the extent in @@ -458,7 +458,7 @@ xdes_find_bit_downward( mtr_t* mtr) /* in: mtr */ { ulint i; - + ut_ad(descr && mtr); ut_ad(val <= TRUE); ut_ad(hint < FSP_EXTENT_SIZE); @@ -477,9 +477,9 @@ xdes_find_bit_downward( return(i); } } - - return(ULINT_UNDEFINED); -} + + return(ULINT_UNDEFINED); +} /************************************************************************** Returns the number of used pages in a descriptor. */ @@ -493,7 +493,7 @@ xdes_get_n_used( { ulint i; ulint count = 0; - + ut_ad(descr && mtr); ut_ad(mtr_memo_contains(mtr, buf_block_align(descr), MTR_MEMO_PAGE_X_FIX)); @@ -503,8 +503,8 @@ xdes_get_n_used( } } - return(count); -} + return(count); +} /************************************************************************** Returns true if extent contains no used pages. */ @@ -558,7 +558,7 @@ xdes_set_state( ut_ad(mtr_memo_contains(mtr, buf_block_align(descr), MTR_MEMO_PAGE_X_FIX)); - mlog_write_ulint(descr + XDES_STATE, state, MLOG_4BYTES, mtr); + mlog_write_ulint(descr + XDES_STATE, state, MLOG_4BYTES, mtr); } /************************************************************************** @@ -575,7 +575,7 @@ xdes_get_state( ut_ad(mtr_memo_contains(mtr, buf_block_align(descr), MTR_MEMO_PAGE_X_FIX)); - return(mtr_read_ulint(descr + XDES_STATE, MLOG_4BYTES, mtr)); + return(mtr_read_ulint(descr + XDES_STATE, MLOG_4BYTES, mtr)); } /************************************************************************** @@ -599,7 +599,7 @@ xdes_init( } xdes_set_state(descr, XDES_FREE, mtr); -} +} /************************************************************************ Calculates the page where the descriptor of a page resides. */ @@ -610,8 +610,10 @@ xdes_calc_descriptor_page( /* out: descriptor page offset */ ulint offset) /* in: page offset */ { - ut_ad(UNIV_PAGE_SIZE > XDES_ARR_OFFSET - + (XDES_DESCRIBED_PER_PAGE / FSP_EXTENT_SIZE) * XDES_SIZE); +#if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET \ + + (XDES_DESCRIBED_PER_PAGE / FSP_EXTENT_SIZE) * XDES_SIZE +# error +#endif return(ut_2pow_round(offset, XDES_DESCRIBED_PER_PAGE)); } @@ -644,7 +646,7 @@ xdes_get_descriptor_with_space_hdr( space or if offset > free limit */ fsp_header_t* sp_header,/* in: space header, x-latched */ ulint space, /* in: space id */ - ulint offset, /* in: page offset; + ulint offset, /* in: page offset; if equal to the free limit, we try to add new extents to the space free list */ @@ -687,10 +689,10 @@ xdes_get_descriptor_with_space_hdr( #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(descr_page, SYNC_FSP_PAGE); #endif /* UNIV_SYNC_DEBUG */ - } + } return(descr_page + XDES_ARR_OFFSET - + XDES_SIZE * xdes_calc_descriptor_index(offset)); + + XDES_SIZE * xdes_calc_descriptor_index(offset)); } /************************************************************************ @@ -718,7 +720,7 @@ xdes_get_descriptor( + buf_page_get(space, 0, RW_X_LATCH, mtr); #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(sp_header, SYNC_FSP_PAGE); -#endif /* UNIV_SYNC_DEBUG */ +#endif /* UNIV_SYNC_DEBUG */ return(xdes_get_descriptor_with_space_hdr(sp_header, space, offset, mtr)); } @@ -789,13 +791,13 @@ Inits a file page whose prior contents should be ignored. */ static void fsp_init_file_page_low( -/*=====================*/ +/*===================*/ byte* ptr) /* in: pointer to a page */ { page_t* page; page = buf_frame_align(ptr); - buf_block_align(page)->check_index_page_at_flush = FALSE; + buf_block_align(page)->check_index_page_at_flush = FALSE; #ifdef UNIV_BASIC_LOG_DEBUG memset(page, 0xff, UNIV_PAGE_SIZE); @@ -807,7 +809,6 @@ fsp_init_file_page_low( /*************************************************************** Inits a file page whose prior contents should be ignored. */ - static void fsp_init_file_page( @@ -816,10 +817,10 @@ fsp_init_file_page( mtr_t* mtr) /* in: mtr */ { fsp_init_file_page_low(page); - + mlog_write_initial_log_record(page, MLOG_INIT_FILE_PAGE, mtr); } - + /*************************************************************** Parses a redo log record of a file page init. */ @@ -836,7 +837,7 @@ fsp_parse_init_file_page( if (page) { fsp_init_file_page_low(page); } - + return(ptr); } @@ -872,11 +873,11 @@ fsp_header_init( /*============*/ ulint space, /* in: space id */ ulint size, /* in: current size in blocks */ - mtr_t* mtr) /* in: mini-transaction handle */ + mtr_t* mtr) /* in: mini-transaction handle */ { fsp_header_t* header; page_t* page; - + ut_ad(mtr); mtr_x_lock(fil_space_get_latch(space), mtr); @@ -891,22 +892,26 @@ fsp_header_init( fsp_init_file_page(page, mtr); + mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_FSP_HDR, + MLOG_2BYTES, mtr); + header = FSP_HEADER_OFFSET + page; mlog_write_ulint(header + FSP_SPACE_ID, space, MLOG_4BYTES, mtr); + mlog_write_ulint(header + FSP_NOT_USED, 0, MLOG_4BYTES, mtr); + + mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr); + mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr); + mlog_write_ulint(header + FSP_LOWEST_NO_WRITE, 0, MLOG_4BYTES, mtr); + mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr); - mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr); - mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr); - mlog_write_ulint(header + FSP_LOWEST_NO_WRITE, 0, MLOG_4BYTES, mtr); - mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr); - flst_init(header + FSP_FREE, mtr); flst_init(header + FSP_FREE_FRAG, mtr); flst_init(header + FSP_FULL_FRAG, mtr); flst_init(header + FSP_SEG_INODES_FULL, mtr); flst_init(header + FSP_SEG_INODES_FREE, mtr); - mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1), mtr); + mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1), mtr); if (space == 0) { fsp_fill_free_list(FALSE, space, header, mtr); btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, space, @@ -933,10 +938,10 @@ fsp_header_get_space_id( id = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); if (id != fsp_id) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: space id in fsp header %lu, but in the page header %lu\n", - (ulong) fsp_id, - (ulong) id); + (ulong) fsp_id, (ulong) id); + return(ULINT_UNDEFINED); } @@ -951,21 +956,21 @@ fsp_header_inc_size( /*================*/ ulint space, /* in: space id */ ulint size_inc,/* in: size increment in pages */ - mtr_t* mtr) /* in: mini-transaction handle */ + mtr_t* mtr) /* in: mini-transaction handle */ { fsp_header_t* header; ulint size; - + ut_ad(mtr); - mtr_x_lock(fil_space_get_latch(space), mtr); + mtr_x_lock(fil_space_get_latch(space), mtr); header = fsp_get_space_header(space, mtr); size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); mlog_write_ulint(header + FSP_SIZE, size + size_inc, MLOG_4BYTES, - mtr); + mtr); } /************************************************************************** @@ -985,17 +990,17 @@ fsp_header_get_free_limit( mtr_t mtr; ut_a(space == 0); /* We have only one log_fsp_current_... variable */ - + mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); header = fsp_get_space_header(space, &mtr); limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, &mtr); limit = limit / ((1024 * 1024) / UNIV_PAGE_SIZE); - + log_fsp_current_free_limit_set_and_checkpoint(limit); mtr_commit(&mtr); @@ -1019,10 +1024,10 @@ fsp_header_get_tablespace_size( mtr_t mtr; ut_a(space == 0); /* We have only one log_fsp_current_... variable */ - + mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); header = fsp_get_space_header(space, &mtr); @@ -1053,14 +1058,14 @@ fsp_try_extend_data_file_with_pages( ut_a(space != 0); size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); - + ut_a(page_no >= size); success = fil_extend_space_to_desired_size(&actual_size, space, page_no + 1); /* actual_size now has the space size in pages; it may be less than we wanted if we ran out of disk space */ - + mlog_write_ulint(header + FSP_SIZE, actual_size, MLOG_4BYTES, mtr); return(success); @@ -1116,10 +1121,10 @@ fsp_try_extend_data_file( size_increase = SRV_AUTO_EXTEND_INCREMENT; } } else { - if (space == 0) { + if (space == 0) { size_increase = SRV_AUTO_EXTEND_INCREMENT; } else { - /* We extend single-table tablespaces first one extent + /* We extend single-table tablespaces first one extent at a time, but for bigger tablespaces more. It is not enough to extend always by one extent, because some extents are frag page extents. */ @@ -1135,14 +1140,14 @@ fsp_try_extend_data_file( *actual_increase = new_size - old_size; - return(FALSE); + return(FALSE); } size = FSP_EXTENT_SIZE; } if (size < 32 * FSP_EXTENT_SIZE) { - size_increase = FSP_EXTENT_SIZE; + size_increase = FSP_EXTENT_SIZE; } else { /* Below in fsp_fill_free_list() we assume that we add at most FSP_FREE_ADD extents at @@ -1151,18 +1156,18 @@ fsp_try_extend_data_file( } } } - + if (size_increase == 0) { return(TRUE); } - + success = fil_extend_space_to_desired_size(&actual_size, space, size + size_increase); /* We ignore any fragments of a full megabyte when storing the size to the space header */ - mlog_write_ulint(header + FSP_SIZE, + mlog_write_ulint(header + FSP_SIZE, ut_calc_align_down(actual_size, (1024 * 1024) / UNIV_PAGE_SIZE), MLOG_4BYTES, mtr); new_size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); @@ -1192,7 +1197,7 @@ fsp_fill_free_list( ulint limit; ulint size; xdes_t* descr; - ulint count = 0; + ulint count = 0; ulint frag_n_used; page_t* descr_page; page_t* ibuf_page; @@ -1201,7 +1206,7 @@ fsp_fill_free_list( mtr_t ibuf_mtr; ut_ad(header && mtr); - + /* Check if we can fill free list from above the free list limit */ size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr); @@ -1223,17 +1228,17 @@ fsp_fill_free_list( } i = limit; - + while ((init_space && i < 1) - || ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) { + || ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) { mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE, - MLOG_4BYTES, mtr); + MLOG_4BYTES, mtr); /* Update the free limit info in the log system and make a checkpoint */ if (space == 0) { - log_fsp_current_free_limit_set_and_checkpoint( + log_fsp_current_free_limit_set_and_checkpoint( (i + FSP_EXTENT_SIZE) / ((1024 * 1024) / UNIV_PAGE_SIZE)); } @@ -1252,13 +1257,15 @@ fsp_fill_free_list( SYNC_FSP_PAGE); #endif /* UNIV_SYNC_DEBUG */ fsp_init_file_page(descr_page, mtr); + mlog_write_ulint(descr_page + FIL_PAGE_TYPE, + FIL_PAGE_TYPE_XDES, MLOG_2BYTES, mtr); } /* Initialize the ibuf bitmap page in a separate mini-transaction because it is low in the latching order, and we must be able to release its latch before returning from the fsp routine */ - + mtr_start(&ibuf_mtr); ibuf_page = buf_page_create(space, @@ -1279,7 +1286,9 @@ fsp_fill_free_list( mtr); xdes_init(descr, mtr); - ut_ad(XDES_DESCRIBED_PER_PAGE % FSP_EXTENT_SIZE == 0); +#if XDES_DESCRIBED_PER_PAGE % FSP_EXTENT_SIZE +# error "XDES_DESCRIBED_PER_PAGE % FSP_EXTENT_SIZE != 0" +#endif if (0 == i % XDES_DESCRIBED_PER_PAGE) { @@ -1289,24 +1298,24 @@ fsp_fill_free_list( xdes_set_bit(descr, XDES_FREE_BIT, 0, FALSE, mtr); xdes_set_bit(descr, XDES_FREE_BIT, - FSP_IBUF_BITMAP_OFFSET, FALSE, mtr); + FSP_IBUF_BITMAP_OFFSET, FALSE, mtr); xdes_set_state(descr, XDES_FREE_FRAG, mtr); flst_add_last(header + FSP_FREE_FRAG, - descr + XDES_FLST_NODE, mtr); + descr + XDES_FLST_NODE, mtr); frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, - MLOG_4BYTES, mtr); + MLOG_4BYTES, mtr); mlog_write_ulint(header + FSP_FRAG_N_USED, - frag_n_used + 2, MLOG_4BYTES, mtr); + frag_n_used + 2, MLOG_4BYTES, mtr); } else { flst_add_last(header + FSP_FREE, - descr + XDES_FLST_NODE, mtr); + descr + XDES_FLST_NODE, mtr); count++; } i += FSP_EXTENT_SIZE; } -} +} /************************************************************************** Allocates a new free extent. */ @@ -1325,7 +1334,7 @@ fsp_alloc_free_extent( fsp_header_t* header; fil_addr_t first; xdes_t* descr; - + ut_ad(mtr); header = fsp_get_space_header(space, mtr); @@ -1334,7 +1343,7 @@ fsp_alloc_free_extent( if (descr && (xdes_get_state(descr, mtr) == XDES_FREE)) { /* Ok, we can take this extent */ - } else { + } else { /* Take the first extent in the free list */ first = flst_get_first(header + FSP_FREE, mtr); @@ -1348,7 +1357,7 @@ fsp_alloc_free_extent( return(NULL); /* No free extents left */ } - + descr = xdes_lst_get_descriptor(space, first, mtr); } @@ -1378,7 +1387,7 @@ fsp_alloc_free_page( ulint page_no; ulint space_size; ibool success; - + ut_ad(mtr); header = fsp_get_space_header(space, mtr); @@ -1399,7 +1408,7 @@ fsp_alloc_free_page( extent containing a descriptor page is added to the FREE_FRAG list. But we will allocate our page from the the free extent anyway. */ - + descr = fsp_alloc_free_extent(space, hint, mtr); if (descr == NULL) { @@ -1436,22 +1445,22 @@ fsp_alloc_free_page( space_size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); if (space_size <= page_no) { - /* It must be that we are extending a single-table tablespace + /* It must be that we are extending a single-table tablespace whose size is still < 64 pages */ ut_a(space != 0); if (page_no >= FSP_EXTENT_SIZE) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: trying to extend a single-table tablespace %lu\n" "InnoDB: by single page(s) though the space size %lu. Page no %lu.\n", (ulong) space, (ulong) space_size, (ulong) page_no); return(FIL_NULL); } success = fsp_try_extend_data_file_with_pages(space, page_no, - header, mtr); + header, mtr); if (!success) { /* No disk space left */ - return(FIL_NULL); + return(FIL_NULL); } } @@ -1468,7 +1477,7 @@ fsp_alloc_free_page( flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, mtr); xdes_set_state(descr, XDES_FULL_FRAG, mtr); - + flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE, mtr); mlog_write_ulint(header + FSP_FRAG_N_USED, @@ -1479,17 +1488,17 @@ fsp_alloc_free_page( /* Initialize the allocated page to the buffer pool, so that it can be obtained immediately with buf_page_get without need for a disk read. */ - + buf_page_create(space, page_no, mtr); - page = buf_page_get(space, page_no, RW_X_LATCH, mtr); + page = buf_page_get(space, page_no, RW_X_LATCH, mtr); #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_FSP_PAGE); #endif /* UNIV_SYNC_DEBUG */ /* Prior contents of the page should be ignored */ fsp_init_file_page(page, mtr); - + return(page_no); } @@ -1507,7 +1516,7 @@ fsp_free_page( xdes_t* descr; ulint state; ulint frag_n_used; - + ut_ad(mtr); /* fprintf(stderr, "Freeing page %lu in space %lu\n", page, space); */ @@ -1517,7 +1526,7 @@ fsp_free_page( descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr); state = xdes_get_state(descr, mtr); - + if (state != XDES_FREE_FRAG && state != XDES_FULL_FRAG) { fprintf(stderr, "InnoDB: Error: File space extent descriptor of page %lu has state %lu\n", @@ -1526,7 +1535,7 @@ fsp_free_page( fputs("InnoDB: Dump of descriptor: ", stderr); ut_print_buf(stderr, ((byte*)descr) - 50, 200); putc('\n', stderr); - + if (state == XDES_FREE) { /* We put here some fault tolerance: if the page is already free, return without doing anything! */ @@ -1572,11 +1581,11 @@ fsp_free_page( } if (xdes_is_free(descr, mtr)) { - /* The extent has become free: move it to another list */ + /* The extent has become free: move it to another list */ flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, mtr); fsp_free_extent(space, page, mtr); - } + } } /************************************************************************** @@ -1591,7 +1600,7 @@ fsp_free_extent( { fsp_header_t* header; xdes_t* descr; - + ut_ad(mtr); header = fsp_get_space_header(space, mtr); @@ -1629,7 +1638,7 @@ fsp_seg_inode_page_get_nth_inode( } /************************************************************************** -Looks for a used segment inode on a segment inode page. */ +Looks for a used segment inode on a segment inode page. */ static ulint fsp_seg_inode_page_find_used( @@ -1649,7 +1658,7 @@ fsp_seg_inode_page_find_used( if (ut_dulint_cmp(mach_read_from_8(inode + FSEG_ID), ut_dulint_zero) != 0) { /* This is used */ - + return(i); } } @@ -1658,7 +1667,7 @@ fsp_seg_inode_page_find_used( } /************************************************************************** -Looks for an unused segment inode on a segment inode page. */ +Looks for an unused segment inode on a segment inode page. */ static ulint fsp_seg_inode_page_find_free( @@ -1679,7 +1688,7 @@ fsp_seg_inode_page_find_free( if (ut_dulint_cmp(mach_read_from_8(inode + FSEG_ID), ut_dulint_zero) == 0) { /* This is unused */ - + return(i); } } @@ -1704,7 +1713,7 @@ fsp_alloc_seg_inode_page( ulint i; space = buf_frame_get_space_id(space_header); - + page_no = fsp_alloc_free_page(space, 0, mtr); if (page_no == FIL_NULL) { @@ -1712,11 +1721,12 @@ fsp_alloc_seg_inode_page( return(FALSE); } - page = buf_page_get(space, page_no, RW_X_LATCH, mtr); + page = buf_page_get(space, page_no, RW_X_LATCH, mtr); buf_block_align(page)->check_index_page_at_flush = FALSE; - fil_page_set_type(page, FIL_PAGE_INODE); + mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_INODE, + MLOG_2BYTES, mtr); #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_FSP_PAGE); #endif /* UNIV_SYNC_DEBUG */ @@ -1749,7 +1759,7 @@ fsp_alloc_seg_inode( fseg_inode_t* inode; ibool success; ulint n; - + if (flst_get_len(space_header + FSP_SEG_INODES_FREE, mtr) == 0) { /* Allocate a new segment inode page */ @@ -1776,7 +1786,7 @@ fsp_alloc_seg_inode( inode = fsp_seg_inode_page_get_nth_inode(page, n, mtr); if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, n + 1, - mtr)) { + mtr)) { /* There are no other unused headers left on the page: move it to another list */ @@ -1787,7 +1797,7 @@ fsp_alloc_seg_inode( page + FSEG_INODE_PAGE_NODE, mtr); } - return(inode); + return(inode); } /************************************************************************** @@ -1802,7 +1812,7 @@ fsp_free_seg_inode( { page_t* page; fsp_header_t* space_header; - + page = buf_frame_align(inode); space_header = fsp_get_space_header(space, mtr); @@ -1820,9 +1830,9 @@ fsp_free_seg_inode( page + FSEG_INODE_PAGE_NODE, mtr); } - mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr); - mlog_write_ulint(inode + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr); - + mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr); + mlog_write_ulint(inode + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr); + if (ULINT_UNDEFINED == fsp_seg_inode_page_find_used(page, mtr)) { /* There are no other used headers left on the page: free it */ @@ -1849,10 +1859,10 @@ fseg_inode_get( inode_addr.page = mach_read_from_4(header + FSEG_HDR_PAGE_NO); inode_addr.boffset = mach_read_from_2(header + FSEG_HDR_OFFSET); - + inode = fut_get_ptr(mach_read_from_4(header + FSEG_HDR_SPACE), inode_addr, RW_X_LATCH, mtr); - + ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); return(inode); @@ -1865,7 +1875,7 @@ ulint fseg_get_nth_frag_page_no( /*======================*/ /* out: page number, FIL_NULL if not in use */ - fseg_inode_t* inode, /* in: segment inode */ + fseg_inode_t* inode, /* in: segment inode */ ulint n, /* in: slot index */ mtr_t* mtr __attribute__((unused))) /* in: mtr handle */ { @@ -1883,7 +1893,7 @@ UNIV_INLINE void fseg_set_nth_frag_page_no( /*======================*/ - fseg_inode_t* inode, /* in: segment inode */ + fseg_inode_t* inode, /* in: segment inode */ ulint n, /* in: slot index */ ulint page_no,/* in: page number to set */ mtr_t* mtr) /* in: mtr handle */ @@ -1905,7 +1915,7 @@ fseg_find_free_frag_page_slot( /*==========================*/ /* out: slot index; ULINT_UNDEFINED if none found */ - fseg_inode_t* inode, /* in: segment inode */ + fseg_inode_t* inode, /* in: segment inode */ mtr_t* mtr) /* in: mtr handle */ { ulint i; @@ -1933,7 +1943,7 @@ fseg_find_last_used_frag_page_slot( /*===============================*/ /* out: slot index; ULINT_UNDEFINED if none found */ - fseg_inode_t* inode, /* in: segment inode */ + fseg_inode_t* inode, /* in: segment inode */ mtr_t* mtr) /* in: mtr handle */ { ulint i; @@ -1961,7 +1971,7 @@ ulint fseg_get_n_frag_pages( /*==================*/ /* out: number of fragment pages */ - fseg_inode_t* inode, /* in: segment inode */ + fseg_inode_t* inode, /* in: segment inode */ mtr_t* mtr) /* in: mtr handle */ { ulint i; @@ -2017,16 +2027,16 @@ fseg_create_general( if (page != 0) { header = byte_offset + buf_page_get(space, page, RW_X_LATCH, mtr); - } - + } + #ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&kernel_mutex) - || mtr_memo_contains(mtr, fil_space_get_latch(space), - MTR_MEMO_X_LOCK)); + || mtr_memo_contains(mtr, fil_space_get_latch(space), + MTR_MEMO_X_LOCK)); #endif /* UNIV_SYNC_DEBUG */ latch = fil_space_get_latch(space); - mtr_x_lock(latch, mtr); + mtr_x_lock(latch, mtr); if (rw_lock_get_x_lock_count(latch) == 1) { /* This thread did not own the latch before this call: free @@ -2037,7 +2047,7 @@ fseg_create_general( } } - if (!has_done_reservation) { + if (!has_done_reservation) { success = fsp_reserve_free_extents(&n_reserved, space, 2, FSP_NORMAL, mtr); if (!success) { @@ -2062,22 +2072,22 @@ fseg_create_general( mlog_write_dulint(space_header + FSP_SEG_ID, ut_dulint_add(seg_id, 1), mtr); - mlog_write_dulint(inode + FSEG_ID, seg_id, mtr); - mlog_write_ulint(inode + FSEG_NOT_FULL_N_USED, 0, MLOG_4BYTES, mtr); + mlog_write_dulint(inode + FSEG_ID, seg_id, mtr); + mlog_write_ulint(inode + FSEG_NOT_FULL_N_USED, 0, MLOG_4BYTES, mtr); flst_init(inode + FSEG_FREE, mtr); flst_init(inode + FSEG_NOT_FULL, mtr); flst_init(inode + FSEG_FULL, mtr); mlog_write_ulint(inode + FSEG_MAGIC_N, FSEG_MAGIC_N_VALUE, - MLOG_4BYTES, mtr); + MLOG_4BYTES, mtr); for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) { fseg_set_nth_frag_page_no(inode, i, FIL_NULL, mtr); } if (page == 0) { page = fseg_alloc_free_page_low(space, inode, 0, FSP_UP, mtr); - + if (page == FIL_NULL) { fsp_free_seg_inode(space, inode, mtr); @@ -2087,7 +2097,9 @@ fseg_create_general( header = byte_offset + buf_page_get(space, page, RW_X_LATCH, mtr); - } + mlog_write_ulint(header - byte_offset + FIL_PAGE_TYPE, + FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr); + } mlog_write_ulint(header + FSEG_HDR_OFFSET, inode - buf_frame_align(inode), MLOG_2BYTES, mtr); @@ -2100,11 +2112,11 @@ fseg_create_general( ret = buf_frame_align(header); funct_exit: - if (!has_done_reservation) { - + if (!has_done_reservation) { + fil_space_release_free_extents(space, n_reserved); } - + return(ret); } @@ -2137,7 +2149,7 @@ ulint fseg_n_reserved_pages_low( /*======================*/ /* out: number of reserved pages */ - fseg_inode_t* inode, /* in: segment inode */ + fseg_inode_t* inode, /* in: segment inode */ ulint* used, /* out: number of pages used (<= reserved) */ mtr_t* mtr) /* in: mtr handle */ { @@ -2146,7 +2158,7 @@ fseg_n_reserved_pages_low( ut_ad(inode && used && mtr); ut_ad(mtr_memo_contains(mtr, buf_block_align(inode), MTR_MEMO_PAGE_X_FIX)); - + *used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED, MLOG_4BYTES, mtr) + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL, mtr) + fseg_get_n_frag_pages(inode, mtr); @@ -2167,7 +2179,7 @@ ulint fseg_n_reserved_pages( /*==================*/ /* out: number of reserved pages */ - fseg_header_t* header, /* in: segment header */ + fseg_header_t* header, /* in: segment header */ ulint* used, /* out: number of pages used (<= reserved) */ mtr_t* mtr) /* in: mtr handle */ { @@ -2179,13 +2191,13 @@ fseg_n_reserved_pages( #ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&kernel_mutex) - || mtr_memo_contains(mtr, fil_space_get_latch(space), - MTR_MEMO_X_LOCK)); + || mtr_memo_contains(mtr, fil_space_get_latch(space), + MTR_MEMO_X_LOCK)); #endif /* UNIV_SYNC_DEBUG */ - mtr_x_lock(fil_space_get_latch(space), mtr); + mtr_x_lock(fil_space_get_latch(space), mtr); inode = fseg_inode_get(header, mtr); - + ret = fseg_n_reserved_pages_low(inode, used, mtr); return(ret); @@ -2211,7 +2223,7 @@ fseg_fill_free_list( dulint seg_id; ulint reserved; ulint used; - + ut_ad(inode && mtr); reserved = fseg_n_reserved_pages_low(inode, &used, mtr); @@ -2228,22 +2240,22 @@ fseg_fill_free_list( return; } - + for (i = 0; i < FSEG_FREE_LIST_MAX_LEN; i++) { descr = xdes_get_descriptor(space, hint, mtr); if ((descr == NULL) || - (XDES_FREE != xdes_get_state(descr, mtr))) { + (XDES_FREE != xdes_get_state(descr, mtr))) { /* We cannot allocate the desired extent: stop */ - return; + return; } descr = fsp_alloc_free_extent(space, hint, mtr); - + xdes_set_state(descr, XDES_FSEG, mtr); - + seg_id = mtr_read_dulint(inode + FSEG_ID, mtr); mlog_write_dulint(descr + XDES_ID, seg_id, mtr); @@ -2269,11 +2281,11 @@ fseg_alloc_free_extent( { xdes_t* descr; dulint seg_id; - fil_addr_t first; - + fil_addr_t first; + if (flst_get_len(inode + FSEG_FREE, mtr) > 0) { /* Segment free list is not empty, allocate from it */ - + first = flst_get_first(inode + FSEG_FREE, mtr); descr = xdes_lst_get_descriptor(space, first, mtr); @@ -2287,11 +2299,11 @@ fseg_alloc_free_extent( } seg_id = mtr_read_dulint(inode + FSEG_ID, mtr); - + xdes_set_state(descr, XDES_FSEG, mtr); mlog_write_dulint(descr + XDES_ID, seg_id, mtr); flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr); - + /* Try to fill the segment free list */ fseg_fill_free_list(inode, space, xdes_get_offset(descr) + FSP_EXTENT_SIZE, mtr); @@ -2311,7 +2323,7 @@ fseg_alloc_free_page_low( /* out: the allocated page number, FIL_NULL if no page could be allocated */ ulint space, /* in: space */ - fseg_inode_t* seg_inode, /* in: segment inode */ + fseg_inode_t* seg_inode, /* in: segment inode */ ulint hint, /* in: hint of which page would be desirable */ byte direction, /* in: if the new page is needed because of an index page split, and records are @@ -2333,7 +2345,7 @@ fseg_alloc_free_page_low( ibool frag_page_allocated = FALSE; ibool success; ulint n; - + ut_ad(mtr); ut_ad((direction >= FSP_UP) && (direction <= FSP_NO_DIR)); ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == @@ -2341,33 +2353,33 @@ fseg_alloc_free_page_low( seg_id = mtr_read_dulint(seg_inode + FSEG_ID, mtr); ut_ad(ut_dulint_cmp(seg_id, ut_dulint_zero) > 0); - + reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr); - + space_header = fsp_get_space_header(space, mtr); descr = xdes_get_descriptor_with_space_hdr(space_header, space, - hint, mtr); + hint, mtr); if (descr == NULL) { /* Hint outside space or too high above free limit: reset hint */ hint = 0; descr = xdes_get_descriptor(space, hint, mtr); } - + /* In the big if-else below we look for ret_page and ret_descr */ - /*-------------------------------------------------------------*/ + /*-------------------------------------------------------------*/ if ((xdes_get_state(descr, mtr) == XDES_FSEG) - && (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, + && (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, mtr), seg_id)) - && (xdes_get_bit(descr, XDES_FREE_BIT, + && (xdes_get_bit(descr, XDES_FREE_BIT, hint % FSP_EXTENT_SIZE, mtr) == TRUE)) { /* 1. We can take the hinted page =================================*/ ret_descr = descr; ret_page = hint; - /*-------------------------------------------------------------*/ + /*-------------------------------------------------------------*/ } else if ((xdes_get_state(descr, mtr) == XDES_FREE) && ((reserved - used) < reserved / FSEG_FILLFACTOR) && (used >= FSEG_FRAG_LIMIT)) { @@ -2379,7 +2391,7 @@ fseg_alloc_free_page_low( ret_descr = fsp_alloc_free_extent(space, hint, mtr); ut_a(ret_descr == descr); - + xdes_set_state(ret_descr, XDES_FSEG, mtr); mlog_write_dulint(ret_descr + XDES_ID, seg_id, mtr); flst_add_last(seg_inode + FSEG_FREE, @@ -2389,7 +2401,7 @@ fseg_alloc_free_page_low( fseg_fill_free_list(seg_inode, space, hint + FSP_EXTENT_SIZE, mtr); ret_page = hint; - /*-------------------------------------------------------------*/ + /*-------------------------------------------------------------*/ } else if ((direction != FSP_NO_DIR) && ((reserved - used) < reserved / FSEG_FILLFACTOR) && (used >= FSEG_FRAG_LIMIT) @@ -2402,16 +2414,16 @@ fseg_alloc_free_page_low( ======================================================== highest page in it, depending on the direction ==============================================*/ - ret_page = xdes_get_offset(ret_descr); + ret_page = xdes_get_offset(ret_descr); if (direction == FSP_DOWN) { ret_page += FSP_EXTENT_SIZE - 1; } - /*-------------------------------------------------------------*/ + /*-------------------------------------------------------------*/ } else if ((xdes_get_state(descr, mtr) == XDES_FSEG) - && (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, + && (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, mtr), seg_id)) - && (!xdes_is_full(descr, mtr))) { + && (!xdes_is_full(descr, mtr))) { /* 4. We can take the page from the same extent as the ====================================================== @@ -2423,7 +2435,7 @@ fseg_alloc_free_page_low( ret_page = xdes_get_offset(ret_descr) + xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE, hint % FSP_EXTENT_SIZE, mtr); - /*-------------------------------------------------------------*/ + /*-------------------------------------------------------------*/ } else if (reserved - used > 0) { /* 5. We take any unused page from the segment ==============================================*/ @@ -2443,15 +2455,15 @@ fseg_alloc_free_page_low( ret_page = xdes_get_offset(ret_descr) + xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE, 0, mtr); - /*-------------------------------------------------------------*/ + /*-------------------------------------------------------------*/ } else if (used < FSEG_FRAG_LIMIT) { /* 6. We allocate an individual page from the space ===================================================*/ ret_page = fsp_alloc_free_page(space, hint, mtr); ret_descr = NULL; - + frag_page_allocated = TRUE; - + if (ret_page != FIL_NULL) { /* Put the page in the fragment page array of the segment */ @@ -2461,7 +2473,7 @@ fseg_alloc_free_page_low( fseg_set_nth_frag_page_no(seg_inode, n, ret_page, mtr); } - /*-------------------------------------------------------------*/ + /*-------------------------------------------------------------*/ } else { /* 7. We allocate a new extent and take its first page ======================================================*/ @@ -2471,12 +2483,12 @@ fseg_alloc_free_page_low( ret_page = FIL_NULL; } else { ret_page = xdes_get_offset(ret_descr); - } + } } - + if (ret_page == FIL_NULL) { /* Page could not be allocated */ - + return(FIL_NULL); } @@ -2484,18 +2496,18 @@ fseg_alloc_free_page_low( space_size = fil_space_get_size(space); if (space_size <= ret_page) { - /* It must be that we are extending a single-table + /* It must be that we are extending a single-table tablespace whose size is still < 64 pages */ if (ret_page >= FSP_EXTENT_SIZE) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error (2): trying to extend a single-table tablespace %lu\n" "InnoDB: by single page(s) though the space size %lu. Page no %lu.\n", (ulong) space, (ulong) space_size, (ulong) ret_page); return(FIL_NULL); } - + success = fsp_try_extend_data_file_with_pages(space, ret_page, space_header, mtr); if (!success) { @@ -2509,7 +2521,7 @@ fseg_alloc_free_page_low( /* Initialize the allocated page to buffer pool, so that it can be obtained immediately with buf_page_get without need for a disk read */ - + page = buf_page_create(space, ret_page, mtr); ut_a(page == buf_page_get(space, ret_page, RW_X_LATCH, mtr)); @@ -2520,21 +2532,21 @@ fseg_alloc_free_page_low( /* The prior contents of the page should be ignored */ fsp_init_file_page(page, mtr); - + /* At this point we know the extent and the page offset. The extent is still in the appropriate list (FSEG_NOT_FULL or FSEG_FREE), and the page is not yet marked as used. */ - + ut_ad(xdes_get_descriptor(space, ret_page, mtr) == ret_descr); ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT, ret_page % FSP_EXTENT_SIZE, mtr) == TRUE); - + fseg_mark_page_used(seg_inode, space, ret_page, mtr); } buf_reset_check_index_page_at_flush(space, ret_page); - - return(ret_page); + + return(ret_page); } /************************************************************************** @@ -2572,19 +2584,19 @@ fseg_alloc_free_page_general( #ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&kernel_mutex) - || mtr_memo_contains(mtr, fil_space_get_latch(space), - MTR_MEMO_X_LOCK)); + || mtr_memo_contains(mtr, fil_space_get_latch(space), + MTR_MEMO_X_LOCK)); #endif /* UNIV_SYNC_DEBUG */ latch = fil_space_get_latch(space); - mtr_x_lock(latch, mtr); - + mtr_x_lock(latch, mtr); + if (rw_lock_get_x_lock_count(latch) == 1) { /* This thread did not own the latch before this call: free excess pages from the insert buffer free list */ if (space == 0) { - ibuf_free_excess_pages(space); + ibuf_free_excess_pages(space); } } @@ -2642,7 +2654,7 @@ fsp_reserve_free_pages( /*===================*/ /* out: TRUE if there were >= 3 free pages, or we were able to extend */ - ulint space, /* in: space id, must be != 0 */ + ulint space, /* in: space id, must be != 0 */ fsp_header_t* space_header, /* in: header of that space, x-latched */ ulint size, /* in: size of the tablespace in pages, @@ -2719,11 +2731,11 @@ fsp_reserve_free_extents( ibool success; ulint n_pages_added; - ut_ad(mtr); + ut_ad(mtr); #ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&kernel_mutex) - || mtr_memo_contains(mtr, fil_space_get_latch(space), - MTR_MEMO_X_LOCK)); + || mtr_memo_contains(mtr, fil_space_get_latch(space), + MTR_MEMO_X_LOCK)); #endif /* UNIV_SYNC_DEBUG */ *n_reserved = n_ext; @@ -2734,7 +2746,7 @@ fsp_reserve_free_extents( space_header = fsp_get_space_header(space, mtr); try_again: size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, mtr); - + if (size < FSP_EXTENT_SIZE / 2) { /* Use different rules for small single-table tablespaces */ *n_reserved = 0; @@ -2742,7 +2754,7 @@ try_again: } n_free_list_ext = flst_get_len(space_header + FSP_FREE, mtr); - + free_limit = mtr_read_ulint(space_header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr); @@ -2757,7 +2769,7 @@ try_again: n_free_up = n_free_up - n_free_up / (XDES_DESCRIBED_PER_PAGE / FSP_EXTENT_SIZE); } - + n_free = n_free_list_ext + n_free_up; if (alloc_type == FSP_NORMAL) { @@ -2821,12 +2833,12 @@ fsp_get_available_space_in_free_extents( ulint reserve; rw_lock_t* latch; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ mtr_start(&mtr); - + latch = fil_space_get_latch(space); mtr_x_lock(latch, &mtr); @@ -2834,20 +2846,21 @@ fsp_get_available_space_in_free_extents( space_header = fsp_get_space_header(space, &mtr); size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, &mtr); - + n_free_list_ext = flst_get_len(space_header + FSP_FREE, &mtr); - + free_limit = mtr_read_ulint(space_header + FSP_FREE_LIMIT, MLOG_4BYTES, &mtr); mtr_commit(&mtr); if (size < FSP_EXTENT_SIZE) { - ut_a(space != 0); /* This must be a single-table - tablespace */ - return(0); /* TODO: count free frag pages and return - a value based on that */ + ut_a(space != 0); /* This must be a single-table + tablespace */ + + return(0); /* TODO: count free frag pages and + return a value based on that */ } - + /* Below we play safe when counting free extents above the free limit: some of them will contain extent descriptor pages, and therefore will not be free extents */ @@ -2859,7 +2872,7 @@ fsp_get_available_space_in_free_extents( n_free_up = n_free_up - n_free_up / (XDES_DESCRIBED_PER_PAGE / FSP_EXTENT_SIZE); } - + n_free = n_free_list_ext + n_free_up; /* We reserve 1 extent + 0.5 % of the space size to undo logs @@ -2875,7 +2888,7 @@ fsp_get_available_space_in_free_extents( return(((n_free - reserve) * FSP_EXTENT_SIZE) * (UNIV_PAGE_SIZE / 1024)); } - + /************************************************************************ Marks a page used. The page must reside within the extents of the given segment. */ @@ -2892,9 +2905,9 @@ fseg_mark_page_used( ulint not_full_n_used; ut_ad(seg_inode && mtr); - + descr = xdes_get_descriptor(space, page, mtr); - + ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr) == mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr)); @@ -2924,7 +2937,7 @@ fseg_mark_page_used( descr + XDES_FLST_NODE, mtr); flst_add_last(seg_inode + FSEG_FULL, descr + XDES_FLST_NODE, mtr); - + mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED, not_full_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES, mtr); @@ -2948,7 +2961,7 @@ fseg_free_page_low( dulint descr_id; dulint seg_id; ulint i; - + ut_ad(seg_inode && mtr); ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); @@ -2979,7 +2992,7 @@ fseg_free_page_low( "InnoDB: about forcing recovery.\n", stderr); ut_error; } - + state = xdes_get_state(descr, mtr); if (state != XDES_FSEG) { @@ -2987,7 +3000,7 @@ fseg_free_page_low( for (i = 0;; i++) { if (fseg_get_nth_frag_page_no(seg_inode, i, mtr) - == page) { + == page) { fseg_set_nth_frag_page_no(seg_inode, i, FIL_NULL, mtr); @@ -2996,11 +3009,11 @@ fseg_free_page_low( } fsp_free_page(space, page, mtr); - + return; } - /* If we get here, the page is in some extent of the segment */ + /* If we get here, the page is in some extent of the segment */ descr_id = mtr_read_dulint(descr + XDES_ID, mtr); seg_id = mtr_read_dulint(seg_inode + FSEG_ID, mtr); @@ -3023,7 +3036,7 @@ fseg_free_page_low( ut_print_buf(stderr, seg_inode, 40); putc('\n', stderr); - fprintf(stderr, + fprintf(stderr, "InnoDB: Serious error: InnoDB is trying to free space %lu page %lu,\n" "InnoDB: which does not belong to segment %lu %lu but belongs\n" "InnoDB: to segment %lu %lu.\n", @@ -3056,11 +3069,11 @@ fseg_free_page_low( xdes_set_bit(descr, XDES_CLEAN_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr); if (xdes_is_free(descr, mtr)) { - /* The extent has become free: free it to space */ + /* The extent has become free: free it to space */ flst_remove(seg_inode + FSEG_NOT_FULL, descr + XDES_FLST_NODE, mtr); fsp_free_extent(space, page, mtr); - } + } } /************************************************************************** @@ -3078,10 +3091,10 @@ fseg_free_page( #ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&kernel_mutex) - || mtr_memo_contains(mtr, fil_space_get_latch(space), - MTR_MEMO_X_LOCK)); + || mtr_memo_contains(mtr, fil_space_get_latch(space), + MTR_MEMO_X_LOCK)); #endif /* UNIV_SYNC_DEBUG */ - mtr_x_lock(fil_space_get_latch(space), mtr); + mtr_x_lock(fil_space_get_latch(space), mtr); seg_inode = fseg_inode_get(seg_header, mtr); @@ -3108,7 +3121,7 @@ fseg_free_extent( ulint not_full_n_used; ulint descr_n_used; ulint i; - + ut_ad(seg_inode && mtr); descr = xdes_get_descriptor(space, page, mtr); @@ -3116,10 +3129,10 @@ fseg_free_extent( ut_a(xdes_get_state(descr, mtr) == XDES_FSEG); ut_a(0 == ut_dulint_cmp( mtr_read_dulint(descr + XDES_ID, mtr), - mtr_read_dulint(seg_inode + FSEG_ID, mtr))); + mtr_read_dulint(seg_inode + FSEG_ID, mtr))); first_page_in_extent = page - (page % FSP_EXTENT_SIZE); - + for (i = 0; i < FSP_EXTENT_SIZE; i++) { if (FALSE == xdes_get_bit(descr, XDES_FREE_BIT, i, mtr)) { @@ -3157,7 +3170,7 @@ fseg_free_extent( #ifdef UNIV_DEBUG_FILE_ACCESSES for (i = 0; i < FSP_EXTENT_SIZE; i++) { - buf_page_set_file_page_was_freed(space, + buf_page_set_file_page_was_freed(space, first_page_in_extent + i); } #endif @@ -3189,10 +3202,10 @@ fseg_free_step( #ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&kernel_mutex) - || mtr_memo_contains(mtr, fil_space_get_latch(space), - MTR_MEMO_X_LOCK)); + || mtr_memo_contains(mtr, fil_space_get_latch(space), + MTR_MEMO_X_LOCK)); #endif /* UNIV_SYNC_DEBUG */ - mtr_x_lock(fil_space_get_latch(space), mtr); + mtr_x_lock(fil_space_get_latch(space), mtr); descr = xdes_get_descriptor(space, buf_frame_get_page_no(header), mtr); @@ -3211,7 +3224,7 @@ fseg_free_step( page = xdes_get_offset(descr); fseg_free_extent(inode, space, page, mtr); - + return(FALSE); } @@ -3261,13 +3274,13 @@ fseg_free_step_not_header( ulint page_no; space = buf_frame_get_space_id(header); - + #ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&kernel_mutex) - || mtr_memo_contains(mtr, fil_space_get_latch(space), - MTR_MEMO_X_LOCK)); + || mtr_memo_contains(mtr, fil_space_get_latch(space), + MTR_MEMO_X_LOCK)); #endif /* UNIV_SYNC_DEBUG */ - mtr_x_lock(fil_space_get_latch(space), mtr); + mtr_x_lock(fil_space_get_latch(space), mtr); inode = fseg_inode_get(header, mtr); @@ -3278,7 +3291,7 @@ fseg_free_step_not_header( page = xdes_get_offset(descr); fseg_free_extent(inode, space, page, mtr); - + return(FALSE); } @@ -3291,12 +3304,12 @@ fseg_free_step_not_header( } page_no = fseg_get_nth_frag_page_no(inode, n, mtr); - + if (page_no == buf_frame_get_page_no(header)) { return(TRUE); } - + fseg_free_page_low(inode, space, page_no, mtr); return(FALSE); @@ -3329,7 +3342,7 @@ fseg_free( header = fut_get_ptr(space, addr, RW_X_LATCH, &mtr); finished = fseg_free_step(header, &mtr); - + mtr_commit(&mtr); if (finished) { @@ -3355,13 +3368,13 @@ fseg_get_first_extent( fil_addr_t first; ulint space; xdes_t* descr; - + ut_ad(inode && mtr); space = buf_frame_get_space_id(inode); first = fil_addr_null; - + if (flst_get_len(inode + FSEG_FULL, mtr) > 0) { first = flst_get_first(inode + FSEG_FULL, mtr); @@ -3401,16 +3414,16 @@ fseg_validate_low( fil_addr_t node_addr; ulint n_used = 0; ulint n_used2 = 0; - + ut_ad(mtr_memo_contains(mtr2, buf_block_align(inode), MTR_MEMO_PAGE_X_FIX)); ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); space = buf_frame_get_space_id(inode); - - seg_id = mtr_read_dulint(inode + FSEG_ID, mtr2); + + seg_id = mtr_read_dulint(inode + FSEG_ID, mtr2); n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED, - MLOG_4BYTES, mtr2); + MLOG_4BYTES, mtr2); flst_validate(inode + FSEG_FREE, mtr2); flst_validate(inode + FSEG_NOT_FULL, mtr2); flst_validate(inode + FSEG_FULL, mtr2); @@ -3420,7 +3433,7 @@ fseg_validate_low( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); descr = xdes_lst_get_descriptor(space, node_addr, &mtr); @@ -3439,7 +3452,7 @@ fseg_validate_low( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); descr = xdes_lst_get_descriptor(space, node_addr, &mtr); @@ -3461,7 +3474,7 @@ fseg_validate_low( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); descr = xdes_lst_get_descriptor(space, node_addr, &mtr); @@ -3478,7 +3491,7 @@ fseg_validate_low( return(TRUE); } - + /*********************************************************************** Validates a segment. */ @@ -3495,7 +3508,7 @@ fseg_validate( space = buf_frame_get_space_id(header); - mtr_x_lock(fil_space_get_latch(space), mtr2); + mtr_x_lock(fil_space_get_latch(space), mtr2); inode = fseg_inode_get(header, mtr2); @@ -3524,8 +3537,8 @@ fseg_print_low( ulint reserved; ulint used; ulint page_no; - dulint d_var; - + dulint d_var; + ut_ad(mtr_memo_contains(mtr, buf_block_align(inode), MTR_MEMO_PAGE_X_FIX)); space = buf_frame_get_space_id(inode); @@ -3533,13 +3546,13 @@ fseg_print_low( reserved = fseg_n_reserved_pages_low(inode, &used, mtr); - d_var = mtr_read_dulint(inode + FSEG_ID, mtr); + d_var = mtr_read_dulint(inode + FSEG_ID, mtr); seg_id_low = ut_dulint_get_low(d_var); seg_id_high = ut_dulint_get_high(d_var); - + n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED, - MLOG_4BYTES, mtr); + MLOG_4BYTES, mtr); n_frag = fseg_get_n_frag_pages(inode, mtr); n_free = flst_get_len(inode + FSEG_FREE, mtr); n_not_full = flst_get_len(inode + FSEG_NOT_FULL, mtr); @@ -3551,7 +3564,7 @@ fseg_print_low( (ulong) seg_id_high, (ulong) seg_id_low, (ulong) space, (ulong) page_no, (ulong) reserved, (ulong) used, (ulong) n_full, (ulong) n_frag, (ulong) n_free, (ulong) n_not_full, - (ulong) n_used); + (ulong) n_used); } /*********************************************************************** @@ -3568,7 +3581,7 @@ fseg_print( space = buf_frame_get_space_id(header); - mtr_x_lock(fil_space_get_latch(space), mtr); + mtr_x_lock(fil_space_get_latch(space), mtr); inode = fseg_inode_get(header, mtr); @@ -3602,28 +3615,28 @@ fsp_validate( ulint n; ulint seg_inode_len_free; ulint seg_inode_len_full; - + /* Start first a mini-transaction mtr2 to lock out all other threads from the fsp system */ mtr_start(&mtr2); - mtr_x_lock(fil_space_get_latch(space), &mtr2); - + mtr_x_lock(fil_space_get_latch(space), &mtr2); + mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); - + mtr_x_lock(fil_space_get_latch(space), &mtr); + header = fsp_get_space_header(space, &mtr); - size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr); + size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr); free_limit = mtr_read_ulint(header + FSP_FREE_LIMIT, - MLOG_4BYTES, &mtr); + MLOG_4BYTES, &mtr); frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, - MLOG_4BYTES, &mtr); + MLOG_4BYTES, &mtr); n_full_frag_pages = FSP_EXTENT_SIZE * flst_get_len(header + FSP_FULL_FRAG, &mtr); - + ut_a(free_limit <= size || (space != 0 && size < FSP_EXTENT_SIZE)); - + flst_validate(header + FSP_FREE, &mtr); flst_validate(header + FSP_FREE_FRAG, &mtr); flst_validate(header + FSP_FULL_FRAG, &mtr); @@ -3632,7 +3645,7 @@ fsp_validate( /* Validate FSP_FREE list */ mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); header = fsp_get_space_header(space, &mtr); node_addr = flst_get_first(header + FSP_FREE, &mtr); @@ -3641,7 +3654,7 @@ fsp_validate( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); descr_count++; descr = xdes_lst_get_descriptor(space, node_addr, &mtr); @@ -3655,7 +3668,7 @@ fsp_validate( /* Validate FSP_FREE_FRAG list */ mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); header = fsp_get_space_header(space, &mtr); node_addr = flst_get_first(header + FSP_FREE_FRAG, &mtr); @@ -3664,7 +3677,7 @@ fsp_validate( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); descr_count++; descr = xdes_lst_get_descriptor(space, node_addr, &mtr); @@ -3681,7 +3694,7 @@ fsp_validate( /* Validate FSP_FULL_FRAG list */ mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); header = fsp_get_space_header(space, &mtr); node_addr = flst_get_first(header + FSP_FULL_FRAG, &mtr); @@ -3690,7 +3703,7 @@ fsp_validate( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); descr_count++; descr = xdes_lst_get_descriptor(space, node_addr, &mtr); @@ -3701,14 +3714,14 @@ fsp_validate( node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr); mtr_commit(&mtr); } - + /* Validate segments */ mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); header = fsp_get_space_header(space, &mtr); - node_addr = flst_get_first(header + FSP_SEG_INODES_FULL, &mtr); + node_addr = flst_get_first(header + FSP_SEG_INODES_FULL, &mtr); seg_inode_len_full = flst_get_len(header + FSP_SEG_INODES_FULL, &mtr); @@ -3716,86 +3729,93 @@ fsp_validate( while (!fil_addr_is_null(node_addr)) { - for (n = 0; n < FSP_SEG_INODES_PER_PAGE; n++) { + for (n = 0; n < FSP_SEG_INODES_PER_PAGE; n++) { - mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_start(&mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); - seg_inode_page = fut_get_ptr(space, node_addr, RW_X_LATCH, - &mtr) - FSEG_INODE_PAGE_NODE; + seg_inode_page = fut_get_ptr(space, node_addr, + RW_X_LATCH, &mtr) - FSEG_INODE_PAGE_NODE; - seg_inode = fsp_seg_inode_page_get_nth_inode(seg_inode_page, - n, &mtr); - ut_a(ut_dulint_cmp(mach_read_from_8(seg_inode + FSEG_ID), - ut_dulint_zero) != 0); - fseg_validate_low(seg_inode, &mtr); + seg_inode = fsp_seg_inode_page_get_nth_inode( + seg_inode_page, n, &mtr); + ut_a(ut_dulint_cmp( + mach_read_from_8(seg_inode + FSEG_ID), + ut_dulint_zero) != 0); + fseg_validate_low(seg_inode, &mtr); - descr_count += flst_get_len(seg_inode + FSEG_FREE, &mtr); - descr_count += flst_get_len(seg_inode + FSEG_FULL, &mtr); - descr_count += flst_get_len(seg_inode + FSEG_NOT_FULL, &mtr); + descr_count += flst_get_len(seg_inode + FSEG_FREE, + &mtr); + descr_count += flst_get_len(seg_inode + FSEG_FULL, + &mtr); + descr_count += flst_get_len(seg_inode + FSEG_NOT_FULL, + &mtr); - n_used2 += fseg_get_n_frag_pages(seg_inode, &mtr); + n_used2 += fseg_get_n_frag_pages(seg_inode, &mtr); - next_node_addr = flst_get_next_addr(seg_inode_page - + FSEG_INODE_PAGE_NODE, &mtr); - mtr_commit(&mtr); - } + next_node_addr = flst_get_next_addr(seg_inode_page + + FSEG_INODE_PAGE_NODE, &mtr); + mtr_commit(&mtr); + } - node_addr = next_node_addr; + node_addr = next_node_addr; } mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); header = fsp_get_space_header(space, &mtr); node_addr = flst_get_first(header + FSP_SEG_INODES_FREE, &mtr); seg_inode_len_free = flst_get_len(header + FSP_SEG_INODES_FREE, &mtr); - + mtr_commit(&mtr); while (!fil_addr_is_null(node_addr)) { - for (n = 0; n < FSP_SEG_INODES_PER_PAGE; n++) { - - mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); - - seg_inode_page = fut_get_ptr(space, node_addr, RW_X_LATCH, - &mtr) - FSEG_INODE_PAGE_NODE; - - seg_inode = fsp_seg_inode_page_get_nth_inode(seg_inode_page, - n, &mtr); - if (ut_dulint_cmp(mach_read_from_8(seg_inode + FSEG_ID), - ut_dulint_zero) != 0) { - fseg_validate_low(seg_inode, &mtr); + for (n = 0; n < FSP_SEG_INODES_PER_PAGE; n++) { + + mtr_start(&mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); + + seg_inode_page = fut_get_ptr(space, node_addr, + RW_X_LATCH, &mtr) - FSEG_INODE_PAGE_NODE; + + seg_inode = fsp_seg_inode_page_get_nth_inode( + seg_inode_page, n, &mtr); + if (ut_dulint_cmp(mach_read_from_8( + seg_inode + FSEG_ID), + ut_dulint_zero) != 0) { + fseg_validate_low(seg_inode, &mtr); + + descr_count += flst_get_len( + seg_inode + FSEG_FREE, &mtr); + descr_count += flst_get_len( + seg_inode + FSEG_FULL, &mtr); + descr_count += flst_get_len( + seg_inode + FSEG_NOT_FULL, &mtr); + n_used2 += fseg_get_n_frag_pages( + seg_inode, &mtr); + } - descr_count += flst_get_len(seg_inode + FSEG_FREE, - &mtr); - descr_count += flst_get_len(seg_inode + FSEG_FULL, - &mtr); - descr_count += flst_get_len(seg_inode + FSEG_NOT_FULL, - &mtr); - n_used2 += fseg_get_n_frag_pages(seg_inode, &mtr); + next_node_addr = flst_get_next_addr(seg_inode_page + + FSEG_INODE_PAGE_NODE, &mtr); + mtr_commit(&mtr); } - next_node_addr = flst_get_next_addr(seg_inode_page - + FSEG_INODE_PAGE_NODE, &mtr); - mtr_commit(&mtr); - } - - node_addr = next_node_addr; + node_addr = next_node_addr; } - + ut_a(descr_count * FSP_EXTENT_SIZE == free_limit); ut_a(n_used + n_full_frag_pages == n_used2 + 2* ((free_limit + XDES_DESCRIBED_PER_PAGE - 1) - / XDES_DESCRIBED_PER_PAGE) - + seg_inode_len_full + seg_inode_len_free); + / XDES_DESCRIBED_PER_PAGE) + + seg_inode_len_full + seg_inode_len_free); ut_a(frag_n_used == n_used); mtr_commit(&mtr2); + return(TRUE); } @@ -3822,27 +3842,27 @@ fsp_print( ulint seg_id_high; ulint n; ulint n_segs = 0; - dulint d_var; + dulint d_var; mtr_t mtr; mtr_t mtr2; - + /* Start first a mini-transaction mtr2 to lock out all other threads from the fsp system */ mtr_start(&mtr2); - mtr_x_lock(fil_space_get_latch(space), &mtr2); + mtr_x_lock(fil_space_get_latch(space), &mtr2); mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); - + mtr_x_lock(fil_space_get_latch(space), &mtr); + header = fsp_get_space_header(space, &mtr); - size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr); + size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr); free_limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, - &mtr); + &mtr); frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES, &mtr); n_free = flst_get_len(header + FSP_FREE, &mtr); @@ -3864,47 +3884,48 @@ fsp_print( (ulong) n_free_frag, (ulong) frag_n_used, (ulong) n_full_frag, (ulong) seg_id_high, (ulong) seg_id_low); - mtr_commit(&mtr); + mtr_commit(&mtr); /* Print segments */ mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); header = fsp_get_space_header(space, &mtr); - node_addr = flst_get_first(header + FSP_SEG_INODES_FULL, &mtr); + node_addr = flst_get_first(header + FSP_SEG_INODES_FULL, &mtr); mtr_commit(&mtr); while (!fil_addr_is_null(node_addr)) { - for (n = 0; n < FSP_SEG_INODES_PER_PAGE; n++) { + for (n = 0; n < FSP_SEG_INODES_PER_PAGE; n++) { - mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_start(&mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); - seg_inode_page = fut_get_ptr(space, node_addr, RW_X_LATCH, - &mtr) - FSEG_INODE_PAGE_NODE; + seg_inode_page = fut_get_ptr(space, node_addr, + RW_X_LATCH, &mtr) - FSEG_INODE_PAGE_NODE; - seg_inode = fsp_seg_inode_page_get_nth_inode(seg_inode_page, - n, &mtr); - ut_a(ut_dulint_cmp(mach_read_from_8(seg_inode + FSEG_ID), - ut_dulint_zero) != 0); - fseg_print_low(seg_inode, &mtr); + seg_inode = fsp_seg_inode_page_get_nth_inode( + seg_inode_page, n, &mtr); + ut_a(ut_dulint_cmp(mach_read_from_8( + seg_inode + FSEG_ID), + ut_dulint_zero) != 0); + fseg_print_low(seg_inode, &mtr); - n_segs++; - - next_node_addr = flst_get_next_addr(seg_inode_page - + FSEG_INODE_PAGE_NODE, &mtr); - mtr_commit(&mtr); - } + n_segs++; + + next_node_addr = flst_get_next_addr(seg_inode_page + + FSEG_INODE_PAGE_NODE, &mtr); + mtr_commit(&mtr); + } - node_addr = next_node_addr; + node_addr = next_node_addr; } mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); header = fsp_get_space_header(space, &mtr); @@ -3914,31 +3935,32 @@ fsp_print( while (!fil_addr_is_null(node_addr)) { - for (n = 0; n < FSP_SEG_INODES_PER_PAGE; n++) { + for (n = 0; n < FSP_SEG_INODES_PER_PAGE; n++) { - mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space), &mtr); + mtr_start(&mtr); + mtr_x_lock(fil_space_get_latch(space), &mtr); - seg_inode_page = fut_get_ptr(space, node_addr, RW_X_LATCH, - &mtr) - FSEG_INODE_PAGE_NODE; + seg_inode_page = fut_get_ptr(space, node_addr, + RW_X_LATCH, &mtr) - FSEG_INODE_PAGE_NODE; - seg_inode = fsp_seg_inode_page_get_nth_inode(seg_inode_page, - n, &mtr); - if (ut_dulint_cmp(mach_read_from_8(seg_inode + FSEG_ID), - ut_dulint_zero) != 0) { + seg_inode = fsp_seg_inode_page_get_nth_inode( + seg_inode_page, n, &mtr); + if (ut_dulint_cmp(mach_read_from_8( + seg_inode + FSEG_ID), + ut_dulint_zero) != 0) { - fseg_print_low(seg_inode, &mtr); - n_segs++; - } + fseg_print_low(seg_inode, &mtr); + n_segs++; + } - next_node_addr = flst_get_next_addr(seg_inode_page - + FSEG_INODE_PAGE_NODE, &mtr); - mtr_commit(&mtr); - } + next_node_addr = flst_get_next_addr(seg_inode_page + + FSEG_INODE_PAGE_NODE, &mtr); + mtr_commit(&mtr); + } - node_addr = next_node_addr; + node_addr = next_node_addr; } - + mtr_commit(&mtr2); fprintf(stderr, "NUMBER of file segments: %lu\n", (ulong) n_segs); diff --git a/storage/innobase/fut/fut0lst.c b/storage/innobase/fut/fut0lst.c index 8deaa8adb3f..cdf7719dde0 100644 --- a/storage/innobase/fut/fut0lst.c +++ b/storage/innobase/fut/fut0lst.c @@ -38,7 +38,7 @@ flst_add_to_empty( MTR_MEMO_PAGE_X_FIX)); len = flst_get_len(base, mtr); ut_a(len == 0); - + buf_ptr_get_fsp_addr(node, &space, &node_addr); /* Update first and last fields of base node */ @@ -50,7 +50,7 @@ flst_add_to_empty( flst_write_addr(node + FLST_NEXT, fil_addr_null, mtr); /* Update len of base node */ - mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr); + mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr); } /************************************************************************ @@ -68,7 +68,7 @@ flst_add_last( ulint len; fil_addr_t last_addr; flst_node_t* last_node; - + ut_ad(mtr && base && node); ut_ad(base != node); ut_ad(mtr_memo_contains(mtr, buf_block_align(base), @@ -89,10 +89,10 @@ flst_add_last( mtr); } - flst_insert_after(base, last_node, node, mtr); + flst_insert_after(base, last_node, node, mtr); } else { /* else call flst_add_to_empty */ - flst_add_to_empty(base, node, mtr); + flst_add_to_empty(base, node, mtr); } } @@ -111,7 +111,7 @@ flst_add_first( ulint len; fil_addr_t first_addr; flst_node_t* first_node; - + ut_ad(mtr && base && node); ut_ad(base != node); ut_ad(mtr_memo_contains(mtr, buf_block_align(base), @@ -133,10 +133,10 @@ flst_add_first( RW_X_LATCH, mtr); } - flst_insert_before(base, node, first_node, mtr); + flst_insert_before(base, node, first_node, mtr); } else { /* else call flst_add_to_empty */ - flst_add_to_empty(base, node, mtr); + flst_add_to_empty(base, node, mtr); } } @@ -157,7 +157,7 @@ flst_insert_after( flst_node_t* node3; fil_addr_t node3_addr; ulint len; - + ut_ad(mtr && node1 && node2 && base); ut_ad(base != node1); ut_ad(base != node2); @@ -173,7 +173,7 @@ flst_insert_after( buf_ptr_get_fsp_addr(node2, &space, &node2_addr); node3_addr = flst_get_next_addr(node1, mtr); - + /* Set prev and next fields of node2 */ flst_write_addr(node2 + FLST_PREV, node1_addr, mtr); flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr); @@ -186,13 +186,13 @@ flst_insert_after( /* node1 was last in list: update last field in base */ flst_write_addr(base + FLST_LAST, node2_addr, mtr); } - + /* Set next field of node1 */ flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr); /* Update len of base node */ len = flst_get_len(base, mtr); - mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr); + mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr); } /************************************************************************ @@ -212,7 +212,7 @@ flst_insert_before( fil_addr_t node2_addr; fil_addr_t node3_addr; ulint len; - + ut_ad(mtr && node2 && node3 && base); ut_ad(base != node2); ut_ad(base != node3); @@ -228,7 +228,7 @@ flst_insert_before( buf_ptr_get_fsp_addr(node3, &space, &node3_addr); node1_addr = flst_get_prev_addr(node3, mtr); - + /* Set prev and next fields of node2 */ flst_write_addr(node2 + FLST_PREV, node1_addr, mtr); flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr); @@ -241,13 +241,13 @@ flst_insert_before( /* node3 was first in list: update first field in base */ flst_write_addr(base + FLST_FIRST, node2_addr, mtr); } - + /* Set prev field of node3 */ flst_write_addr(node3 + FLST_PREV, node2_addr, mtr); /* Update len of base node */ len = flst_get_len(base, mtr); - mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr); + mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr); } /************************************************************************ @@ -267,7 +267,7 @@ flst_remove( flst_node_t* node3; fil_addr_t node3_addr; ulint len; - + ut_ad(mtr && node2 && base); ut_ad(mtr_memo_contains(mtr, buf_block_align(base), MTR_MEMO_PAGE_X_FIX)); @@ -282,7 +282,7 @@ flst_remove( if (!fil_addr_is_null(node1_addr)) { /* Update next field of node1 */ - + if (node1_addr.page == node2_addr.page) { node1 = buf_frame_align(node2) + node1_addr.boffset; @@ -290,7 +290,7 @@ flst_remove( node1 = fut_get_ptr(space, node1_addr, RW_X_LATCH, mtr); } - + ut_ad(node1 != node2); flst_write_addr(node1 + FLST_NEXT, node3_addr, mtr); @@ -309,7 +309,7 @@ flst_remove( node3 = fut_get_ptr(space, node3_addr, RW_X_LATCH, mtr); } - + ut_ad(node2 != node3); flst_write_addr(node3 + FLST_PREV, node1_addr, mtr); @@ -317,12 +317,12 @@ flst_remove( /* node2 was last in list: update last field in base */ flst_write_addr(base + FLST_LAST, node1_addr, mtr); } - + /* Update len of base node */ len = flst_get_len(base, mtr); ut_ad(len > 0); - mlog_write_ulint(base + FLST_LEN, len - 1, MLOG_4BYTES, mtr); + mlog_write_ulint(base + FLST_LEN, len - 1, MLOG_4BYTES, mtr); } /************************************************************************ @@ -344,14 +344,14 @@ flst_cut_end( fil_addr_t node1_addr; fil_addr_t node2_addr; ulint len; - + ut_ad(mtr && node2 && base); ut_ad(mtr_memo_contains(mtr, buf_block_align(base), MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains(mtr, buf_block_align(node2), MTR_MEMO_PAGE_X_FIX)); ut_ad(n_nodes > 0); - + buf_ptr_get_fsp_addr(node2, &space, &node2_addr); node1_addr = flst_get_prev_addr(node2, mtr); @@ -367,7 +367,7 @@ flst_cut_end( node1 = fut_get_ptr(space, node1_addr, RW_X_LATCH, mtr); } - + flst_write_addr(node1 + FLST_NEXT, fil_addr_null, mtr); } else { /* node2 was first in list: update the field in base */ @@ -380,7 +380,7 @@ flst_cut_end( len = flst_get_len(base, mtr); ut_ad(len >= n_nodes); - mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr); + mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr); } /************************************************************************ @@ -399,7 +399,7 @@ flst_truncate_end( fil_addr_t node2_addr; ulint len; ulint space; - + ut_ad(mtr && node2 && base); ut_ad(mtr_memo_contains(mtr, buf_block_align(base), MTR_MEMO_PAGE_X_FIX)); @@ -408,7 +408,7 @@ flst_truncate_end( if (n_nodes == 0) { ut_ad(fil_addr_is_null(flst_get_next_addr(node2, mtr))); - + return; } @@ -423,7 +423,7 @@ flst_truncate_end( len = flst_get_len(base, mtr); ut_ad(len >= n_nodes); - mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr); + mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr); } /************************************************************************ @@ -443,7 +443,7 @@ flst_validate( ulint len; ulint i; mtr_t mtr2; - + ut_ad(base); ut_ad(mtr_memo_contains(mtr1, buf_block_align(base), MTR_MEMO_PAGE_X_FIX)); @@ -470,7 +470,7 @@ flst_validate( mtr_commit(&mtr2); /* Commit mtr2 each round to prevent buffer becoming full */ } - + ut_a(fil_addr_is_null(node_addr)); node_addr = flst_get_last(base, mtr1); @@ -484,7 +484,7 @@ flst_validate( mtr_commit(&mtr2); /* Commit mtr2 each round to prevent buffer becoming full */ } - + ut_a(fil_addr_is_null(node_addr)); return(TRUE); @@ -501,10 +501,10 @@ flst_print( { buf_frame_t* frame; ulint len; - + ut_ad(base && mtr); ut_ad(mtr_memo_contains(mtr, buf_block_align(base), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); frame = buf_frame_align(base); len = flst_get_len(base, mtr); @@ -512,7 +512,7 @@ flst_print( fprintf(stderr, "FILE-BASED LIST:\n" "Base node in space %lu page %lu byte offset %lu; len %lu\n", - (ulong) buf_frame_get_space_id(frame), - (ulong) buf_frame_get_page_no(frame), - (ulong) (base - frame), (ulong) len); + (ulong) buf_frame_get_space_id(frame), + (ulong) buf_frame_get_page_no(frame), + (ulong) (base - frame), (ulong) len); } diff --git a/storage/innobase/ha/ha0ha.c b/storage/innobase/ha/ha0ha.c index fdc3d48c14b..6b03ea5f2fe 100644 --- a/storage/innobase/ha/ha0ha.c +++ b/storage/innobase/ha/ha0ha.c @@ -42,7 +42,7 @@ ha_create( /* Creating MEM_HEAP_BTR_SEARCH type heaps can potentially fail, but in practise it never should in this case, hence the asserts. */ - + if (n_mutexes == 0) { if (in_btr_search) { table->heap = mem_heap_create_in_btr_search(4096); @@ -53,7 +53,7 @@ ha_create( return(table); } - + hash_create_mutexes(table, n_mutexes, mutex_level); table->heaps = mem_alloc(n_mutexes * sizeof(void*)); @@ -66,7 +66,7 @@ ha_create( table->heaps[i] = mem_heap_create_in_buffer(4096); } } - + return(table); } @@ -119,7 +119,7 @@ ha_insert_for_fold( prev_node = prev_node->next; } - + /* We have to allocate a new chain node */ node = mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t)); @@ -132,7 +132,7 @@ ha_insert_for_fold( return(FALSE); } - + ha_node_set_data(node, data); if (table->adaptive) { @@ -151,7 +151,7 @@ ha_insert_for_fold( return(TRUE); } - + while (prev_node->next != NULL) { prev_node = prev_node->next; @@ -160,7 +160,7 @@ ha_insert_for_fold( prev_node->next = node; return(TRUE); -} +} /*************************************************************** Deletes a hash node. */ @@ -200,7 +200,7 @@ ha_delete( ut_a(node); ha_delete_hash_node(table, node); -} +} /************************************************************* Looks for an element when we know the pointer to the data, and updates @@ -269,7 +269,7 @@ ha_remove_all_nodes_to_page( } #ifdef UNIV_DEBUG /* Check that all nodes really got deleted */ - + node = ha_chain_get_first(table, fold); while (node) { @@ -281,20 +281,26 @@ ha_remove_all_nodes_to_page( } /***************************************************************** -Validates a hash table. */ +Validates a given range of the cells in hash table. */ ibool ha_validate( /*========*/ - /* out: TRUE if ok */ - hash_table_t* table) /* in: hash table */ + /* out: TRUE if ok */ + hash_table_t* table, /* in: hash table */ + ulint start_index, /* in: start index */ + ulint end_index) /* in: end index */ { hash_cell_t* cell; ha_node_t* node; ibool ok = TRUE; ulint i; - for (i = 0; i < hash_get_n_cells(table); i++) { + ut_a(start_index <= end_index); + ut_a(start_index < hash_get_n_cells(table)); + ut_a(end_index < hash_get_n_cells(table)); + + for (i = start_index; i <= end_index; i++) { cell = hash_get_nth_cell(table, i); @@ -316,7 +322,7 @@ ha_validate( } return(ok); -} +} /***************************************************************** Prints info of a hash table. */ @@ -356,7 +362,7 @@ ha_print_info( if (table->heap->free_block) { n_bufs++; } - + fprintf(file, ", node heap has %lu buffer(s)\n", (ulong) n_bufs); } -} +} diff --git a/storage/innobase/ha/hash0hash.c b/storage/innobase/ha/hash0hash.c index facdea66198..659aeb815d8 100644 --- a/storage/innobase/ha/hash0hash.c +++ b/storage/innobase/ha/hash0hash.c @@ -19,8 +19,8 @@ Reserves the mutex for a fold value in a hash table. */ void hash_mutex_enter( /*=============*/ - hash_table_t* table, /* in: hash table */ - ulint fold) /* in: fold */ + hash_table_t* table, /* in: hash table */ + ulint fold) /* in: fold */ { mutex_enter(hash_get_mutex(table, fold)); } @@ -31,8 +31,8 @@ Releases the mutex for a fold value in a hash table. */ void hash_mutex_exit( /*============*/ - hash_table_t* table, /* in: hash table */ - ulint fold) /* in: fold */ + hash_table_t* table, /* in: hash table */ + ulint fold) /* in: fold */ { mutex_exit(hash_get_mutex(table, fold)); } @@ -43,7 +43,7 @@ Reserves all the mutexes of a hash table, in an ascending order. */ void hash_mutex_enter_all( /*=================*/ - hash_table_t* table) /* in: hash table */ + hash_table_t* table) /* in: hash table */ { ulint i; @@ -59,7 +59,7 @@ Releases all the mutexes of a hash table. */ void hash_mutex_exit_all( /*================*/ - hash_table_t* table) /* in: hash table */ + hash_table_t* table) /* in: hash table */ { ulint i; @@ -84,13 +84,13 @@ hash_create( hash_table_t* table; ulint i; hash_cell_t* cell; - + prime = ut_find_prime(n); table = mem_alloc(sizeof(hash_table_t)); array = ut_malloc(sizeof(hash_cell_t) * prime); - + table->adaptive = FALSE; table->array = array; table->n_cells = prime; @@ -99,7 +99,7 @@ hash_create( table->heaps = NULL; table->heap = NULL; table->magic_n = HASH_TABLE_MAGIC_N; - + /* Initialize the cell array */ for (i = 0; i < prime; i++) { diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index d7fa48b6e66..36cc97e5e0e 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -29,7 +29,7 @@ Created 7/19/1997 Heikki Tuuri #include "log0recv.h" #include "que0que.h" -/* STRUCTURE OF AN INSERT BUFFER RECORD +/* STRUCTURE OF AN INSERT BUFFER RECORD In versions < 4.1.x: @@ -140,8 +140,7 @@ access order rules. */ /* The insert buffer control structure */ ibuf_t* ibuf = NULL; -static -ulint ibuf_rnd = 986058871; +static ulint ibuf_rnd = 986058871; ulint ibuf_flush_count = 0; @@ -369,14 +368,14 @@ ibuf_init_at_db_start(void) /* Note that also a pessimistic delete can sometimes make a B-tree grow in size, as the references on the upper levels of the tree can change */ - + ibuf->max_size = buf_pool_get_curr_size() / UNIV_PAGE_SIZE / IBUF_POOL_SIZE_PER_MAX_SIZE; ibuf->meter = IBUF_THRESHOLD + 1; UT_LIST_INIT(ibuf->data_list); - ibuf->size = 0; + ibuf->size = 0; #ifdef UNIV_IBUF_DEBUG { @@ -390,7 +389,7 @@ ibuf_init_at_db_start(void) ibuf_count_set(i, j, 0); } } - } + } #endif mutex_create(&ibuf_pessimistic_insert_mutex); @@ -427,7 +426,7 @@ ibuf_data_sizes_update( #endif /* UNIV_SYNC_DEBUG */ old_size = data->size; - + data->free_list_len = flst_get_len(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr); @@ -473,7 +472,7 @@ ibuf_data_init_for_space( dict_table_t* table; dict_index_t* index; ulint n_used; - + ut_a(space == 0); #ifdef UNIV_LOG_DEBUG @@ -499,11 +498,11 @@ ibuf_data_init_for_space( fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, &n_used, &mtr); ibuf_enter(); - + ut_ad(n_used >= 2); data->seg_size = n_used; - + root = buf_page_get(space, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, &mtr); #ifdef UNIV_SYNC_DEBUG @@ -514,7 +513,7 @@ ibuf_data_init_for_space( data->n_inserts = 0; data->n_merges = 0; data->n_merged_recs = 0; - + ibuf_data_sizes_update(data, root, &mtr); /* if (!data->empty) { @@ -533,7 +532,7 @@ ibuf_data_init_for_space( sprintf(buf, "SYS_IBUF_TABLE_%lu", (ulong) space); /* use old-style record format for the insert buffer */ - table = dict_mem_table_create(buf, space, 2, FALSE); + table = dict_mem_table_create(buf, space, 2, 0); dict_mem_table_add_col(table, "PAGE_NO", DATA_BINARY, 0, 0, 0); dict_mem_table_add_col(table, "TYPES", DATA_BINARY, 0, 0, 0); @@ -545,8 +544,8 @@ ibuf_data_init_for_space( index = dict_mem_index_create(buf, "CLUST_IND", space, DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,2); - dict_mem_index_add_field(index, "PAGE_NO", 0, 0); - dict_mem_index_add_field(index, "TYPES", 0, 0); + dict_mem_index_add_field(index, "PAGE_NO", 0); + dict_mem_index_add_field(index, "TYPES", 0); index->id = ut_dulint_add(DICT_IBUF_ID_MIN, space); @@ -574,18 +573,18 @@ ibuf_bitmap_page_init( { ulint bit_offset; ulint byte_offset; - ulint i; /* Write all zeros to the bitmap */ bit_offset = XDES_DESCRIBED_PER_PAGE * IBUF_BITS_PER_PAGE; - byte_offset = bit_offset / 8 + 1; + byte_offset = bit_offset / 8 + 1; /* better: (bit_offset + 7) / 8 */ - for (i = IBUF_BITMAP; i < IBUF_BITMAP + byte_offset; i++) { + fil_page_set_type(page, FIL_PAGE_IBUF_BITMAP); - *(page + i) = (byte)0; - } + memset(page + IBUF_BITMAP, 0, byte_offset); + + /* The remaining area (up to the page trailer) is uninitialized. */ mlog_write_initial_log_record(page, MLOG_IBUF_BITMAP_INIT, mtr); } @@ -621,8 +620,9 @@ ibuf_bitmap_page_get_bits( page_t* page, /* in: bitmap page */ ulint page_no,/* in: page whose bits to get */ ulint bit, /* in: IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ... */ - mtr_t* mtr __attribute__((unused))) /* in: mtr containing an x-latch - to the bitmap page */ + mtr_t* mtr __attribute__((unused))) /* in: mtr containing an + x-latch to the bitmap + page */ { ulint byte_offset; ulint bit_offset; @@ -630,12 +630,14 @@ ibuf_bitmap_page_get_bits( ulint value; ut_ad(bit < IBUF_BITS_PER_PAGE); - ut_ad(IBUF_BITS_PER_PAGE % 2 == 0); +#if IBUF_BITS_PER_PAGE % 2 +# error "IBUF_BITS_PER_PAGE % 2 != 0" +#endif ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); bit_offset = (page_no % XDES_DESCRIBED_PER_PAGE) * IBUF_BITS_PER_PAGE - + bit; + + bit; byte_offset = bit_offset / 8; bit_offset = bit_offset % 8; @@ -648,7 +650,7 @@ ibuf_bitmap_page_get_bits( if (bit == IBUF_BITMAP_FREE) { ut_ad(bit_offset + 1 < 8); - + value = value * 2 + ut_bit_get_nth(map_byte, bit_offset + 1); } @@ -672,15 +674,18 @@ ibuf_bitmap_page_set_bits( ulint map_byte; ut_ad(bit < IBUF_BITS_PER_PAGE); - ut_ad(IBUF_BITS_PER_PAGE % 2 == 0); +#if IBUF_BITS_PER_PAGE % 2 +# error "IBUF_BITS_PER_PAGE % 2 != 0" +#endif ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); #ifdef UNIV_IBUF_DEBUG ut_a((bit != IBUF_BITMAP_BUFFERED) || (val != FALSE) - || (0 == ibuf_count_get(buf_frame_get_space_id(page), page_no))); + || (0 == ibuf_count_get(buf_frame_get_space_id(page), + page_no))); #endif bit_offset = (page_no % XDES_DESCRIBED_PER_PAGE) * IBUF_BITS_PER_PAGE - + bit; + + bit; byte_offset = bit_offset / 8; bit_offset = bit_offset % 8; @@ -692,14 +697,14 @@ ibuf_bitmap_page_set_bits( if (bit == IBUF_BITMAP_FREE) { ut_ad(bit_offset + 1 < 8); ut_ad(val <= 3); - + map_byte = ut_bit_set_nth(map_byte, bit_offset, val / 2); map_byte = ut_bit_set_nth(map_byte, bit_offset + 1, val % 2); } else { ut_ad(val <= 1); map_byte = ut_bit_set_nth(map_byte, bit_offset, val); } - + mlog_write_ulint(page + IBUF_BITMAP + byte_offset, map_byte, MLOG_1BYTE, mtr); } @@ -715,8 +720,8 @@ ibuf_bitmap_page_no_calc( ulint page_no) /* in: tablespace page number */ { return(FSP_IBUF_BITMAP_OFFSET - + XDES_DESCRIBED_PER_PAGE - * (page_no / XDES_DESCRIBED_PER_PAGE)); + + XDES_DESCRIBED_PER_PAGE + * (page_no / XDES_DESCRIBED_PER_PAGE)); } /************************************************************************ @@ -779,7 +784,7 @@ ibuf_set_free_bits_low( "Setting page no %lu free bits to %lu should be %lu\n", buf_frame_get_page_no(page), val, ibuf_index_page_calc_free(page)); */ - + ut_a(val <= ibuf_index_page_calc_free(page)); #endif ibuf_bitmap_page_set_bits(bitmap_page, buf_frame_get_page_no(page), @@ -818,7 +823,7 @@ ibuf_set_free_bits( } mtr_start(&mtr); - + bitmap_page = ibuf_bitmap_get_map_page(buf_frame_get_space_id(page), buf_frame_get_page_no(page), &mtr); @@ -844,7 +849,7 @@ ibuf_set_free_bits( ibuf_index_page_calc_free(page)); */ ut_a(val <= ibuf_index_page_calc_free(page)); -#endif +#endif ibuf_bitmap_page_set_bits(bitmap_page, buf_frame_get_page_no(page), IBUF_BITMAP_FREE, val, &mtr); mtr_commit(&mtr); @@ -931,7 +936,7 @@ ibuf_update_free_bits_for_two_pages_low( performed by another OS thread. */ mutex_enter(&ibuf_bitmap_mutex); - + state = ibuf_index_page_calc_free(page1); ibuf_set_free_bits_low(index->type, page1, state, mtr); @@ -1028,7 +1033,7 @@ ibuf_page_low( return(FALSE); } -#endif +#endif if (ibuf_fixed_addr_page(page_no)) { return(TRUE); @@ -1122,13 +1127,18 @@ ibuf_dummy_index_create( { dict_table_t* table; dict_index_t* index; + table = dict_mem_table_create("IBUF_DUMMY", - DICT_HDR_SPACE, n, comp); + DICT_HDR_SPACE, n, comp ? DICT_TF_COMPACT : 0); + index = dict_mem_index_create("IBUF_DUMMY", "IBUF_DUMMY", - DICT_HDR_SPACE, 0, n); + DICT_HDR_SPACE, 0, n); + index->table = table; + /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */ index->cached = TRUE; + return(index); } /************************************************************************ @@ -1136,7 +1146,7 @@ Add a column to the dummy index */ static void ibuf_dummy_index_add_col( -/*====================*/ +/*=====================*/ dict_index_t* index, /* in: dummy index */ dtype_t* type, /* in: the data type of the column */ ulint len) /* in: length of the column */ @@ -1148,7 +1158,7 @@ ibuf_dummy_index_add_col( dtype_get_len(type), dtype_get_prec(type)); dict_index_add_col(index, - dict_table_get_nth_col(index->table, i), 0, len); + dict_table_get_nth_col(index->table, i), len); } /************************************************************************ Deallocates a dummy index for inserting a record to a non-clustered index. @@ -1156,7 +1166,7 @@ Deallocates a dummy index for inserting a record to a non-clustered index. static void ibuf_dummy_index_free( -/*====================*/ +/*==================*/ dict_index_t* index) /* in: dummy index */ { dict_table_t* table = index->table; @@ -1378,7 +1388,7 @@ ibuf_entry_build( byte* buf; byte* buf2; ulint i; - + /* Starting from 4.1.x, we have to build a tuple whose (1) first field is the space id, (2) the second field a single marker byte (0) to tell that this @@ -1467,7 +1477,7 @@ ibuf_entry_build( dtuple_set_types_binary(tuple, n_fields + 4); return(tuple); -} +} /************************************************************************* Builds a search tuple used to search buffered inserts for an index page. @@ -1484,7 +1494,7 @@ ibuf_search_tuple_build( dtuple_t* tuple; dfield_t* field; byte* buf; - + ut_a(space == 0); ut_a(trx_doublewrite_must_reset_space_ids); ut_a(!trx_sys_multiple_tablespace_format); @@ -1521,7 +1531,7 @@ ibuf_new_search_tuple_build( dtuple_t* tuple; dfield_t* field; byte* buf; - + ut_a(trx_sys_multiple_tablespace_format); tuple = dtuple_create(heap, 3); @@ -1637,7 +1647,7 @@ ibuf_add_free_page( /* Acquire the fsp latch before the ibuf header, obeying the latching order */ mtr_x_lock(fil_space_get_latch(space), &mtr); - + header_page = ibuf_header_page_get(space, &mtr); /* Allocate a new page: NOTE that if the page has been a part of a @@ -1674,9 +1684,10 @@ ibuf_add_free_page( /* Add the page to the free list and update the ibuf size data */ flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, - page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr); + page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr); - fil_page_set_type(page, FIL_PAGE_IBUF_FREE_LIST); + mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_IBUF_FREE_LIST, + MLOG_2BYTES, &mtr); ibuf_data->seg_size++; ibuf_data->free_list_len++; @@ -1721,7 +1732,7 @@ ibuf_remove_free_page( /* Acquire the fsp latch before the ibuf header, obeying the latching order */ mtr_x_lock(fil_space_get_latch(space), &mtr); - + header_page = ibuf_header_page_get(space, &mtr); /* Prevent pessimistic inserts to insert buffer trees for a while */ @@ -1736,16 +1747,16 @@ ibuf_remove_free_page( mutex_exit(&ibuf_mutex); ibuf_exit(); - + mutex_exit(&ibuf_pessimistic_insert_mutex); mtr_commit(&mtr); return; } - + mtr_start(&mtr2); - + root = ibuf_tree_root_get(ibuf_data, space, &mtr2); page_no = flst_get_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, @@ -1755,32 +1766,32 @@ ibuf_remove_free_page( /* NOTE that we must release the latch on the ibuf tree root because in fseg_free_page we access level 1 pages, and the root is a level 2 page. */ - + mtr_commit(&mtr2); mutex_exit(&ibuf_mutex); ibuf_exit(); - + /* Since pessimistic inserts were prevented, we know that the page is still in the free list. NOTE that also deletes may take pages from the free list, but they take them from the start, and the free list was so long that they cannot have taken the last page from it. */ - + fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, space, page_no, &mtr); #ifdef UNIV_DEBUG_FILE_ACCESSES buf_page_reset_file_page_was_freed(space, page_no); #endif ibuf_enter(); - + mutex_enter(&ibuf_mutex); root = ibuf_tree_root_get(ibuf_data, space, &mtr); ut_ad(page_no == flst_get_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, &mtr) - .page); + .page); page = buf_page_get(space, page_no, RW_X_LATCH, &mtr); @@ -1789,13 +1800,13 @@ ibuf_remove_free_page( #endif /* UNIV_SYNC_DEBUG */ /* Remove the page from the free list and update the ibuf size data */ - + flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, - page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr); + page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr); ibuf_data->seg_size--; ibuf_data->free_list_len--; - + mutex_exit(&ibuf_pessimistic_insert_mutex); /* Set the bit indicating that this page is no more an ibuf tree page @@ -1818,7 +1829,7 @@ ibuf_remove_free_page( /*************************************************************************** Frees excess pages from the ibuf free list. This function is called when an OS thread calls fsp services to allocate a new file segment, or a new page to a -file segment, and the thread did not own the fsp latch before this call. */ +file segment, and the thread did not own the fsp latch before this call. */ void ibuf_free_excess_pages( @@ -1829,7 +1840,7 @@ ibuf_free_excess_pages( ulint i; if (space != 0) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: calling ibuf_free_excess_pages for space %lu\n", (ulong) space); return; } @@ -1839,7 +1850,7 @@ ibuf_free_excess_pages( #endif /* UNIV_SYNC_DEBUG */ ut_ad(rw_lock_get_x_lock_count(fil_space_get_latch(space)) == 1); ut_ad(!ibuf_inside()); - + /* NOTE: We require that the thread did not own the latch before, because then we know that we can obey the correct latching order for ibuf latches */ @@ -1937,7 +1948,7 @@ ibuf_get_merge_page_nos( n_pages = 0; prev_page_no = 0; prev_space_id = 0; - + /* Go backwards from the first rec until we reach the border of the 'merge area', or the page start or the limit of storeable pages is reached */ @@ -1948,14 +1959,14 @@ ibuf_get_merge_page_nos( rec_space_id = ibuf_rec_get_space(rec); if (rec_space_id != first_space_id - || rec_page_no / IBUF_MERGE_AREA - != first_page_no / IBUF_MERGE_AREA) { + || rec_page_no / IBUF_MERGE_AREA + != first_page_no / IBUF_MERGE_AREA) { - break; + break; } - + if (rec_page_no != prev_page_no - || rec_space_id != prev_space_id) { + || rec_space_id != prev_space_id) { n_pages++; } @@ -1975,7 +1986,7 @@ ibuf_get_merge_page_nos( prev_space_id = 0; sum_volumes = 0; volume_for_page = 0; - + while (*n_stored < limit) { if (page_rec_is_supremum(rec)) { /* When no more records available, mark this with @@ -1992,19 +2003,19 @@ ibuf_get_merge_page_nos( ut_a(*n_stored < IBUF_MAX_N_PAGES_MERGED); #endif if ((rec_space_id != prev_space_id - || rec_page_no != prev_page_no) - && (prev_space_id != 0 || prev_page_no != 0)) { + || rec_page_no != prev_page_no) + && (prev_space_id != 0 || prev_page_no != 0)) { if ((prev_page_no == first_page_no - && prev_space_id == first_space_id) - || contract - || (volume_for_page > - ((IBUF_MERGE_THRESHOLD - 1) - * 4 * UNIV_PAGE_SIZE - / IBUF_PAGE_SIZE_PER_FREE_SPACE) - / IBUF_MERGE_THRESHOLD)) { - - space_ids[*n_stored] = prev_space_id; + && prev_space_id == first_space_id) + || contract + || (volume_for_page > + ((IBUF_MERGE_THRESHOLD - 1) + * 4 * UNIV_PAGE_SIZE + / IBUF_PAGE_SIZE_PER_FREE_SPACE) + / IBUF_MERGE_THRESHOLD)) { + + space_ids[*n_stored] = prev_space_id; space_versions[*n_stored] = fil_space_get_version( prev_space_id); @@ -2016,10 +2027,10 @@ ibuf_get_merge_page_nos( } if (rec_space_id != first_space_id - || rec_page_no / IBUF_MERGE_AREA - != first_page_no / IBUF_MERGE_AREA) { + || rec_page_no / IBUF_MERGE_AREA + != first_page_no / IBUF_MERGE_AREA) { - break; + break; } volume_for_page = 0; @@ -2034,7 +2045,7 @@ ibuf_get_merge_page_nos( rec_volume = ibuf_rec_get_volume(rec); volume_for_page += rec_volume; - + prev_page_no = rec_page_no; prev_space_id = rec_space_id; @@ -2081,7 +2092,7 @@ loop: mutex_enter(&ibuf_mutex); - ut_ad(ibuf_validate_low()); + ut_ad(ibuf_validate_low()); /* Choose an ibuf tree at random (though there really is only one tree in the current implementation) */ @@ -2096,15 +2107,15 @@ loop: for (;;) { if (!data->empty) { all_trees_empty = FALSE; - + if (rnd_pos < data->size) { break; } - + rnd_pos -= data->size; } - + data = UT_LIST_GET_NEXT(data_list, data); if (data == NULL) { @@ -2113,7 +2124,7 @@ loop: return(0); } - + data = UT_LIST_GET_FIRST(ibuf->data_list); } } @@ -2127,7 +2138,7 @@ loop: mtr_start(&mtr); ibuf_enter(); - + /* Open a cursor to a randomly chosen leaf of the tree, at a random position within the leaf */ @@ -2136,19 +2147,19 @@ loop: if (0 == page_get_n_recs(btr_pcur_get_page(&pcur))) { /* This tree is empty */ - - data->empty = TRUE; - ibuf_exit(); + data->empty = TRUE; + + ibuf_exit(); - mtr_commit(&mtr); - btr_pcur_close(&pcur); + mtr_commit(&mtr); + btr_pcur_close(&pcur); - mutex_exit(&ibuf_mutex); + mutex_exit(&ibuf_mutex); - goto loop; + goto loop; } - + mutex_exit(&ibuf_mutex); sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur), @@ -2165,7 +2176,7 @@ loop: buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos, n_stored); *n_pages = n_stored; - + return(sum_sizes + 1); } @@ -2204,13 +2215,13 @@ ibuf_contract_for_n_pages( them */ { ulint sum_bytes = 0; - ulint sum_pages = 0; + ulint sum_pages = 0; ulint n_bytes; ulint n_pag2; - + while (sum_pages < n_pages) { n_bytes = ibuf_contract_ext(&n_pag2, sync); - + if (n_bytes == 0) { return(sum_bytes); } @@ -2244,7 +2255,7 @@ ibuf_contract_after_insert( } sync = FALSE; - + if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_ON_INSERT_SYNC) { sync = TRUE; @@ -2291,7 +2302,7 @@ ibuf_get_volume_buffered( page_t* prev_page; ulint next_page_no; page_t* next_page; - + ut_a(trx_sys_multiple_tablespace_format); ut_ad((pcur->latch_mode == BTR_MODIFY_PREV) @@ -2301,7 +2312,7 @@ ibuf_get_volume_buffered( pcur */ volume = 0; - + rec = btr_pcur_get_rec(pcur); page = buf_frame_align(rec); @@ -2315,9 +2326,9 @@ ibuf_get_volume_buffered( break; } - + if (page_no != ibuf_rec_get_page_no(rec) - || space != ibuf_rec_get_space(rec)) { + || space != ibuf_rec_get_space(rec)) { goto count_later; } @@ -2328,7 +2339,7 @@ ibuf_get_volume_buffered( } /* Look at the previous page */ - + prev_page_no = btr_page_get_prev(page, mtr); if (prev_page_no == FIL_NULL) { @@ -2344,19 +2355,19 @@ ibuf_get_volume_buffered( rec = page_get_supremum_rec(prev_page); rec = page_rec_get_prev(rec); - + for (;;) { if (page_rec_is_infimum(rec)) { /* We cannot go to yet a previous page, because we do not have the x-latch on it, and cannot acquire one because of the latching order: we have to give up */ - + return(UNIV_PAGE_SIZE); } - + if (page_no != ibuf_rec_get_page_no(rec) - || space != ibuf_rec_get_space(rec)) { + || space != ibuf_rec_get_space(rec)) { goto count_later; } @@ -2365,7 +2376,7 @@ ibuf_get_volume_buffered( rec = page_rec_get_prev(rec); } - + count_later: rec = btr_pcur_get_rec(pcur); @@ -2378,9 +2389,9 @@ count_later: break; } - + if (page_no != ibuf_rec_get_page_no(rec) - || space != ibuf_rec_get_space(rec)) { + || space != ibuf_rec_get_space(rec)) { return(volume); } @@ -2391,7 +2402,7 @@ count_later: } /* Look at the next page */ - + next_page_no = btr_page_get_next(page, mtr); if (next_page_no == FIL_NULL) { @@ -2412,12 +2423,12 @@ count_later: if (page_rec_is_supremum(rec)) { /* We give up */ - + return(UNIV_PAGE_SIZE); } - + if (page_no != ibuf_rec_get_page_no(rec) - || space != ibuf_rec_get_space(rec)) { + || space != ibuf_rec_get_space(rec)) { return(volume); } @@ -2448,7 +2459,7 @@ ibuf_update_max_tablespace_id(void) ibuf_data = fil_space_get_ibuf_data(0); ibuf_index = ibuf_data->index; - ut_a(!ibuf_index->table->comp); + ut_a(!dict_table_is_comp(ibuf_index->table)); ibuf_enter(); @@ -2468,7 +2479,7 @@ ibuf_update_max_tablespace_id(void) field = rec_get_nth_field_old(rec, 0, &len); ut_a(len == 4); - + max_space_id = mach_read_from_4(field); } @@ -2518,7 +2529,7 @@ ibuf_insert_low( ulint bits; mtr_t mtr; mtr_t bitmap_mtr; - + ut_a(!(index->type & DICT_CLUSTERED)); ut_ad(dtuple_check_typed(entry)); @@ -2543,7 +2554,7 @@ ibuf_insert_low( #ifdef UNIV_IBUF_DEBUG fputs("Ibuf too big\n", stderr); -#endif +#endif /* Use synchronous contract (== TRUE) */ ibuf_contract(TRUE); @@ -2564,7 +2575,7 @@ ibuf_insert_low( mutex_exit(&ibuf_mutex); ibuf_exit(); - + mutex_exit(&ibuf_pessimistic_insert_mutex); err = ibuf_add_free_page(0, ibuf_data); @@ -2577,7 +2588,7 @@ ibuf_insert_low( mutex_enter(&ibuf_pessimistic_insert_mutex); ibuf_enter(); - + mutex_enter(&ibuf_mutex); } } else { @@ -2588,12 +2599,12 @@ ibuf_insert_low( heap = mem_heap_create(512); - /* Build the entry which contains the space id and the page number as + /* Build the entry which contains the space id and the page number as the first fields and the type information for other fields, and which will be inserted to the insert buffer. */ - ibuf_entry = ibuf_entry_build(entry, index->table->comp, - space, page_no, heap); + ibuf_entry = ibuf_entry_build(entry, dict_table_is_comp(index->table), + space, page_no, heap); /* Open a cursor to the insert buffer tree to calculate if we can add the new entry to it without exceeding the free space limit for the @@ -2610,7 +2621,7 @@ ibuf_insert_low( #ifdef UNIV_IBUF_DEBUG ut_a((buffered == 0) || ibuf_count_get(space, page_no)); #endif - mtr_start(&bitmap_mtr); + mtr_start(&bitmap_mtr); bitmap_page = ibuf_bitmap_get_map_page(space, page_no, &bitmap_mtr); @@ -2632,16 +2643,16 @@ ibuf_insert_low( > ibuf_index_page_calc_free_from_bits(bits)) { mtr_commit(&bitmap_mtr); - /* It may not fit */ + /* It may not fit */ err = DB_STRONG_FAIL; - do_merge = TRUE; + do_merge = TRUE; ibuf_get_merge_page_nos(FALSE, btr_pcur_get_rec(&pcur), space_ids, space_versions, page_nos, &n_stored); goto function_exit; - } + } /* Set the bitmap bit denoting that the insert buffer contains buffered entries for this index page, if the bit is not set yet */ @@ -2654,9 +2665,9 @@ ibuf_insert_low( } mtr_commit(&bitmap_mtr); - + cursor = btr_pcur_get_btr_cur(&pcur); - + if (mode == BTR_MODIFY_PREV) { err = btr_cur_optimistic_insert(BTR_NO_LOCKING_FLAG, cursor, ibuf_entry, &ins_rec, @@ -2674,7 +2685,7 @@ ibuf_insert_low( because a pessimistic insert releases the tree x-latch, which would cause the x-latching of the root after that to break the latching order. */ - + root = ibuf_tree_root_get(ibuf_data, 0, &mtr); err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG @@ -2703,18 +2714,18 @@ function_exit: ibuf_count_get(space, page_no) + 1); } #endif - if (mode == BTR_MODIFY_TREE) { + if (mode == BTR_MODIFY_TREE) { ut_ad(ibuf_validate_low()); mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_pessimistic_insert_mutex); } - + mtr_commit(&mtr); - btr_pcur_close(&pcur); + btr_pcur_close(&pcur); ibuf_exit(); - mem_heap_free(heap); + mem_heap_free(heap); mutex_enter(&ibuf_mutex); @@ -2722,13 +2733,13 @@ function_exit: ibuf_data->empty = FALSE; ibuf_data->n_inserts++; } - + mutex_exit(&ibuf_mutex); - if ((mode == BTR_MODIFY_TREE) && (err == DB_SUCCESS)) { + if ((mode == BTR_MODIFY_TREE) && (err == DB_SUCCESS)) { ibuf_contract_after_insert(entry_size); } - + if (do_merge) { #ifdef UNIV_IBUF_DEBUG ut_a(n_stored <= IBUF_MAX_N_PAGES_MERGED); @@ -2736,7 +2747,7 @@ function_exit: buf_read_ibuf_merge_pages(FALSE, space_ids, space_versions, page_nos, n_stored); } - + return(err); } @@ -2761,19 +2772,20 @@ ibuf_insert( ut_ad(dtuple_check_typed(entry)); ut_a(!(index->type & DICT_CLUSTERED)); - + if (rec_get_converted_size(index, entry) - >= page_get_free_space_of_empty(index->table->comp) / 2) { + >= page_get_free_space_of_empty( + dict_table_is_comp(index->table)) / 2) { return(FALSE); } - + err = ibuf_insert_low(BTR_MODIFY_PREV, entry, index, space, page_no, thr); if (err == DB_FAIL) { err = ibuf_insert_low(BTR_MODIFY_TREE, entry, index, space, page_no, thr); } - + if (err == DB_SUCCESS) { #ifdef UNIV_IBUF_DEBUG /* fprintf(stderr, "Ibuf insert for page no %lu of index %s\n", @@ -2787,7 +2799,7 @@ ibuf_insert( return(FALSE); } } - + /************************************************************************ During merge, inserts to an index page a secondary index entry extracted from the insert buffer. */ @@ -2810,7 +2822,8 @@ ibuf_insert_to_index_page( ut_ad(ibuf_inside()); ut_ad(dtuple_check_typed(entry)); - if (UNIV_UNLIKELY(index->table->comp != (ibool)!!page_is_comp(page))) { + if (UNIV_UNLIKELY(dict_table_is_comp(index->table) + != (ibool)!!page_is_comp(page))) { fputs( "InnoDB: Trying to insert a record from the insert buffer to an index page\n" "InnoDB: but the 'compact' flag does not match!\n", stderr); @@ -2827,7 +2840,7 @@ ibuf_insert_to_index_page( dump: buf_page_print(page); - dtuple_print(stderr, entry); + dtuple_print(stderr, entry); fputs( "InnoDB: The table where where this index record belongs\n" @@ -2840,14 +2853,14 @@ ibuf_insert_to_index_page( low_match = page_cur_search(page, index, entry, PAGE_CUR_LE, &page_cur); - + if (low_match == dtuple_get_n_fields(entry)) { rec = page_cur_get_rec(&page_cur); - + btr_cur_del_unmark_for_ibuf(rec, mtr); } else { rec = page_cur_tuple_insert(&page_cur, entry, index, mtr); - + if (rec == NULL) { /* If the record did not fit, reorganize */ @@ -2873,7 +2886,7 @@ ibuf_insert_to_index_page( "\nInnoDB: The table where where this index record belongs\n" "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n" "InnoDB: that table.\n", stderr); - + bitmap_page = ibuf_bitmap_get_map_page( buf_frame_get_space_id(page), buf_frame_get_page_no(page), @@ -2887,7 +2900,7 @@ ibuf_insert_to_index_page( fputs( "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); - } + } } } } @@ -2915,7 +2928,7 @@ ibuf_delete_rec( ibuf_data_t* ibuf_data; page_t* root; ulint err; - + ut_ad(ibuf_inside()); success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr); @@ -2930,7 +2943,7 @@ ibuf_delete_rec( #endif return(FALSE); } - + /* We have to resort to a pessimistic delete from ibuf */ btr_pcur_store_position(pcur, mtr); @@ -2944,7 +2957,7 @@ ibuf_delete_rec( mutex_enter(&ibuf_mutex); mtr_start(mtr); - + success = btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr); if (!success) { @@ -3051,7 +3064,7 @@ ibuf_merge_or_delete_for_page( return; } -#endif +#endif if (ibuf_fixed_addr_page(page_no) || fsp_descr_page(page_no) || trx_sys_hdr_page(space, page_no)) { return; @@ -3103,12 +3116,12 @@ ibuf_merge_or_delete_for_page( if (!trx_sys_multiple_tablespace_format) { ut_a(trx_doublewrite_must_reset_space_ids); - search_tuple = ibuf_search_tuple_build(space, page_no, heap); + search_tuple = ibuf_search_tuple_build(space, page_no, heap); } else { - search_tuple = ibuf_new_search_tuple_build(space, page_no, + search_tuple = ibuf_new_search_tuple_build(space, page_no, heap); } - + if (page) { /* Move the ownership of the x-latch on the page to this OS thread, so that we can acquire a second x-latch on it. This @@ -3117,22 +3130,22 @@ ibuf_merge_or_delete_for_page( block = buf_block_align(page); rw_lock_x_lock_move_ownership(&(block->lock)); - + if (fil_page_get_type(page) != FIL_PAGE_INDEX) { corruption_noticed = TRUE; - + ut_print_timestamp(stderr); mtr_start(&mtr); fputs(" InnoDB: Dump of the ibuf bitmap page:\n", stderr); - + bitmap_page = ibuf_bitmap_get_map_page(space, page_no, &mtr); buf_page_print(bitmap_page); - + mtr_commit(&mtr); fputs("\nInnoDB: Dump of the page:\n", stderr); @@ -3169,7 +3182,7 @@ loop: buf_page_dbg_add_level(page, SYNC_TREE_NODE); #endif /* UNIV_SYNC_DEBUG */ } - + /* Position pcur in the insert buffer at the first entry for this index page */ btr_pcur_open_on_user_rec(ibuf_data->index, search_tuple, PAGE_CUR_GE, @@ -3187,7 +3200,7 @@ loop: /* Check if the entry is for this index page */ if (ibuf_rec_get_page_no(ibuf_rec) != page_no - || ibuf_rec_get_space(ibuf_rec) != space) { + || ibuf_rec_get_space(ibuf_rec) != space) { if (page) { page_header_reset_last_insert(page, &mtr); } @@ -3198,7 +3211,7 @@ loop: fputs("InnoDB: Discarding record\n ", stderr); rec_print_old(stderr, ibuf_rec); fputs("\n from the insert buffer!\n\n", stderr); - } else if (page) { + } else if (page) { /* Now we have at pcur a record which should be inserted to the index page; NOTE that the call below copies pointers to fields in ibuf_rec, and we must @@ -3208,12 +3221,12 @@ loop: dulint max_trx_id = page_get_max_trx_id( buf_frame_align(ibuf_rec)); page_update_max_trx_id(page, max_trx_id); - + entry = ibuf_build_entry_from_ibuf_rec(ibuf_rec, heap, &dummy_index); #ifdef UNIV_IBUF_DEBUG volume += rec_get_converted_size(dummy_index, entry) - + page_dir_calc_reserved_space(1); + + page_dir_calc_reserved_space(1); ut_a(volume <= 4 * UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE); #endif @@ -3223,7 +3236,7 @@ loop: } n_inserts++; - + /* Delete the record from ibuf */ if (ibuf_delete_rec(space, page_no, &pcur, search_tuple, &mtr)) { @@ -3235,7 +3248,7 @@ loop: if (btr_pcur_is_after_last_on_page(&pcur, &mtr)) { mtr_commit(&mtr); - btr_pcur_close(&pcur); + btr_pcur_close(&pcur); goto loop; } @@ -3274,13 +3287,13 @@ reset_bit: n_inserts, volume, page_no); */ #endif mtr_commit(&mtr); - btr_pcur_close(&pcur); + btr_pcur_close(&pcur); mem_heap_free(heap); /* Protect our statistics keeping from race conditions */ mutex_enter(&ibuf_mutex); - ibuf_data->n_merges++; + ibuf_data->n_merges++; ibuf_data->n_merged_recs += n_inserts; mutex_exit(&ibuf_mutex); @@ -3328,7 +3341,7 @@ ibuf_delete_for_discarded_space( cursor positioned at the first entry for this space id */ search_tuple = ibuf_new_search_tuple_build(space, 0, heap); - + n_inserts = 0; loop: ibuf_enter(); @@ -3359,7 +3372,7 @@ loop: page_no = ibuf_rec_get_page_no(ibuf_rec); n_inserts++; - + /* Delete the record from ibuf */ closed = ibuf_delete_rec(space, page_no, &pcur, search_tuple, &mtr); @@ -3374,7 +3387,7 @@ loop: if (btr_pcur_is_after_last_on_page(&pcur, &mtr)) { mtr_commit(&mtr); - btr_pcur_close(&pcur); + btr_pcur_close(&pcur); ibuf_exit(); @@ -3384,12 +3397,12 @@ loop: leave_loop: mtr_commit(&mtr); - btr_pcur_close(&pcur); + btr_pcur_close(&pcur); /* Protect our statistics keeping from race conditions */ mutex_enter(&ibuf_mutex); - ibuf_data->n_merges++; + ibuf_data->n_merges++; ibuf_data->n_merged_recs += n_inserts; mutex_exit(&ibuf_mutex); @@ -3420,12 +3433,12 @@ ibuf_validate_low(void) #endif /* UNIV_SYNC_DEBUG */ sum_sizes = 0; - + data = UT_LIST_GET_FIRST(ibuf->data_list); while (data) { sum_sizes += data->size; - + data = UT_LIST_GET_NEXT(data_list, data); } @@ -3468,7 +3481,7 @@ ibuf_is_empty(void) "InnoDB: run to completion.\n"); } } else { - ut_a(data->empty == FALSE); + ut_a(data->empty == FALSE); is_empty = FALSE; } @@ -3503,10 +3516,10 @@ ibuf_print( while (data) { fprintf(file, - "Ibuf for space %lu: size %lu, free list len %lu, seg size %lu,", - (ulong) data->space, (ulong) data->size, - (ulong) data->free_list_len, - (ulong) data->seg_size); + "Ibuf for space %lu: size %lu, free list len %lu, seg size %lu,", + (ulong) data->space, (ulong) data->size, + (ulong) data->free_list_len, + (ulong) data->seg_size); if (data->empty) { fputs(" is empty\n", file); @@ -3516,21 +3529,21 @@ ibuf_print( fprintf(file, "Ibuf for space %lu: size %lu, free list len %lu, seg size %lu,\n" "%lu inserts, %lu merged recs, %lu merges\n", - (ulong) data->space, - (ulong) data->size, - (ulong) data->free_list_len, - (ulong) data->seg_size, - (ulong) data->n_inserts, - (ulong) data->n_merged_recs, - (ulong) data->n_merges); + (ulong) data->space, + (ulong) data->size, + (ulong) data->free_list_len, + (ulong) data->seg_size, + (ulong) data->n_inserts, + (ulong) data->n_merged_recs, + (ulong) data->n_merges); #ifdef UNIV_IBUF_DEBUG for (i = 0; i < IBUF_COUNT_N_PAGES; i++) { if (ibuf_count_get(data->space, i) > 0) { fprintf(stderr, "Ibuf count for page %lu is %lu\n", - (ulong) i, - (ulong) ibuf_count_get(data->space, i)); + (ulong) i, + (ulong) ibuf_count_get(data->space, i)); } } #endif diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index d28b0b129a1..288b0459b13 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -43,7 +43,7 @@ optimization */ /* This flag ORed to latch mode says that we can ignore possible UNIQUE definition on secondary indexes when we decide if we can use the insert buffer to speed up inserts */ -#define BTR_IGNORE_SEC_UNIQUE 2048 +#define BTR_IGNORE_SEC_UNIQUE 2048 /****************************************************************** Gets the root node of a tree and x-latches it. */ @@ -144,7 +144,7 @@ UNIV_INLINE ulint btr_node_ptr_get_child_page_no( /*===========================*/ - /* out: child node address */ + /* out: child node address */ rec_t* rec, /* in: node pointer record */ const ulint* offsets);/* in: array returned by rec_get_offsets() */ /**************************************************************** @@ -277,6 +277,7 @@ btr_node_ptr_delete( dict_tree_t* tree, /* in: index tree */ page_t* page, /* in: page whose node pointer is deleted */ mtr_t* mtr); /* in: mtr */ +#ifdef UNIV_DEBUG /**************************************************************** Checks that the node pointer to a page is appropriate. */ @@ -287,6 +288,7 @@ btr_check_node_ptr( dict_tree_t* tree, /* in: index tree */ page_t* page, /* in: index page */ mtr_t* mtr); /* in: mtr */ +#endif /* UNIV_DEBUG */ /***************************************************************** Tries to merge the page first to the left immediate brother if such a brother exists, and the node pointers to the current page and to the @@ -374,7 +376,7 @@ void btr_page_free( /*==========*/ dict_tree_t* tree, /* in: index tree */ - page_t* page, /* in: page to be freed, x-latched */ + page_t* page, /* in: page to be freed, x-latched */ mtr_t* mtr); /* in: mtr */ /****************************************************************** Frees a file page used in an index tree. Can be used also to BLOB @@ -385,7 +387,7 @@ void btr_page_free_low( /*==============*/ dict_tree_t* tree, /* in: index tree */ - page_t* page, /* in: page to be freed, x-latched */ + page_t* page, /* in: page to be freed, x-latched */ ulint level, /* in: page level */ mtr_t* mtr); /* in: mtr */ #ifdef UNIV_BTR_PRINT @@ -412,7 +414,7 @@ the index. */ ibool btr_index_rec_validate( -/*====================*/ +/*===================*/ /* out: TRUE if ok */ rec_t* rec, /* in: index record */ dict_index_t* index, /* in: index */ @@ -429,11 +431,11 @@ btr_validate_tree( dict_tree_t* tree, /* in: tree */ trx_t* trx); /* in: transaction or NULL */ -#define BTR_N_LEAF_PAGES 1 +#define BTR_N_LEAF_PAGES 1 #define BTR_TOTAL_SIZE 2 #ifndef UNIV_NONINL #include "btr0btr.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic index a0860b1c3a7..c24b1603bd2 100644 --- a/storage/innobase/include/btr0btr.ic +++ b/storage/innobase/include/btr0btr.ic @@ -28,7 +28,7 @@ btr_page_get( page = buf_page_get(space, page_no, mode, mtr); #ifdef UNIV_SYNC_DEBUG if (mode != RW_NO_LATCH) { - + buf_page_dbg_add_level(page, SYNC_TREE_NODE); } #endif @@ -72,7 +72,7 @@ btr_page_get_level_low( ulint level; ut_ad(page); - + level = mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL); ut_ad(level <= BTR_MAX_NODE_LEVEL); @@ -92,7 +92,7 @@ btr_page_get_level( { ut_ad(page && mtr); - return(btr_page_get_level_low(page)); + return(btr_page_get_level_low(page)); } /************************************************************ @@ -124,9 +124,9 @@ btr_page_get_next( { ut_ad(page && mtr); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_S_FIX)); + MTR_MEMO_PAGE_X_FIX) + || mtr_memo_contains(mtr, buf_block_align(page), + MTR_MEMO_PAGE_S_FIX)); return(mach_read_from_4(page + FIL_PAGE_NEXT)); } @@ -157,7 +157,7 @@ btr_page_get_prev( mtr_t* mtr __attribute__((unused))) /* in: mini-transaction handle */ { ut_ad(page && mtr); - + return(mach_read_from_4(page + FIL_PAGE_PREV)); } @@ -182,7 +182,7 @@ UNIV_INLINE ulint btr_node_ptr_get_child_page_no( /*===========================*/ - /* out: child node address */ + /* out: child node address */ rec_t* rec, /* in: node pointer record */ const ulint* offsets)/* in: array returned by rec_get_offsets() */ { @@ -192,12 +192,12 @@ btr_node_ptr_get_child_page_no( ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec)); - /* The child address is in the last field */ + /* The child address is in the last field */ field = rec_get_nth_field(rec, offsets, rec_offs_n_fields(offsets) - 1, &len); ut_ad(len == 4); - + page_no = mach_read_from_4(field); if (UNIV_UNLIKELY(page_no == 0)) { @@ -223,11 +223,11 @@ btr_leaf_page_release( ut_ad(!mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_MODIFY)); if (latch_mode == BTR_SEARCH_LEAF) { - mtr_memo_release(mtr, buf_block_align(page), + mtr_memo_release(mtr, buf_block_align(page), MTR_MEMO_PAGE_S_FIX); } else { ut_ad(latch_mode == BTR_MODIFY_LEAF); - mtr_memo_release(mtr, buf_block_align(page), + mtr_memo_release(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX); } } diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index 352d1739b6a..cb6cb1b1a4d 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -72,7 +72,7 @@ UNIV_INLINE void btr_cur_position( /*=============*/ - dict_index_t* index, /* in: index */ + dict_index_t* index, /* in: index */ rec_t* rec, /* in: record in tree */ btr_cur_t* cursor);/* in: cursor */ /************************************************************************ @@ -550,7 +550,7 @@ btr_push_update_extern_fields( to have space for all fields in rec */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ upd_t* update);/* in: update vector or NULL */ - + /*######################################################################*/ @@ -697,5 +697,5 @@ extern ulint btr_cur_n_sea_old; #ifndef UNIV_NONINL #include "btr0cur.ic" #endif - + #endif diff --git a/storage/innobase/include/btr0cur.ic b/storage/innobase/include/btr0cur.ic index bf8a6efb68d..5d2ae768416 100644 --- a/storage/innobase/include/btr0cur.ic +++ b/storage/innobase/include/btr0cur.ic @@ -53,7 +53,8 @@ btr_cur_get_page( btr_cur_t* cursor) /* in: tree cursor */ { page_t* page = buf_frame_align(page_cur_get_rec(&(cursor->page_cur))); - ut_ad(!!page_is_comp(page) == cursor->index->table->comp); + ut_ad(!!page_is_comp(page) + == dict_table_is_comp(cursor->index->table)); return(page); } @@ -75,7 +76,7 @@ UNIV_INLINE void btr_cur_position( /*=============*/ - dict_index_t* index, /* in: index */ + dict_index_t* index, /* in: index */ rec_t* rec, /* in: record in tree */ btr_cur_t* cursor) /* in: cursor */ { @@ -96,7 +97,7 @@ btr_cur_compress_recommendation( mtr_t* mtr) /* in: mtr */ { page_t* page; - + ut_ad(mtr_memo_contains(mtr, buf_block_align( btr_cur_get_page(cursor)), MTR_MEMO_PAGE_X_FIX)); @@ -104,27 +105,27 @@ btr_cur_compress_recommendation( page = btr_cur_get_page(cursor); if ((page_get_data_size(page) < BTR_CUR_PAGE_COMPRESS_LIMIT) - || ((btr_page_get_next(page, mtr) == FIL_NULL) - && (btr_page_get_prev(page, mtr) == FIL_NULL))) { + || ((btr_page_get_next(page, mtr) == FIL_NULL) + && (btr_page_get_prev(page, mtr) == FIL_NULL))) { /* The page fillfactor has dropped below a predefined minimum value OR the level in the B-tree contains just one page: we recommend compression if this is not the root page. */ - + if (dict_tree_get_page((cursor->index)->tree) - == buf_frame_get_page_no(page)) { + == buf_frame_get_page_no(page)) { - /* It is the root page */ + /* It is the root page */ - return(FALSE); + return(FALSE); } return(TRUE); } return(FALSE); -} +} /************************************************************************* Checks if the record on which the cursor is placed can be deleted without @@ -140,7 +141,7 @@ btr_cur_can_delete_without_compress( mtr_t* mtr) /* in: mtr */ { page_t* page; - + ut_ad(mtr_memo_contains(mtr, buf_block_align( btr_cur_get_page(cursor)), MTR_MEMO_PAGE_X_FIX)); @@ -148,21 +149,21 @@ btr_cur_can_delete_without_compress( page = btr_cur_get_page(cursor); if ((page_get_data_size(page) - rec_size < BTR_CUR_PAGE_COMPRESS_LIMIT) - || ((btr_page_get_next(page, mtr) == FIL_NULL) - && (btr_page_get_prev(page, mtr) == FIL_NULL)) - || (page_get_n_recs(page) < 2)) { + || ((btr_page_get_next(page, mtr) == FIL_NULL) + && (btr_page_get_prev(page, mtr) == FIL_NULL)) + || (page_get_n_recs(page) < 2)) { /* The page fillfactor will drop below a predefined minimum value, OR the level in the B-tree contains just one page, OR the page will become empty: we recommend compression if this is not the root page. */ - + if (dict_tree_get_page((cursor->index)->tree) - == buf_frame_get_page_no(page)) { + == buf_frame_get_page_no(page)) { - /* It is the root page */ + /* It is the root page */ - return(TRUE); + return(TRUE); } return(FALSE); diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h index eb3822aab7a..0276fe45922 100644 --- a/storage/innobase/include/btr0pcur.h +++ b/storage/innobase/include/btr0pcur.h @@ -152,7 +152,7 @@ btr_pcur_open_on_user_rec( ulint mode, /* in: PAGE_CUR_L, ... */ ulint latch_mode, /* in: BTR_SEARCH_LEAF or BTR_MODIFY_LEAF */ - btr_pcur_t* cursor, /* in: memory buffer for persistent + btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */ mtr_t* mtr); /* in: mtr */ /************************************************************************** @@ -208,7 +208,7 @@ btr_pcur_restore_position( whose ordering fields are identical to the ones of the original user record */ ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */ - btr_pcur_t* cursor, /* in: detached persistent cursor */ + btr_pcur_t* cursor, /* in: detached persistent cursor */ mtr_t* mtr); /* in: mtr */ /****************************************************************** If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY, @@ -387,7 +387,7 @@ btr_pcur_is_on_user_rec( btr_pcur_t* cursor, /* in: persistent cursor */ mtr_t* mtr); /* in: mtr */ /************************************************************* -Checks if the persistent cursor is after the last user record on +Checks if the persistent cursor is after the last user record on a page. */ UNIV_INLINE ibool @@ -396,7 +396,7 @@ btr_pcur_is_after_last_on_page( btr_pcur_t* cursor, /* in: persistent cursor */ mtr_t* mtr); /* in: mtr */ /************************************************************* -Checks if the persistent cursor is before the first user record on +Checks if the persistent cursor is before the first user record on a page. */ UNIV_INLINE ibool @@ -512,5 +512,5 @@ struct btr_pcur_struct{ #ifndef UNIV_NONINL #include "btr0pcur.ic" #endif - + #endif diff --git a/storage/innobase/include/btr0pcur.ic b/storage/innobase/include/btr0pcur.ic index 9a7d7867025..a8aa82cf203 100644 --- a/storage/innobase/include/btr0pcur.ic +++ b/storage/innobase/include/btr0pcur.ic @@ -102,7 +102,7 @@ btr_pcur_get_rec( { ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + return(page_cur_get_rec(btr_pcur_get_page_cur(cursor))); } @@ -152,7 +152,7 @@ btr_pcur_get_low_match( } /************************************************************* -Checks if the persistent cursor is after the last user record on +Checks if the persistent cursor is after the last user record on a page. */ UNIV_INLINE ibool @@ -164,12 +164,12 @@ btr_pcur_is_after_last_on_page( UT_NOT_USED(mtr); ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor))); } /************************************************************* -Checks if the persistent cursor is before the first user record on +Checks if the persistent cursor is before the first user record on a page. */ UNIV_INLINE ibool @@ -181,7 +181,7 @@ btr_pcur_is_before_first_on_page( UT_NOT_USED(mtr); ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor))); } @@ -196,9 +196,9 @@ btr_pcur_is_on_user_rec( { ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + if ((btr_pcur_is_before_first_on_page(cursor, mtr)) - || (btr_pcur_is_after_last_on_page(cursor, mtr))) { + || (btr_pcur_is_after_last_on_page(cursor, mtr))) { return(FALSE); } @@ -218,7 +218,7 @@ btr_pcur_is_before_first_in_tree( { ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + if (btr_page_get_prev(btr_pcur_get_page(cursor), mtr) != FIL_NULL) { return(FALSE); @@ -239,7 +239,7 @@ btr_pcur_is_after_last_in_tree( { ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + if (btr_page_get_next(btr_pcur_get_page(cursor), mtr) != FIL_NULL) { return(FALSE); @@ -260,7 +260,7 @@ btr_pcur_move_to_next_on_page( UT_NOT_USED(mtr); ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + page_cur_move_to_next(btr_pcur_get_page_cur(cursor)); cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; @@ -278,7 +278,7 @@ btr_pcur_move_to_prev_on_page( UT_NOT_USED(mtr); ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + page_cur_move_to_prev(btr_pcur_get_page_cur(cursor)); cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; @@ -295,7 +295,7 @@ btr_pcur_move_to_last_on_page( { UT_NOT_USED(mtr); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + page_cur_set_after_last(buf_frame_align(btr_pcur_get_rec(cursor)), btr_pcur_get_page_cur(cursor)); @@ -356,14 +356,14 @@ btr_pcur_move_to_next( ut_ad(cursor->latch_mode != BTR_NO_LATCHES); cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; - + if (btr_pcur_is_after_last_on_page(cursor, mtr)) { if (btr_pcur_is_after_last_in_tree(cursor, mtr)) { return(FALSE); } - + btr_pcur_move_to_next_page(cursor, mtr); return(TRUE); @@ -371,7 +371,7 @@ btr_pcur_move_to_next( btr_pcur_move_to_next_on_page(cursor, mtr); - return(TRUE); + return(TRUE); } /****************************************************************** @@ -388,12 +388,12 @@ btr_pcur_commit( { ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED); - pcur->latch_mode = BTR_NO_LATCHES; + pcur->latch_mode = BTR_NO_LATCHES; mtr_commit(pcur->mtr); pcur->pos_state = BTR_PCUR_WAS_POSITIONED; -} +} /****************************************************************** Differs from btr_pcur_commit in that we can specify the mtr to commit. */ @@ -406,12 +406,12 @@ btr_pcur_commit_specify_mtr( { ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED); - pcur->latch_mode = BTR_NO_LATCHES; + pcur->latch_mode = BTR_NO_LATCHES; mtr_commit(mtr); pcur->pos_state = BTR_PCUR_WAS_POSITIONED; -} +} /****************************************************************** Sets the pcur latch mode to BTR_NO_LATCHES. */ @@ -422,7 +422,7 @@ btr_pcur_detach( btr_pcur_t* pcur) /* in: persistent cursor */ { ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED); - + pcur->latch_mode = BTR_NO_LATCHES; pcur->pos_state = BTR_PCUR_WAS_POSITIONED; @@ -440,7 +440,7 @@ btr_pcur_is_detached( if (pcur->latch_mode == BTR_NO_LATCHES) { return(TRUE); - } + } return(FALSE); } @@ -452,7 +452,7 @@ void btr_pcur_init( /*==========*/ btr_pcur_t* pcur) /* in: persistent cursor */ -{ +{ pcur->old_stored = BTR_PCUR_OLD_NOT_STORED; pcur->old_rec_buf = NULL; pcur->old_rec = NULL; @@ -485,7 +485,7 @@ btr_pcur_open( cursor->latch_mode = latch_mode; cursor->search_mode = mode; - + /* Search with the tree cursor */ btr_cursor = btr_pcur_get_btr_cur(cursor); @@ -527,7 +527,7 @@ btr_pcur_open_with_no_init( cursor->latch_mode = latch_mode; cursor->search_mode = mode; - + /* Search with the tree cursor */ btr_cursor = btr_pcur_get_btr_cur(cursor); @@ -591,7 +591,7 @@ btr_pcur_open_at_rnd_pos( cursor->latch_mode = latch_mode; cursor->search_mode = PAGE_CUR_G; - + btr_pcur_init(cursor); btr_cur_open_at_rnd_pos(index, latch_mode, @@ -601,7 +601,7 @@ btr_pcur_open_at_rnd_pos( cursor->trx_if_known = NULL; } - + /****************************************************************** Frees the possible memory heap of a persistent cursor and sets the latch mode of the persistent cursor to BTR_NO_LATCHES. */ @@ -622,7 +622,7 @@ btr_pcur_close( cursor->btr_cur.page_cur.rec = NULL; cursor->old_rec = NULL; cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; - + cursor->latch_mode = BTR_NO_LATCHES; cursor->pos_state = BTR_PCUR_NOT_POSITIONED; diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h index 78e88a24083..b64d5e62e03 100644 --- a/storage/innobase/include/btr0sea.h +++ b/storage/innobase/include/btr0sea.h @@ -57,13 +57,13 @@ both have sensible values. */ ibool btr_search_guess_on_hash( /*=====================*/ - /* out: TRUE if succeeded */ + /* out: TRUE if succeeded */ dict_index_t* index, /* in: index */ btr_search_t* info, /* in: index search info */ dtuple_t* tuple, /* in: logical record */ ulint mode, /* in: PAGE_CUR_L, ... */ - ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */ - btr_cur_t* cursor, /* out: tree cursor */ + ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */ + btr_cur_t* cursor, /* out: tree cursor */ ulint has_search_latch,/* in: latch mode the caller currently has on btr_search_latch: RW_S_LATCH, RW_X_LATCH, or 0 */ @@ -169,7 +169,7 @@ struct btr_search_struct{ ulint n_hash_potential;/* number of consecutive searches which would have succeeded, or did succeed, using the hash index */ - /*----------------------*/ + /*----------------------*/ ulint n_fields; /* recommended prefix length for hash search: number of full fields */ ulint n_bytes; /* recommended prefix: number of bytes in @@ -250,4 +250,4 @@ much timeout. This is to reduce contention. */ #include "btr0sea.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/btr0sea.ic b/storage/innobase/include/btr0sea.ic index 8a41042f713..f4e33027c25 100644 --- a/storage/innobase/include/btr0sea.ic +++ b/storage/innobase/include/btr0sea.ic @@ -16,7 +16,7 @@ Updates the search info. */ void btr_search_info_update_slow( /*========================*/ - btr_search_t* info, /* in: search info */ + btr_search_t* info, /* in/out: search info */ btr_cur_t* cursor);/* in: cursor which was just positioned */ /************************************************************************ diff --git a/storage/innobase/include/btr0types.h b/storage/innobase/include/btr0types.h index 03a61480e2e..8fa0bf0602d 100644 --- a/storage/innobase/include/btr0types.h +++ b/storage/innobase/include/btr0types.h @@ -15,7 +15,7 @@ Created 2/17/1996 Heikki Tuuri #include "page0types.h" typedef struct btr_pcur_struct btr_pcur_t; -typedef struct btr_cur_struct btr_cur_t; +typedef struct btr_cur_struct btr_cur_t; typedef struct btr_search_struct btr_search_t; -#endif +#endif diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index ae8d0411c12..12aac878614 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1,14 +1,14 @@ /* Innobase relational database engine; Copyright (C) 2001 Innobase Oy - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License 2 as published by the Free Software Foundation in June 1991. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License 2 along with this program (in file COPYING); if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ @@ -55,14 +55,14 @@ Created 11/5/1995 Heikki Tuuri /* Magic value to use instead of checksums when they are disabled */ #define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL -extern buf_pool_t* buf_pool; /* The buffer pool of the database */ +extern buf_pool_t* buf_pool; /* The buffer pool of the database */ #ifdef UNIV_DEBUG extern ibool buf_debug_prints;/* If this is set TRUE, the program prints info whenever read or flush occurs */ #endif /* UNIV_DEBUG */ extern ulint srv_buf_pool_write_requests; /* variable to count write request - issued */ + issued */ /************************************************************************ Creates the buffer pool. */ @@ -134,7 +134,7 @@ buf_frame_copy( NOTE! The following macros should be used instead of buf_page_get_gen, to improve debugging. Only values RW_S_LATCH and RW_X_LATCH are allowed in LA! */ -#define buf_page_get(SP, OF, LA, MTR) buf_page_get_gen(\ +#define buf_page_get(SP, OF, LA, MTR) buf_page_get_gen(\ SP, OF, LA, NULL,\ BUF_GET, __FILE__, __LINE__, MTR) /****************************************************************** @@ -143,13 +143,13 @@ read the contents of the page unless you know it is safe. Do not modify the contents of the page! We have separated this case, because it is error-prone programming not to set a latch, and it should be used with care. */ -#define buf_page_get_with_no_latch(SP, OF, MTR) buf_page_get_gen(\ +#define buf_page_get_with_no_latch(SP, OF, MTR) buf_page_get_gen(\ SP, OF, RW_NO_LATCH, NULL,\ BUF_GET_NO_LATCH, __FILE__, __LINE__, MTR) /****************************************************************** NOTE! The following macros should be used instead of buf_page_get_gen, to improve debugging. Only values RW_S_LATCH and RW_X_LATCH are allowed as LA! */ -#define buf_page_get_nowait(SP, OF, LA, MTR) buf_page_get_gen(\ +#define buf_page_get_nowait(SP, OF, LA, MTR) buf_page_get_gen(\ SP, OF, LA, NULL,\ BUF_GET_NOWAIT, __FILE__, __LINE__, MTR) /****************************************************************** @@ -266,7 +266,7 @@ the buffer pool. */ void buf_page_make_young( -/*=================*/ +/*================*/ buf_frame_t* frame); /* in: buffer frame of a file page */ /************************************************************************ Returns TRUE if the page can be found in the buffer pool hash table. NOTE @@ -380,7 +380,7 @@ buf_block_modify_clock_inc( /* out: new value */ buf_block_t* block); /* in: block */ /************************************************************************ -Returns the value of the modify clock. The caller must have an s-lock +Returns the value of the modify clock. The caller must have an s-lock or x-lock on the block. */ UNIV_INLINE dulint @@ -396,12 +396,12 @@ on 32-bit and 64-bit architectures. */ ulint buf_calc_page_new_checksum( /*=======================*/ - /* out: checksum */ - byte* page); /* in: buffer page */ + /* out: checksum */ + byte* page); /* in: buffer page */ /************************************************************************ In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only looked at the first few bytes of the page. This calculates that old -checksum. +checksum. NOTE: we must first store the new formula checksum to FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum because this takes that field as an input! */ @@ -409,8 +409,8 @@ because this takes that field as an input! */ ulint buf_calc_page_old_checksum( /*=======================*/ - /* out: checksum */ - byte* page); /* in: buffer page */ + /* out: checksum */ + byte* page); /* in: buffer page */ /************************************************************************ Checks if a page is corrupt. */ @@ -648,7 +648,7 @@ Sets the io_fix flag to BUF_IO_READ and sets a non-recursive exclusive lock on the buffer frame. The io-handler must take care that the flag is cleared and the lock released later. This is one of the functions which perform the state transition NOT_USED => FILE_PAGE to a block (the other is -buf_page_create). */ +buf_page_create). */ buf_block_t* buf_page_init_for_read( @@ -704,7 +704,7 @@ buf_get_free_list_len(void); /*=======================*/ - + /* The buffer control block structure */ struct buf_block_struct{ @@ -745,8 +745,6 @@ struct buf_block_struct{ buffer pool which are index pages, but this flag is not set because we do not keep track of all pages */ - dict_index_t* index; /* index for which the adaptive - hash index has been created */ /* 2. Page flushing fields */ UT_LIST_NODE_T(buf_block_t) flush_list; @@ -820,7 +818,7 @@ struct buf_block_struct{ /* 5. Hash search fields: NOTE that the first 4 fields are NOT protected by any semaphore! */ - + ulint n_hash_helps; /* counter which controls building of a new hash index for the page */ ulint n_fields; /* recommended prefix length for hash @@ -832,8 +830,14 @@ struct buf_block_struct{ whether the leftmost record of several records with the same prefix should be indexed in the hash index */ - - /* The following 4 fields are protected by btr_search_latch: */ + + /* These 6 fields may only be modified when we have + an x-latch on btr_search_latch AND + a) we are holding an s-latch or x-latch on block->lock or + b) we know that block->buf_fix_count == 0. + + An exception to this is when we init or create a page + in the buffer pool in buf0buf.c. */ ibool is_hashed; /* TRUE if hash index has already been built on this page; note that it does @@ -850,6 +854,8 @@ struct buf_block_struct{ ulint curr_side; /* BTR_SEARCH_LEFT_SIDE or BTR_SEARCH_RIGHT_SIDE in hash indexing */ + dict_index_t* index; /* Index for which the adaptive + hash index has been created. */ /* 6. Debug fields */ #ifdef UNIV_SYNC_DEBUG rw_lock_t debug_latch; /* in the debug version, each thread @@ -857,9 +863,9 @@ struct buf_block_struct{ an s-latch here; so we can use the debug utilities in sync0rw */ #endif - ibool file_page_was_freed; - /* this is set to TRUE when fsp - frees a page in buffer pool */ + ibool file_page_was_freed; + /* this is set to TRUE when fsp + frees a page in buffer pool */ }; #define BUF_BLOCK_MAGIC_N 41526563 @@ -971,7 +977,7 @@ struct buf_pool_struct{ physical memory is mapped to a frame */ UT_LIST_BASE_NODE_T(buf_block_t) LRU; /* base node of the LRU list */ - buf_block_t* LRU_old; /* pointer to the about 3/8 oldest + buf_block_t* LRU_old; /* pointer to the about 3/8 oldest blocks in the LRU list; NULL if LRU length less than BUF_LRU_OLD_MIN_LEN */ ulint LRU_old_len; /* length of the LRU list from @@ -1013,8 +1019,8 @@ MEMORY: is not in free list, LRU list, or flush list, nor page FILE_PAGE: space and offset are defined, is in page hash table if io_fix == BUF_IO_WRITE, pool: no_flush[block->flush_type] is in reset state, - pool: n_flush[block->flush_type] > 0 - + pool: n_flush[block->flush_type] > 0 + (1) if buf_fix_count == 0, then is in LRU list, not in free list is in flush list, @@ -1023,23 +1029,23 @@ FILE_PAGE: space and offset are defined, is in page hash table if and only if io_fix == BUF_IO_READ is s-locked, if and only if io_fix == BUF_IO_WRITE - + (2) if buf_fix_count > 0, then is not in LRU list, not in free list is in flush list, if and only if oldest_modification > 0 - if io_fix == BUF_IO_READ, + if io_fix == BUF_IO_READ, is x-locked if io_fix == BUF_IO_WRITE, is s-locked - + State transitions: NOT_USED => READY_FOR_USE READY_FOR_USE => MEMORY READY_FOR_USE => FILE_PAGE MEMORY => NOT_USED -FILE_PAGE => NOT_USED NOTE: This transition is allowed if and only if +FILE_PAGE => NOT_USED NOTE: This transition is allowed if and only if (1) buf_fix_count == 0, (2) oldest_modification == 0, and (3) io_fix == 0. diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index d949254d47d..15187c03636 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -41,7 +41,7 @@ buf_pool_get_curr_size(void) /* out: size in bytes */ { return((buf_pool->n_frames) * UNIV_PAGE_SIZE); -} +} /************************************************************************* Gets the maximum size of buffer buf_pool in bytes. In the case of AWE, the @@ -53,7 +53,7 @@ buf_pool_get_max_size(void) /* out: size in bytes */ { return((buf_pool->n_frames) * UNIV_PAGE_SIZE); -} +} /*********************************************************************** Accessor function for block array. */ @@ -69,7 +69,7 @@ buf_pool_get_nth_block( ut_ad(i < buf_pool->max_size); return(i + buf_pool->blocks); -} +} /*********************************************************************** Checks if a pointer points to the block array of the buffer pool (blocks, not @@ -82,13 +82,14 @@ buf_pool_is_block( void* ptr) /* in: pointer to memory */ { if ((buf_pool->blocks <= (buf_block_t*)ptr) - && ((buf_block_t*)ptr < buf_pool->blocks + buf_pool->max_size)) { + && ((buf_block_t*)ptr < buf_pool->blocks + + buf_pool->max_size)) { return(TRUE); } return(FALSE); -} +} /************************************************************************ Gets the smallest oldest_modification lsn for any page in the pool. Returns @@ -102,7 +103,7 @@ buf_pool_get_oldest_modification(void) { buf_block_t* block; dulint lsn; - + mutex_enter(&(buf_pool->mutex)); block = UT_LIST_GET_LAST(buf_pool->flush_list); @@ -130,7 +131,7 @@ buf_pool_clock_tic(void) #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); #endif /* UNIV_SYNC_DEBUG */ - + buf_pool->ulint_clock++; return(buf_pool->ulint_clock); @@ -148,12 +149,12 @@ buf_block_get_frame( ut_ad(block); ut_ad(block >= buf_pool->blocks); ut_ad(block < buf_pool->blocks + buf_pool->max_size); - ut_ad(block->state != BUF_BLOCK_NOT_USED); - ut_ad((block->state != BUF_BLOCK_FILE_PAGE) - || (block->buf_fix_count > 0)); - + ut_ad(block->state != BUF_BLOCK_NOT_USED); + ut_ad((block->state != BUF_BLOCK_FILE_PAGE) + || (block->buf_fix_count > 0)); + return(block->frame); -} +} /************************************************************************* Gets the space id of a block. */ @@ -169,9 +170,9 @@ buf_block_get_space( ut_ad(block < buf_pool->blocks + buf_pool->max_size); ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_ad(block->buf_fix_count > 0); - + return(block->space); -} +} /************************************************************************* Gets the page number of a block. */ @@ -187,9 +188,9 @@ buf_block_get_page_no( ut_ad(block < buf_pool->blocks + buf_pool->max_size); ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_ad(block->buf_fix_count > 0); - + return(block->offset); -} +} /*********************************************************************** Gets the block to whose frame the pointer is pointing to. */ @@ -208,9 +209,9 @@ buf_block_align( frame_zero = buf_pool->frame_zero; if (UNIV_UNLIKELY((ulint)ptr < (ulint)frame_zero) - || UNIV_UNLIKELY((ulint)ptr > (ulint)(buf_pool->high_end))) { + || UNIV_UNLIKELY((ulint)ptr > (ulint)(buf_pool->high_end))) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fprintf(stderr, "InnoDB: Error: trying to access a stray pointer %p\n" "InnoDB: buf pool start is at %p, end at %p\n" @@ -218,15 +219,15 @@ buf_block_align( "InnoDB: corruption. If this happens in an InnoDB database recovery,\n" "InnoDB: you can look from section 6.1 at http://www.innodb.com/ibman.html\n" "InnoDB: how to force recovery.\n", - ptr, frame_zero, + ptr, frame_zero, buf_pool->high_end); ut_error; } - + block = *(buf_pool->blocks_of_frames + (((ulint)(ptr - frame_zero)) >> UNIV_PAGE_SIZE_SHIFT)); return(block); -} +} /*********************************************************************** Gets the frame the pointer is pointing to. */ @@ -244,9 +245,9 @@ buf_frame_align( frame = ut_align_down(ptr, UNIV_PAGE_SIZE); if (UNIV_UNLIKELY((ulint)frame < (ulint)(buf_pool->frame_zero)) - || UNIV_UNLIKELY((ulint)frame >= (ulint)(buf_pool->high_end))) { + || UNIV_UNLIKELY((ulint)frame >= (ulint)(buf_pool->high_end))) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fprintf(stderr, "InnoDB: Error: trying to access a stray pointer %p\n" "InnoDB: buf pool start is at %p, end at %p\n" @@ -254,7 +255,7 @@ buf_frame_align( "InnoDB: corruption. If this happens in an InnoDB database recovery,\n" "InnoDB: you can look from section 6.1 at http://www.innodb.com/ibman.html\n" "InnoDB: how to force recovery.\n", - ptr, buf_pool->frame_zero, + ptr, buf_pool->frame_zero, buf_pool->high_end); ut_error; } @@ -371,7 +372,7 @@ buf_page_address_fold( ulint offset) /* in: offset of the page within space */ { return((space << 20) + space + offset); -} +} /************************************************************************ This function is used to get info if there is an io operation @@ -411,7 +412,7 @@ buf_frame_get_newest_modification( { buf_block_t* block; dulint lsn; - + ut_ad(frame); block = buf_block_align(frame); @@ -448,7 +449,7 @@ buf_frame_modify_clock_inc( #ifdef UNIV_SYNC_DEBUG ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0)) - || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE)); + || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE)); #endif /*UNIV_SYNC_DEBUG */ UT_DULINT_INC(block->modify_clock); @@ -469,7 +470,7 @@ buf_block_modify_clock_inc( { #ifdef UNIV_SYNC_DEBUG ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0)) - || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE)); + || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE)); #endif /* UNIV_SYNC_DEBUG */ UT_DULINT_INC(block->modify_clock); @@ -478,7 +479,7 @@ buf_block_modify_clock_inc( } /************************************************************************ -Returns the value of the modify clock. The caller must have an s-lock +Returns the value of the modify clock. The caller must have an s-lock or x-lock on the block. */ UNIV_INLINE dulint @@ -489,7 +490,7 @@ buf_block_get_modify_clock( { #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED) - || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE)); + || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE)); #endif /* UNIV_SYNC_DEBUG */ return(block->modify_clock); @@ -506,7 +507,7 @@ buf_block_buf_fix_inc_debug( const char* file __attribute__ ((unused)), /* in: file name */ ulint line __attribute__ ((unused))) /* in: line */ { -#ifdef UNIV_SYNC_DEBUG +#ifdef UNIV_SYNC_DEBUG ibool ret; ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line); @@ -539,7 +540,7 @@ buf_page_hash_get( { buf_block_t* block; ulint fold; - + ut_ad(buf_pool); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); @@ -552,7 +553,7 @@ buf_page_hash_get( HASH_SEARCH(hash, buf_pool->page_hash, fold, block, (block->space == space) && (block->offset == offset)); ut_a(block == NULL || block->state == BUF_BLOCK_FILE_PAGE); - + return(block); } @@ -589,16 +590,16 @@ buf_page_get_release_on_io( /* The page was not in the buffer buf_pool: release the latches down to the savepoint */ - + mtr_rollback_to_savepoint(mtr, savepoint); - + buf_page_get(space, offset, RW_S_LATCH, mtr); - + /* When we get here, the page is in buffer, but we release the latches again down to the savepoint, before returning */ mtr_rollback_to_savepoint(mtr, savepoint); - + return(NULL); } @@ -615,7 +616,7 @@ buf_page_release( mtr_t* mtr) /* in: mtr */ { ulint buf_fix_count; - + ut_ad(block); mutex_enter_fast(&(buf_pool->mutex)); @@ -654,9 +655,9 @@ void buf_page_dbg_add_level( /*===================*/ buf_frame_t* frame __attribute__((unused)), /* in: buffer page - where we have acquired latch */ + where we have acquired latch */ ulint level __attribute__((unused))) /* in: latching order - level */ + level */ { sync_thread_add_level(&(buf_block_align(frame)->lock), level); } diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index 1b40acaa269..322848509f4 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -110,11 +110,11 @@ available to replacement in the free list and at the end of the LRU list (to make sure that a read-ahead batch can be read efficiently in a single sweep). */ -#define BUF_FLUSH_FREE_BLOCK_MARGIN (5 + BUF_READ_AHEAD_AREA) -#define BUF_FLUSH_EXTRA_MARGIN (BUF_FLUSH_FREE_BLOCK_MARGIN / 4 + 100) +#define BUF_FLUSH_FREE_BLOCK_MARGIN (5 + BUF_READ_AHEAD_AREA) +#define BUF_FLUSH_EXTRA_MARGIN (BUF_FLUSH_FREE_BLOCK_MARGIN / 4 + 100) #ifndef UNIV_NONINL #include "buf0flu.ic" #endif - + #endif diff --git a/storage/innobase/include/buf0flu.ic b/storage/innobase/include/buf0flu.ic index 9a8a021e029..ea619cd4063 100644 --- a/storage/innobase/include/buf0flu.ic +++ b/storage/innobase/include/buf0flu.ic @@ -48,11 +48,11 @@ buf_flush_note_modification( ut_ad(ut_dulint_cmp(mtr->start_lsn, ut_dulint_zero) != 0); ut_ad(mtr->modifications); ut_ad(ut_dulint_cmp(block->newest_modification, mtr->end_lsn) <= 0); - + block->newest_modification = mtr->end_lsn; if (ut_dulint_is_zero(block->oldest_modification)) { - + block->oldest_modification = mtr->start_lsn; ut_ad(!ut_dulint_is_zero(block->oldest_modification)); @@ -62,7 +62,7 @@ buf_flush_note_modification( mtr->start_lsn) <= 0); } - ++srv_buf_pool_write_requests; + ++srv_buf_pool_write_requests; } /************************************************************************ @@ -85,13 +85,13 @@ buf_flush_recv_note_modification( #endif /* UNIV_SYNC_DEBUG */ mutex_enter(&(buf_pool->mutex)); - + ut_ad(ut_dulint_cmp(block->newest_modification, end_lsn) <= 0); - + block->newest_modification = end_lsn; if (ut_dulint_is_zero(block->oldest_modification)) { - + block->oldest_modification = start_lsn; ut_ad(!ut_dulint_is_zero(block->oldest_modification)); diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h index fb29b44ba98..f8150db0437 100644 --- a/storage/innobase/include/buf0lru.h +++ b/storage/innobase/include/buf0lru.h @@ -73,7 +73,7 @@ ibool buf_LRU_search_and_free_block( /*==========================*/ /* out: TRUE if freed */ - ulint n_iterations); /* in: how many times this has been called + ulint n_iterations); /* in: how many times this has been called repeatedly without result: a high value means that we should search farther; if value is k < 10, then we only search k/10 * number diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index 2136de0f9b3..8e906fcb2e5 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -19,23 +19,23 @@ Created 5/30/1994 Heikki Tuuri typedef struct big_rec_struct big_rec_t; /* Some non-inlined functions used in the MySQL interface: */ -void +void dfield_set_data_noninline( - dfield_t* field, /* in: field */ + dfield_t* field, /* in: field */ void* data, /* in: data */ ulint len); /* in: length or UNIV_SQL_NULL */ -void* +void* dfield_get_data_noninline( dfield_t* field); /* in: field */ ulint dfield_get_len_noninline( dfield_t* field); /* in: field */ -ulint +ulint dtuple_get_n_fields_noninline( - dtuple_t* tuple); /* in: tuple */ -dfield_t* + dtuple_t* tuple); /* in: tuple */ +dfield_t* dtuple_get_nth_field_noninline( - dtuple_t* tuple, /* in: tuple */ + dtuple_t* tuple, /* in: tuple */ ulint n); /* in: index of field */ /************************************************************************* @@ -57,7 +57,7 @@ dfield_set_type( /************************************************************************* Gets pointer to the data in a field. */ UNIV_INLINE -void* +void* dfield_get_data( /*============*/ /* out: pointer to data */ @@ -68,24 +68,24 @@ UNIV_INLINE ulint dfield_get_len( /*===========*/ - /* out: length of data; UNIV_SQL_NULL if + /* out: length of data; UNIV_SQL_NULL if SQL null data */ dfield_t* field); /* in: field */ /************************************************************************* Sets length in a field. */ UNIV_INLINE -void +void dfield_set_len( /*===========*/ - dfield_t* field, /* in: field */ + dfield_t* field, /* in: field */ ulint len); /* in: length or UNIV_SQL_NULL */ /************************************************************************* Sets pointer to the data and length in a field. */ UNIV_INLINE -void +void dfield_set_data( /*============*/ - dfield_t* field, /* in: field */ + dfield_t* field, /* in: field */ const void* data, /* in: data */ ulint len); /* in: length or UNIV_SQL_NULL */ /************************************************************************** @@ -99,10 +99,10 @@ data_write_sql_null( /************************************************************************* Copies the data and len fields. */ UNIV_INLINE -void +void dfield_copy_data( /*=============*/ - dfield_t* field1, /* in: field to copy to */ + dfield_t* field1, /* in: field to copy to */ dfield_t* field2);/* in: field to copy from */ /************************************************************************* Copies a data field to another. */ @@ -134,19 +134,19 @@ dfield_data_is_binary_equal( /************************************************************************* Gets number of fields in a data tuple. */ UNIV_INLINE -ulint +ulint dtuple_get_n_fields( /*================*/ /* out: number of fields */ - dtuple_t* tuple); /* in: tuple */ + dtuple_t* tuple); /* in: tuple */ /************************************************************************* Gets nth field of a tuple. */ UNIV_INLINE -dfield_t* +dfield_t* dtuple_get_nth_field( /*=================*/ /* out: nth field */ - dtuple_t* tuple, /* in: tuple */ + dtuple_t* tuple, /* in: tuple */ ulint n); /* in: index of field */ /************************************************************************* Gets info bits in a data tuple. */ @@ -155,14 +155,14 @@ ulint dtuple_get_info_bits( /*=================*/ /* out: info bits */ - dtuple_t* tuple); /* in: tuple */ + dtuple_t* tuple); /* in: tuple */ /************************************************************************* Sets info bits in a data tuple. */ UNIV_INLINE void dtuple_set_info_bits( /*=================*/ - dtuple_t* tuple, /* in: tuple */ + dtuple_t* tuple, /* in: tuple */ ulint info_bits); /* in: info bits */ /************************************************************************* Gets number of fields used in record comparisons. */ @@ -189,10 +189,10 @@ UNIV_INLINE dtuple_t* dtuple_create( /*==========*/ - /* out, own: created tuple */ + /* out, own: created tuple */ mem_heap_t* heap, /* in: memory heap where the tuple is created */ - ulint n_fields); /* in: number of fields */ + ulint n_fields); /* in: number of fields */ /************************************************************************* Creates a dtuple for use in MySQL. */ @@ -201,7 +201,7 @@ dtuple_t* dtuple_create_for_mysql( /*====================*/ /* out, own created dtuple */ - void** heap, /* out: created memory heap */ + void** heap, /* out: created memory heap */ ulint n_fields); /* in: number of fields */ /************************************************************************* Frees a dtuple used in MySQL. */ @@ -212,7 +212,7 @@ dtuple_free_for_mysql( void* heap); /************************************************************************* Sets number of fields used in a tuple. Normally this is set in -dtuple_create, but if you want later to set it smaller, you can use this. */ +dtuple_create, but if you want later to set it smaller, you can use this. */ void dtuple_set_n_fields( @@ -314,12 +314,20 @@ dfield_print( dfield_t* dfield);/* in: dfield */ /***************************************************************** Pretty prints a dfield value according to its data type. Also the hex string -is printed if a string contains non-printable characters. */ +is printed if a string contains non-printable characters. */ void dfield_print_also_hex( /*==================*/ dfield_t* dfield); /* in: dfield */ +/***************************************************************** +Print a dfield value using ut_print_buf. */ + +void +dfield_print_raw( +/*=============*/ + FILE* f, /* in: output stream */ + dfield_t* dfield); /* in: dfield */ /************************************************************** The following function prints the contents of a tuple. */ @@ -395,13 +403,13 @@ struct dtuple_struct { UT_LIST_NODE_T(dtuple_t) tuple_list; /* data tuples can be linked into a list using this field */ - ulint magic_n; + ulint magic_n; }; #define DATA_TUPLE_MAGIC_N 65478679 /* A slot for a field in a big rec vector */ -typedef struct big_rec_field_struct big_rec_field_t; +typedef struct big_rec_field_struct big_rec_field_t; struct big_rec_field_struct { ulint field_no; /* field number in record */ ulint len; /* stored data len */ @@ -416,7 +424,7 @@ struct big_rec_struct { ulint n_fields; /* number of stored fields */ big_rec_field_t* fields; /* stored fields */ }; - + #ifndef UNIV_NONINL #include "data0data.ic" #endif diff --git a/storage/innobase/include/data0data.ic b/storage/innobase/include/data0data.ic index 0769372e16f..6b07ade2934 100644 --- a/storage/innobase/include/data0data.ic +++ b/storage/innobase/include/data0data.ic @@ -9,7 +9,9 @@ Created 5/30/1994 Heikki Tuuri #include "mem0mem.h" #include "ut0rnd.h" +#ifdef UNIV_DEBUG extern byte data_error; +#endif /* UNIV_DEBUG */ /************************************************************************* Gets pointer to the type struct of SQL data field. */ @@ -42,7 +44,7 @@ dfield_set_type( /************************************************************************* Gets pointer to the data in a field. */ UNIV_INLINE -void* +void* dfield_get_data( /*============*/ /* out: pointer to data */ @@ -50,7 +52,7 @@ dfield_get_data( { ut_ad(field); ut_ad((field->len == UNIV_SQL_NULL) - || (field->data != &data_error)); + || (field->data != &data_error)); return(field->data); } @@ -61,13 +63,13 @@ UNIV_INLINE ulint dfield_get_len( /*===========*/ - /* out: length of data; UNIV_SQL_NULL if + /* out: length of data; UNIV_SQL_NULL if SQL null data */ dfield_t* field) /* in: field */ { ut_ad(field); ut_ad((field->len == UNIV_SQL_NULL) - || (field->data != &data_error)); + || (field->data != &data_error)); return(field->len); } @@ -75,10 +77,10 @@ dfield_get_len( /************************************************************************* Sets length in a field. */ UNIV_INLINE -void +void dfield_set_len( /*===========*/ - dfield_t* field, /* in: field */ + dfield_t* field, /* in: field */ ulint len) /* in: length or UNIV_SQL_NULL */ { ut_ad(field); @@ -89,10 +91,10 @@ dfield_set_len( /************************************************************************* Sets pointer to the data and length in a field. */ UNIV_INLINE -void +void dfield_set_data( /*============*/ - dfield_t* field, /* in: field */ + dfield_t* field, /* in: field */ const void* data, /* in: data */ ulint len) /* in: length or UNIV_SQL_NULL */ { @@ -105,10 +107,10 @@ dfield_set_data( /************************************************************************* Copies the data and len fields. */ UNIV_INLINE -void +void dfield_copy_data( /*=============*/ - dfield_t* field1, /* in: field to copy to */ + dfield_t* field1, /* in: field to copy to */ dfield_t* field2) /* in: field to copy from */ { ut_ad(field1 && field2); @@ -142,11 +144,12 @@ dfield_datas_are_binary_equal( ulint len; len = field1->len; - + if ((len != field2->len) - || ((len != UNIV_SQL_NULL) - && (0 != ut_memcmp(field1->data, field2->data, len)))) { - + || ((len != UNIV_SQL_NULL) + && (0 != ut_memcmp(field1->data, field2->data, + len)))) { + return(FALSE); } @@ -160,7 +163,7 @@ ulint dtuple_get_info_bits( /*=================*/ /* out: info bits */ - dtuple_t* tuple) /* in: tuple */ + dtuple_t* tuple) /* in: tuple */ { ut_ad(tuple); @@ -173,7 +176,7 @@ UNIV_INLINE void dtuple_set_info_bits( /*=================*/ - dtuple_t* tuple, /* in: tuple */ + dtuple_t* tuple, /* in: tuple */ ulint info_bits) /* in: info bits */ { ut_ad(tuple); @@ -219,7 +222,7 @@ ulint dtuple_get_n_fields( /*================*/ /* out: number of fields */ - dtuple_t* tuple) /* in: tuple */ + dtuple_t* tuple) /* in: tuple */ { ut_ad(tuple); @@ -229,11 +232,11 @@ dtuple_get_n_fields( /************************************************************************* Gets nth field of a tuple. */ UNIV_INLINE -dfield_t* +dfield_t* dtuple_get_nth_field( /*=================*/ /* out: nth field */ - dtuple_t* tuple, /* in: tuple */ + dtuple_t* tuple, /* in: tuple */ ulint n) /* in: index of field */ { ut_ad(tuple); @@ -249,17 +252,17 @@ UNIV_INLINE dtuple_t* dtuple_create( /*==========*/ - /* out, own: created tuple */ + /* out, own: created tuple */ mem_heap_t* heap, /* in: memory heap where the tuple is created */ - ulint n_fields) /* in: number of fields */ + ulint n_fields) /* in: number of fields */ { - dtuple_t* tuple; + dtuple_t* tuple; ut_ad(heap); tuple = (dtuple_t*) mem_heap_alloc(heap, sizeof(dtuple_t) - + n_fields * sizeof(dfield_t)); + + n_fields * sizeof(dfield_t)); tuple->info_bits = 0; tuple->n_fields = n_fields; tuple->n_fields_cmp = n_fields; @@ -270,14 +273,14 @@ dtuple_create( { /* In the debug version, initialize fields to an error value */ ulint i; - + for (i = 0; i < n_fields; i++) { (tuple->fields + i)->data = &data_error; dfield_get_type(tuple->fields + i)->mtype = DATA_ERROR; } } #endif - return(tuple); + return(tuple); } /************************************************************** @@ -292,10 +295,10 @@ dtuple_get_data_size( dtuple_t* tuple) /* in: typed data tuple */ { dfield_t* field; - ulint n_fields; - ulint len; - ulint i; - ulint sum = 0; + ulint n_fields; + ulint len; + ulint i; + ulint sum = 0; ut_ad(tuple); ut_ad(dtuple_check_typed(tuple)); @@ -313,7 +316,7 @@ dtuple_get_data_size( sum += len; } - + return(sum); } @@ -328,7 +331,7 @@ dtuple_set_types_binary( { dtype_t* dfield_type; ulint i; - + for (i = 0; i < n; i++) { dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i)); dtype_set(dfield_type, DATA_BINARY, 0, 0, 0); @@ -364,10 +367,10 @@ dtuple_fold( field = dtuple_get_nth_field(tuple, i); data = (byte*) dfield_get_data(field); - len = dfield_get_len(field); - + len = dfield_get_len(field); + if (len != UNIV_SQL_NULL) { - fold = ut_fold_ulint_pair(fold, + fold = ut_fold_ulint_pair(fold, ut_fold_binary(data, len)); } } @@ -376,17 +379,17 @@ dtuple_fold( field = dtuple_get_nth_field(tuple, i); data = (byte*) dfield_get_data(field); - len = dfield_get_len(field); - + len = dfield_get_len(field); + if (len != UNIV_SQL_NULL) { if (len > n_bytes) { len = n_bytes; } - fold = ut_fold_ulint_pair(fold, + fold = ut_fold_ulint_pair(fold, ut_fold_binary(data, len)); } - } + } return(fold); } @@ -423,7 +426,7 @@ dtuple_contains_null( for (i = 0; i < n; i++) { if (dfield_get_len(dtuple_get_nth_field(tuple, i)) - == UNIV_SQL_NULL) { + == UNIV_SQL_NULL) { return(TRUE); } diff --git a/storage/innobase/include/data0type.h b/storage/innobase/include/data0type.h index 7e9692eca5a..d7c9dcb45a2 100644 --- a/storage/innobase/include/data0type.h +++ b/storage/innobase/include/data0type.h @@ -13,13 +13,14 @@ Created 1/16/1996 Heikki Tuuri extern ulint data_mysql_default_charset_coll; #define DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL 8 +#define DATA_MYSQL_BINARY_CHARSET_COLL 63 /* SQL data type struct */ typedef struct dtype_struct dtype_t; /* This variable is initialized as the standard binary variable length data type */ -extern dtype_t* dtype_binary; +extern dtype_t* dtype_binary; /*-------------------------------------------*/ /* The 'MAIN TYPE' of a column */ @@ -101,7 +102,7 @@ InnoDB's own internal system tables have different precise types for their columns, and for them the precise type is usually not used at all. */ -#define DATA_ENGLISH 4 /* English language character string: this +#define DATA_ENGLISH 4 /* English language character string: this is a relic from pre-MySQL time and only used for InnoDB's own system tables */ #define DATA_ERROR 111 /* another relic from pre-MySQL time */ @@ -127,7 +128,7 @@ be less than 256 */ a row in a compressed form */ #define DATA_MIX_ID_LEN 9 /* maximum stored length for mix id (in a compressed dulint form) */ -#define DATA_N_SYS_COLS 4 /* number of system columns defined above */ +#define DATA_N_SYS_COLS 4 /* number of system columns defined above */ /* Flags ORed to the precise data type */ #define DATA_NOT_NULL 256 /* this is ORed to the precise type when @@ -311,7 +312,7 @@ dtype_get_pad_char( /*===============*/ /* out: padding character code, or ULINT_UNDEFINED if no padding specified */ - dtype_t* type); /* in: type */ + const dtype_t* type); /* in: type */ /*************************************************************************** Returns the size of a fixed size data type, 0 if not a fixed size type. */ UNIV_INLINE diff --git a/storage/innobase/include/data0type.ic b/storage/innobase/include/data0type.ic index d4a7b3c64b8..aabf471a70c 100644 --- a/storage/innobase/include/data0type.ic +++ b/storage/innobase/include/data0type.ic @@ -8,6 +8,7 @@ Created 1/16/1996 Heikki Tuuri #include "mach0data.h" +#ifndef UNIV_HOTBACKUP /********************************************************************** Get the variable length bounds of the given character set. @@ -20,6 +21,7 @@ innobase_get_cset_width( ulint cset, /* in: MySQL charset-collation code */ ulint* mbminlen, /* out: minimum length of a char (in bytes) */ ulint* mbmaxlen); /* out: maximum length of a char (in bytes) */ +#endif /* !UNIV_HOTBACKUP */ /************************************************************************* Gets the MySQL charset-collation code for MySQL string types. */ @@ -55,9 +57,21 @@ dtype_set_mblen( { ut_ad(type); if (dtype_is_string_type(type->mtype)) { +#ifndef UNIV_HOTBACKUP innobase_get_cset_width(dtype_get_charset_coll(type->prtype), &type->mbminlen, &type->mbmaxlen); ut_ad(type->mbminlen <= type->mbmaxlen); +#else /* !UNIV_HOTBACKUP */ +#ifdef notdefined +printf("ibbackup: DEBUG: type->mtype=%lu, type->prtype=%lu\n", + type->mtype, type->prtype); +#endif + ut_a(type->mtype <= DATA_BINARY); +#ifdef notdefined + ut_a(type->prtype == (DATA_BINARY | DATA_NOT_NULL)); +#endif + type->mbminlen = type->mbmaxlen = 1; +#endif /* !UNIV_HOTBACKUP */ } else { type->mbminlen = type->mbmaxlen = 0; } @@ -77,7 +91,7 @@ dtype_set( { ut_ad(type); ut_ad(mtype <= DATA_MTYPE_MAX); - + type->mtype = mtype; type->prtype = prtype; type->len = len; @@ -188,26 +202,35 @@ dtype_get_pad_char( /*===============*/ /* out: padding character code, or ULINT_UNDEFINED if no padding specified */ - dtype_t* type) /* in: type */ + const dtype_t* type) /* in: type */ { - if (type->mtype == DATA_CHAR - || type->mtype == DATA_VARCHAR - || type->mtype == DATA_BINARY - || type->mtype == DATA_FIXBINARY - || type->mtype == DATA_MYSQL - || type->mtype == DATA_VARMYSQL - || (type->mtype == DATA_BLOB - && (type->prtype & DATA_BINARY_TYPE) == 0)) { - + switch (type->mtype) { + case DATA_FIXBINARY: + case DATA_BINARY: + if (UNIV_UNLIKELY(dtype_get_charset_coll(type->prtype) + == DATA_MYSQL_BINARY_CHARSET_COLL)) { + /* Starting from 5.0.18, do not pad + VARBINARY or BINARY columns. */ + return(ULINT_UNDEFINED); + } + /* Fall through */ + case DATA_CHAR: + case DATA_VARCHAR: + case DATA_MYSQL: + case DATA_VARMYSQL: /* Space is the padding character for all char and binary - strings, and starting from 5.0.3, also for TEXT strings. */ + strings, and starting from 5.0.3, also for TEXT strings. */ - return((ulint)' '); + return(0x20); + case DATA_BLOB: + if ((type->prtype & DATA_BINARY_TYPE) == 0) { + return(0x20); + } + /* Fall through */ + default: + /* No padding specified */ + return(ULINT_UNDEFINED); } - - /* No padding specified */ - - return(ULINT_UNDEFINED); } /************************************************************************** @@ -233,7 +256,7 @@ dtype_new_store_for_order_and_null_size( buf[0] = buf[0] | 128; } - /* In versions < 4.1.2 we had: if (type->prtype & DATA_NONLATIN1) { + /* In versions < 4.1.2 we had: if (type->prtype & DATA_NONLATIN1) { buf[0] = buf[0] | 64; } */ @@ -262,20 +285,20 @@ dtype_read_for_order_and_null_size( byte* buf) /* in: buffer for stored type order info */ { ut_ad(4 == DATA_ORDER_NULL_TYPE_BUF_SIZE); - + type->mtype = buf[0] & 63; type->prtype = buf[1]; if (buf[0] & 128) { - type->prtype = type->prtype | DATA_BINARY_TYPE; + type->prtype = type->prtype | DATA_BINARY_TYPE; } type->len = mach_read_from_2(buf + 2); - + type->prtype = dtype_form_prtype(type->prtype, data_mysql_default_charset_coll); dtype_set_mblen(type); -} +} /************************************************************************** Reads to a type the stored information which determines its alphabetical @@ -293,7 +316,7 @@ dtype_new_read_for_order_and_null_size( #if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE #error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE" #endif - + type->mtype = buf[0] & 63; type->prtype = buf[1]; @@ -323,13 +346,12 @@ dtype_new_read_for_order_and_null_size( charset_coll = data_mysql_default_charset_coll; } - + type->prtype = dtype_form_prtype(type->prtype, charset_coll); - } + } dtype_set_mblen(type); } -#ifndef UNIV_HOTBACKUP /*************************************************************************** Returns the size of a fixed size data type, 0 if not a fixed size type. */ UNIV_INLINE @@ -374,8 +396,13 @@ dtype_get_fixed_size( if (type->prtype & DATA_BINARY_TYPE) { return(dtype_get_len(type)); } else { +#ifdef UNIV_HOTBACKUP + if (type->mbminlen == type->mbmaxlen) { + return(dtype_get_len(type)); + } +#else /* UNIV_HOTBACKUP */ /* We play it safe here and ask MySQL for - mbminlen and mbmaxlen. Although + mbminlen and mbmaxlen. Although type->mbminlen and type->mbmaxlen are initialized if and only if type->prtype is (in one of the 3 functions in this file), @@ -405,6 +432,7 @@ dtype_get_fixed_size( if (mbminlen == mbmaxlen) { return(dtype_get_len(type)); } +#endif /* !UNIV_HOTBACKUP */ } /* fall through for variable-length charsets */ case DATA_VARCHAR: @@ -412,7 +440,7 @@ dtype_get_fixed_size( case DATA_DECIMAL: case DATA_VARMYSQL: case DATA_BLOB: - return(0); + return(0); default: ut_error; } @@ -470,13 +498,12 @@ dtype_get_min_size( case DATA_DECIMAL: case DATA_VARMYSQL: case DATA_BLOB: - return(0); + return(0); default: ut_error; } return(0); } -#endif /* !UNIV_HOTBACKUP */ /*************************************************************************** Returns a stored SQL NULL size for a type. For fixed length types it is diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index 7f75e7e10a6..843c70af577 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -42,14 +42,14 @@ Created 5/24/1996 Heikki Tuuri #define DB_CANNOT_ADD_CONSTRAINT 38 /* adding a foreign key constraint to a table failed */ #define DB_CORRUPTION 39 /* data structure corruption noticed */ -#define DB_COL_APPEARS_TWICE_IN_INDEX 40 /* InnoDB cannot handle an index - where same column appears twice */ +#define DB_COL_APPEARS_TWICE_IN_INDEX 40/* InnoDB cannot handle an index + where same column appears twice */ #define DB_CANNOT_DROP_CONSTRAINT 41 /* dropping a foreign key constraint from a table failed */ #define DB_NO_SAVEPOINT 42 /* no savepoint exists with the given name */ #define DB_TABLESPACE_ALREADY_EXISTS 43 /* we cannot create a new single-table - tablespace because a file of the same + tablespace because a file of the same name already exists */ #define DB_TABLESPACE_DELETED 44 /* tablespace does not exist or is being dropped right now */ @@ -63,11 +63,11 @@ Created 5/24/1996 Heikki Tuuri table */ /* The following are partial failure codes */ -#define DB_FAIL 1000 -#define DB_OVERFLOW 1001 -#define DB_UNDERFLOW 1002 +#define DB_FAIL 1000 +#define DB_OVERFLOW 1001 +#define DB_UNDERFLOW 1002 #define DB_STRONG_FAIL 1003 #define DB_RECORD_NOT_FOUND 1500 #define DB_END_OF_INDEX 1501 -#endif +#endif diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h index 86702cbca05..39e3bdf72b0 100644 --- a/storage/innobase/include/dict0boot.h +++ b/storage/innobase/include/dict0boot.h @@ -26,7 +26,7 @@ Gets a pointer to the dictionary header and x-latches its page. */ dict_hdr_t* dict_hdr_get( /*=========*/ - /* out: pointer to the dictionary header, + /* out: pointer to the dictionary header, page x-latched */ mtr_t* mtr); /* in: mtr */ /************************************************************************** @@ -94,7 +94,7 @@ dict_create(void); assigned as the id the number DICT_IBUF_ID_MIN plus the space id */ #define DICT_IBUF_ID_MIN ut_dulint_create(0xFFFFFFFFUL, 0) - + /* The offset of the dictionary header on the page */ #define DICT_HDR FSEG_PAGE_DATA @@ -120,7 +120,7 @@ clustered index */ #define DICT_SYS_INDEXES_PAGE_NO_FIELD 8 #define DICT_SYS_INDEXES_SPACE_NO_FIELD 7 #define DICT_SYS_INDEXES_TYPE_FIELD 6 - + /* When a row id which is zero modulo this number (which must be a power of two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is updated */ @@ -130,4 +130,4 @@ updated */ #include "dict0boot.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/dict0boot.ic b/storage/innobase/include/dict0boot.ic index 8a91feed018..fe2a9e36653 100644 --- a/storage/innobase/include/dict0boot.ic +++ b/storage/innobase/include/dict0boot.ic @@ -28,7 +28,7 @@ dict_sys_get_new_row_id(void) mutex_enter(&(dict_sys->mutex)); id = dict_sys->row_id; - + if (0 == (ut_dulint_get_low(id) % DICT_HDR_ROW_ID_WRITE_MARGIN)) { dict_hdr_flush_row_id(); @@ -39,7 +39,7 @@ dict_sys_get_new_row_id(void) mutex_exit(&(dict_sys->mutex)); return(id); -} +} /************************************************************************** Reads a row id from a record or other 6-byte stored form. */ @@ -50,10 +50,12 @@ dict_sys_read_row_id( /* out: row id */ byte* field) /* in: record field */ { - ut_ad(DATA_ROW_ID_LEN == 6); +#if DATA_ROW_ID_LEN != 6 +# error "DATA_ROW_ID_LEN != 6" +#endif return(mach_read_from_6(field)); -} +} /************************************************************************** Writes a row id to a record or other 6-byte stored form. */ @@ -64,9 +66,11 @@ dict_sys_write_row_id( byte* field, /* in: record field */ dulint row_id) /* in: row id */ { - ut_ad(DATA_ROW_ID_LEN == 6); +#if DATA_ROW_ID_LEN != 6 +# error "DATA_ROW_ID_LEN != 6" +#endif mach_write_to_6(field, row_id); -} +} diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h index 5dd571be59c..bd0890dbfa7 100644 --- a/storage/innobase/include/dict0crea.h +++ b/storage/innobase/include/dict0crea.h @@ -15,7 +15,7 @@ Created 1/8/1996 Heikki Tuuri #include "que0types.h" #include "row0types.h" #include "mtr0mtr.h" - + /************************************************************************* Creates a table create graph. */ diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 5215d51cabe..dc8c72b0e7d 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -26,6 +26,7 @@ Created 1/8/1996 Heikki Tuuri #include "ut0byte.h" #include "trx0types.h" +#ifndef UNIV_HOTBACKUP /********************************************************************** Makes all characters in a NUL-terminated UTF-8 string lower case. */ @@ -33,6 +34,7 @@ void dict_casedn_str( /*============*/ char* a); /* in/out: string to put in lower case */ +#endif /* !UNIV_HOTBACKUP */ /************************************************************************ Get the database name length in a table name. */ @@ -197,7 +199,8 @@ dict_foreign_add_to_cache( /*======================*/ /* out: DB_SUCCESS or error code */ dict_foreign_t* foreign, /* in, own: foreign key constraint */ - ibool check_types); /* in: TRUE=check type compatibility */ + ibool check_charsets);/* in: TRUE=check charset + compatibility */ /************************************************************************* Checks if a table is referenced by foreign keys. */ @@ -305,7 +308,7 @@ Checks if a table is in the dictionary cache. */ UNIV_INLINE dict_table_t* dict_table_check_if_in_cache_low( -/*==============================*/ +/*=============================*/ /* out: table, NULL if not found */ const char* table_name); /* in: table name */ /************************************************************************** @@ -484,6 +487,15 @@ dict_table_get_sys_col_no( dict_table_t* table, /* in: table */ ulint sys); /* in: DATA_ROW_ID, ... */ /************************************************************************ +Check whether the table uses the compact page format. */ +UNIV_INLINE +ibool +dict_table_is_comp( +/*===============*/ + /* out: TRUE if table uses the + compact page format */ + const dict_table_t* table); /* in: table */ +/************************************************************************ Checks if a column is in the ordering columns of the clustered index of a table. Column prefixes are treated like whole columns. */ @@ -659,7 +671,6 @@ dict_index_add_col( /*===============*/ dict_index_t* index, /* in: index */ dict_col_t* col, /* in: column */ - ulint order, /* in: order criterion */ ulint prefix_len); /* in: column prefix length */ /*********************************************************************** Copies types of fields contained in index to tuple. */ @@ -679,13 +690,6 @@ dict_index_get_tree( /* out: index tree */ dict_index_t* index); /* in: index */ /************************************************************************* -Gets the field order criterion. */ -UNIV_INLINE -ulint -dict_field_get_order( -/*=================*/ - dict_field_t* field); -/************************************************************************* Gets the field column. */ UNIV_INLINE dict_col_t* @@ -770,7 +774,7 @@ dict_tree_build_node_ptr( pointer */ ulint page_no,/* in: page number to put in node pointer */ mem_heap_t* heap, /* in: memory heap where pointer created */ - ulint level); /* in: level of rec in tree: 0 means leaf + ulint level); /* in: level of rec in tree: 0 means leaf level */ /************************************************************************** Copies an initial segment of a physical record, long enough to specify an @@ -872,7 +876,7 @@ dict_update_statistics_low( /*=======================*/ dict_table_t* table, /* in: table */ ibool has_dict_mutex);/* in: TRUE if the caller has the - dictionary mutex */ + dictionary mutex */ /************************************************************************* Calculates new estimates for table and index statistics. The statistics are used in query optimization. */ @@ -940,13 +944,13 @@ struct dict_sys_struct{ header and flushed to a file; in recovery this must be derived from the log records */ - hash_table_t* table_hash; /* hash table of the tables, based + hash_table_t* table_hash; /* hash table of the tables, based on name */ - hash_table_t* table_id_hash; /* hash table of the tables, based + hash_table_t* table_id_hash; /* hash table of the tables, based on id */ - hash_table_t* col_hash; /* hash table of the columns */ + hash_table_t* col_hash; /* hash table of the columns */ UT_LIST_BASE_NODE_T(dict_table_t) - table_LRU; /* LRU list of tables */ + table_LRU; /* LRU list of tables */ ulint size; /* varying space in bytes occupied by the data dictionary table and index objects */ diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 928a693f860..b99ca7815a8 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -93,7 +93,7 @@ dict_table_get_n_user_cols( ut_ad(table); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); ut_ad(table->cached); - + return(table->n_cols - DATA_N_SYS_COLS); } @@ -127,7 +127,7 @@ dict_table_get_n_cols( ut_ad(table); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); ut_ad(table->cached); - + return(table->n_cols); } @@ -164,7 +164,7 @@ dict_table_get_sys_col( ut_ad(sys < DATA_N_SYS_COLS); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - col = dict_table_get_nth_col(table, table->n_cols + col = dict_table_get_nth_col(table, table->n_cols - DATA_N_SYS_COLS + sys); ut_ad(col->type.mtype == DATA_SYS); ut_ad(col->type.prtype == (sys | DATA_NOT_NULL)); @@ -190,6 +190,25 @@ dict_table_get_sys_col_no( } /************************************************************************ +Check whether the table uses the compact page format. */ +UNIV_INLINE +ibool +dict_table_is_comp( +/*===============*/ + /* out: TRUE if table uses the + compact page format */ + const dict_table_t* table) /* in: table */ +{ + ut_ad(table); + +#if DICT_TF_COMPACT != TRUE +#error +#endif + + return(UNIV_LIKELY(table->flags & DICT_TF_COMPACT)); +} + +/************************************************************************ Gets the number of fields in the internal representation of an index, including fields added by the dictionary system. */ UNIV_INLINE @@ -202,7 +221,7 @@ dict_index_get_n_fields( { ut_ad(index); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - + return(index->n_fields); } @@ -222,7 +241,7 @@ dict_index_get_n_unique( ut_ad(index); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); ut_ad(index->cached); - + return(index->n_uniq); } @@ -241,7 +260,7 @@ dict_index_get_n_unique_in_tree( ut_ad(index); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); ut_ad(index->cached); - + if (index->type & DICT_CLUSTERED) { return(dict_index_get_n_unique(index)); @@ -324,19 +343,6 @@ dict_index_get_tree( ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); return(index->tree); -} - -/************************************************************************* -Gets the field order criterion. */ -UNIV_INLINE -ulint -dict_field_get_order( -/*=================*/ - dict_field_t* field) -{ - ut_ad(field); - - return(field->order); } /************************************************************************* @@ -494,13 +500,13 @@ Checks if a table is in the dictionary cache. */ UNIV_INLINE dict_table_t* dict_table_check_if_in_cache_low( -/*==============================*/ +/*=============================*/ /* out: table, NULL if not found */ const char* table_name) /* in: table name */ { dict_table_t* table; ulint table_fold; - + ut_ad(table_name); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); @@ -525,14 +531,14 @@ dict_table_get_low( const char* table_name) /* in: table name */ { dict_table_t* table; - + ut_ad(table_name); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ table = dict_table_check_if_in_cache_low(table_name); - + if (table == NULL) { table = dict_load_table(table_name); } @@ -557,7 +563,7 @@ dict_table_get_on_id_low( ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ UT_NOT_USED(trx); - + /* Look for the table name in the hash table */ fold = ut_fold_dulint(table_id); @@ -572,9 +578,9 @@ dict_table_get_on_id_low( /* lock_push(trx, table, LOCK_DICT_MEM_FIX) */ } - + /* TODO: should get the type information from MySQL */ - + return(table); } @@ -587,9 +593,9 @@ dict_table_release( dict_table_t* table) /* in: table to be released */ { mutex_enter(&(dict_sys->mutex)); - - table->mem_fix--; - + + table->mem_fix--; + mutex_exit(&(dict_sys->mutex)); } @@ -604,7 +610,7 @@ dict_table_get_index( const char* name) /* in: index name */ { dict_index_t* index = NULL; - + index = dict_table_get_first_index(table); while (index != NULL) { @@ -614,7 +620,7 @@ dict_table_get_index( } index = dict_table_get_next_index(index); - } - + } + return(index); } diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h index f13620bc6e8..7e19c2eb3c0 100644 --- a/storage/innobase/include/dict0load.h +++ b/storage/innobase/include/dict0load.h @@ -60,7 +60,7 @@ dict_table_t* dict_load_table_on_id( /*==================*/ /* out: table; NULL if table does not exist */ - dulint table_id); /* in: table id */ + dulint table_id); /* in: table id */ /************************************************************************ This function is called when the database is booted. Loads system table index definitions except for the clustered index which @@ -82,7 +82,8 @@ dict_load_foreigns( /*===============*/ /* out: DB_SUCCESS or error code */ const char* table_name, /* in: table name */ - ibool check_types); /* in: TRUE=check type compatibility */ + ibool check_charsets);/* in: TRUE=check charsets + compatibility */ /************************************************************************ Prints to the standard output information on all tables found in the data dictionary system table. */ diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 7eec86d0bcb..ab07213de3b 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -29,12 +29,9 @@ Created 1/8/1996 Heikki Tuuri combination of types */ #define DICT_CLUSTERED 1 /* clustered index */ #define DICT_UNIQUE 2 /* unique index */ -#define DICT_UNIVERSAL 4 /* index which can contain records from any +#define DICT_UNIVERSAL 4 /* index which can contain records from any other index */ -#define DICT_IBUF 8 /* insert buffer tree */ - -/* Flags for ordering an index field: OR'ing of the flags allowed */ -#define DICT_DESCEND 1 /* in descending order (default ascending) */ +#define DICT_IBUF 8 /* insert buffer tree */ /* Types for a table object */ #define DICT_TABLE_ORDINARY 1 @@ -42,6 +39,9 @@ combination of types */ #define DICT_TABLE_CLUSTER 3 /* this means that the table is really a cluster definition */ +/* Table flags */ +#define DICT_TF_COMPACT 1 /* compact page format */ + /************************************************************************** Creates a table memory object. */ @@ -55,7 +55,7 @@ dict_mem_table_create( is ignored if the table is made a member of a cluster */ ulint n_cols, /* in: number of columns */ - ibool comp); /* in: TRUE=compact page format */ + ulint flags); /* in: table flags */ /************************************************************************** Creates a cluster memory object. */ @@ -116,8 +116,6 @@ dict_mem_index_add_field( /*=====================*/ dict_index_t* index, /* in: index */ const char* name, /* in: column name */ - ulint order, /* in: order criterion; 0 means an - ascending order */ ulint prefix_len); /* in: 0 or the column prefix length in a MySQL index like INDEX (textcol(25)) */ @@ -148,7 +146,7 @@ struct dict_col_struct{ const char* name; /* name */ dtype_t type; /* data type */ dict_table_t* table; /* back pointer to table of this column */ - ulint aux; /* this is used as an auxiliary variable + ulint aux; /* this is used as an auxiliary variable in some of the functions below */ }; @@ -163,8 +161,6 @@ UTF-8 charset. In that charset, a character may take at most 3 bytes. */ struct dict_field_struct{ dict_col_t* col; /* pointer to the table column */ const char* name; /* name of the column */ - ulint order; /* flags for ordering this field: - DICT_DESCEND, ... */ ulint prefix_len; /* 0 or the length of the column prefix in bytes in a MySQL index of type, e.g., INDEX (textcol(25)); @@ -175,10 +171,6 @@ struct dict_field_struct{ ulint fixed_len; /* 0 or the fixed length of the column if smaller than DICT_MAX_INDEX_COL_LEN */ - ulint fixed_offs; /* offset to the field, or - ULINT_UNDEFINED if it is not fixed - within the record (due to preceding - variable-length fields) */ }; /* Data structure for an index tree */ @@ -280,7 +272,7 @@ struct dict_foreign_struct{ constraint is defined: we allow the indexes to contain more fields than mentioned in the constraint, as long - as the first fields are as mentioned */ + as the first fields are as mentioned */ dict_index_t* foreign_index; /* foreign index; we require that both tables contain explicitly defined indexes for the constraint: InnoDB @@ -311,6 +303,7 @@ a foreign key constraint is enforced, therefore RESTRICT just means no flag */ struct dict_table_struct{ dulint id; /* id of the table or cluster */ ulint type; /* DICT_TABLE_ORDINARY, ... */ + ulint flags; /* DICT_TF_COMPACT, ... */ mem_heap_t* heap; /* memory heap */ const char* name; /* table name */ const char* dir_path_of_temp_table;/* NULL or the directory path @@ -328,7 +321,6 @@ struct dict_table_struct{ ibool tablespace_discarded;/* this flag is set TRUE when the user calls DISCARD TABLESPACE on this table, and reset to FALSE in IMPORT TABLESPACE */ - ibool comp; /* flag: TRUE=compact page format */ hash_node_t name_hash; /* hash chain node */ hash_node_t id_hash; /* hash chain node */ ulint n_def; /* number of columns defined so far */ @@ -345,7 +337,7 @@ struct dict_table_struct{ which refer to this table */ UT_LIST_NODE_T(dict_table_t) table_LRU; /* node of the LRU list of tables */ - ulint mem_fix;/* count of how many times the table + ulint mem_fix;/* count of how many times the table and its indexes has been fixed in memory; currently NOT used */ ulint n_mysql_handles_opened; @@ -408,9 +400,9 @@ struct dict_table_struct{ database pages */ ulint stat_sum_of_other_index_sizes; /* other indexes in database pages */ - ibool stat_initialized; /* TRUE if statistics have + ibool stat_initialized; /* TRUE if statistics have been calculated the first time - after database startup or table creation */ + after database startup or table creation */ ulint stat_modified_counter; /* when a row is inserted, updated, or deleted, we add 1 to this number; we calculate new @@ -432,11 +424,11 @@ struct dict_table_struct{ inited; MySQL gets the init value by executing SELECT MAX(auto inc column) */ ib_longlong autoinc;/* autoinc counter value to give to the - next inserted row */ + next inserted row */ ulint magic_n;/* magic number */ }; #define DICT_TABLE_MAGIC_N 76333786 - + #ifndef UNIV_NONINL #include "dict0mem.ic" #endif diff --git a/storage/innobase/include/dyn0dyn.h b/storage/innobase/include/dyn0dyn.h index 1df976a5301..7affccbf67e 100644 --- a/storage/innobase/include/dyn0dyn.h +++ b/storage/innobase/include/dyn0dyn.h @@ -76,7 +76,7 @@ dyn_array_get_element( /*==================*/ /* out: pointer to element */ dyn_array_t* arr, /* in: dyn array */ - ulint pos); /* in: position of element as bytes + ulint pos); /* in: position of element as bytes from array start */ /**************************************************************** Returns the size of stored data in a dyn array. */ @@ -140,11 +140,11 @@ dyn_push_string( /* NOTE! Do not use the fields of the struct directly: the definition appears here only for the compiler to know its size! */ struct dyn_block_struct{ - mem_heap_t* heap; /* in the first block this is != NULL + mem_heap_t* heap; /* in the first block this is != NULL if dynamic allocation has been needed */ ulint used; /* number of data bytes used in this block */ byte data[DYN_ARRAY_DATA_SIZE]; - /* storage for array elements */ + /* storage for array elements */ UT_LIST_BASE_NODE_T(dyn_block_t) base; /* linear list of dyn blocks: this node is used only in the first block */ @@ -163,4 +163,4 @@ struct dyn_block_struct{ #include "dyn0dyn.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/dyn0dyn.ic b/storage/innobase/include/dyn0dyn.ic index c1b8f2cb8ce..fcb3c17287a 100644 --- a/storage/innobase/include/dyn0dyn.ic +++ b/storage/innobase/include/dyn0dyn.ic @@ -41,7 +41,7 @@ dyn_array_get_last_block( if (arr->heap == NULL) { return(arr); - } + } return(UT_LIST_GET_LAST(arr->base)); } @@ -57,13 +57,13 @@ dyn_array_get_next_block( dyn_block_t* block) /* in: dyn array block */ { ut_ad(arr && block); - + if (arr->heap == NULL) { ut_ad(arr == block); - + return(NULL); } - + return(UT_LIST_GET_NEXT(list, block)); } @@ -106,7 +106,9 @@ dyn_array_create( size sizeof(dyn_array_t) */ { ut_ad(arr); - ut_ad(DYN_ARRAY_DATA_SIZE < DYN_BLOCK_FULL_FLAG); +#if DYN_ARRAY_DATA_SIZE >= DYN_BLOCK_FULL_FLAG +# error "DYN_ARRAY_DATA_SIZE >= DYN_BLOCK_FULL_FLAG" +#endif arr->heap = NULL; arr->used = 0; @@ -153,13 +155,13 @@ dyn_array_push( ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); ut_ad(size <= DYN_ARRAY_DATA_SIZE); ut_ad(size); - + block = arr; used = block->used; if (used + size > DYN_ARRAY_DATA_SIZE) { /* Get the last array block */ - + block = dyn_array_get_last_block(arr); used = block->used; @@ -195,13 +197,13 @@ dyn_array_open( ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); ut_ad(size <= DYN_ARRAY_DATA_SIZE); ut_ad(size); - + block = arr; used = block->used; if (used + size > DYN_ARRAY_DATA_SIZE) { /* Get the last array block */ - + block = dyn_array_get_last_block(arr); used = block->used; @@ -217,7 +219,7 @@ dyn_array_open( ut_ad(arr->buf_end == 0); arr->buf_end = used + size; -#endif +#endif return((block->data) + used); } @@ -234,13 +236,13 @@ dyn_array_close( ut_ad(arr); ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); - + block = dyn_array_get_last_block(arr); ut_ad(arr->buf_end + block->data >= ptr); block->used = ptr - block->data; - + ut_ad(block->used <= DYN_ARRAY_DATA_SIZE); #ifdef UNIV_DEBUG @@ -256,7 +258,7 @@ dyn_array_get_element( /*==================*/ /* out: pointer to element */ dyn_array_t* arr, /* in: dyn array */ - ulint pos) /* in: position of element as bytes + ulint pos) /* in: position of element as bytes from array start */ { dyn_block_t* block; @@ -267,7 +269,7 @@ dyn_array_get_element( /* Get the first array block */ block = dyn_array_get_first_block(arr); - + if (arr->heap != NULL) { used = dyn_block_get_used(block); @@ -282,7 +284,7 @@ dyn_array_get_element( ut_ad(block); ut_ad(dyn_block_get_used(block) >= pos); - + return(block->data + pos); } @@ -296,7 +298,7 @@ dyn_array_get_data_size( dyn_array_t* arr) /* in: dyn array */ { dyn_block_t* block; - ulint sum = 0; + ulint sum = 0; ut_ad(arr); ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); @@ -305,7 +307,7 @@ dyn_array_get_data_size( return(arr->used); } - + /* Get the first array block */ block = dyn_array_get_first_block(arr); @@ -334,10 +336,10 @@ dyn_push_string( n_copied = DYN_ARRAY_DATA_SIZE; } else { n_copied = len; - } + } memcpy(dyn_array_push(arr, n_copied), str, n_copied); - + str += n_copied; len -= n_copied; } diff --git a/storage/innobase/include/eval0eval.h b/storage/innobase/include/eval0eval.h index 6561f0c8ae7..f950512adfd 100644 --- a/storage/innobase/include/eval0eval.h +++ b/storage/innobase/include/eval0eval.h @@ -77,7 +77,7 @@ Gets a iboolean value from a query node. */ UNIV_INLINE ibool eval_node_get_ibool_val( -/*===================*/ +/*====================*/ /* out: iboolean value */ que_node_t* node); /* in: query graph node */ /********************************************************************* @@ -94,4 +94,4 @@ eval_cmp( #include "eval0eval.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/eval0eval.ic b/storage/innobase/include/eval0eval.ic index 069cbfe5f37..26e9b8e41fe 100644 --- a/storage/innobase/include/eval0eval.ic +++ b/storage/innobase/include/eval0eval.ic @@ -54,7 +54,7 @@ eval_node_ensure_val_buf( dfield_set_len(dfield, size); data = dfield_get_data(dfield); - + if (!data || que_node_get_val_buf_size(node) < size) { data = eval_node_alloc_val_buf(node, size); @@ -77,7 +77,7 @@ eval_sym( if (sym_node->indirection) { /* The symbol table node is an alias for a variable or a column */ - + dfield_copy_data(que_node_get_val(sym_node), que_node_get_val(sym_node->indirection)); } @@ -97,7 +97,7 @@ eval_exp( return; } - + eval_func(exp_node); } @@ -116,13 +116,13 @@ eval_node_set_int_val( dfield = que_node_get_val(node); data = dfield_get_data(dfield); - + if (data == NULL) { data = eval_node_alloc_val_buf(node, 4); } ut_ad(dfield_get_len(dfield) == 4); - + mach_write_to_4(data, (ulint)val); } @@ -141,7 +141,7 @@ eval_node_get_int_val( ut_ad(dfield_get_len(dfield) == 4); - return((int)mach_read_from_4(dfield_get_data(dfield))); + return((int)mach_read_from_4(dfield_get_data(dfield))); } /********************************************************************* @@ -149,7 +149,7 @@ Gets a iboolean value from a query node. */ UNIV_INLINE ibool eval_node_get_ibool_val( -/*===================*/ +/*====================*/ /* out: iboolean value */ que_node_t* node) /* in: query graph node */ { @@ -159,7 +159,7 @@ eval_node_get_ibool_val( dfield = que_node_get_val(node); data = dfield_get_data(dfield); - + ut_ad(data != NULL); return(mach_read_from_1(data)); @@ -170,7 +170,7 @@ Sets a iboolean value as the value of a function node. */ UNIV_INLINE void eval_node_set_ibool_val( -/*===================*/ +/*====================*/ func_node_t* func_node, /* in: function node */ ibool val) /* in: value to set */ { @@ -180,7 +180,7 @@ eval_node_set_ibool_val( dfield = que_node_get_val(func_node); data = dfield_get_data(dfield); - + if (data == NULL) { /* Allocate 1 byte to hold the value */ @@ -188,7 +188,7 @@ eval_node_set_ibool_val( } ut_ad(dfield_get_len(dfield) == 1); - + mach_write_to_1(data, val); } @@ -204,7 +204,7 @@ eval_node_copy_and_alloc_val( ulint len) /* in: string length or UNIV_SQL_NULL */ { byte* data; - + if (len == UNIV_SQL_NULL) { dfield_set_len(que_node_get_val(node), len); @@ -212,7 +212,7 @@ eval_node_copy_and_alloc_val( } data = eval_node_ensure_val_buf(node, len); - + ut_memcpy(data, str, len); } @@ -226,7 +226,7 @@ eval_node_copy_val( que_node_t* node2) /* in: node to copy from */ { dfield_t* dfield2; - + dfield2 = que_node_get_val(node2); eval_node_copy_and_alloc_val(node1, dfield_get_data(dfield2), diff --git a/storage/innobase/include/eval0proc.h b/storage/innobase/include/eval0proc.h index 5d685ad9076..2cf98f26265 100644 --- a/storage/innobase/include/eval0proc.h +++ b/storage/innobase/include/eval0proc.h @@ -76,4 +76,4 @@ return_step( #include "eval0proc.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/eval0proc.ic b/storage/innobase/include/eval0proc.ic index 0d7ecb6d1dc..cf738056576 100644 --- a/storage/innobase/include/eval0proc.ic +++ b/storage/innobase/include/eval0proc.ic @@ -22,19 +22,19 @@ proc_step( proc_node_t* node; ut_ad(thr); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_PROC); if (thr->prev_node == que_node_get_parent(node)) { /* Start execution from the first statement in the statement list */ - + thr->run_node = node->stat_list; } else { /* Move to the next statement */ ut_ad(que_node_get_next(thr->prev_node) == NULL); - + thr->run_node = NULL; } @@ -43,7 +43,7 @@ proc_step( } return(thr); -} +} /************************************************************************** Performs an execution step of a procedure call node. */ @@ -57,15 +57,15 @@ proc_eval_step( func_node_t* node; ut_ad(thr); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_FUNC); /* Evaluate the procedure */ eval_exp(node); - + thr->run_node = que_node_get_parent(node); return(thr); -} +} diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index aa1ec5c25a5..53bb496c190 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -63,7 +63,20 @@ extern fil_addr_t fil_addr_null; #define FIL_PAGE_LSN 16 /* lsn of the end of the newest modification log record to the page */ #define FIL_PAGE_TYPE 24 /* file page type: FIL_PAGE_INDEX,..., - 2 bytes */ + 2 bytes. + + The contents of this field can only + be trusted in the following case: + if the page is an uncompressed + B-tree index page, then it is + guaranteed that the value is + FIL_PAGE_INDEX. + The opposite does not hold. + + In tablespaces created by + MySQL/InnoDB 5.1.7 or later, the + contents of this field is valid + for all uncompressed pages. */ #define FIL_PAGE_FILE_FLUSH_LSN 26 /* this is only defined for the first page in a data file: the file has been flushed to disk at least up @@ -79,14 +92,22 @@ extern fil_addr_t fil_addr_null; to the last 4 bytes of FIL_PAGE_LSN */ #define FIL_PAGE_DATA_END 8 -/* File page types */ -#define FIL_PAGE_INDEX 17855 -#define FIL_PAGE_UNDO_LOG 2 -#define FIL_PAGE_INODE 3 -#define FIL_PAGE_IBUF_FREE_LIST 4 +/* File page types (values of FIL_PAGE_TYPE) */ +#define FIL_PAGE_INDEX 17855 /* B-tree node */ +#define FIL_PAGE_UNDO_LOG 2 /* Undo log page */ +#define FIL_PAGE_INODE 3 /* Index node */ +#define FIL_PAGE_IBUF_FREE_LIST 4 /* Insert buffer free list */ +/* File page types introduced in MySQL/InnoDB 5.1.7 */ +#define FIL_PAGE_TYPE_ALLOCATED 0 /* Freshly allocated page */ +#define FIL_PAGE_IBUF_BITMAP 5 /* Insert buffer bitmap */ +#define FIL_PAGE_TYPE_SYS 6 /* System page */ +#define FIL_PAGE_TYPE_TRX_SYS 7 /* Transaction system data */ +#define FIL_PAGE_TYPE_FSP_HDR 8 /* File space header */ +#define FIL_PAGE_TYPE_XDES 9 /* Extent descriptor page */ +#define FIL_PAGE_TYPE_BLOB 10 /* Uncompressed BLOB page */ /* Space types */ -#define FIL_TABLESPACE 501 +#define FIL_TABLESPACE 501 #define FIL_LOG 502 extern ulint fil_n_log_flushes; @@ -271,7 +292,7 @@ Decrements the count of pending insert buffer page merges. */ void fil_decr_pending_ibuf_merges( -/*========================*/ +/*=========================*/ ulint id); /* in: space id */ /*********************************************************************** Parses the body of a log record written about an .ibd file operation. That is, @@ -289,13 +310,13 @@ datadir that we should use in replaying the file operations. */ byte* fil_op_log_parse_or_replay( /*=======================*/ - /* out: end of log record, or NULL if the + /* out: end of log record, or NULL if the record was not completely contained between ptr and end_ptr */ - byte* ptr, /* in: buffer containing the log record body, + byte* ptr, /* in: buffer containing the log record body, or an initial segment of it, if the record does not fir completely between ptr and end_ptr */ - byte* end_ptr, /* in: buffer end */ + byte* end_ptr, /* in: buffer end */ ulint type, /* in: the type of this log record */ ibool do_replay, /* in: TRUE if we want to replay the operation, and not just parse the log record */ @@ -619,7 +640,7 @@ void fil_aio_wait( /*=========*/ ulint segment); /* in: the number of the segment in the aio - array to wait for */ + array to wait for */ /************************************************************************** Flushes to disk possible writes cached by the OS. If the space does not exist or is being dropped, does not do anything. */ @@ -665,7 +686,7 @@ Sets the file page type. */ void fil_page_set_type( /*==============*/ - byte* page, /* in: file page */ + byte* page, /* in: file page */ ulint type); /* in: type */ /************************************************************************* Gets the file page type. */ @@ -675,7 +696,7 @@ fil_page_get_type( /*==============*/ /* out: type; NOTE that if the type has not been written to page, the return value not defined */ - byte* page); /* in: file page */ + byte* page); /* in: file page */ typedef struct fil_space_struct fil_space_t; diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 2fcde882df7..11b664b6826 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -80,8 +80,8 @@ Reads the space id from the first page of a tablespace. */ ulint fsp_header_get_space_id( /*====================*/ - /* out: space id, ULINT UNDEFINED if error */ - page_t* page); /* in: first page of a tablespace */ + /* out: space id, ULINT UNDEFINED if error */ + page_t* page); /* in: first page of a tablespace */ /************************************************************************** Writes the space id to a tablespace header. This function is used past the buffer pool when we in fil0fil.c create a new single-table tablespace. */ @@ -100,7 +100,7 @@ fsp_header_init( /*============*/ ulint space, /* in: space id */ ulint size, /* in: current size in blocks */ - mtr_t* mtr); /* in: mini-transaction handle */ + mtr_t* mtr); /* in: mini-transaction handle */ /************************************************************************** Increases the space size field of a space. */ @@ -109,7 +109,7 @@ fsp_header_inc_size( /*================*/ ulint space, /* in: space id */ ulint size_inc,/* in: size increment in pages */ - mtr_t* mtr); /* in: mini-transaction handle */ + mtr_t* mtr); /* in: mini-transaction handle */ /************************************************************************** Creates a new segment. */ @@ -158,7 +158,7 @@ ulint fseg_n_reserved_pages( /*==================*/ /* out: number of reserved pages */ - fseg_header_t* header, /* in: segment header */ + fseg_header_t* header, /* in: segment header */ ulint* used, /* out: number of pages used (<= reserved) */ mtr_t* mtr); /* in: mtr handle */ /************************************************************************** @@ -232,9 +232,9 @@ ibool fsp_reserve_free_extents( /*=====================*/ /* out: TRUE if we were able to make the reservation */ - ulint* n_reserved,/* out: number of extents actually reserved; if we - return TRUE and the tablespace size is < 64 pages, - then this can be 0, otherwise it is n_ext */ + ulint* n_reserved,/* out: number of extents actually reserved; if we + return TRUE and the tablespace size is < 64 pages, + then this can be 0, otherwise it is n_ext */ ulint space, /* in: space id */ ulint n_ext, /* in: number of extents to reserve */ ulint alloc_type,/* in: FSP_NORMAL, FSP_UNDO, or FSP_CLEANING */ diff --git a/storage/innobase/include/fut0lst.ic b/storage/innobase/include/fut0lst.ic index c0d61833b48..4681a1ce509 100644 --- a/storage/innobase/include/fut0lst.ic +++ b/storage/innobase/include/fut0lst.ic @@ -40,9 +40,9 @@ flst_write_addr( ut_ad(mtr_memo_contains(mtr, buf_block_align(faddr), MTR_MEMO_PAGE_X_FIX)); - mlog_write_ulint(faddr + FIL_ADDR_PAGE, addr.page, MLOG_4BYTES, mtr); + mlog_write_ulint(faddr + FIL_ADDR_PAGE, addr.page, MLOG_4BYTES, mtr); mlog_write_ulint(faddr + FIL_ADDR_BYTE, addr.boffset, - MLOG_2BYTES, mtr); + MLOG_2BYTES, mtr); } /************************************************************************ @@ -59,10 +59,10 @@ flst_read_addr( ut_ad(faddr && mtr); - addr.page = mtr_read_ulint(faddr + FIL_ADDR_PAGE, MLOG_4BYTES, mtr); - addr.boffset = mtr_read_ulint(faddr + FIL_ADDR_BYTE, MLOG_2BYTES, + addr.page = mtr_read_ulint(faddr + FIL_ADDR_PAGE, MLOG_4BYTES, mtr); + addr.boffset = mtr_read_ulint(faddr + FIL_ADDR_BYTE, MLOG_2BYTES, mtr); - return(addr); + return(addr); } /************************************************************************ @@ -76,9 +76,9 @@ flst_init( { ut_ad(mtr_memo_contains(mtr, buf_block_align(base), MTR_MEMO_PAGE_X_FIX)); - mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr); - flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr); - flst_write_addr(base + FLST_LAST, fil_addr_null, mtr); + mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr); + flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr); + flst_write_addr(base + FLST_LAST, fil_addr_null, mtr); } /************************************************************************ diff --git a/storage/innobase/include/ha0ha.h b/storage/innobase/include/ha0ha.h index 60ccb0be5d5..9fc80ed301c 100644 --- a/storage/innobase/include/ha0ha.h +++ b/storage/innobase/include/ha0ha.h @@ -99,13 +99,15 @@ ha_remove_all_nodes_to_page( ulint fold, /* in: fold value */ page_t* page); /* in: buffer page */ /***************************************************************** -Validates a hash table. */ +Validates a given range of the cells in hash table. */ ibool ha_validate( /*========*/ - /* out: TRUE if ok */ - hash_table_t* table); /* in: hash table */ + /* out: TRUE if ok */ + hash_table_t* table, /* in: hash table */ + ulint start_index, /* in: start index */ + ulint end_index); /* in: end index */ /***************************************************************** Prints info of a hash table. */ @@ -128,4 +130,4 @@ struct ha_node_struct { #include "ha0ha.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h index 51315e40875..a5cd32d956f 100644 --- a/storage/innobase/include/hash0hash.h +++ b/storage/innobase/include/hash0hash.h @@ -109,8 +109,8 @@ do {\ \ while (struct3333->NAME != DATA) {\ \ - ut_a(struct3333);\ struct3333 = struct3333->NAME;\ + ut_a(struct3333);\ }\ \ struct3333->NAME = DATA->NAME;\ @@ -153,8 +153,8 @@ hash_cell_t* hash_get_nth_cell( /*==============*/ /* out: pointer to cell */ - hash_table_t* table, /* in: hash table */ - ulint n); /* in: cell index */ + hash_table_t* table, /* in: hash table */ + ulint n); /* in: cell index */ /***************************************************************** Returns the number of cells in a hash table. */ UNIV_INLINE @@ -229,8 +229,8 @@ ulint hash_get_mutex_no( /*==============*/ /* out: mutex number */ - hash_table_t* table, /* in: hash table */ - ulint fold); /* in: fold */ + hash_table_t* table, /* in: hash table */ + ulint fold); /* in: fold */ /**************************************************************** Gets the nth heap in a hash table. */ UNIV_INLINE @@ -238,8 +238,8 @@ mem_heap_t* hash_get_nth_heap( /*==============*/ /* out: mem heap */ - hash_table_t* table, /* in: hash table */ - ulint i); /* in: index of the heap */ + hash_table_t* table, /* in: hash table */ + ulint i); /* in: index of the heap */ /**************************************************************** Gets the heap for a fold value in a hash table. */ UNIV_INLINE @@ -247,8 +247,8 @@ mem_heap_t* hash_get_heap( /*==========*/ /* out: mem heap */ - hash_table_t* table, /* in: hash table */ - ulint fold); /* in: fold */ + hash_table_t* table, /* in: hash table */ + ulint fold); /* in: fold */ /**************************************************************** Gets the nth mutex in a hash table. */ UNIV_INLINE @@ -256,8 +256,8 @@ mutex_t* hash_get_nth_mutex( /*===============*/ /* out: mutex */ - hash_table_t* table, /* in: hash table */ - ulint i); /* in: index of the mutex */ + hash_table_t* table, /* in: hash table */ + ulint i); /* in: index of the mutex */ /**************************************************************** Gets the mutex for a fold value in a hash table. */ UNIV_INLINE @@ -265,38 +265,38 @@ mutex_t* hash_get_mutex( /*===========*/ /* out: mutex */ - hash_table_t* table, /* in: hash table */ - ulint fold); /* in: fold */ + hash_table_t* table, /* in: hash table */ + ulint fold); /* in: fold */ /**************************************************************** Reserves the mutex for a fold value in a hash table. */ void hash_mutex_enter( /*=============*/ - hash_table_t* table, /* in: hash table */ - ulint fold); /* in: fold */ + hash_table_t* table, /* in: hash table */ + ulint fold); /* in: fold */ /**************************************************************** Releases the mutex for a fold value in a hash table. */ void hash_mutex_exit( /*============*/ - hash_table_t* table, /* in: hash table */ - ulint fold); /* in: fold */ + hash_table_t* table, /* in: hash table */ + ulint fold); /* in: fold */ /**************************************************************** Reserves all the mutexes of a hash table, in an ascending order. */ void hash_mutex_enter_all( /*=================*/ - hash_table_t* table); /* in: hash table */ + hash_table_t* table); /* in: hash table */ /**************************************************************** Releases all the mutexes of a hash table. */ void hash_mutex_exit_all( /*================*/ - hash_table_t* table); /* in: hash table */ + hash_table_t* table); /* in: hash table */ struct hash_cell_struct{ diff --git a/storage/innobase/include/hash0hash.ic b/storage/innobase/include/hash0hash.ic index 0d713140c13..49bcc7b31d0 100644 --- a/storage/innobase/include/hash0hash.ic +++ b/storage/innobase/include/hash0hash.ic @@ -15,8 +15,8 @@ hash_cell_t* hash_get_nth_cell( /*==============*/ /* out: pointer to cell */ - hash_table_t* table, /* in: hash table */ - ulint n) /* in: cell index */ + hash_table_t* table, /* in: hash table */ + ulint n) /* in: cell index */ { ut_ad(n < table->n_cells); @@ -55,8 +55,8 @@ ulint hash_get_mutex_no( /*==============*/ /* out: mutex number */ - hash_table_t* table, /* in: hash table */ - ulint fold) /* in: fold */ + hash_table_t* table, /* in: hash table */ + ulint fold) /* in: fold */ { return(ut_2pow_remainder(fold, table->n_mutexes)); } @@ -68,8 +68,8 @@ mem_heap_t* hash_get_nth_heap( /*==============*/ /* out: mem heap */ - hash_table_t* table, /* in: hash table */ - ulint i) /* in: index of the heap */ + hash_table_t* table, /* in: hash table */ + ulint i) /* in: index of the heap */ { ut_ad(i < table->n_mutexes); @@ -83,8 +83,8 @@ mem_heap_t* hash_get_heap( /*==========*/ /* out: mem heap */ - hash_table_t* table, /* in: hash table */ - ulint fold) /* in: fold */ + hash_table_t* table, /* in: hash table */ + ulint fold) /* in: fold */ { ulint i; @@ -104,11 +104,11 @@ mutex_t* hash_get_nth_mutex( /*===============*/ /* out: mutex */ - hash_table_t* table, /* in: hash table */ - ulint i) /* in: index of the mutex */ + hash_table_t* table, /* in: hash table */ + ulint i) /* in: index of the mutex */ { ut_ad(i < table->n_mutexes); - + return(table->mutexes + i); } @@ -119,8 +119,8 @@ mutex_t* hash_get_mutex( /*===========*/ /* out: mutex */ - hash_table_t* table, /* in: hash table */ - ulint fold) /* in: fold */ + hash_table_t* table, /* in: hash table */ + ulint fold) /* in: fold */ { ulint i; diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index 4f38ab4f1e9..34f29ae5dec 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -180,7 +180,7 @@ ibuf_page_low( /*************************************************************************** Frees excess pages from the ibuf free list. This function is called when an OS thread calls fsp services to allocate a new file segment, or a new page to a -file segment, and the thread did not own the fsp latch before this call. */ +file segment, and the thread did not own the fsp latch before this call. */ void ibuf_free_excess_pages( @@ -304,4 +304,4 @@ for the file segment from which the pages for the ibuf tree are allocated */ #include "ibuf0ibuf.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/ibuf0ibuf.ic b/storage/innobase/include/ibuf0ibuf.ic index 68f7ce9c1d0..4eea8f41e32 100644 --- a/storage/innobase/include/ibuf0ibuf.ic +++ b/storage/innobase/include/ibuf0ibuf.ic @@ -41,7 +41,7 @@ struct ibuf_data_struct{ /* If the ibuf meter exceeds this value, then the suitable inserts are made to the insert buffer instead of directly to the disk page */ -#define IBUF_THRESHOLD 50 +#define IBUF_THRESHOLD 50 struct ibuf_struct{ ulint size; /* current size of the ibuf index @@ -88,13 +88,13 @@ ibuf_should_try( decide */ { if (!(index->type & DICT_CLUSTERED) - && (ignore_sec_unique || !(index->type & DICT_UNIQUE)) - && ibuf->meter > IBUF_THRESHOLD) { + && (ignore_sec_unique || !(index->type & DICT_UNIQUE)) + && ibuf->meter > IBUF_THRESHOLD) { ibuf_flush_count++; if (ibuf_flush_count % 8 == 0) { - + buf_LRU_try_free_flushed_blocks(); } @@ -132,13 +132,13 @@ ibuf_index_page_calc_free_bits( for the page */ { ulint n; - + n = max_ins_size / (UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE); if (n == 3) { n = 2; } - + if (n > 3) { n = 3; } @@ -206,8 +206,9 @@ ibuf_update_free_bits_if_full( before = ibuf_index_page_calc_free_bits(max_ins_size); if (max_ins_size >= increase) { - ut_ad(ULINT_UNDEFINED > UNIV_PAGE_SIZE); - +#if ULINT32_UNDEFINED <= UNIV_PAGE_SIZE +# error "ULINT32_UNDEFINED <= UNIV_PAGE_SIZE" +#endif after = ibuf_index_page_calc_free_bits(max_ins_size - increase); #ifdef UNIV_IBUF_DEBUG diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 86e579bc007..3dda3a7cca8 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -224,7 +224,7 @@ lock_rec_restore_from_page_infimum( rec_t* rec, /* in: record whose lock state is restored */ page_t* page); /* in: page (rec is not necessarily on this page) whose infimum stored the lock state; lock bits are - reset on the infimum */ + reset on the infimum */ /************************************************************************* Returns TRUE if there are explicit record locks on a page. */ @@ -427,7 +427,7 @@ to a lock. */ void lock_rec_unlock( /*============*/ - trx_t* trx, /* in: transaction that has set a record + trx_t* trx, /* in: transaction that has set a record lock */ rec_t* rec, /* in: record */ ulint lock_mode); /* in: LOCK_S or LOCK_X */ @@ -477,7 +477,7 @@ searching for a lock in the hash table. */ UNIV_INLINE ulint lock_rec_fold( -/*===========*/ +/*==========*/ /* out: folded value */ ulint space, /* in: space */ ulint page_no);/* in: page number */ @@ -624,7 +624,7 @@ extern lock_sys_t* lock_sys; waiting for its turn in the wait queue */ /* Precise modes */ #define LOCK_ORDINARY 0 /* this flag denotes an ordinary next-key lock - in contrast to LOCK_GAP or LOCK_REC_NOT_GAP */ + in contrast to LOCK_GAP or LOCK_REC_NOT_GAP */ #define LOCK_GAP 512 /* this gap bit should be so high that it can be ORed to the other flags; when this bit is set, it means that the @@ -634,7 +634,7 @@ extern lock_sys_t* lock_sys; the bit is set; locks of this type are created when records are removed from the index chain of records */ -#define LOCK_REC_NOT_GAP 1024 /* this bit means that the lock is only on +#define LOCK_REC_NOT_GAP 1024 /* this bit means that the lock is only on the index record and does NOT block inserts to the gap before the index record; this is used in the case when we retrieve a record @@ -650,7 +650,7 @@ extern lock_sys_t* lock_sys; remains set when the waiting lock is granted, or if the lock is inherited to a neighboring record */ - + /* When lock bits are reset, the following flags are available: */ #define LOCK_RELEASE_WAIT 1 #define LOCK_NOT_RELEASE_WAIT 2 @@ -678,4 +678,4 @@ extern lock_sys_t* lock_sys; #include "lock0lock.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/lock0types.h b/storage/innobase/include/lock0types.h index 6c3e54ee1fc..43fd2d60da5 100644 --- a/storage/innobase/include/lock0types.h +++ b/storage/innobase/include/lock0types.h @@ -13,4 +13,4 @@ Created 5/7/1996 Heikki Tuuri typedef struct lock_struct lock_t; typedef struct lock_sys_struct lock_sys_t; -#endif +#endif diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 7f3f10438b4..43662d02a34 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -19,7 +19,7 @@ typedef struct log_group_struct log_group_t; #ifdef UNIV_DEBUG extern ibool log_do_write; -extern ibool log_debug_writes; +extern ibool log_debug_writes; #else /* UNIV_DEBUG */ # define log_do_write TRUE #endif /* UNIV_DEBUG */ @@ -493,9 +493,9 @@ Peeks the current lsn. */ ibool log_peek_lsn( /*=========*/ - /* out: TRUE if success, FALSE if could not get the - log system mutex */ - dulint* lsn); /* out: if returns TRUE, current lsn is here */ + /* out: TRUE if success, FALSE if could not get the + log system mutex */ + dulint* lsn); /* out: if returns TRUE, current lsn is here */ /************************************************************************** Refreshes the statistics used to print per-second averages. */ @@ -514,7 +514,7 @@ extern log_t* log_sys; /* The counting of lsn's starts from this value: this must be non-zero */ #define LOG_START_LSN ut_dulint_create(0, 16 * OS_FILE_LOG_BLOCK_SIZE) -#define LOG_BUFFER_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE) +#define LOG_BUFFER_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE) #define LOG_ARCHIVE_BUF_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE / 4) /* Offsets of a log block header */ @@ -571,8 +571,8 @@ extern log_t* log_sys; #define LOG_CHECKPOINT_ARRAY_END (LOG_CHECKPOINT_GROUP_ARRAY\ + LOG_MAX_N_GROUPS * 8) -#define LOG_CHECKPOINT_CHECKSUM_1 LOG_CHECKPOINT_ARRAY_END -#define LOG_CHECKPOINT_CHECKSUM_2 (4 + LOG_CHECKPOINT_ARRAY_END) +#define LOG_CHECKPOINT_CHECKSUM_1 LOG_CHECKPOINT_ARRAY_END +#define LOG_CHECKPOINT_CHECKSUM_2 (4 + LOG_CHECKPOINT_ARRAY_END) #define LOG_CHECKPOINT_FSP_FREE_LIMIT (8 + LOG_CHECKPOINT_ARRAY_END) /* current fsp free limit in tablespace 0, in units of one @@ -678,7 +678,7 @@ struct log_group_struct{ this buffer to the group */ UT_LIST_NODE_T(log_group_t) log_groups; /* list of log groups */ -}; +}; struct log_struct{ byte pad[64]; /* padding to prevent other memory @@ -731,13 +731,13 @@ struct log_struct{ be advanced, it is enough that the write i/o has been completed for all log groups */ - dulint write_lsn; /* end lsn for the current running + dulint write_lsn; /* end lsn for the current running write */ ulint write_end_offset;/* the data in buffer has been written up to this offset when the current write ends: this field will then be copied to buf_next_to_write */ - dulint current_flush_lsn;/* end lsn for the current running + dulint current_flush_lsn;/* end lsn for the current running write + flush operation */ dulint flushed_to_disk_lsn; /* how far we have written the log @@ -774,11 +774,11 @@ struct log_struct{ called */ /* Fields involved in checkpoints */ - ulint log_group_capacity; /* capacity of the log group; if - the checkpoint age exceeds this, it is - a serious error because it is possible - we will then overwrite log and spoil - crash recovery */ + ulint log_group_capacity; /* capacity of the log group; if + the checkpoint age exceeds this, it is + a serious error because it is possible + we will then overwrite log and spoil + crash recovery */ ulint max_modified_age_async; /* when this recommended value for lsn - buf_pool_get_oldest_modification() diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic index ca7531783a2..898a8f3b6e3 100644 --- a/storage/innobase/include/log0log.ic +++ b/storage/innobase/include/log0log.ic @@ -61,7 +61,7 @@ log_block_set_flush_bit( } mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, field); -} +} /**************************************************************** Gets a log block number stored in the header. */ @@ -73,7 +73,7 @@ log_block_get_hdr_no( header */ byte* log_block) /* in: log block */ { - return(~LOG_BLOCK_FLUSH_BIT_MASK + return(~LOG_BLOCK_FLUSH_BIT_MASK & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)); } @@ -90,7 +90,7 @@ log_block_set_hdr_no( { ut_ad(n > 0); ut_ad(n < LOG_BLOCK_FLUSH_BIT_MASK); - + mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, n); } @@ -183,7 +183,7 @@ log_block_convert_lsn_to_no( no = ut_dulint_get_low(lsn) / OS_FILE_LOG_BLOCK_SIZE; no += (ut_dulint_get_high(lsn) % OS_FILE_LOG_BLOCK_SIZE) * 2 * (0x80000000UL / OS_FILE_LOG_BLOCK_SIZE); - + no = no & 0x3FFFFFFFUL; return(no + 1); @@ -201,10 +201,10 @@ log_block_calc_checksum( ulint sum; ulint sh; ulint i; - + sum = 1; sh = 0; - + for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) { sum = sum & 0x7FFFFFFFUL; sum += (((ulint)(*(block + i))) << sh) + (ulint)(*(block + i)); @@ -260,7 +260,7 @@ log_block_init( #endif /* UNIV_SYNC_DEBUG */ no = log_block_convert_lsn_to_no(lsn); - + log_block_set_hdr_no(log_block, no); log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE); @@ -284,14 +284,14 @@ log_block_init_in_old_format( #endif /* UNIV_SYNC_DEBUG */ no = log_block_convert_lsn_to_no(lsn); - + log_block_set_hdr_no(log_block, no); mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM, no); log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE); log_block_set_first_rec_group(log_block, 0); } - + /**************************************************************** Writes to the log the string given. The log must be released with log_release. */ @@ -318,29 +318,29 @@ log_reserve_and_write_fast( if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) { - /* The string does not fit within the current log block - or the log block would become full */ + /* The string does not fit within the current log block + or the log block would become full */ - *success = FALSE; + *success = FALSE; mutex_exit(&(log->mutex)); - return(ut_dulint_zero); + return(ut_dulint_zero); } *start_lsn = log->lsn; - + ut_memcpy(log->buf + log->buf_free, str, len); log_block_set_data_len(ut_align_down(log->buf + log->buf_free, - OS_FILE_LOG_BLOCK_SIZE), + OS_FILE_LOG_BLOCK_SIZE), data_len); #ifdef UNIV_LOG_DEBUG log->old_buf_free = log->buf_free; log->old_lsn = log->lsn; #endif log->buf_free += len; - + ut_ad(log->buf_free <= log->buf_size); lsn = ut_dulint_add(log->lsn, len); diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 658df4d5586..7bdf8bf6100 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -341,14 +341,14 @@ extern ibool recv_recovery_on; extern ibool recv_no_ibuf_operations; extern ibool recv_needed_recovery; -extern ibool recv_lsn_checks_on; +extern ibool recv_lsn_checks_on; #ifdef UNIV_HOTBACKUP extern ibool recv_is_making_a_backup; #endif /* UNIV_HOTBACKUP */ extern ulint recv_max_parsed_page_no; /* Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many -times! */ +times! */ #define RECV_PARSING_BUF_SIZE (2 * 1024 * 1024) /* Size of block reads when the log groups are scanned forward to do a diff --git a/storage/innobase/include/mach0data.h b/storage/innobase/include/mach0data.h index f9a3ff521d5..8377114a723 100644 --- a/storage/innobase/include/mach0data.h +++ b/storage/innobase/include/mach0data.h @@ -1,6 +1,6 @@ /********************************************************************** Utilities for converting data from the database file -to the machine format. +to the machine format. (c) 1995 Innobase Oy @@ -21,37 +21,37 @@ module. */ /*********************************************************** The following function is used to store data in one byte. */ UNIV_INLINE -void +void mach_write_to_1( /*============*/ - byte* b, /* in: pointer to byte where to store */ - ulint n); /* in: ulint integer to be stored, >= 0, < 256 */ + byte* b, /* in: pointer to byte where to store */ + ulint n); /* in: ulint integer to be stored, >= 0, < 256 */ /************************************************************ The following function is used to fetch data from one byte. */ UNIV_INLINE -ulint +ulint mach_read_from_1( /*=============*/ /* out: ulint integer, >= 0, < 256 */ - byte* b); /* in: pointer to byte */ + byte* b); /* in: pointer to byte */ /*********************************************************** The following function is used to store data in two consecutive bytes. We store the most significant byte to the lower address. */ UNIV_INLINE -void +void mach_write_to_2( /*============*/ - byte* b, /* in: pointer to two bytes where to store */ - ulint n); /* in: ulint integer to be stored, >= 0, < 64k */ + byte* b, /* in: pointer to two bytes where to store */ + ulint n); /* in: ulint integer to be stored, >= 0, < 64k */ /************************************************************ The following function is used to fetch data from two consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -ulint +ulint mach_read_from_2( /*=============*/ /* out: ulint integer, >= 0, < 64k */ - byte* b); /* in: pointer to two bytes */ + byte* b); /* in: pointer to two bytes */ /************************************************************ The following function is used to convert a 16-bit data item @@ -77,38 +77,38 @@ mach_decode_2( The following function is used to store data in 3 consecutive bytes. We store the most significant byte to the lowest address. */ UNIV_INLINE -void +void mach_write_to_3( /*============*/ - byte* b, /* in: pointer to 3 bytes where to store */ - ulint n); /* in: ulint integer to be stored */ + byte* b, /* in: pointer to 3 bytes where to store */ + ulint n); /* in: ulint integer to be stored */ /************************************************************ The following function is used to fetch data from 3 consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -ulint +ulint mach_read_from_3( /*=============*/ /* out: ulint integer */ - byte* b); /* in: pointer to 3 bytes */ + byte* b); /* in: pointer to 3 bytes */ /*********************************************************** The following function is used to store data in four consecutive bytes. We store the most significant byte to the lowest address. */ UNIV_INLINE -void +void mach_write_to_4( /*============*/ - byte* b, /* in: pointer to four bytes where to store */ - ulint n); /* in: ulint integer to be stored */ + byte* b, /* in: pointer to four bytes where to store */ + ulint n); /* in: ulint integer to be stored */ /************************************************************ The following function is used to fetch data from 4 consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -ulint +ulint mach_read_from_4( /*=============*/ /* out: ulint integer */ - byte* b); /* in: pointer to four bytes */ + byte* b); /* in: pointer to four bytes */ /************************************************************* Writes a ulint in a compressed form (1..5 bytes). */ UNIV_INLINE @@ -116,8 +116,8 @@ ulint mach_write_compressed( /*==================*/ /* out: stored size in bytes */ - byte* b, /* in: pointer to memory where to store */ - ulint n); /* in: ulint integer to be stored */ + byte* b, /* in: pointer to memory where to store */ + ulint n); /* in: ulint integer to be stored */ /************************************************************* Returns the size of an ulint when written in the compressed form. */ UNIV_INLINE @@ -125,7 +125,7 @@ ulint mach_get_compressed_size( /*=====================*/ /* out: compressed size in bytes */ - ulint n); /* in: ulint integer to be stored */ + ulint n); /* in: ulint integer to be stored */ /************************************************************* Reads a ulint in a compressed form. */ UNIV_INLINE @@ -133,61 +133,61 @@ ulint mach_read_compressed( /*=================*/ /* out: read integer */ - byte* b); /* in: pointer to memory from where to read */ + byte* b); /* in: pointer to memory from where to read */ /*********************************************************** The following function is used to store data in 6 consecutive bytes. We store the most significant byte to the lowest address. */ UNIV_INLINE -void +void mach_write_to_6( /*============*/ - byte* b, /* in: pointer to 6 bytes where to store */ - dulint n); /* in: dulint integer to be stored */ + byte* b, /* in: pointer to 6 bytes where to store */ + dulint n); /* in: dulint integer to be stored */ /************************************************************ The following function is used to fetch data from 6 consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -dulint +dulint mach_read_from_6( /*=============*/ /* out: dulint integer */ - byte* b); /* in: pointer to 6 bytes */ + byte* b); /* in: pointer to 6 bytes */ /*********************************************************** The following function is used to store data in 7 consecutive bytes. We store the most significant byte to the lowest address. */ UNIV_INLINE -void +void mach_write_to_7( /*============*/ - byte* b, /* in: pointer to 7 bytes where to store */ - dulint n); /* in: dulint integer to be stored */ + byte* b, /* in: pointer to 7 bytes where to store */ + dulint n); /* in: dulint integer to be stored */ /************************************************************ The following function is used to fetch data from 7 consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -dulint +dulint mach_read_from_7( /*=============*/ /* out: dulint integer */ - byte* b); /* in: pointer to 7 bytes */ + byte* b); /* in: pointer to 7 bytes */ /*********************************************************** The following function is used to store data in 8 consecutive bytes. We store the most significant byte to the lowest address. */ UNIV_INLINE -void +void mach_write_to_8( /*============*/ - byte* b, /* in: pointer to 8 bytes where to store */ - dulint n); /* in: dulint integer to be stored */ + byte* b, /* in: pointer to 8 bytes where to store */ + dulint n); /* in: dulint integer to be stored */ /************************************************************ The following function is used to fetch data from 8 consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -dulint +dulint mach_read_from_8( /*=============*/ /* out: dulint integer */ - byte* b); /* in: pointer to 8 bytes */ + byte* b); /* in: pointer to 8 bytes */ /************************************************************* Writes a dulint in a compressed form (5..9 bytes). */ UNIV_INLINE @@ -195,8 +195,8 @@ ulint mach_dulint_write_compressed( /*=========================*/ /* out: size in bytes */ - byte* b, /* in: pointer to memory where to store */ - dulint n); /* in: dulint integer to be stored */ + byte* b, /* in: pointer to memory where to store */ + dulint n); /* in: dulint integer to be stored */ /************************************************************* Returns the size of a dulint when written in the compressed form. */ UNIV_INLINE @@ -204,7 +204,7 @@ ulint mach_dulint_get_compressed_size( /*============================*/ /* out: compressed size in bytes */ - dulint n); /* in: dulint integer to be stored */ + dulint n); /* in: dulint integer to be stored */ /************************************************************* Reads a dulint in a compressed form. */ UNIV_INLINE @@ -212,7 +212,7 @@ dulint mach_dulint_read_compressed( /*========================*/ /* out: read dulint */ - byte* b); /* in: pointer to memory from where to read */ + byte* b); /* in: pointer to memory from where to read */ /************************************************************* Writes a dulint in a compressed form (1..11 bytes). */ UNIV_INLINE @@ -220,8 +220,8 @@ ulint mach_dulint_write_much_compressed( /*==============================*/ /* out: size in bytes */ - byte* b, /* in: pointer to memory where to store */ - dulint n); /* in: dulint integer to be stored */ + byte* b, /* in: pointer to memory where to store */ + dulint n); /* in: dulint integer to be stored */ /************************************************************* Returns the size of a dulint when written in the compressed form. */ UNIV_INLINE @@ -229,7 +229,7 @@ ulint mach_dulint_get_much_compressed_size( /*=================================*/ /* out: compressed size in bytes */ - dulint n); /* in: dulint integer to be stored */ + dulint n); /* in: dulint integer to be stored */ /************************************************************* Reads a dulint in a compressed form. */ UNIV_INLINE @@ -237,7 +237,7 @@ dulint mach_dulint_read_much_compressed( /*=============================*/ /* out: read dulint */ - byte* b); /* in: pointer to memory from where to read */ + byte* b); /* in: pointer to memory from where to read */ /************************************************************* Reads a ulint in a compressed form if the log record fully contains it. */ @@ -246,9 +246,9 @@ mach_parse_compressed( /*==================*/ /* out: pointer to end of the stored field, NULL if not complete */ - byte* ptr, /* in: pointer to buffer from where to read */ + byte* ptr, /* in: pointer to buffer from where to read */ byte* end_ptr,/* in: pointer to end of the buffer */ - ulint* val); /* out: read value */ + ulint* val); /* out: read value */ /************************************************************* Reads a dulint in a compressed form if the log record fully contains it. */ @@ -257,9 +257,9 @@ mach_dulint_parse_compressed( /*=========================*/ /* out: pointer to end of the stored field, NULL if not complete */ - byte* ptr, /* in: pointer to buffer from where to read */ + byte* ptr, /* in: pointer to buffer from where to read */ byte* end_ptr,/* in: pointer to end of the buffer */ - dulint* val); /* out: read value */ + dulint* val); /* out: read value */ /************************************************************* Reads a double. It is stored in a little-endian format. */ UNIV_INLINE @@ -267,31 +267,31 @@ double mach_double_read( /*=============*/ /* out: double read */ - byte* b); /* in: pointer to memory from where to read */ + byte* b); /* in: pointer to memory from where to read */ /************************************************************* Writes a double. It is stored in a little-endian format. */ UNIV_INLINE void mach_double_write( /*==============*/ - byte* b, /* in: pointer to memory where to write */ - double d); /* in: double */ + byte* b, /* in: pointer to memory where to write */ + double d); /* in: double */ /************************************************************* Reads a float. It is stored in a little-endian format. */ UNIV_INLINE float mach_float_read( -/*=============*/ +/*============*/ /* out: float read */ - byte* b); /* in: pointer to memory from where to read */ + byte* b); /* in: pointer to memory from where to read */ /************************************************************* Writes a float. It is stored in a little-endian format. */ UNIV_INLINE void mach_float_write( -/*==============*/ - byte* b, /* in: pointer to memory where to write */ - float d); /* in: float */ +/*=============*/ + byte* b, /* in: pointer to memory where to write */ + float d); /* in: float */ /************************************************************* Reads a ulint stored in the little-endian format. */ UNIV_INLINE @@ -326,7 +326,7 @@ mach_write_to_2_little_endian( /*==========================*/ byte* dest, /* in: where to write */ ulint n); /* in: unsigned long int to write */ - + #ifndef UNIV_NONINL #include "mach0data.ic" #endif diff --git a/storage/innobase/include/mach0data.ic b/storage/innobase/include/mach0data.ic index 888f3f743e4..2199565aff4 100644 --- a/storage/innobase/include/mach0data.ic +++ b/storage/innobase/include/mach0data.ic @@ -1,6 +1,6 @@ /********************************************************************** Utilities for converting data from the database file -to the machine format. +to the machine format. (c) 1995 Innobase Oy @@ -10,11 +10,11 @@ Created 11/28/1995 Heikki Tuuri /*********************************************************** The following function is used to store data in one byte. */ UNIV_INLINE -void +void mach_write_to_1( /*============*/ - byte* b, /* in: pointer to byte where to store */ - ulint n) /* in: ulint integer to be stored, >= 0, < 256 */ + byte* b, /* in: pointer to byte where to store */ + ulint n) /* in: ulint integer to be stored, >= 0, < 256 */ { ut_ad(b); ut_ad(n <= 0xFFUL); @@ -25,11 +25,11 @@ mach_write_to_1( /************************************************************ The following function is used to fetch data from one byte. */ UNIV_INLINE -ulint +ulint mach_read_from_1( /*=============*/ /* out: ulint integer, >= 0, < 256 */ - byte* b) /* in: pointer to byte */ + byte* b) /* in: pointer to byte */ { ut_ad(b); return((ulint)(b[0])); @@ -39,11 +39,11 @@ mach_read_from_1( The following function is used to store data in two consecutive bytes. We store the most significant byte to the lowest address. */ UNIV_INLINE -void +void mach_write_to_2( /*============*/ - byte* b, /* in: pointer to two bytes where to store */ - ulint n) /* in: ulint integer to be stored */ + byte* b, /* in: pointer to two bytes where to store */ + ulint n) /* in: ulint integer to be stored */ { ut_ad(b); ut_ad(n <= 0xFFFFUL); @@ -56,16 +56,16 @@ mach_write_to_2( The following function is used to fetch data from 2 consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -ulint +ulint mach_read_from_2( /*=============*/ /* out: ulint integer */ - byte* b) /* in: pointer to 2 bytes */ + byte* b) /* in: pointer to 2 bytes */ { ut_ad(b); return( ((ulint)(b[0]) << 8) + (ulint)(b[1]) - ); + ); } /************************************************************ @@ -103,11 +103,11 @@ mach_decode_2( The following function is used to store data in 3 consecutive bytes. We store the most significant byte to the lowest address. */ UNIV_INLINE -void +void mach_write_to_3( /*============*/ - byte* b, /* in: pointer to 3 bytes where to store */ - ulint n) /* in: ulint integer to be stored */ + byte* b, /* in: pointer to 3 bytes where to store */ + ulint n) /* in: ulint integer to be stored */ { ut_ad(b); ut_ad(n <= 0xFFFFFFUL); @@ -121,28 +121,28 @@ mach_write_to_3( The following function is used to fetch data from 3 consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -ulint +ulint mach_read_from_3( /*=============*/ /* out: ulint integer */ - byte* b) /* in: pointer to 3 bytes */ + byte* b) /* in: pointer to 3 bytes */ { ut_ad(b); return( ((ulint)(b[0]) << 16) + ((ulint)(b[1]) << 8) + (ulint)(b[2]) - ); + ); } /*********************************************************** The following function is used to store data in four consecutive bytes. We store the most significant byte to the lowest address. */ UNIV_INLINE -void +void mach_write_to_4( /*============*/ - byte* b, /* in: pointer to four bytes where to store */ - ulint n) /* in: ulint integer to be stored */ + byte* b, /* in: pointer to four bytes where to store */ + ulint n) /* in: ulint integer to be stored */ { ut_ad(b); @@ -154,7 +154,7 @@ mach_write_to_4( __asm MOV EAX, n __asm BSWAP EAX /* Intel is little-endian, must swap bytes */ __asm MOV n, EAX - + *((ulint*)b) = n; #else b[0] = (byte)(n >> 24); @@ -168,11 +168,11 @@ mach_write_to_4( The following function is used to fetch data from 4 consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -ulint +ulint mach_read_from_4( /*=============*/ /* out: ulint integer */ - byte* b) /* in: pointer to four bytes */ + byte* b) /* in: pointer to four bytes */ { #if (0 == 1) && !defined(__STDC__) && defined(UNIV_INTEL) && (UNIV_WORD_SIZE == 4) && defined(UNIV_VISUALC) /* We do not use this even on Intel, because unaligned accesses may @@ -194,7 +194,7 @@ mach_read_from_4( + ((ulint)(b[1]) << 16) + ((ulint)(b[2]) << 8) + (ulint)(b[3]) - ); + ); #endif } @@ -203,15 +203,15 @@ Writes a ulint in a compressed form where the first byte codes the length of the stored ulint. We look at the most significant bits of the byte. If the most significant bit is zero, it means 1-byte storage, else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0, -it means 3-byte storage, else if 4th is 0, it means 4-byte storage, +it means 3-byte storage, else if 4th is 0, it means 4-byte storage, else the storage is 5-byte. */ UNIV_INLINE ulint mach_write_compressed( /*==================*/ /* out: compressed size in bytes */ - byte* b, /* in: pointer to memory where to store */ - ulint n) /* in: ulint integer (< 2^32) to be stored */ + byte* b, /* in: pointer to memory where to store */ + ulint n) /* in: ulint integer (< 2^32) to be stored */ { ut_ad(b); @@ -241,7 +241,7 @@ ulint mach_get_compressed_size( /*=====================*/ /* out: compressed size in bytes */ - ulint n) /* in: ulint integer (< 2^32) to be stored */ + ulint n) /* in: ulint integer (< 2^32) to be stored */ { if (n < 0x80UL) { return(1); @@ -263,7 +263,7 @@ ulint mach_read_compressed( /*=================*/ /* out: read integer (< 2^32) */ - byte* b) /* in: pointer to memory from where to read */ + byte* b) /* in: pointer to memory from where to read */ { ulint flag; @@ -289,11 +289,11 @@ mach_read_compressed( The following function is used to store data in 8 consecutive bytes. We store the most significant byte to the lowest address. */ UNIV_INLINE -void +void mach_write_to_8( /*============*/ - byte* b, /* in: pointer to 8 bytes where to store */ - dulint n) /* in: dulint integer to be stored */ + byte* b, /* in: pointer to 8 bytes where to store */ + dulint n) /* in: dulint integer to be stored */ { ut_ad(b); @@ -305,11 +305,11 @@ mach_write_to_8( The following function is used to fetch data from 8 consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -dulint +dulint mach_read_from_8( /*=============*/ /* out: dulint integer */ - byte* b) /* in: pointer to 8 bytes */ + byte* b) /* in: pointer to 8 bytes */ { ulint high; ulint low; @@ -319,18 +319,18 @@ mach_read_from_8( high = mach_read_from_4(b); low = mach_read_from_4(b + 4); - return(ut_dulint_create(high, low)); + return(ut_dulint_create(high, low)); } /*********************************************************** The following function is used to store data in 7 consecutive bytes. We store the most significant byte to the lowest address. */ UNIV_INLINE -void +void mach_write_to_7( /*============*/ - byte* b, /* in: pointer to 7 bytes where to store */ - dulint n) /* in: dulint integer to be stored */ + byte* b, /* in: pointer to 7 bytes where to store */ + dulint n) /* in: dulint integer to be stored */ { ut_ad(b); @@ -342,11 +342,11 @@ mach_write_to_7( The following function is used to fetch data from 7 consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -dulint +dulint mach_read_from_7( /*=============*/ /* out: dulint integer */ - byte* b) /* in: pointer to 7 bytes */ + byte* b) /* in: pointer to 7 bytes */ { ulint high; ulint low; @@ -356,18 +356,18 @@ mach_read_from_7( high = mach_read_from_3(b); low = mach_read_from_4(b + 3); - return(ut_dulint_create(high, low)); + return(ut_dulint_create(high, low)); } /*********************************************************** The following function is used to store data in 6 consecutive bytes. We store the most significant byte to the lowest address. */ UNIV_INLINE -void +void mach_write_to_6( /*============*/ - byte* b, /* in: pointer to 6 bytes where to store */ - dulint n) /* in: dulint integer to be stored */ + byte* b, /* in: pointer to 6 bytes where to store */ + dulint n) /* in: dulint integer to be stored */ { ut_ad(b); @@ -379,11 +379,11 @@ mach_write_to_6( The following function is used to fetch data from 6 consecutive bytes. The most significant byte is at the lowest address. */ UNIV_INLINE -dulint +dulint mach_read_from_6( /*=============*/ /* out: dulint integer */ - byte* b) /* in: pointer to 7 bytes */ + byte* b) /* in: pointer to 7 bytes */ { ulint high; ulint low; @@ -393,7 +393,7 @@ mach_read_from_6( high = mach_read_from_2(b); low = mach_read_from_4(b + 2); - return(ut_dulint_create(high, low)); + return(ut_dulint_create(high, low)); } /************************************************************* @@ -403,8 +403,8 @@ ulint mach_dulint_write_compressed( /*=========================*/ /* out: size in bytes */ - byte* b, /* in: pointer to memory where to store */ - dulint n) /* in: dulint integer to be stored */ + byte* b, /* in: pointer to memory where to store */ + dulint n) /* in: dulint integer to be stored */ { ulint size; @@ -423,7 +423,7 @@ ulint mach_dulint_get_compressed_size( /*============================*/ /* out: compressed size in bytes */ - dulint n) /* in: dulint integer to be stored */ + dulint n) /* in: dulint integer to be stored */ { return(4 + mach_get_compressed_size(ut_dulint_get_high(n))); } @@ -435,7 +435,7 @@ dulint mach_dulint_read_compressed( /*========================*/ /* out: read dulint */ - byte* b) /* in: pointer to memory from where to read */ + byte* b) /* in: pointer to memory from where to read */ { ulint high; ulint low; @@ -449,7 +449,7 @@ mach_dulint_read_compressed( low = mach_read_from_4(b + size); - return(ut_dulint_create(high, low)); + return(ut_dulint_create(high, low)); } /************************************************************* @@ -459,17 +459,17 @@ ulint mach_dulint_write_much_compressed( /*==============================*/ /* out: size in bytes */ - byte* b, /* in: pointer to memory where to store */ - dulint n) /* in: dulint integer to be stored */ + byte* b, /* in: pointer to memory where to store */ + dulint n) /* in: dulint integer to be stored */ { ulint size; ut_ad(b); - + if (ut_dulint_get_high(n) == 0) { return(mach_write_compressed(b, ut_dulint_get_low(n))); } - + *b = (byte)0xFF; size = 1 + mach_write_compressed(b + 1, ut_dulint_get_high(n)); @@ -485,14 +485,14 @@ ulint mach_dulint_get_much_compressed_size( /*=================================*/ /* out: compressed size in bytes */ - dulint n) /* in: dulint integer to be stored */ + dulint n) /* in: dulint integer to be stored */ { if (0 == ut_dulint_get_high(n)) { return(mach_get_compressed_size(ut_dulint_get_low(n))); } return(1 + mach_get_compressed_size(ut_dulint_get_high(n)) - + mach_get_compressed_size(ut_dulint_get_low(n))); + + mach_get_compressed_size(ut_dulint_get_low(n))); } /************************************************************* @@ -502,7 +502,7 @@ dulint mach_dulint_read_much_compressed( /*=============================*/ /* out: read dulint */ - byte* b) /* in: pointer to memory from where to read */ + byte* b) /* in: pointer to memory from where to read */ { ulint high; ulint low; @@ -521,7 +521,7 @@ mach_dulint_read_much_compressed( low = mach_read_compressed(b + size); - return(ut_dulint_create(high, low)); + return(ut_dulint_create(high, low)); } /************************************************************* @@ -531,9 +531,9 @@ double mach_double_read( /*=============*/ /* out: double read */ - byte* b) /* in: pointer to memory from where to read */ + byte* b) /* in: pointer to memory from where to read */ { - double d; + double d; ulint i; byte* ptr; @@ -547,7 +547,7 @@ mach_double_read( #endif } - return(d); + return(d); } /************************************************************* @@ -556,8 +556,8 @@ UNIV_INLINE void mach_double_write( /*==============*/ - byte* b, /* in: pointer to memory where to write */ - double d) /* in: double */ + byte* b, /* in: pointer to memory where to write */ + double d) /* in: double */ { ulint i; byte* ptr; @@ -578,11 +578,11 @@ Reads a float. It is stored in a little-endian format. */ UNIV_INLINE float mach_float_read( -/*=============*/ +/*============*/ /* out: float read */ - byte* b) /* in: pointer to memory from where to read */ + byte* b) /* in: pointer to memory from where to read */ { - float d; + float d; ulint i; byte* ptr; @@ -596,7 +596,7 @@ mach_float_read( #endif } - return(d); + return(d); } /************************************************************* @@ -604,9 +604,9 @@ Writes a float. It is stored in a little-endian format. */ UNIV_INLINE void mach_float_write( -/*==============*/ - byte* b, /* in: pointer to memory where to write */ - float d) /* in: float */ +/*=============*/ + byte* b, /* in: pointer to memory where to write */ + float d) /* in: float */ { ulint i; byte* ptr; @@ -639,7 +639,7 @@ mach_read_from_n_little_endian( ut_ad(buf_size > 0); ptr = buf + buf_size; - + for (;;) { ptr--; @@ -671,7 +671,7 @@ mach_write_to_n_little_endian( ut_ad(dest_size > 0); end = dest + dest_size; - + for (;;) { *dest = (byte)(n & 0xFF); @@ -681,7 +681,7 @@ mach_write_to_n_little_endian( if (dest == end) { break; - } + } } ut_ad(n == 0); diff --git a/storage/innobase/include/mem0dbg.h b/storage/innobase/include/mem0dbg.h index 96f30842df6..0f4441f4f9d 100644 --- a/storage/innobase/include/mem0dbg.h +++ b/storage/innobase/include/mem0dbg.h @@ -11,11 +11,11 @@ Created 6/9/1994 Heikki Tuuri check fields whose sizes are given below */ #ifdef UNIV_MEM_DEBUG -#define MEM_FIELD_HEADER_SIZE ut_calc_align(2 * sizeof(ulint),\ +#define MEM_FIELD_HEADER_SIZE ut_calc_align(2 * sizeof(ulint),\ UNIV_MEM_ALIGNMENT) -#define MEM_FIELD_TRAILER_SIZE sizeof(ulint) +#define MEM_FIELD_TRAILER_SIZE sizeof(ulint) #else -#define MEM_FIELD_HEADER_SIZE 0 +#define MEM_FIELD_HEADER_SIZE 0 #endif @@ -25,8 +25,7 @@ UNIV_MEM_ALIGNMENT. In the debug version there are also check fields at the both ends of the field. */ #ifdef UNIV_MEM_DEBUG #define MEM_SPACE_NEEDED(N) ut_calc_align((N) + MEM_FIELD_HEADER_SIZE\ - + MEM_FIELD_TRAILER_SIZE,\ - UNIV_MEM_ALIGNMENT) + + MEM_FIELD_TRAILER_SIZE, UNIV_MEM_ALIGNMENT) #else #define MEM_SPACE_NEEDED(N) ut_calc_align((N), UNIV_MEM_ALIGNMENT) #endif @@ -41,23 +40,23 @@ of blocks. */ void mem_heap_validate_or_print( /*=======================*/ - mem_heap_t* heap, /* in: memory heap */ + mem_heap_t* heap, /* in: memory heap */ byte* top, /* in: calculate and validate only until this top pointer in the heap is reached, if this pointer is NULL, ignored */ - ibool print, /* in: if TRUE, prints the contents + ibool print, /* in: if TRUE, prints the contents of the heap; works only in the debug version */ - ibool* error, /* out: TRUE if error */ - ulint* us_size,/* out: allocated memory + ibool* error, /* out: TRUE if error */ + ulint* us_size,/* out: allocated memory (for the user) in the heap, if a NULL pointer is passed as this argument, it is ignored; in the non-debug version this is always -1 */ - ulint* ph_size,/* out: physical size of the heap, + ulint* ph_size,/* out: physical size of the heap, if a NULL pointer is passed as this argument, it is ignored */ - ulint* n_blocks); /* out: number of blocks in the heap, + ulint* n_blocks); /* out: number of blocks in the heap, if a NULL pointer is passed as this argument, it is ignored */ #ifdef UNIV_MEM_DEBUG @@ -115,7 +114,7 @@ the neighborhood of a given pointer. */ void mem_analyze_corruption( /*===================*/ - byte* ptr); /* in: pointer to place of possible corruption */ + void* ptr); /* in: pointer to place of possible corruption */ /********************************************************************* Prints information of dynamic memory usage and currently allocated memory heaps or buffers. Can only be used in the debug version. */ diff --git a/storage/innobase/include/mem0dbg.ic b/storage/innobase/include/mem0dbg.ic index 7ce5f6f1ba5..e8a34adb3fa 100644 --- a/storage/innobase/include/mem0dbg.ic +++ b/storage/innobase/include/mem0dbg.ic @@ -34,8 +34,8 @@ Used to initialize allocated memory. */ void mem_init_buf( /*=========*/ - byte* buf, /* in: pointer to buffer */ - ulint n); /* in: length of buffer */ + byte* buf, /* in: pointer to buffer */ + ulint n); /* in: length of buffer */ /******************************************************************* Initializes a buffer to a random combination of hex DE and AD. Used to erase freed memory.*/ @@ -43,8 +43,8 @@ Used to erase freed memory.*/ void mem_erase_buf( /*==========*/ - byte* buf, /* in: pointer to buffer */ - ulint n); /* in: length of buffer */ + byte* buf, /* in: pointer to buffer */ + ulint n); /* in: length of buffer */ /******************************************************************* Inserts a created memory heap to the hash table of current allocated memory heaps. diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h index 399ab8a338e..e2f8be98b01 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -49,8 +49,8 @@ the size is not specified, i.e., 0 is given as the parameter in the call of create. The standard size is the maximum (payload) size of the blocks used for allocations of small buffers. */ -#define MEM_BLOCK_START_SIZE 64 -#define MEM_BLOCK_STANDARD_SIZE 8000 +#define MEM_BLOCK_START_SIZE 64 +#define MEM_BLOCK_STANDARD_SIZE 8000 /* If a memory heap is allowed to grow into the buffer pool, the following is the maximum size for a single allocated buffer: */ @@ -67,24 +67,21 @@ mem_init( Use this macro instead of the corresponding function! Macro for memory heap creation. */ -#define mem_heap_create(N) mem_heap_create_func(\ - (N), NULL, MEM_HEAP_DYNAMIC,\ - __FILE__, __LINE__) +#define mem_heap_create(N) mem_heap_create_func(\ + (N), NULL, MEM_HEAP_DYNAMIC, __FILE__, __LINE__) /****************************************************************** Use this macro instead of the corresponding function! Macro for memory heap creation. */ #define mem_heap_create_in_buffer(N) mem_heap_create_func(\ - (N), NULL, MEM_HEAP_BUFFER,\ - __FILE__, __LINE__) + (N), NULL, MEM_HEAP_BUFFER, __FILE__, __LINE__) /****************************************************************** Use this macro instead of the corresponding function! Macro for memory heap creation. */ -#define mem_heap_create_in_btr_search(N) mem_heap_create_func(\ - (N), NULL, MEM_HEAP_BTR_SEARCH |\ - MEM_HEAP_BUFFER,\ - __FILE__, __LINE__) +#define mem_heap_create_in_btr_search(N) mem_heap_create_func(\ + (N), NULL, MEM_HEAP_BTR_SEARCH | MEM_HEAP_BUFFER,\ + __FILE__, __LINE__) /****************************************************************** Use this macro instead of the corresponding function! Macro for fast memory heap creation. An initial block of memory B is given by the @@ -92,8 +89,7 @@ caller, N is its size, and this memory block is not freed by mem_heap_free. See the parameter comment in mem_heap_create_func below. */ #define mem_heap_fast_create(N, B) mem_heap_create_func(\ - (N), (B), MEM_HEAP_DYNAMIC,\ - __FILE__, __LINE__) + (N), (B), MEM_HEAP_DYNAMIC, __FILE__, __LINE__) /****************************************************************** Use this macro instead of the corresponding function! Macro for memory @@ -114,7 +110,7 @@ mem_heap_create_func( MEM_HEAP_BTR_SEARCH type heaps)*/ ulint n, /* in: desired start block size, this means that a single user buffer - of size n will fit in the block, + of size n will fit in the block, 0 creates a default size block; if init_block is not NULL, n tells its size in bytes */ @@ -128,7 +124,7 @@ mem_heap_create_func( block is not unintentionally erased (if allocated in the stack), before the memory heap is explicitly freed. */ - ulint type, /* in: heap type */ + ulint type, /* in: heap type */ const char* file_name, /* in: file name where created */ ulint line); /* in: line where created */ /********************************************************************* @@ -139,9 +135,9 @@ UNIV_INLINE void mem_heap_free_func( /*===============*/ - mem_heap_t* heap, /* in, own: heap to be freed */ - const char* file_name, /* in: file name where freed */ - ulint line); /* in: line where freed */ + mem_heap_t* heap, /* in, own: heap to be freed */ + const char* file_name, /* in: file name where freed */ + ulint line); /* in: line where freed */ /******************************************************************* Allocates n bytes of memory from a memory heap. */ UNIV_INLINE @@ -151,8 +147,8 @@ mem_heap_alloc( /* out: allocated storage, NULL if did not succeed (only possible for MEM_HEAP_BTR_SEARCH type heaps) */ - mem_heap_t* heap, /* in: memory heap */ - ulint n); /* in: number of bytes; if the heap is allowed + mem_heap_t* heap, /* in: memory heap */ + ulint n); /* in: number of bytes; if the heap is allowed to grow into the buffer pool, this must be <= MEM_MAX_ALLOC_IN_BUF */ /********************************************************************* @@ -160,9 +156,9 @@ Returns a pointer to the heap top. */ UNIV_INLINE byte* mem_heap_get_heap_top( -/*==================*/ +/*==================*/ /* out: pointer to the heap top */ - mem_heap_t* heap); /* in: memory heap */ + mem_heap_t* heap); /* in: memory heap */ /********************************************************************* Frees the space in a memory heap exceeding the pointer given. The pointer must have been acquired from mem_heap_get_heap_top. The first @@ -171,7 +167,7 @@ UNIV_INLINE void mem_heap_free_heap_top( /*===================*/ - mem_heap_t* heap, /* in: heap from which to free */ + mem_heap_t* heap, /* in: heap from which to free */ byte* old_top);/* in: pointer to old top of heap */ /********************************************************************* Empties a memory heap. The first memory block of the heap is not freed. */ @@ -179,48 +175,48 @@ UNIV_INLINE void mem_heap_empty( /*===========*/ - mem_heap_t* heap); /* in: heap to empty */ + mem_heap_t* heap); /* in: heap to empty */ /********************************************************************* Returns a pointer to the topmost element in a memory heap. The size of the element must be given. */ UNIV_INLINE void* mem_heap_get_top( -/*=============*/ +/*=============*/ /* out: pointer to the topmost element */ - mem_heap_t* heap, /* in: memory heap */ - ulint n); /* in: size of the topmost element */ + mem_heap_t* heap, /* in: memory heap */ + ulint n); /* in: size of the topmost element */ /********************************************************************* Frees the topmost element in a memory heap. The size of the element must be given. */ UNIV_INLINE void mem_heap_free_top( -/*==============*/ - mem_heap_t* heap, /* in: memory heap */ - ulint n); /* in: size of the topmost element */ +/*==============*/ + mem_heap_t* heap, /* in: memory heap */ + ulint n); /* in: size of the topmost element */ /********************************************************************* Returns the space in bytes occupied by a memory heap. */ UNIV_INLINE ulint mem_heap_get_size( /*==============*/ - mem_heap_t* heap); /* in: heap */ + mem_heap_t* heap); /* in: heap */ /****************************************************************** Use this macro instead of the corresponding function! Macro for memory buffer allocation */ -#define mem_alloc(N) mem_alloc_func((N), __FILE__, __LINE__) +#define mem_alloc(N) mem_alloc_func((N), __FILE__, __LINE__) /****************************************************************** Use this macro instead of the corresponding function! Macro for memory buffer allocation */ -#define mem_alloc_noninline(N) mem_alloc_func_noninline(\ +#define mem_alloc_noninline(N) mem_alloc_func_noninline(\ (N), __FILE__, __LINE__) /******************************************************************* NOTE: Use the corresponding macro instead of this function. Allocates a single buffer of memory from the dynamic memory of -the C compiler. Is like malloc of C. The buffer must be freed +the C compiler. Is like malloc of C. The buffer must be freed with mem_free. */ UNIV_INLINE void* @@ -234,7 +230,7 @@ mem_alloc_func( /******************************************************************* NOTE: Use the corresponding macro instead of this function. Allocates a single buffer of memory from the dynamic memory of -the C compiler. Is like malloc of C. The buffer must be freed +the C compiler. Is like malloc of C. The buffer must be freed with mem_free. */ void* @@ -249,7 +245,7 @@ mem_alloc_func_noninline( Use this macro instead of the corresponding function! Macro for memory buffer freeing */ -#define mem_free(PTR) mem_free_func((PTR), __FILE__, __LINE__) +#define mem_free(PTR) mem_free_func((PTR), __FILE__, __LINE__) /******************************************************************* NOTE: Use the corresponding macro instead of this function. Frees a single buffer of storage from @@ -326,11 +322,11 @@ mem_validate_all_blocks(void); #endif /*#######################################################################*/ - + /* The info header of a block in a memory heap */ struct mem_block_info_struct { - ulint magic_n;/* magic number for debugging */ + ulint magic_n;/* magic number for debugging */ char file_name[8];/* file name where the mem heap was created */ ulint line; /* line number where the mem heap was created */ UT_LIST_BASE_NODE_T(mem_block_t) base; /* In the first block in the @@ -340,23 +336,23 @@ struct mem_block_info_struct { and prev in the list. The first block allocated to the heap is also the first block in this list, though it also contains the base node of the list. */ - ulint len; /* physical length of this block in bytes */ - ulint type; /* type of heap: MEM_HEAP_DYNAMIC, or + ulint len; /* physical length of this block in bytes */ + ulint type; /* type of heap: MEM_HEAP_DYNAMIC, or MEM_HEAP_BUF possibly ORed to MEM_HEAP_BTR_SEARCH */ ibool init_block; /* TRUE if this is the first block used in fast creation of a heap: the memory will be freed by the creator, not by mem_heap_free */ - ulint free; /* offset in bytes of the first free position for + ulint free; /* offset in bytes of the first free position for user data in the block */ - ulint start; /* the value of the struct field 'free' at the + ulint start; /* the value of the struct field 'free' at the creation of the block */ - byte* free_block; + byte* free_block; /* if the MEM_HEAP_BTR_SEARCH bit is set in type, and this is the heap root, this can contain an allocated buffer frame, which can be appended as a free block to the heap, if we need more space; otherwise, this is NULL */ -#ifdef MEM_PERIODIC_CHECK +#ifdef MEM_PERIODIC_CHECK UT_LIST_NODE_T(mem_block_t) mem_block_list; /* List of all mem blocks allocated; protected by the mem_comm_pool mutex */ @@ -367,7 +363,7 @@ struct mem_block_info_struct { #define MEM_FREED_BLOCK_MAGIC_N 547711122 /* Header size for a memory heap block */ -#define MEM_BLOCK_HEADER_SIZE ut_calc_align(sizeof(mem_block_info_t),\ +#define MEM_BLOCK_HEADER_SIZE ut_calc_align(sizeof(mem_block_info_t),\ UNIV_MEM_ALIGNMENT) #include "mem0dbg.h" @@ -375,4 +371,4 @@ struct mem_block_info_struct { #include "mem0mem.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic index 291b68723b4..db0ab7aba8c 100644 --- a/storage/innobase/include/mem0mem.ic +++ b/storage/innobase/include/mem0mem.ic @@ -53,7 +53,7 @@ mem_heap_add_block( /* out: created block, NULL if did not succeed (only possible for MEM_HEAP_BTR_SEARCH type heaps)*/ - mem_heap_t* heap, /* in: memory heap */ + mem_heap_t* heap, /* in: memory heap */ ulint n); /* in: number of bytes user needs */ UNIV_INLINE @@ -131,25 +131,25 @@ mem_heap_alloc( /* out: allocated storage, NULL if did not succeed (only possible for MEM_HEAP_BTR_SEARCH type heaps) */ - mem_heap_t* heap, /* in: memory heap */ - ulint n) /* in: number of bytes; if the heap is allowed + mem_heap_t* heap, /* in: memory heap */ + ulint n) /* in: number of bytes; if the heap is allowed to grow into the buffer pool, this must be <= MEM_MAX_ALLOC_IN_BUF */ { mem_block_t* block; void* buf; ulint free; - + ut_ad(mem_heap_check(heap)); block = UT_LIST_GET_LAST(heap->base); ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF)); - + /* Check if there is enough space in block. If not, create a new block to the heap */ - if (mem_block_get_len(block) + if (mem_block_get_len(block) < mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) { block = mem_heap_add_block(heap, n); @@ -187,13 +187,13 @@ Returns a pointer to the heap top. */ UNIV_INLINE byte* mem_heap_get_heap_top( -/*==================*/ +/*==================*/ /* out: pointer to the heap top */ - mem_heap_t* heap) /* in: memory heap */ + mem_heap_t* heap) /* in: memory heap */ { mem_block_t* block; byte* buf; - + ut_ad(mem_heap_check(heap)); block = UT_LIST_GET_LAST(heap->base); @@ -201,7 +201,7 @@ mem_heap_get_heap_top( buf = (byte*)block + mem_block_get_free(block); return(buf); -} +} /********************************************************************* Frees the space in a memory heap exceeding the pointer given. The @@ -211,19 +211,19 @@ UNIV_INLINE void mem_heap_free_heap_top( /*===================*/ - mem_heap_t* heap, /* in: heap from which to free */ + mem_heap_t* heap, /* in: heap from which to free */ byte* old_top)/* in: pointer to old top of heap */ { mem_block_t* block; mem_block_t* prev_block; #ifdef UNIV_MEM_DEBUG ibool error; - ulint total_size; + ulint total_size; ulint size; -#endif +#endif ut_ad(mem_heap_check(heap)); - + #ifdef UNIV_MEM_DEBUG /* Validate the heap and get its total allocated size */ @@ -247,7 +247,7 @@ mem_heap_free_heap_top( break; } - + /* Store prev_block value before freeing the current block (the current block will be erased in freeing) */ @@ -257,17 +257,17 @@ mem_heap_free_heap_top( block = prev_block; } - + ut_ad(block); /* Set the free field of block */ - mem_block_set_free(block, old_top - (byte*)block); + mem_block_set_free(block, old_top - (byte*)block); #ifdef UNIV_MEM_DEBUG ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); /* In the debug version erase block from top up */ - + mem_erase_buf(old_top, (byte*)block + block->len - old_top); /* Update allocated memory count */ @@ -279,9 +279,9 @@ mem_heap_free_heap_top( /* If free == start, we may free the block if it is not the first one */ - - if ((heap != block) && (mem_block_get_free(block) == - mem_block_get_start(block))) { + + if ((heap != block) && (mem_block_get_free(block) == + mem_block_get_start(block))) { mem_heap_block_free(heap, block); } } @@ -292,14 +292,14 @@ UNIV_INLINE void mem_heap_empty( /*===========*/ - mem_heap_t* heap) /* in: heap to empty */ + mem_heap_t* heap) /* in: heap to empty */ { mem_heap_free_heap_top(heap, (byte*)heap + mem_block_get_start(heap)); if (heap->free_block) { mem_heap_free_block_free(heap); } -} +} /********************************************************************* Returns a pointer to the topmost element in a memory heap. The size of the @@ -307,14 +307,14 @@ element must be given. */ UNIV_INLINE void* mem_heap_get_top( -/*=============*/ +/*=============*/ /* out: pointer to the topmost element */ - mem_heap_t* heap, /* in: memory heap */ - ulint n) /* in: size of the topmost element */ + mem_heap_t* heap, /* in: memory heap */ + ulint n) /* in: size of the topmost element */ { mem_block_t* block; void* buf; - + ut_ad(mem_heap_check(heap)); block = UT_LIST_GET_LAST(heap->base); @@ -326,7 +326,7 @@ mem_heap_get_top( /* In the debug version, advance buf to point at the storage which was given to the caller in the allocation*/ - + buf = (byte*)buf + MEM_FIELD_HEADER_SIZE; /* Check that the field lengths agree */ @@ -334,7 +334,7 @@ mem_heap_get_top( #endif return(buf); -} +} /********************************************************************* Frees the topmost element in a memory heap. The size of the element must be @@ -342,12 +342,12 @@ given. */ UNIV_INLINE void mem_heap_free_top( -/*==============*/ - mem_heap_t* heap, /* in: memory heap */ - ulint n) /* in: size of the topmost element */ +/*==============*/ + mem_heap_t* heap, /* in: memory heap */ + ulint n) /* in: size of the topmost element */ { mem_block_t* block; - + ut_ad(mem_heap_check(heap)); block = UT_LIST_GET_LAST(heap->base); @@ -365,9 +365,9 @@ mem_heap_free_top( /* If free == start, we may free the block if it is not the first one */ - - if ((heap != block) && (mem_block_get_free(block) == - mem_block_get_start(block))) { + + if ((heap != block) && (mem_block_get_free(block) == + mem_block_get_start(block))) { mem_heap_block_free(heap, block); } } @@ -385,7 +385,7 @@ mem_heap_create_func( MEM_HEAP_BTR_SEARCH type heaps)*/ ulint n, /* in: desired start block size, this means that a single user buffer - of size n will fit in the block, + of size n will fit in the block, 0 creates a default size block; if init_block is not NULL, n tells its size in bytes */ @@ -399,25 +399,25 @@ mem_heap_create_func( block is not unintentionally erased (if allocated in the stack), before the memory heap is explicitly freed. */ - ulint type, /* in: heap type */ + ulint type, /* in: heap type */ const char* file_name, /* in: file name where created */ ulint line) /* in: line where created */ { - mem_block_t* block; + mem_block_t* block; if (n > 0) { block = mem_heap_create_block(NULL, n, init_block, type, file_name, line); } else { - block = mem_heap_create_block(NULL, MEM_BLOCK_START_SIZE, + block = mem_heap_create_block(NULL, MEM_BLOCK_START_SIZE, init_block, type, file_name, line); } if (block == NULL) { - + return(NULL); } - + UT_LIST_INIT(block->base); /* Add the created block itself as the first block in the list */ @@ -428,7 +428,7 @@ mem_heap_create_func( mem_hash_insert(block, file_name, line); #endif - + return(block); } @@ -440,16 +440,16 @@ UNIV_INLINE void mem_heap_free_func( /*===============*/ - mem_heap_t* heap, /* in, own: heap to be freed */ + mem_heap_t* heap, /* in, own: heap to be freed */ const char* file_name __attribute__((unused)), /* in: file name where freed */ - ulint line __attribute__((unused))) + ulint line __attribute__((unused))) { mem_block_t* block; mem_block_t* prev_block; ut_ad(mem_heap_check(heap)); - + block = UT_LIST_GET_LAST(heap->base); #ifdef UNIV_MEM_DEBUG @@ -457,15 +457,15 @@ mem_heap_free_func( /* In the debug version remove the heap from the hash table of heaps and check its consistency */ - mem_hash_remove(heap, file_name, line); + mem_hash_remove(heap, file_name, line); #endif - + if (heap->free_block) { mem_heap_free_block_free(heap); } - while (block != NULL) { + while (block != NULL) { /* Store the contents of info before freeing current block (it is erased in freeing) */ @@ -480,7 +480,7 @@ mem_heap_free_func( /******************************************************************* NOTE: Use the corresponding macro instead of this function. Allocates a single buffer of memory from the dynamic memory of -the C compiler. Is like malloc of C. The buffer must be freed +the C compiler. Is like malloc of C. The buffer must be freed with mem_free. */ UNIV_INLINE void* @@ -492,8 +492,8 @@ mem_alloc_func( ulint line /* in: line where created */ ) { - mem_heap_t* heap; - void* buf; + mem_heap_t* heap; + void* buf; heap = mem_heap_create_func(n, NULL, MEM_HEAP_DYNAMIC, file_name, line); @@ -523,10 +523,10 @@ mem_free_func( ulint line /* in: line where created */ ) { - mem_heap_t* heap; + mem_heap_t* heap; heap = (mem_heap_t*)((byte*)ptr - MEM_BLOCK_HEADER_SIZE - - MEM_FIELD_HEADER_SIZE); + - MEM_FIELD_HEADER_SIZE); mem_heap_free_func(heap, file_name, line); } @@ -536,16 +536,16 @@ UNIV_INLINE ulint mem_heap_get_size( /*==============*/ - mem_heap_t* heap) /* in: heap */ + mem_heap_t* heap) /* in: heap */ { - mem_block_t* block; - ulint size = 0; + mem_block_t* block; + ulint size = 0; ut_ad(mem_heap_check(heap)); - + block = heap; - while (block != NULL) { + while (block != NULL) { size += mem_block_get_len(block); block = UT_LIST_GET_NEXT(list, block); diff --git a/storage/innobase/include/mem0pool.h b/storage/innobase/include/mem0pool.h index 43707bd5f61..bf659ca9a72 100644 --- a/storage/innobase/include/mem0pool.h +++ b/storage/innobase/include/mem0pool.h @@ -25,14 +25,14 @@ struct mem_area_struct{ ulint size_and_free; /* memory area size is obtained by anding with ~MEM_AREA_FREE; area in a free list if ANDing with - MEM_AREA_FREE results in nonzero */ + MEM_AREA_FREE results in nonzero */ UT_LIST_NODE_T(mem_area_t) free_list; /* free list node */ }; /* Each memory area takes this many extra bytes for control information */ #define MEM_AREA_EXTRA_SIZE (ut_calc_align(sizeof(struct mem_area_struct),\ - UNIV_MEM_ALIGNMENT)) + UNIV_MEM_ALIGNMENT)) /************************************************************************ Creates a memory pool. */ @@ -97,7 +97,7 @@ Prints info of a memory pool. */ void mem_pool_print_info( /*================*/ - FILE* outfile,/* in: output file to write to */ + FILE* outfile,/* in: output file to write to */ mem_pool_t* pool); /* in: memory pool */ @@ -105,4 +105,4 @@ mem_pool_print_info( #include "mem0pool.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/mtr0log.ic b/storage/innobase/include/mtr0log.ic index 08d9a6448eb..1a5ef033f87 100644 --- a/storage/innobase/include/mtr0log.ic +++ b/storage/innobase/include/mtr0log.ic @@ -73,10 +73,18 @@ mlog_catenate_ulint( mlog = &(mtr->log); - ut_ad(MLOG_1BYTE == 1); - ut_ad(MLOG_2BYTES == 2); - ut_ad(MLOG_4BYTES == 4); - +#if MLOG_1BYTE != 1 +# error "MLOG_1BYTE != 1" +#endif +#if MLOG_2BYTES != 2 +# error "MLOG_2BYTES != 2" +#endif +#if MLOG_4BYTES != 4 +# error "MLOG_4BYTES != 4" +#endif +#if MLOG_8BYTES != 8 +# error "MLOG_8BYTES != 8" +#endif ptr = dyn_array_push(mlog, type); if (type == MLOG_4BYTES) { @@ -86,7 +94,7 @@ mlog_catenate_ulint( } else { ut_ad(type == MLOG_1BYTE); mach_write_to_1(ptr, val); - } + } } /************************************************************ @@ -156,7 +164,7 @@ mlog_write_initial_log_record_fast( ulint space; ulint offset; - ut_ad(mtr_memo_contains(mtr, buf_block_align(ptr), + ut_ad(mtr_memo_contains(mtr, buf_block_align(ptr), MTR_MEMO_PAGE_X_FIX)); ut_ad(type <= MLOG_BIGGEST_TYPE); ut_ad(ptr && log_ptr); @@ -167,7 +175,7 @@ mlog_write_initial_log_record_fast( offset = buf_block_get_page_no(block); mach_write_to_1(log_ptr, type); - log_ptr++; + log_ptr++; log_ptr += mach_write_compressed(log_ptr, space); log_ptr += mach_write_compressed(log_ptr, offset); @@ -188,7 +196,7 @@ mlog_write_initial_log_record_fast( } #endif return(log_ptr); -} +} /************************************************************ Writes a log record about an .ibd file create/delete/rename. */ @@ -216,4 +224,4 @@ mlog_write_initial_log_record_for_file_op( mtr->n_log_recs++; return(log_ptr); -} +} diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index f44e813cf6b..3167ea3bc03 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -27,7 +27,7 @@ Created 11/26/1995 Heikki Tuuri (operations in fsp0fsp.* ) */ #define MTR_LOG_SHORT_INSERTS 24 /* inserts are logged in a shorter form */ - + /* Types for the mlock objects to store in the mtr memo; NOTE that the first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */ #define MTR_MEMO_PAGE_S_FIX RW_S_LATCH @@ -47,31 +47,31 @@ flag value must give the length also! */ has been called only once, this flag is ORed to the type of that first log record */ -#define MLOG_1BYTE ((byte)1) /* one byte is written */ -#define MLOG_2BYTES ((byte)2) /* 2 bytes ... */ -#define MLOG_4BYTES ((byte)4) /* 4 bytes ... */ -#define MLOG_8BYTES ((byte)8) /* 8 bytes ... */ +#define MLOG_1BYTE (1) /* one byte is written */ +#define MLOG_2BYTES (2) /* 2 bytes ... */ +#define MLOG_4BYTES (4) /* 4 bytes ... */ +#define MLOG_8BYTES (8) /* 8 bytes ... */ #define MLOG_REC_INSERT ((byte)9) /* record insert */ -#define MLOG_REC_CLUST_DELETE_MARK ((byte)10) /* mark clustered index record +#define MLOG_REC_CLUST_DELETE_MARK ((byte)10) /* mark clustered index record deleted */ -#define MLOG_REC_SEC_DELETE_MARK ((byte)11) /* mark secondary index record +#define MLOG_REC_SEC_DELETE_MARK ((byte)11) /* mark secondary index record deleted */ #define MLOG_REC_UPDATE_IN_PLACE ((byte)13) /* update of a record, preserves record field sizes */ #define MLOG_REC_DELETE ((byte)14) /* delete a record from a page */ -#define MLOG_LIST_END_DELETE ((byte)15) /* delete record list end on +#define MLOG_LIST_END_DELETE ((byte)15) /* delete record list end on index page */ -#define MLOG_LIST_START_DELETE ((byte)16) /* delete record list start on +#define MLOG_LIST_START_DELETE ((byte)16) /* delete record list start on index page */ -#define MLOG_LIST_END_COPY_CREATED ((byte)17) /* copy record list end to a +#define MLOG_LIST_END_COPY_CREATED ((byte)17) /* copy record list end to a new created index page */ -#define MLOG_PAGE_REORGANIZE ((byte)18) /* reorganize an index page */ -#define MLOG_PAGE_CREATE ((byte)19) /* create an index page */ -#define MLOG_UNDO_INSERT ((byte)20) /* insert entry in an undo +#define MLOG_PAGE_REORGANIZE ((byte)18) /* reorganize an index page */ +#define MLOG_PAGE_CREATE ((byte)19) /* create an index page */ +#define MLOG_UNDO_INSERT ((byte)20) /* insert entry in an undo log */ #define MLOG_UNDO_ERASE_END ((byte)21) /* erase an undo log page end */ -#define MLOG_UNDO_INIT ((byte)22) /* initialize a page in an +#define MLOG_UNDO_INIT ((byte)22) /* initialize a page in an undo log */ #define MLOG_UNDO_HDR_DISCARD ((byte)23) /* discard an update undo log header */ @@ -132,9 +132,9 @@ flag value must give the length also! */ #define MLOG_BIGGEST_TYPE ((byte)46) /* biggest value (used in asserts) */ - + /******************************************************************* -Starts a mini-transaction and creates a mini-transaction handle +Starts a mini-transaction and creates a mini-transaction handle and buffer in the memory buffer given by the caller. */ UNIV_INLINE mtr_t* @@ -144,7 +144,7 @@ mtr_start( the mtr handle */ mtr_t* mtr); /* in: memory buffer for the mtr buffer */ /******************************************************************* -Starts a mini-transaction and creates a mini-transaction handle +Starts a mini-transaction and creates a mini-transaction handle and buffer in the memory buffer given by the caller. */ mtr_t* @@ -187,7 +187,7 @@ mtr_release_s_latch_at_savepoint( /*=============================*/ mtr_t* mtr, /* in: mtr */ ulint savepoint, /* in: savepoint */ - rw_lock_t* lock); /* in: latch to release */ + rw_lock_t* lock); /* in: latch to release */ /******************************************************************* Gets the logging mode of a mini-transaction. */ UNIV_INLINE @@ -220,7 +220,7 @@ Reads 8 bytes from a file page buffered in the buffer pool. */ dulint mtr_read_dulint( -/*===========*/ +/*============*/ /* out: value read */ byte* ptr, /* in: pointer from where to read */ mtr_t* mtr); /* in: mini-transaction handle */ @@ -336,7 +336,7 @@ struct mtr_struct{ #define MTR_ACTIVE 12231 #define MTR_COMMITTING 56456 #define MTR_COMMITTED 34676 - + #ifndef UNIV_NONINL #include "mtr0mtr.ic" #endif diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic index 4fc6dd2f6a9..d81f6cb9c0d 100644 --- a/storage/innobase/include/mtr0mtr.ic +++ b/storage/innobase/include/mtr0mtr.ic @@ -11,7 +11,7 @@ Created 11/26/1995 Heikki Tuuri #include "mach0data.h" /******************************************************************* -Starts a mini-transaction and creates a mini-transaction handle +Starts a mini-transaction and creates a mini-transaction handle and a buffer in the memory buffer given by the caller. */ UNIV_INLINE mtr_t* @@ -33,7 +33,7 @@ mtr_start( mtr->magic_n = MTR_MAGIC_N; #endif return(mtr); -} +} /******************************************************* Pushes an object to an mtr memo stack. */ @@ -49,12 +49,12 @@ mtr_memo_push( mtr_memo_slot_t* slot; ut_ad(object); - ut_ad(type >= MTR_MEMO_PAGE_S_FIX); + ut_ad(type >= MTR_MEMO_PAGE_S_FIX); ut_ad(type <= MTR_MEMO_X_LOCK); ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); - memo = &(mtr->memo); + memo = &(mtr->memo); slot = dyn_array_push(memo, sizeof(mtr_memo_slot_t)); @@ -72,11 +72,11 @@ mtr_set_savepoint( mtr_t* mtr) /* in: mtr */ { dyn_array_t* memo; - + ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); - memo = &(mtr->memo); + memo = &(mtr->memo); return(dyn_array_get_data_size(memo)); } @@ -90,11 +90,11 @@ mtr_release_s_latch_at_savepoint( /*=============================*/ mtr_t* mtr, /* in: mtr */ ulint savepoint, /* in: savepoint */ - rw_lock_t* lock) /* in: latch to release */ + rw_lock_t* lock) /* in: latch to release */ { mtr_memo_slot_t* slot; dyn_array_t* memo; - + ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_ACTIVE); @@ -102,7 +102,7 @@ mtr_release_s_latch_at_savepoint( memo = &(mtr->memo); ut_ad(dyn_array_get_data_size(memo) > savepoint); - + slot = dyn_array_get_element(memo, savepoint); ut_ad(slot->object == lock); diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 224fd59a76b..4ab7fda7358 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -28,8 +28,8 @@ extern ibool os_aio_print_debug; extern ulint os_file_n_pending_preads; extern ulint os_file_n_pending_pwrites; -extern ulint os_n_pending_reads; -extern ulint os_n_pending_writes; +extern ulint os_n_pending_reads; +extern ulint os_n_pending_writes; #ifdef __WIN__ @@ -75,7 +75,7 @@ log. */ #define OS_FILE_OPEN_RETRY 56 /* for os_file_create() on the first ibdata file */ -#define OS_FILE_READ_ONLY 333 +#define OS_FILE_READ_ONLY 333 #define OS_FILE_READ_WRITE 444 #define OS_FILE_READ_ALLOW_DELETE 555 /* for ibbackup */ @@ -91,9 +91,10 @@ log. */ #define OS_FILE_NOT_FOUND 71 #define OS_FILE_DISK_FULL 72 #define OS_FILE_ALREADY_EXISTS 73 -#define OS_FILE_AIO_RESOURCES_RESERVED 74 /* wait for OS aio resources +#define OS_FILE_PATH_ERROR 74 +#define OS_FILE_AIO_RESOURCES_RESERVED 75 /* wait for OS aio resources to become available again */ -#define OS_FILE_ERROR_NOT_SPECIFIED 75 +#define OS_FILE_ERROR_NOT_SPECIFIED 76 /* Types for aio operations */ #define OS_FILE_READ 10 @@ -109,7 +110,7 @@ log. */ pages or ibuf bitmap pages */ #define OS_AIO_IBUF 22 /* Asynchronous i/o for ibuf pages or ibuf bitmap pages */ -#define OS_AIO_LOG 23 /* Asynchronous i/o for the log */ +#define OS_AIO_LOG 23 /* Asynchronous i/o for the log */ #define OS_AIO_SYNC 24 /* Asynchronous i/o where the calling thread will itself wait for the i/o to complete, doing also the job of the i/o-handler thread; @@ -124,12 +125,12 @@ log. */ in the call of os_aio(...), if the caller wants to post several i/o requests in a batch, and only after that - wake the i/o-handler thread; this has - effect only in simulated aio */ -#define OS_WIN31 1 -#define OS_WIN95 2 -#define OS_WINNT 3 -#define OS_WIN2000 4 + wake the i/o-handler thread; this has + effect only in simulated aio */ +#define OS_WIN31 1 +#define OS_WIN95 2 +#define OS_WINNT 3 +#define OS_WIN2000 4 extern ulint os_n_file_reads; extern ulint os_n_file_writes; @@ -138,10 +139,10 @@ extern ulint os_n_fsyncs; /* File types for directory entry data type */ enum os_file_type_enum{ - OS_FILE_TYPE_UNKNOWN = 0, - OS_FILE_TYPE_FILE, /* regular file */ - OS_FILE_TYPE_DIR, /* directory */ - OS_FILE_TYPE_LINK /* symbolic link */ + OS_FILE_TYPE_UNKNOWN = 0, + OS_FILE_TYPE_FILE, /* regular file */ + OS_FILE_TYPE_DIR, /* directory */ + OS_FILE_TYPE_LINK /* symbolic link */ }; typedef enum os_file_type_enum os_file_type_t; @@ -156,14 +157,14 @@ struct os_file_stat_struct{ char name[OS_FILE_MAX_PATH]; /* path to a file */ os_file_type_t type; /* file type */ ib_longlong size; /* file size */ - time_t ctime; /* creation time */ + time_t ctime; /* creation time */ time_t mtime; /* modification time */ time_t atime; /* access time */ }; typedef struct os_file_stat_struct os_file_stat_t; #ifdef __WIN__ -typedef HANDLE os_file_dir_t; /* directory stream */ +typedef HANDLE os_file_dir_t; /* directory stream */ #else typedef DIR* os_file_dir_t; /* directory stream */ #endif @@ -174,7 +175,7 @@ Gets the operating system version. Currently works only on Windows. */ ulint os_get_os_version(void); /*===================*/ - /* out: OS_WIN95, OS_WIN31, OS_WINNT, or OS_WIN2000 */ + /* out: OS_WIN95, OS_WIN31, OS_WINNT, or OS_WIN2000 */ /******************************************************************** Creates the seek mutexes used in positioned reads and writes. */ @@ -182,12 +183,15 @@ void os_io_init_simple(void); /*===================*/ /*************************************************************************** -Creates a temporary file. */ +Creates a temporary file. This function is like tmpfile(3), but +the temporary file is created in the MySQL temporary directory. +On Netware, this function is like tmpfile(3), because the C run-time +library of Netware does not expose the delete-on-close flag. */ FILE* os_file_create_tmpfile(void); /*========================*/ - /* out: temporary file handle (never NULL) */ + /* out: temporary file handle, or NULL on error */ /*************************************************************************** The os_file_opendir() function opens a directory stream corresponding to the directory named by the dirname argument. The directory stream is positioned @@ -256,7 +260,7 @@ os_file_create_simple( opened (if does not exist, error), or OS_FILE_CREATE if a new file is created (if exists, error), or - OS_FILE_CREATE_PATH if new file + OS_FILE_CREATE_PATH if new file (if exists, error) and subdirectories along its path are created (if needed)*/ ulint access_type,/* in: OS_FILE_READ_ONLY or @@ -430,7 +434,7 @@ os_file_read( offset where to read */ ulint offset_high,/* in: most significant 32 bits of offset */ - ulint n); /* in: number of bytes to read */ + ulint n); /* in: number of bytes to read */ /*********************************************************************** Rewind file to its start, read at most size - 1 bytes from it to str, and NUL-terminate str. All errors are silently ignored. This function is @@ -457,7 +461,7 @@ os_file_read_no_error_handling( offset where to read */ ulint offset_high,/* in: most significant 32 bits of offset */ - ulint n); /* in: number of bytes to read */ + ulint n); /* in: number of bytes to read */ /*********************************************************************** Requests a synchronous write operation. */ @@ -475,7 +479,7 @@ os_file_write( offset where to write */ ulint offset_high,/* in: most significant 32 bits of offset */ - ulint n); /* in: number of bytes to write */ + ulint n); /* in: number of bytes to write */ /*********************************************************************** Check the existence and type of the given file. */ @@ -483,7 +487,7 @@ ibool os_file_status( /*===========*/ /* out: TRUE if call succeeded */ - const char* path, /* in: pathname of the file */ + const char* path, /* in: pathname of the file */ ibool* exists, /* out: TRUE if file exists */ os_file_type_t* type); /* out: type of the file (if it exists) */ /******************************************************************** @@ -500,18 +504,18 @@ yields a complete pathname. The return value is a copy of the directory component of the pathname. The copy is allocated from heap. It is the caller responsibility -to free it after it is no longer needed. +to free it after it is no longer needed. The following list of examples (taken from SUSv2) shows the strings returned by dirname and basename for different paths: - path dirname basename - "/usr/lib" "/usr" "lib" - "/usr/" "/" "usr" - "usr" "." "usr" - "/" "/" "/" - "." "." "." - ".." "." ".." + path dirname basename + "/usr/lib" "/usr" "lib" + "/usr/" "/" "usr" + "usr" "." "usr" + "/" "/" "/" + "." "." "." + ".." "." ".." */ char* @@ -522,7 +526,7 @@ os_file_dirname( const char* path); /* in: pathname */ /******************************************************************** Creates all missing subdirectories along the given path. */ - + ibool os_file_create_subdirs_if_needed( /*=============================*/ @@ -577,7 +581,7 @@ os_aio( offset where to read or write */ ulint offset_high, /* in: most significant 32 bits of offset */ - ulint n, /* in: number of bytes to read or write */ + ulint n, /* in: number of bytes to read or write */ fil_node_t* message1,/* in: messages for the aio handler (these can be used to identify a completed aio operation); if mode is OS_AIO_SYNC, these @@ -635,7 +639,7 @@ os_aio_windows_handle( sync aio is used, and this parameter is ignored */ ulint pos, /* this parameter is used only in sync aio: - wait for the aio slot at this position */ + wait for the aio slot at this position */ fil_node_t**message1, /* out: the messages passed with the aio request; note that also in the case where the aio operation failed, these output @@ -720,7 +724,7 @@ ibool os_file_get_status( /*===============*/ /* out: TRUE if stat information found */ - const char* path, /* in: pathname of the file */ + const char* path, /* in: pathname of the file */ os_file_stat_t* stat_info); /* information of a file in a directory */ -#endif +#endif diff --git a/storage/innobase/include/os0proc.h b/storage/innobase/include/os0proc.h index b0b72e18675..f54e08de7ee 100644 --- a/storage/innobase/include/os0proc.h +++ b/storage/innobase/include/os0proc.h @@ -116,20 +116,21 @@ Allocates large pages memory. */ void* os_mem_alloc_large( -/*=================*/ - /* out: allocated memory */ - ulint n, /* in: number of bytes */ - ibool set_to_zero, /* in: TRUE if allocated memory should be set - to zero if UNIV_SET_MEM_TO_ZERO is defined */ - ibool assert_on_error); /* in: if TRUE, we crash mysqld if the memory - cannot be allocated */ +/*===============*/ + /* out: allocated memory */ + ulint n, /* in: number of bytes */ + ibool set_to_zero, /* in: TRUE if allocated memory + should be set to zero if + UNIV_SET_MEM_TO_ZERO is defined */ + ibool assert_on_error);/* in: if TRUE, we crash mysqld if + the memory cannot be allocated */ /******************************************************************** Frees large pages memory. */ void os_mem_free_large( -/*=================*/ -void *ptr); /* in: number of bytes */ +/*==============*/ +void *ptr); /* in: number of bytes */ /******************************************************************** Sets the priority boost for threads released from waiting within the current process. */ @@ -144,4 +145,4 @@ os_process_set_priority_boost( #include "os0proc.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h index d27b1676f1b..0239cc853ed 100644 --- a/storage/innobase/include/os0sync.h +++ b/storage/innobase/include/os0sync.h @@ -16,10 +16,10 @@ Created 9/6/1995 Heikki Tuuri #define os_fast_mutex_t CRITICAL_SECTION -typedef HANDLE os_native_event_t; +typedef HANDLE os_native_event_t; -typedef struct os_event_struct os_event_struct_t; -typedef os_event_struct_t* os_event_t; +typedef struct os_event_struct os_event_struct_t; +typedef os_event_struct_t* os_event_t; struct os_event_struct { os_native_event_t handle; @@ -30,8 +30,8 @@ struct os_event_struct { #else typedef pthread_mutex_t os_fast_mutex_t; -typedef struct os_event_struct os_event_struct_t; -typedef os_event_struct_t* os_event_t; +typedef struct os_event_struct os_event_struct_t; +typedef os_event_struct_t* os_event_t; struct os_event_struct { os_fast_mutex_t os_mutex; /* this mutex protects the next @@ -79,7 +79,7 @@ Frees created events and OS 'slow' mutexes. */ void os_sync_free(void); /*==============*/ -/************************************************************* +/************************************************************* Creates an event semaphore, i.e., a semaphore which may just have two states: signaled and nonsignaled. The created event is manual reset: it must be reset explicitly by calling sync_os_reset_event. */ @@ -158,9 +158,9 @@ os_event_wait_multiple( /*===================*/ /* out: index of the event which was signaled */ - ulint n, /* in: number of events in the + ulint n, /* in: number of events in the array */ - os_native_event_t* native_event_array); + os_native_event_t* native_event_array); /* in: pointer to an array of event handles */ #endif @@ -234,9 +234,9 @@ void os_fast_mutex_free( /*===============*/ os_fast_mutex_t* fast_mutex); /* in: mutex to free */ - + #ifndef UNIV_NONINL #include "os0sync.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/os0sync.ic b/storage/innobase/include/os0sync.ic index 1337e97152a..75dea9369c2 100644 --- a/storage/innobase/include/os0sync.ic +++ b/storage/innobase/include/os0sync.ic @@ -22,7 +22,7 @@ os_fast_mutex_trylock( thread */ os_fast_mutex_t* fast_mutex) /* in: mutex to acquire */ { -#ifdef __WIN__ +#ifdef __WIN__ EnterCriticalSection(fast_mutex); return(0); diff --git a/storage/innobase/include/os0thread.h b/storage/innobase/include/os0thread.h index c00d28baf60..4685ffad351 100644 --- a/storage/innobase/include/os0thread.h +++ b/storage/innobase/include/os0thread.h @@ -30,8 +30,8 @@ typedef void* os_thread_t; typedef ulint os_thread_id_t; /* In Windows the thread id is an unsigned long int */ #else -typedef pthread_t os_thread_t; -typedef os_thread_t os_thread_id_t; /* In Unix we use the thread +typedef pthread_t os_thread_t; +typedef os_thread_t os_thread_id_t; /* In Unix we use the thread handle itself as the id of the thread */ #endif @@ -69,7 +69,7 @@ os_thread_create( /*=============*/ /* out: handle to the thread */ #ifndef __WIN__ - os_posix_f_t start_f, + os_posix_f_t start_f, #else ulint (*start_f)(void*), /* in: pointer to function from which to start */ @@ -80,7 +80,7 @@ os_thread_create( thread */ int os_thread_join( -/*=============*/ +/*===========*/ os_thread_id_t thread_id); /* in: id of the thread to join */ /********************************************************************* Exits the current thread. */ @@ -142,4 +142,4 @@ os_thread_get_last_error(void); #include "os0thread.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/page0cur.h b/storage/innobase/include/page0cur.h index b03302b0e77..36370201d9b 100644 --- a/storage/innobase/include/page0cur.h +++ b/storage/innobase/include/page0cur.h @@ -57,7 +57,7 @@ page_cur_get_rec( /* out: record */ page_cur_t* cur); /* in: page cursor */ /************************************************************* -Sets the cursor object to point before the first user record +Sets the cursor object to point before the first user record on the page. */ UNIV_INLINE void @@ -66,7 +66,7 @@ page_cur_set_before_first( page_t* page, /* in: index page */ page_cur_t* cur); /* in: cursor */ /************************************************************* -Sets the cursor object to point after the last user record on +Sets the cursor object to point after the last user record on the page. */ UNIV_INLINE void @@ -178,13 +178,13 @@ page_copy_rec_list_end_to_created_page( dict_index_t* index, /* in: record descriptor */ mtr_t* mtr); /* in: mtr */ /*************************************************************** -Deletes a record at the page cursor. The cursor is moved to the +Deletes a record at the page cursor. The cursor is moved to the next record after the deleted one. */ void page_cur_delete_rec( /*================*/ - page_cur_t* cursor, /* in: a page cursor */ + page_cur_t* cursor, /* in: a page cursor */ dict_index_t* index, /* in: record descriptor */ const ulint* offsets,/* in: rec_get_offsets(cursor->rec, index) */ mtr_t* mtr); /* in: mini-transaction handle */ @@ -224,7 +224,7 @@ page_cur_search_with_match( ulint* ilow_matched_bytes, /* in/out: already matched bytes in a field not yet completely matched */ - page_cur_t* cursor); /* out: page cursor */ + page_cur_t* cursor); /* out: page cursor */ /*************************************************************** Positions a page cursor on a randomly chosen user record on a page. If there are no user records, sets the cursor on the infimum record. */ @@ -282,4 +282,4 @@ struct page_cur_struct{ #include "page0cur.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/page0cur.ic b/storage/innobase/include/page0cur.ic index f8346819e84..243550c055f 100644 --- a/storage/innobase/include/page0cur.ic +++ b/storage/innobase/include/page0cur.ic @@ -38,7 +38,7 @@ page_cur_get_rec( } /************************************************************* -Sets the cursor object to point before the first user record +Sets the cursor object to point before the first user record on the page. */ UNIV_INLINE void @@ -51,7 +51,7 @@ page_cur_set_before_first( } /************************************************************* -Sets the cursor object to point after the last user record on +Sets the cursor object to point after the last user record on the page. */ UNIV_INLINE void @@ -181,7 +181,7 @@ page_cur_tuple_insert( /* out: pointer to record if succeed, NULL otherwise */ page_cur_t* cursor, /* in: a page cursor */ - dtuple_t* tuple, /* in: pointer to a data tuple */ + dtuple_t* tuple, /* in: pointer to a data tuple */ dict_index_t* index, /* in: record descriptor */ mtr_t* mtr) /* in: mini-transaction handle */ { diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index c4ffa39d3ac..7f99f670190 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -115,7 +115,7 @@ typedef byte page_dir_slot_t; typedef page_dir_slot_t page_dir_t; /* Offset of the directory start down from the page end. We call the -slot with the highest file address directory start, as it points to +slot with the highest file address directory start, as it points to the first record in the list of records. */ #define PAGE_DIR FIL_PAGE_DATA_END @@ -127,7 +127,7 @@ page end, when the page is empty */ #define PAGE_EMPTY_DIR_START (PAGE_DIR + 2 * PAGE_DIR_SLOT_SIZE) /* The maximum and minimum number of records owned by a directory slot. The -number may drop below the minimum in the first and the last slot in the +number may drop below the minimum in the first and the last slot in the directory. */ #define PAGE_DIR_SLOT_MAX_N_OWNED 8 #define PAGE_DIR_SLOT_MIN_N_OWNED 4 @@ -234,20 +234,20 @@ the positive infinity in the alphabetical order. */ UNIV_INLINE int page_cmp_dtuple_rec_with_match( -/*===========================*/ - /* out: 1, 0, -1, if dtuple is greater, equal, - less than rec, respectively, when only the +/*===========================*/ + /* out: 1, 0, -1, if dtuple is greater, equal, + less than rec, respectively, when only the common first fields are compared */ dtuple_t* dtuple, /* in: data tuple */ - rec_t* rec, /* in: physical record on a page; may also - be page infimum or supremum, in which case - matched-parameter values below are not + rec_t* rec, /* in: physical record on a page; may also + be page infimum or supremum, in which case + matched-parameter values below are not affected */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ - ulint* matched_fields, /* in/out: number of already completely + ulint* matched_fields, /* in/out: number of already completely matched fields; when function returns contains the value for current comparison */ - ulint* matched_bytes); /* in/out: number of already matched + ulint* matched_bytes); /* in/out: number of already matched bytes within the first field not completely matched; when function returns contains the value for current comparison */ @@ -342,7 +342,7 @@ ulint page_dir_slot_get_n_owned( /*======================*/ /* out: number of records */ - page_dir_slot_t* slot); /* in: page directory slot */ + page_dir_slot_t* slot); /* in: page directory slot */ /******************************************************************* This is used to set the owned records field of a directory slot. */ UNIV_INLINE @@ -350,7 +350,7 @@ void page_dir_slot_set_n_owned( /*======================*/ page_dir_slot_t* slot, /* in: directory slot */ - ulint n); /* in: number of records owned + ulint n); /* in: number of records owned by the slot */ /**************************************************************** Calculates the space reserved for directory slots of a given @@ -397,7 +397,7 @@ page_rec_get_next( rec_t* rec); /* in: pointer to record, must not be page supremum */ /**************************************************************** -Sets the pointer to the next record on the page. */ +Sets the pointer to the next record on the page. */ UNIV_INLINE void page_rec_set_next( @@ -436,7 +436,7 @@ TRUE if the record is the infimum record on a page. */ UNIV_INLINE ibool page_rec_is_infimum_low( -/*=====================*/ +/*====================*/ /* out: TRUE if the infimum record */ ulint offset);/* in: record offset on page */ @@ -548,7 +548,7 @@ page_mem_free( /************************************************************** The index page creation function. */ -page_t* +page_t* page_create( /*========*/ /* out: pointer to the page */ @@ -651,19 +651,19 @@ Splits a directory slot which owns too many records. */ void page_dir_split_slot( /*================*/ - page_t* page, /* in: the index page in question */ - ulint slot_no); /* in: the directory slot */ + page_t* page, /* in: the index page in question */ + ulint slot_no); /* in: the directory slot */ /***************************************************************** Tries to balance the given directory slot with too few records -with the upper neighbor, so that there are at least the minimum number -of records owned by the slot; this may result in the merging of +with the upper neighbor, so that there are at least the minimum number +of records owned by the slot; this may result in the merging of two slots. */ void page_dir_balance_slot( /*==================*/ page_t* page, /* in: index page */ - ulint slot_no); /* in: the directory slot */ + ulint slot_no); /* in: the directory slot */ /************************************************************** Parses a log record of a record list end or start deletion. */ @@ -695,7 +695,7 @@ page_parse_create( /**************************************************************** Prints record contents including the data relevant only in the index page context. */ - + void page_rec_print( /*===========*/ @@ -733,7 +733,7 @@ debugging purposes. */ void page_print( -/*======*/ +/*=======*/ page_t* page, /* in: index page */ dict_index_t* index, /* in: dictionary index of the page */ ulint dn, /* in: print dn first and last entries @@ -799,4 +799,4 @@ page_find_rec_with_heap_no( #include "page0page.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index 655ff245aa8..2f651b40319 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -41,7 +41,7 @@ page_update_max_trx_id( ut_ad(page); if (ut_dulint_cmp(page_get_max_trx_id(page), trx_id) < 0) { - + page_set_max_trx_id(page, trx_id); } } @@ -93,8 +93,8 @@ page_header_get_ptr( ut_ad(page); ut_ad((field == PAGE_FREE) - || (field == PAGE_LAST_INSERT) - || (field == PAGE_HEAP_TOP)); + || (field == PAGE_LAST_INSERT) + || (field == PAGE_HEAP_TOP)); offs = page_header_get_field(page, field); @@ -122,8 +122,8 @@ page_header_set_ptr( ut_ad(page); ut_ad((field == PAGE_FREE) - || (field == PAGE_LAST_INSERT) - || (field == PAGE_HEAP_TOP)); + || (field == PAGE_LAST_INSERT) + || (field == PAGE_HEAP_TOP)); if (ptr == NULL) { offs = 0; @@ -177,13 +177,13 @@ page_rec_is_comp( { #ifdef UNIV_RELEASE_NOT_YET_STABLE if (UNIV_UNLIKELY((ulint)rec < (ulint)(buf_pool->frame_zero)) - || UNIV_UNLIKELY((ulint)rec >= (ulint)(buf_pool->high_end))) { + || UNIV_UNLIKELY((ulint)rec >= (ulint)(buf_pool->high_end))) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fprintf(stderr, "InnoDB: Error: trying to read a stray page rec %p\n" "InnoDB: buf pool start is at %p, end at %p\n", - rec, buf_pool->frame_zero, + rec, buf_pool->frame_zero, buf_pool->high_end); ut_error; } @@ -284,7 +284,7 @@ TRUE if the record is the infimum record on a page. */ UNIV_INLINE ibool page_rec_is_infimum_low( -/*=====================*/ +/*====================*/ /* out: TRUE if the infimum record */ ulint offset) /* in: record offset on page */ { @@ -343,20 +343,20 @@ the positive infinity in the alphabetical order. */ UNIV_INLINE int page_cmp_dtuple_rec_with_match( -/*===========================*/ - /* out: 1, 0, -1, if dtuple is greater, equal, - less than rec, respectively, when only the +/*===========================*/ + /* out: 1, 0, -1, if dtuple is greater, equal, + less than rec, respectively, when only the common first fields are compared */ dtuple_t* dtuple, /* in: data tuple */ - rec_t* rec, /* in: physical record on a page; may also - be page infimum or supremum, in which case - matched-parameter values below are not + rec_t* rec, /* in: physical record on a page; may also + be page infimum or supremum, in which case + matched-parameter values below are not affected */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ - ulint* matched_fields, /* in/out: number of already completely + ulint* matched_fields, /* in/out: number of already completely matched fields; when function returns contains the value for current comparison */ - ulint* matched_bytes) /* in/out: number of already matched + ulint* matched_bytes) /* in/out: number of already matched bytes within the first field not completely matched; when function returns contains the value for current comparison */ @@ -461,7 +461,7 @@ page_dir_get_nth_slot( return(page + UNIV_PAGE_SIZE - PAGE_DIR - (n + 1) * PAGE_DIR_SLOT_SIZE); -} +} /****************************************************************** Used to check the consistency of a record on a page. */ @@ -474,7 +474,7 @@ page_rec_check( { page_t* page; - ut_a(rec); + ut_a(rec); page = buf_frame_align(rec); @@ -517,7 +517,7 @@ ulint page_dir_slot_get_n_owned( /*======================*/ /* out: number of records */ - page_dir_slot_t* slot) /* in: page directory slot */ + page_dir_slot_t* slot) /* in: page directory slot */ { rec_t* rec = page_dir_slot_get_rec(slot); return(rec_get_n_owned(rec, page_rec_is_comp(rec))); @@ -530,7 +530,7 @@ void page_dir_slot_set_n_owned( /*======================*/ page_dir_slot_t* slot, /* in: directory slot */ - ulint n) /* in: number of records owned + ulint n) /* in: number of records owned by the slot */ { rec_t* rec = page_dir_slot_get_rec(slot); @@ -549,7 +549,7 @@ page_dir_calc_reserved_space( { return((PAGE_DIR_SLOT_SIZE * n_recs + PAGE_DIR_SLOT_MIN_N_OWNED - 1) / PAGE_DIR_SLOT_MIN_N_OWNED); -} +} /**************************************************************** Gets the pointer to the next record on the page. */ @@ -563,7 +563,7 @@ page_rec_get_next( ulint offs; page_t* page; - ut_ad(page_rec_check(rec)); + ut_ad(page_rec_check(rec)); page = ut_align_down(rec, UNIV_PAGE_SIZE); @@ -584,7 +584,7 @@ page_rec_get_next( } if (UNIV_UNLIKELY(offs == 0)) { - + return(NULL); } @@ -592,7 +592,7 @@ page_rec_get_next( } /**************************************************************** -Sets the pointer to the next record on the page. */ +Sets the pointer to the next record on the page. */ UNIV_INLINE void page_rec_set_next( @@ -604,7 +604,7 @@ page_rec_set_next( page_t* page; ulint offs; - ut_ad(page_rec_check(rec)); + ut_ad(page_rec_check(rec)); ut_ad(!page_rec_is_supremum(rec)); page = ut_align_down(rec, UNIV_PAGE_SIZE); @@ -635,7 +635,7 @@ page_rec_get_prev( rec_t* prev_rec = NULL; page_t* page; - ut_ad(page_rec_check(rec)); + ut_ad(page_rec_check(rec)); page = ut_align_down(rec, UNIV_PAGE_SIZE); @@ -644,16 +644,16 @@ page_rec_get_prev( slot_no = page_dir_find_owner_slot(rec); ut_a(slot_no != 0); - + slot = page_dir_get_nth_slot(page, slot_no - 1); - + rec2 = page_dir_slot_get_rec(slot); - + while (rec != rec2) { prev_rec = rec2; rec2 = page_rec_get_next(rec2); } - + ut_a(prev_rec); return(prev_rec); @@ -696,10 +696,10 @@ page_get_data_size( ulint ret; ret = (ulint)(page_header_get_field(page, PAGE_HEAP_TOP) - - (page_is_comp(page) - ? PAGE_NEW_SUPREMUM_END - : PAGE_OLD_SUPREMUM_END) - - page_header_get_field(page, PAGE_GARBAGE)); + - (page_is_comp(page) + ? PAGE_NEW_SUPREMUM_END + : PAGE_OLD_SUPREMUM_END) + - page_header_get_field(page, PAGE_GARBAGE)); ut_ad(ret < UNIV_PAGE_SIZE); diff --git a/storage/innobase/include/page0types.h b/storage/innobase/include/page0types.h index 525a0366a6f..1fbeeb0f60f 100644 --- a/storage/innobase/include/page0types.h +++ b/storage/innobase/include/page0types.h @@ -13,10 +13,10 @@ Created 2/2/1994 Heikki Tuuri /* Type of the index page */ /* The following define eliminates a name collision on HP-UX */ -#define page_t ib_page_t +#define page_t ib_page_t typedef byte page_t; typedef struct page_search_struct page_search_t; typedef struct page_cur_struct page_cur_t; -#endif +#endif diff --git a/storage/innobase/include/pars0grm.h b/storage/innobase/include/pars0grm.h index b2790949057..e35fcf47692 100644 --- a/storage/innobase/include/pars0grm.h +++ b/storage/innobase/include/pars0grm.h @@ -1,90 +1,220 @@ -#ifndef YYSTYPE -#define YYSTYPE int +/* A Bison parser, made by GNU Bison 1.875d. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + PARS_INT_LIT = 258, + PARS_FLOAT_LIT = 259, + PARS_STR_LIT = 260, + PARS_NULL_LIT = 261, + PARS_ID_TOKEN = 262, + PARS_AND_TOKEN = 263, + PARS_OR_TOKEN = 264, + PARS_NOT_TOKEN = 265, + PARS_GE_TOKEN = 266, + PARS_LE_TOKEN = 267, + PARS_NE_TOKEN = 268, + PARS_PROCEDURE_TOKEN = 269, + PARS_IN_TOKEN = 270, + PARS_OUT_TOKEN = 271, + PARS_BINARY_TOKEN = 272, + PARS_BLOB_TOKEN = 273, + PARS_INT_TOKEN = 274, + PARS_INTEGER_TOKEN = 275, + PARS_FLOAT_TOKEN = 276, + PARS_CHAR_TOKEN = 277, + PARS_IS_TOKEN = 278, + PARS_BEGIN_TOKEN = 279, + PARS_END_TOKEN = 280, + PARS_IF_TOKEN = 281, + PARS_THEN_TOKEN = 282, + PARS_ELSE_TOKEN = 283, + PARS_ELSIF_TOKEN = 284, + PARS_LOOP_TOKEN = 285, + PARS_WHILE_TOKEN = 286, + PARS_RETURN_TOKEN = 287, + PARS_SELECT_TOKEN = 288, + PARS_SUM_TOKEN = 289, + PARS_COUNT_TOKEN = 290, + PARS_DISTINCT_TOKEN = 291, + PARS_FROM_TOKEN = 292, + PARS_WHERE_TOKEN = 293, + PARS_FOR_TOKEN = 294, + PARS_DDOT_TOKEN = 295, + PARS_CONSISTENT_TOKEN = 296, + PARS_READ_TOKEN = 297, + PARS_ORDER_TOKEN = 298, + PARS_BY_TOKEN = 299, + PARS_ASC_TOKEN = 300, + PARS_DESC_TOKEN = 301, + PARS_INSERT_TOKEN = 302, + PARS_INTO_TOKEN = 303, + PARS_VALUES_TOKEN = 304, + PARS_UPDATE_TOKEN = 305, + PARS_SET_TOKEN = 306, + PARS_DELETE_TOKEN = 307, + PARS_CURRENT_TOKEN = 308, + PARS_OF_TOKEN = 309, + PARS_CREATE_TOKEN = 310, + PARS_TABLE_TOKEN = 311, + PARS_INDEX_TOKEN = 312, + PARS_UNIQUE_TOKEN = 313, + PARS_CLUSTERED_TOKEN = 314, + PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 315, + PARS_ON_TOKEN = 316, + PARS_ASSIGN_TOKEN = 317, + PARS_DECLARE_TOKEN = 318, + PARS_CURSOR_TOKEN = 319, + PARS_SQL_TOKEN = 320, + PARS_OPEN_TOKEN = 321, + PARS_FETCH_TOKEN = 322, + PARS_CLOSE_TOKEN = 323, + PARS_NOTFOUND_TOKEN = 324, + PARS_TO_CHAR_TOKEN = 325, + PARS_TO_NUMBER_TOKEN = 326, + PARS_TO_BINARY_TOKEN = 327, + PARS_BINARY_TO_NUMBER_TOKEN = 328, + PARS_SUBSTR_TOKEN = 329, + PARS_REPLSTR_TOKEN = 330, + PARS_CONCAT_TOKEN = 331, + PARS_INSTR_TOKEN = 332, + PARS_LENGTH_TOKEN = 333, + PARS_SYSDATE_TOKEN = 334, + PARS_PRINTF_TOKEN = 335, + PARS_ASSERT_TOKEN = 336, + PARS_RND_TOKEN = 337, + PARS_RND_STR_TOKEN = 338, + PARS_ROW_PRINTF_TOKEN = 339, + PARS_COMMIT_TOKEN = 340, + PARS_ROLLBACK_TOKEN = 341, + PARS_WORK_TOKEN = 342, + NEG = 343 + }; #endif -#define PARS_INT_LIT 257 -#define PARS_FLOAT_LIT 258 -#define PARS_STR_LIT 259 -#define PARS_NULL_LIT 260 -#define PARS_ID_TOKEN 261 -#define PARS_AND_TOKEN 262 -#define PARS_OR_TOKEN 263 -#define PARS_NOT_TOKEN 264 -#define PARS_GE_TOKEN 265 -#define PARS_LE_TOKEN 266 -#define PARS_NE_TOKEN 267 -#define PARS_PROCEDURE_TOKEN 268 -#define PARS_IN_TOKEN 269 -#define PARS_OUT_TOKEN 270 -#define PARS_INT_TOKEN 271 -#define PARS_INTEGER_TOKEN 272 -#define PARS_FLOAT_TOKEN 273 -#define PARS_CHAR_TOKEN 274 -#define PARS_IS_TOKEN 275 -#define PARS_BEGIN_TOKEN 276 -#define PARS_END_TOKEN 277 -#define PARS_IF_TOKEN 278 -#define PARS_THEN_TOKEN 279 -#define PARS_ELSE_TOKEN 280 -#define PARS_ELSIF_TOKEN 281 -#define PARS_LOOP_TOKEN 282 -#define PARS_WHILE_TOKEN 283 -#define PARS_RETURN_TOKEN 284 -#define PARS_SELECT_TOKEN 285 -#define PARS_SUM_TOKEN 286 -#define PARS_COUNT_TOKEN 287 -#define PARS_DISTINCT_TOKEN 288 -#define PARS_FROM_TOKEN 289 -#define PARS_WHERE_TOKEN 290 -#define PARS_FOR_TOKEN 291 -#define PARS_DDOT_TOKEN 292 -#define PARS_CONSISTENT_TOKEN 293 -#define PARS_READ_TOKEN 294 -#define PARS_ORDER_TOKEN 295 -#define PARS_BY_TOKEN 296 -#define PARS_ASC_TOKEN 297 -#define PARS_DESC_TOKEN 298 -#define PARS_INSERT_TOKEN 299 -#define PARS_INTO_TOKEN 300 -#define PARS_VALUES_TOKEN 301 -#define PARS_UPDATE_TOKEN 302 -#define PARS_SET_TOKEN 303 -#define PARS_DELETE_TOKEN 304 -#define PARS_CURRENT_TOKEN 305 -#define PARS_OF_TOKEN 306 -#define PARS_CREATE_TOKEN 307 -#define PARS_TABLE_TOKEN 308 -#define PARS_INDEX_TOKEN 309 -#define PARS_UNIQUE_TOKEN 310 -#define PARS_CLUSTERED_TOKEN 311 -#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 312 -#define PARS_ON_TOKEN 313 -#define PARS_ASSIGN_TOKEN 314 -#define PARS_DECLARE_TOKEN 315 -#define PARS_CURSOR_TOKEN 316 -#define PARS_SQL_TOKEN 317 -#define PARS_OPEN_TOKEN 318 -#define PARS_FETCH_TOKEN 319 -#define PARS_CLOSE_TOKEN 320 -#define PARS_NOTFOUND_TOKEN 321 -#define PARS_TO_CHAR_TOKEN 322 -#define PARS_TO_NUMBER_TOKEN 323 -#define PARS_TO_BINARY_TOKEN 324 -#define PARS_BINARY_TO_NUMBER_TOKEN 325 -#define PARS_SUBSTR_TOKEN 326 -#define PARS_REPLSTR_TOKEN 327 -#define PARS_CONCAT_TOKEN 328 -#define PARS_INSTR_TOKEN 329 -#define PARS_LENGTH_TOKEN 330 -#define PARS_SYSDATE_TOKEN 331 -#define PARS_PRINTF_TOKEN 332 -#define PARS_ASSERT_TOKEN 333 -#define PARS_RND_TOKEN 334 -#define PARS_RND_STR_TOKEN 335 -#define PARS_ROW_PRINTF_TOKEN 336 -#define PARS_COMMIT_TOKEN 337 -#define PARS_ROLLBACK_TOKEN 338 -#define PARS_WORK_TOKEN 339 -#define NEG 340 +#define PARS_INT_LIT 258 +#define PARS_FLOAT_LIT 259 +#define PARS_STR_LIT 260 +#define PARS_NULL_LIT 261 +#define PARS_ID_TOKEN 262 +#define PARS_AND_TOKEN 263 +#define PARS_OR_TOKEN 264 +#define PARS_NOT_TOKEN 265 +#define PARS_GE_TOKEN 266 +#define PARS_LE_TOKEN 267 +#define PARS_NE_TOKEN 268 +#define PARS_PROCEDURE_TOKEN 269 +#define PARS_IN_TOKEN 270 +#define PARS_OUT_TOKEN 271 +#define PARS_BINARY_TOKEN 272 +#define PARS_BLOB_TOKEN 273 +#define PARS_INT_TOKEN 274 +#define PARS_INTEGER_TOKEN 275 +#define PARS_FLOAT_TOKEN 276 +#define PARS_CHAR_TOKEN 277 +#define PARS_IS_TOKEN 278 +#define PARS_BEGIN_TOKEN 279 +#define PARS_END_TOKEN 280 +#define PARS_IF_TOKEN 281 +#define PARS_THEN_TOKEN 282 +#define PARS_ELSE_TOKEN 283 +#define PARS_ELSIF_TOKEN 284 +#define PARS_LOOP_TOKEN 285 +#define PARS_WHILE_TOKEN 286 +#define PARS_RETURN_TOKEN 287 +#define PARS_SELECT_TOKEN 288 +#define PARS_SUM_TOKEN 289 +#define PARS_COUNT_TOKEN 290 +#define PARS_DISTINCT_TOKEN 291 +#define PARS_FROM_TOKEN 292 +#define PARS_WHERE_TOKEN 293 +#define PARS_FOR_TOKEN 294 +#define PARS_DDOT_TOKEN 295 +#define PARS_CONSISTENT_TOKEN 296 +#define PARS_READ_TOKEN 297 +#define PARS_ORDER_TOKEN 298 +#define PARS_BY_TOKEN 299 +#define PARS_ASC_TOKEN 300 +#define PARS_DESC_TOKEN 301 +#define PARS_INSERT_TOKEN 302 +#define PARS_INTO_TOKEN 303 +#define PARS_VALUES_TOKEN 304 +#define PARS_UPDATE_TOKEN 305 +#define PARS_SET_TOKEN 306 +#define PARS_DELETE_TOKEN 307 +#define PARS_CURRENT_TOKEN 308 +#define PARS_OF_TOKEN 309 +#define PARS_CREATE_TOKEN 310 +#define PARS_TABLE_TOKEN 311 +#define PARS_INDEX_TOKEN 312 +#define PARS_UNIQUE_TOKEN 313 +#define PARS_CLUSTERED_TOKEN 314 +#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 315 +#define PARS_ON_TOKEN 316 +#define PARS_ASSIGN_TOKEN 317 +#define PARS_DECLARE_TOKEN 318 +#define PARS_CURSOR_TOKEN 319 +#define PARS_SQL_TOKEN 320 +#define PARS_OPEN_TOKEN 321 +#define PARS_FETCH_TOKEN 322 +#define PARS_CLOSE_TOKEN 323 +#define PARS_NOTFOUND_TOKEN 324 +#define PARS_TO_CHAR_TOKEN 325 +#define PARS_TO_NUMBER_TOKEN 326 +#define PARS_TO_BINARY_TOKEN 327 +#define PARS_BINARY_TO_NUMBER_TOKEN 328 +#define PARS_SUBSTR_TOKEN 329 +#define PARS_REPLSTR_TOKEN 330 +#define PARS_CONCAT_TOKEN 331 +#define PARS_INSTR_TOKEN 332 +#define PARS_LENGTH_TOKEN 333 +#define PARS_SYSDATE_TOKEN 334 +#define PARS_PRINTF_TOKEN 335 +#define PARS_ASSERT_TOKEN 336 +#define PARS_RND_TOKEN 337 +#define PARS_RND_STR_TOKEN 338 +#define PARS_ROW_PRINTF_TOKEN 339 +#define PARS_COMMIT_TOKEN 340 +#define PARS_ROLLBACK_TOKEN 341 +#define PARS_WORK_TOKEN 342 +#define NEG 343 + + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +typedef int YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + extern YYSTYPE yylval; + + + diff --git a/storage/innobase/include/pars0opt.h b/storage/innobase/include/pars0opt.h index d091c3ee2d0..ff92cc062d9 100644 --- a/storage/innobase/include/pars0opt.h +++ b/storage/innobase/include/pars0opt.h @@ -55,4 +55,4 @@ opt_print_query_plan( #include "pars0opt.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/pars0pars.h b/storage/innobase/include/pars0pars.h index 62a41a881e8..2ae2d6cff74 100644 --- a/storage/innobase/include/pars0pars.h +++ b/storage/innobase/include/pars0pars.h @@ -46,6 +46,8 @@ extern pars_res_word_t pars_rnd_str_token; extern pars_res_word_t pars_count_token; extern pars_res_word_t pars_sum_token; extern pars_res_word_t pars_distinct_token; +extern pars_res_word_t pars_binary_token; +extern pars_res_word_t pars_blob_token; extern pars_res_word_t pars_int_token; extern pars_res_word_t pars_char_token; extern pars_res_word_t pars_float_token; @@ -59,7 +61,7 @@ extern pars_res_word_t pars_unique_token; extern pars_res_word_t pars_clustered_token; extern ulint pars_star_denoter; - + /* Procedure parameter types */ #define PARS_INPUT 0 #define PARS_OUTPUT 1 @@ -111,7 +113,7 @@ func_node_t* pars_func( /*======*/ /* out, own: function node in a query tree */ - que_node_t* res_word,/* in: function name reserved word */ + que_node_t* res_word,/* in: function name reserved word */ que_node_t* arg); /* in: first argument in the argument list */ /************************************************************************* Parses an operator expression. */ @@ -190,7 +192,7 @@ pars_update_statement_start( ibool is_delete, /* in: TRUE if delete */ sym_node_t* table_sym, /* in: table name node */ col_assign_node_t* col_assign_list);/* in: column assignment list, NULL - if delete */ + if delete */ /************************************************************************* Parses an update or delete statement. */ @@ -212,7 +214,7 @@ pars_insert_statement( /* out, own: update node in a query tree */ sym_node_t* table_sym, /* in: table name node */ - que_node_t* values_list, /* in: value expression list or NULL */ + que_node_t* values_list, /* in: value expression list or NULL */ sel_node_t* select); /* in: select condition or NULL */ /************************************************************************* Parses a procedure parameter declaration. */ @@ -336,10 +338,15 @@ Parses a column definition at a table creation. */ sym_node_t* pars_column_def( /*============*/ - /* out: column sym table node */ - sym_node_t* sym_node, /* in: column node in the symbol - table */ - pars_res_word_t* type); /* in: data type */ + /* out: column sym table + node */ + sym_node_t* sym_node, /* in: column node in the + symbol table */ + pars_res_word_t* type, /* in: data type */ + sym_node_t* len, /* in: length of column, or + NULL */ + void* is_not_null); /* in: if not NULL, column + is of type NOT NULL. */ /************************************************************************* Parses a table creation operation. */ @@ -464,7 +471,7 @@ struct if_node_struct{ que_node_t* cond; /* if condition */ que_node_t* stat_list; /* statement list */ que_node_t* else_part; /* else-part statement list */ - elsif_node_t* elsif_list; /* elsif element list */ + elsif_node_t* elsif_list; /* elsif element list */ }; /* while-statement node */ @@ -523,4 +530,4 @@ struct col_assign_node_struct{ #include "pars0pars.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/pars0sym.h b/storage/innobase/include/pars0sym.h index 633a49e3cb5..a10d70d48b6 100644 --- a/storage/innobase/include/pars0sym.h +++ b/storage/innobase/include/pars0sym.h @@ -74,7 +74,7 @@ sym_tab_add_id( #define SYM_CLUST_FIELD_NO 0 #define SYM_SEC_FIELD_NO 1 - + struct sym_node_struct{ que_common_t common; /* node type: QUE_NODE_SYMBOL */ @@ -185,4 +185,4 @@ struct sym_tab_struct{ #include "pars0sym.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/pars0types.h b/storage/innobase/include/pars0types.h index 9fbfd6efaa1..cf62617e066 100644 --- a/storage/innobase/include/pars0types.h +++ b/storage/innobase/include/pars0types.h @@ -25,4 +25,4 @@ typedef struct col_assign_node_struct col_assign_node_t; typedef UT_LIST_BASE_NODE_T(sym_node_t) sym_node_list_t; -#endif +#endif diff --git a/storage/innobase/include/que0que.h b/storage/innobase/include/que0que.h index 4113e52d425..4e31e2db4b7 100644 --- a/storage/innobase/include/que0que.h +++ b/storage/innobase/include/que0que.h @@ -50,7 +50,7 @@ UNIV_INLINE que_thr_t* que_fork_get_first_thr( /*===================*/ - que_fork_t* fork); /* in: query fork */ + que_fork_t* fork); /* in: query fork */ /*************************************************************************** Gets the child node of the first thr in a fork. */ UNIV_INLINE @@ -174,7 +174,7 @@ que_thr_handle_error( byte* err_str,/* in, own: error string or NULL; NOTE: the function will take care of freeing of the string! */ - ulint err_len);/* in: error string length */ + ulint err_len);/* in: error string length */ /************************************************************************** Moves a suspended query thread to the QUE_THR_RUNNING state and releases a single worker thread to execute it. This function should be used to end @@ -216,7 +216,7 @@ que_fork_start_command( QUE_THR_RUNNING state, or NULL; the query thread should be executed by que_run_threads by the caller */ - que_fork_t* fork); /* in: a query fork */ + que_fork_t* fork); /* in: a query fork */ /*************************************************************************** Gets the trx of a query thread. */ UNIV_INLINE @@ -359,7 +359,7 @@ struct que_thr_struct{ the control came */ ulint resource; /* resource usage of the query thread thus far */ - ulint lock_state; /* lock state of thread (table or + ulint lock_state; /* lock state of thread (table or row) */ }; @@ -411,7 +411,7 @@ struct que_fork_struct{ /*------------------------------*/ mem_heap_t* heap; /* memory heap where the fork was created */ - + }; /* Query fork (or graph) types */ @@ -485,9 +485,9 @@ struct que_fork_struct{ #define QUE_THR_ERROR 8 /* Query thread lock states */ -#define QUE_THR_LOCK_NOLOCK 0 -#define QUE_THR_LOCK_ROW 1 -#define QUE_THR_LOCK_TABLE 2 +#define QUE_THR_LOCK_NOLOCK 0 +#define QUE_THR_LOCK_ROW 1 +#define QUE_THR_LOCK_TABLE 2 /* From where the cursor position is counted */ #define QUE_CUR_NOT_DEFINED 1 diff --git a/storage/innobase/include/que0que.ic b/storage/innobase/include/que0que.ic index ae4ed10560f..70be4068147 100644 --- a/storage/innobase/include/que0que.ic +++ b/storage/innobase/include/que0que.ic @@ -27,7 +27,7 @@ UNIV_INLINE que_thr_t* que_fork_get_first_thr( /*===================*/ - que_fork_t* fork) /* in: query fork */ + que_fork_t* fork) /* in: query fork */ { return(UT_LIST_GET_FIRST(fork->thrs)); } @@ -38,7 +38,7 @@ UNIV_INLINE que_node_t* que_fork_get_child( /*===============*/ - que_fork_t* fork) /* in: query fork */ + que_fork_t* fork) /* in: query fork */ { que_thr_t* thr; @@ -143,7 +143,7 @@ que_node_list_add_last( que_common_t* cnode2; cnode = node; - + cnode->brother = NULL; if (node_list == NULL) { @@ -152,7 +152,7 @@ que_node_list_add_last( } cnode2 = node_list; - + while (cnode2->brother != NULL) { cnode2 = cnode2->brother; } @@ -188,7 +188,7 @@ que_node_list_get_len( cnode = node_list; len = 0; - + while (cnode != NULL) { len++; cnode = cnode->brother; @@ -228,11 +228,12 @@ que_thr_peek_stop( graph = thr->graph; trx = graph->trx; - + if (graph->state != QUE_FORK_ACTIVE - || trx->que_state == TRX_QUE_LOCK_WAIT - || (UT_LIST_GET_LEN(trx->signals) > 0 - && trx->que_state == TRX_QUE_RUNNING)) { + || trx->que_state == TRX_QUE_LOCK_WAIT + || (UT_LIST_GET_LEN(trx->signals) > 0 + && trx->que_state == TRX_QUE_RUNNING)) { + return(TRUE); } @@ -251,7 +252,7 @@ que_graph_is_select( if (graph->fork_type == QUE_FORK_SELECT_SCROLL || graph->fork_type == QUE_FORK_SELECT_NON_SCROLL) { - return(TRUE); + return(TRUE); } return(FALSE); diff --git a/storage/innobase/include/que0types.h b/storage/innobase/include/que0types.h index e59c2313a5a..30e3f0a172b 100644 --- a/storage/innobase/include/que0types.h +++ b/storage/innobase/include/que0types.h @@ -14,7 +14,7 @@ Created 5/27/1996 Heikki Tuuri /* Pseudotype for all graph nodes */ typedef void que_node_t; - + typedef struct que_fork_struct que_fork_t; /* Query graph root is a fork node */ diff --git a/storage/innobase/include/read0read.h b/storage/innobase/include/read0read.h index 7a91248cf7f..8089a620536 100644 --- a/storage/innobase/include/read0read.h +++ b/storage/innobase/include/read0read.h @@ -24,9 +24,12 @@ point in time are seen in the view. */ read_view_t* read_view_open_now( /*===============*/ - /* out, own: read view struct */ - trx_t* cr_trx, /* in: creating transaction, or NULL */ - mem_heap_t* heap); /* in: memory heap from which allocated */ + /* out, own: read view struct */ + dulint cr_trx_id, /* in: trx_id of creating + transaction, or (0, 0) used in + purge */ + mem_heap_t* heap); /* in: memory heap from which + allocated */ /************************************************************************* Makes a copy of the oldest existing read view, or opens a new. The view must be closed with ..._close. */ @@ -34,9 +37,12 @@ must be closed with ..._close. */ read_view_t* read_view_oldest_copy_or_open_new( /*==============================*/ - /* out, own: read view struct */ - trx_t* cr_trx, /* in: creating transaction, or NULL */ - mem_heap_t* heap); /* in: memory heap from which allocated */ + /* out, own: read view struct */ + dulint cr_trx_id, /* in: trx_id of creating + transaction, or (0, 0) used in + purge */ + mem_heap_t* heap); /* in: memory heap from which + allocated */ /************************************************************************* Closes a read view. */ @@ -60,7 +66,7 @@ read_view_sees_trx_id( /*==================*/ /* out: TRUE if sees */ read_view_t* view, /* in: read view */ - dulint trx_id); /* in: trx id */ + dulint trx_id);/* in: trx id */ /************************************************************************* Prints a read view to stderr. */ @@ -69,7 +75,7 @@ read_view_print( /*============*/ read_view_t* view); /* in: read view */ /************************************************************************* -Create a consistent cursor view for mysql to be used in cursors. In this +Create a consistent cursor view for mysql to be used in cursors. In this consistent read view modifications done by the creating transaction or future transactions are not visible. */ @@ -91,7 +97,7 @@ This function sets a given consistent cursor view to a transaction read view if given consistent cursor view is not NULL. Otherwise, function restores a global read view to a transaction read view. */ -void +void read_cursor_set_for_mysql( /*======================*/ trx_t* trx, /* in: transaction where cursor is set */ @@ -101,6 +107,10 @@ read_cursor_set_for_mysql( read should not see the modifications to the database. */ struct read_view_struct{ + ulint type; /* VIEW_NORMAL, VIEW_HIGH_GRANULARITY */ + 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 @@ -121,12 +131,23 @@ struct read_view_struct{ serialized, except the reading transaction itself; the trx ids in this array are in a descending order */ - trx_t* creator; /* Pointer to the creating transaction, or - NULL if used in purge */ + dulint creator_trx_id; /* trx id of creating transaction, or + (0, 0) used in purge */ UT_LIST_NODE_T(read_view_t) view_list; /* List of read views in trx_sys */ }; +/* Read view types */ +#define VIEW_NORMAL 1 /* Normal consistent read view + where transaction does not see changes + made by active transactions except + creating transaction. */ +#define VIEW_HIGH_GRANULARITY 2 /* High-granularity read view where + transaction does not see changes + made by active transactions and own + changes after a point in time when this + read view was created. */ + /* Implement InnoDB framework to support consistent read views in cursors. This struct holds both heap where consistent read view is allocated and pointer to a read view. */ @@ -134,15 +155,15 @@ is allocated and pointer to a read view. */ struct cursor_view_struct{ mem_heap_t* heap; /* Memory heap for the cursor view */ - read_view_t* read_view; + read_view_t* read_view; /* Consistent read view of the cursor*/ ulint n_mysql_tables_in_use; - /* number of Innobase tables used in the - processing of this cursor */ + /* number of Innobase tables used in the + processing of this cursor */ }; #ifndef UNIV_NONINL #include "read0read.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/read0read.ic b/storage/innobase/include/read0read.ic index ec9ef5814bb..276e01b9f4a 100644 --- a/storage/innobase/include/read0read.ic +++ b/storage/innobase/include/read0read.ic @@ -49,7 +49,7 @@ read_view_sees_trx_id( ulint n_ids; int cmp; ulint i; - + if (ut_dulint_cmp(trx_id, view->up_limit_id) < 0) { return(TRUE); @@ -75,6 +75,6 @@ read_view_sees_trx_id( return(cmp < 0); } } - + return(TRUE); } diff --git a/storage/innobase/include/rem0cmp.h b/storage/innobase/include/rem0cmp.h index 1b1ee26b809..36d91db0e87 100644 --- a/storage/innobase/include/rem0cmp.h +++ b/storage/innobase/include/rem0cmp.h @@ -24,15 +24,16 @@ cmp_types_are_equal( /* out: TRUE if the types are considered equal in comparisons */ dtype_t* type1, /* in: type 1 */ - dtype_t* type2); /* in: type 2 */ + dtype_t* type2, /* in: type 2 */ + ibool check_charsets); /* in: whether to check charsets */ /***************************************************************** This function is used to compare two data fields for which we know the data type. */ UNIV_INLINE int cmp_data_data( -/*==========*/ - /* out: 1, 0, -1, if data1 is greater, equal, +/*==========*/ + /* out: 1, 0, -1, if data1 is greater, equal, less than data2, respectively */ dtype_t* cur_type,/* in: data type of the fields */ byte* data1, /* in: data field (== a pointer to a memory @@ -47,8 +48,8 @@ data type. */ int cmp_data_data_slow( -/*===============*/ - /* out: 1, 0, -1, if data1 is greater, equal, +/*===============*/ + /* out: 1, 0, -1, if data1 is greater, equal, less than data2, respectively */ dtype_t* cur_type,/* in: data type of the fields */ byte* data1, /* in: data field (== a pointer to a memory @@ -63,8 +64,8 @@ has its data type field set. */ UNIV_INLINE int cmp_dfield_dfield( -/*==============*/ - /* out: 1, 0, -1, if dfield1 is greater, equal, +/*==============*/ + /* out: 1, 0, -1, if dfield1 is greater, equal, less than dfield2, respectively */ dfield_t* dfield1,/* in: data field; must have type field set */ dfield_t* dfield2);/* in: data field */ @@ -79,9 +80,9 @@ made. */ int cmp_dtuple_rec_with_match( -/*======================*/ - /* out: 1, 0, -1, if dtuple is greater, equal, - less than rec, respectively, when only the +/*======================*/ + /* out: 1, 0, -1, if dtuple is greater, equal, + less than rec, respectively, when only the common first fields are compared, or until the first externally stored field in rec */ @@ -91,10 +92,10 @@ cmp_dtuple_rec_with_match( has an equal number or more fields than dtuple */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ - ulint* matched_fields, /* in/out: number of already completely + ulint* matched_fields, /* in/out: number of already completely matched fields; when function returns, contains the value for current comparison */ - ulint* matched_bytes); /* in/out: number of already matched + ulint* matched_bytes); /* in/out: number of already matched bytes within the first field not completely matched; when function returns, contains the value for current comparison */ @@ -104,10 +105,10 @@ Compares a data tuple to a physical record. */ int cmp_dtuple_rec( /*===========*/ - /* out: 1, 0, -1, if dtuple is greater, equal, + /* out: 1, 0, -1, if dtuple is greater, equal, less than rec, respectively; see the comments for cmp_dtuple_rec_with_match */ - dtuple_t* dtuple, /* in: data tuple */ + dtuple_t* dtuple, /* in: data tuple */ rec_t* rec, /* in: physical record */ const ulint* offsets);/* in: array returned by rec_get_offsets() */ /****************************************************************** @@ -128,7 +129,7 @@ encountered, then 0 is returned. */ int cmp_rec_rec_with_match( -/*===================*/ +/*===================*/ /* out: 1, 0 , -1 if rec1 is greater, equal, less, respectively, than rec2; only the common first fields are compared */ @@ -137,11 +138,11 @@ cmp_rec_rec_with_match( const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */ dict_index_t* index, /* in: data dictionary index */ - ulint* matched_fields, /* in/out: number of already completely + ulint* matched_fields, /* in/out: number of already completely matched fields; when the function returns, contains the value the for current comparison */ - ulint* matched_bytes);/* in/out: number of already matched + ulint* matched_bytes);/* in/out: number of already matched bytes within the first field not completely matched; when the function returns, contains the value for the current comparison */ @@ -151,7 +152,7 @@ first fields are compared. */ UNIV_INLINE int cmp_rec_rec( -/*========*/ +/*========*/ /* out: 1, 0 , -1 if rec1 is greater, equal, less, respectively, than rec2; only the common first fields are compared */ diff --git a/storage/innobase/include/rem0cmp.ic b/storage/innobase/include/rem0cmp.ic index b86534e0a6a..954634737bc 100644 --- a/storage/innobase/include/rem0cmp.ic +++ b/storage/innobase/include/rem0cmp.ic @@ -12,8 +12,8 @@ data type. */ UNIV_INLINE int cmp_data_data( -/*==========*/ - /* out: 1, 0, -1, if data1 is greater, equal, +/*==========*/ + /* out: 1, 0, -1, if data1 is greater, equal, less than data2, respectively */ dtype_t* cur_type,/* in: data type of the fields */ byte* data1, /* in: data field (== a pointer to a memory @@ -32,8 +32,8 @@ has its data type field set. */ UNIV_INLINE int cmp_dfield_dfield( -/*==============*/ - /* out: 1, 0, -1, if dfield1 is greater, equal, +/*==============*/ + /* out: 1, 0, -1, if dfield1 is greater, equal, less than dfield2, respectively */ dfield_t* dfield1,/* in: data field; must have type field set */ dfield_t* dfield2)/* in: data field */ @@ -51,7 +51,7 @@ first fields are compared. */ UNIV_INLINE int cmp_rec_rec( -/*========*/ +/*========*/ /* out: 1, 0 , -1 if rec1 is greater, equal, less, respectively, than rec2; only the common first fields are compared */ @@ -63,7 +63,7 @@ cmp_rec_rec( { ulint match_f = 0; ulint match_b = 0; - + return(cmp_rec_rec_with_match(rec1, rec2, offsets1, offsets2, index, &match_f, &match_b)); } diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 69b397c9682..b2f3b9d141b 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -45,10 +45,10 @@ offsets[] array, first passed to rec_get_offsets() */ The following function is used to get the offset of the next chained record on the same page. */ UNIV_INLINE -ulint +ulint rec_get_next_offs( /*==============*/ - /* out: the page offset of the next + /* out: the page offset of the next chained record */ rec_t* rec, /* in: physical record */ ulint comp); /* in: nonzero=compact page format */ @@ -182,7 +182,7 @@ The following function tells if a new-style record is a node pointer. */ UNIV_INLINE ibool rec_get_node_ptr_flag( -/*=================*/ +/*==================*/ /* out: TRUE if node pointer */ rec_t* rec); /* in: physical record */ /********************************************************** @@ -191,7 +191,7 @@ of the record in the heap of the index page. */ UNIV_INLINE ulint rec_get_heap_no( -/*=============*/ +/*============*/ /* out: heap order number */ rec_t* rec, /* in: physical record */ ulint comp); /* in: nonzero=compact page format */ @@ -201,7 +201,7 @@ field in the record. */ UNIV_INLINE void rec_set_heap_no( -/*=============*/ +/*============*/ rec_t* rec, /* in: physical record */ ulint comp, /* in: nonzero=compact page format */ ulint heap_no);/* in: the heap number */ @@ -216,7 +216,7 @@ rec_get_1byte_offs_flag( rec_t* rec); /* in: physical record */ /********************************************************** The following function determines the offsets to each field -in the record. It can reuse a previously allocated array. */ +in the record. It can reuse a previously allocated array. */ ulint* rec_get_offsets_func( @@ -264,10 +264,10 @@ data field in an old-style record. */ byte* rec_get_nth_field_old( /*==================*/ - /* out: pointer to the field */ - rec_t* rec, /* in: record */ - ulint n, /* in: index of the field */ - ulint* len); /* out: length of the field; UNIV_SQL_NULL + /* out: pointer to the field */ + rec_t* rec, /* in: record */ + ulint n, /* in: index of the field */ + ulint* len); /* out: length of the field; UNIV_SQL_NULL if SQL null */ /**************************************************************** Gets the physical size of an old-style field. @@ -278,8 +278,8 @@ ulint rec_get_nth_field_size( /*===================*/ /* out: field size in bytes */ - rec_t* rec, /* in: record */ - ulint n); /* in: index of the field */ + rec_t* rec, /* in: record */ + ulint n); /* in: index of the field */ /**************************************************************** The following function is used to get a pointer to the nth data field in a record. */ @@ -287,8 +287,8 @@ UNIV_INLINE byte* rec_get_nth_field( /*==============*/ - /* out: pointer to the field */ - rec_t* rec, /* in: record */ + /* out: pointer to the field */ + rec_t* rec, /* in: record */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ ulint n, /* in: index of the field */ ulint* len); /* out: length of the field; UNIV_SQL_NULL @@ -365,7 +365,7 @@ rec_set_field_extern_bits( mtr_t* mtr); /* in: mtr holding an X-latch to the page where rec is, or NULL; in the NULL case we do not write to log about the change */ -/*************************************************************** +/*************************************************************** This is used to modify the value of an already existing field in a record. The previous value must have exactly the same size as the new value. If len is UNIV_SQL_NULL then the field is treated as an SQL null for old-style @@ -374,7 +374,7 @@ UNIV_INLINE void rec_set_nth_field( /*==============*/ - rec_t* rec, /* in: record */ + rec_t* rec, /* in: record */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ ulint n, /* in: index number of the field */ const void* data, /* in: pointer to the data if not SQL null */ @@ -383,7 +383,7 @@ rec_set_nth_field( length as the previous value. If SQL null, previous value must be SQL null. */ -/************************************************************** +/************************************************************** The following function returns the data size of an old-style physical record, that is the sum of field lengths. SQL null fields are counted as length 0 fields. The value returned by the function @@ -394,12 +394,12 @@ rec_get_data_size_old( /*==================*/ /* out: size */ rec_t* rec); /* in: physical record */ -/************************************************************** +/************************************************************** The following function returns the number of fields in a record. */ UNIV_INLINE ulint rec_offs_n_fields( -/*===============*/ +/*==============*/ /* out: number of fields */ const ulint* offsets);/* in: array returned by rec_get_offsets() */ /************************************************************** @@ -415,7 +415,7 @@ rec_offs_data_size( const ulint* offsets);/* in: array returned by rec_get_offsets() */ /************************************************************** Returns the total size of record minus data size of record. -The value returned by the function is the distance from record +The value returned by the function is the distance from record start to record origin in bytes. */ UNIV_INLINE ulint @@ -492,9 +492,9 @@ rec_fold( Builds a physical record out of a data tuple and stores it beginning from address destination. */ -rec_t* +rec_t* rec_convert_dtuple_to_rec( -/*======================*/ +/*======================*/ /* out: pointer to the origin of physical record */ byte* buf, /* in: start address of the diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index 9c24f385f4f..e716241f26c 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -26,7 +26,7 @@ most significant bytes and bits are written below less significant. downward from origin -> 1 8 bits pointer to next record 2 8 bits pointer to next record - 3 1 bit short flag + 3 1 bit short flag 7 bits number of fields 4 3 bits number of fields 5 bits heap number @@ -99,7 +99,7 @@ and the shift needed to obtain each bit-field of the record. */ #define REC_INFO_BITS_SHIFT 0 /* The deleted flag in info bits */ -#define REC_INFO_DELETED_FLAG 0x20UL /* when bit is set to 1, it means the +#define REC_INFO_DELETED_FLAG 0x20UL /* when bit is set to 1, it means the record has been delete marked */ /* The following masks are used to filter the SQL null bit from one-byte and two-byte offsets */ @@ -137,14 +137,14 @@ rec_set_nth_field_null_bit( rec_t* rec, /* in: record */ ulint i, /* in: ith field */ ibool val); /* in: value to set */ -/*************************************************************** +/*************************************************************** Sets an old-style record field to SQL null. The physical size of the field is not changed. */ void rec_set_nth_field_sql_null( /*=======================*/ - rec_t* rec, /* in: record */ + rec_t* rec, /* in: record */ ulint n); /* in: index of the field */ /*************************************************************** @@ -207,9 +207,9 @@ rec_set_bit_field_1( ut_ad(mask <= 0xFFUL); ut_ad(((mask >> shift) << shift) == mask); ut_ad(((val << shift) & mask) == (val << shift)); - - mach_write_to_1(rec - offs, - (mach_read_from_1(rec - offs) & ~mask) + + mach_write_to_1(rec - offs, + (mach_read_from_1(rec - offs) & ~mask) | (val << shift)); } @@ -250,8 +250,8 @@ rec_set_bit_field_2( ut_ad(((mask >> shift) << shift) == mask); ut_ad(((val << shift) & mask) == (val << shift)); - mach_write_to_2(rec - offs, - (mach_read_from_2(rec - offs) & ~mask) + mach_write_to_2(rec - offs, + (mach_read_from_2(rec - offs) & ~mask) | (val << shift)); } @@ -259,18 +259,21 @@ rec_set_bit_field_2( The following function is used to get the offset of the next chained record on the same page. */ UNIV_INLINE -ulint +ulint rec_get_next_offs( /*==============*/ /* out: the page offset of the next chained record, or 0 if none */ rec_t* rec, /* in: physical record */ ulint comp) /* in: nonzero=compact page format */ -{ +{ ulint field_value; - - ut_ad(REC_NEXT_MASK == 0xFFFFUL); - ut_ad(REC_NEXT_SHIFT == 0); +#if REC_NEXT_MASK != 0xFFFFUL +# error "REC_NEXT_MASK != 0xFFFFUL" +#endif +#if REC_NEXT_SHIFT +# error "REC_NEXT_SHIFT != 0" +#endif field_value = mach_read_from_2(rec - REC_NEXT); @@ -286,16 +289,16 @@ rec_get_next_offs( (int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE */ ut_ad((field_value >= 32768 - ? field_value - 65536 - : field_value) - + ut_align_offset(rec, UNIV_PAGE_SIZE) - < UNIV_PAGE_SIZE); + ? field_value - 65536 + : field_value) + + ut_align_offset(rec, UNIV_PAGE_SIZE) + < UNIV_PAGE_SIZE); #endif if (field_value == 0) { return(0); } - + return(ut_align_offset(rec + field_value, UNIV_PAGE_SIZE)); } else { ut_ad(field_value < UNIV_PAGE_SIZE); @@ -317,8 +320,12 @@ rec_set_next_offs( { ut_ad(rec); ut_ad(UNIV_PAGE_SIZE > next); - ut_ad(REC_NEXT_MASK == 0xFFFFUL); - ut_ad(REC_NEXT_SHIFT == 0); +#if REC_NEXT_MASK != 0xFFFFUL +# error "REC_NEXT_MASK != 0xFFFFUL" +#endif +#if REC_NEXT_SHIFT +# error "REC_NEXT_SHIFT != 0" +#endif if (comp) { ulint field_value; @@ -327,8 +334,8 @@ rec_set_next_offs( /* The following two statements calculate next - offset_of_rec mod 64Ki, where mod is the modulo as a non-negative number */ - - field_value = (ulint)((lint)next + + field_value = (ulint)((lint)next - (lint)ut_align_offset(rec, UNIV_PAGE_SIZE)); field_value &= REC_NEXT_MASK; } else { @@ -361,7 +368,7 @@ rec_get_n_fields_old( ut_ad(ret > 0); return(ret); -} +} /********************************************************** The following function is used to set the number of fields @@ -414,9 +421,11 @@ rec_get_n_fields( { ut_ad(rec); ut_ad(index); - if (UNIV_UNLIKELY(!index->table->comp)) { + + if (!dict_table_is_comp(index->table)) { return(rec_get_n_fields_old(rec)); } + switch (rec_get_status(rec)) { case REC_STATUS_ORDINARY: return(dict_index_get_n_fields(index)); @@ -449,10 +458,10 @@ rec_get_n_owned( ret = rec_get_bit_field_1(rec, comp ? REC_NEW_N_OWNED : REC_OLD_N_OWNED, REC_N_OWNED_MASK, REC_N_OWNED_SHIFT); - ut_ad(ret <= REC_MAX_N_OWNED); + ut_ad(ret <= REC_MAX_N_OWNED); return(ret); -} +} /********************************************************** The following function is used to set the number of owned records. */ @@ -492,7 +501,7 @@ rec_get_info_bits( ut_ad((ret & ~REC_INFO_BITS_MASK) == 0); return(ret); -} +} /********************************************************** The following function is used to set the info bits of a record. */ @@ -609,7 +618,7 @@ rec_set_deleted_flag( ulint val; val = rec_get_info_bits(rec, comp); - + if (flag) { val |= REC_INFO_DELETED_FLAG; } else { @@ -624,7 +633,7 @@ The following function tells if a new-style record is a node pointer. */ UNIV_INLINE ibool rec_get_node_ptr_flag( -/*=================*/ +/*==================*/ /* out: TRUE if node pointer */ rec_t* rec) /* in: physical record */ { @@ -637,7 +646,7 @@ heap of the index page. */ UNIV_INLINE ulint rec_get_heap_no( -/*=============*/ +/*============*/ /* out: heap order number */ rec_t* rec, /* in: physical record */ ulint comp) /* in: nonzero=compact page format */ @@ -652,14 +661,14 @@ rec_get_heap_no( ut_ad(ret <= REC_MAX_HEAP_NO); return(ret); -} +} /********************************************************** The following function is used to set the heap number field in the record. */ UNIV_INLINE void rec_set_heap_no( -/*=============*/ +/*============*/ rec_t* rec, /* in: physical record */ ulint comp, /* in: nonzero=compact page format */ ulint heap_no)/* in: the heap number */ @@ -715,17 +724,17 @@ UNIV_INLINE ulint rec_1_get_field_end_info( /*=====================*/ - /* out: offset of the start of the field, SQL null - flag ORed */ - rec_t* rec, /* in: record */ - ulint n) /* in: field index */ + /* out: offset of the start of the field, SQL null + flag ORed */ + rec_t* rec, /* in: record */ + ulint n) /* in: field index */ { ut_ad(rec_get_1byte_offs_flag(rec)); ut_ad(n < rec_get_n_fields_old(rec)); return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1))); } - + /********************************************************** Returns the offset of nth field end if the record is stored in the 2-byte offsets form. If the field is SQL null, the flag is ORed in the returned @@ -734,10 +743,10 @@ UNIV_INLINE ulint rec_2_get_field_end_info( /*=====================*/ - /* out: offset of the start of the field, SQL null - flag and extern storage flag ORed */ - rec_t* rec, /* in: record */ - ulint n) /* in: field index */ + /* out: offset of the start of the field, SQL null + flag and extern storage flag ORed */ + rec_t* rec, /* in: record */ + ulint n) /* in: field index */ { ut_ad(!rec_get_1byte_offs_flag(rec)); ut_ad(n < rec_get_n_fields_old(rec)); @@ -758,7 +767,7 @@ this position, and following positions hold the end offsets of the fields. */ #define rec_offs_base(offsets) (offsets + REC_OFFS_HEADER_SIZE) -/************************************************************** +/************************************************************** The following function returns the number of allocated elements for an array of offsets. */ UNIV_INLINE @@ -775,7 +784,7 @@ rec_offs_get_n_alloc( return(n_alloc); } -/************************************************************** +/************************************************************** The following function sets the number of allocated elements for an array of offsets. */ UNIV_INLINE @@ -790,12 +799,12 @@ rec_offs_set_n_alloc( offsets[0] = n_alloc; } -/************************************************************** +/************************************************************** The following function returns the number of fields in a record. */ UNIV_INLINE ulint rec_offs_n_fields( -/*===============*/ +/*==============*/ /* out: number of fields */ const ulint* offsets)/* in: array returned by rec_get_offsets() */ { @@ -891,8 +900,8 @@ UNIV_INLINE byte* rec_get_nth_field( /*==============*/ - /* out: pointer to the field */ - rec_t* rec, /* in: record */ + /* out: pointer to the field */ + rec_t* rec, /* in: record */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ ulint n, /* in: index of the field */ ulint* len) /* out: length of the field; UNIV_SQL_NULL @@ -1019,7 +1028,7 @@ rec_set_nth_field_extern_bit( where rec is, or NULL; in the NULL case we do not write to log about the change */ { - if (UNIV_LIKELY(index->table->comp)) { + if (dict_table_is_comp(index->table)) { rec_set_nth_field_extern_bit_new(rec, index, i, val, mtr); } else { rec_set_nth_field_extern_bit_old(rec, i, val, mtr); @@ -1036,17 +1045,17 @@ UNIV_INLINE ulint rec_1_get_prev_field_end_info( /*==========================*/ - /* out: offset of the start of the PREVIOUS field, SQL + /* out: offset of the start of the PREVIOUS field, SQL null flag ORed */ - rec_t* rec, /* in: record */ - ulint n) /* in: field index */ + rec_t* rec, /* in: record */ + ulint n) /* in: field index */ { ut_ad(rec_get_1byte_offs_flag(rec)); ut_ad(n <= rec_get_n_fields_old(rec)); return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n))); } - + /********************************************************** Returns the offset of n - 1th field end if the record is stored in the 2-byte offsets form. If the field is SQL null, the flag is ORed in the returned @@ -1055,10 +1064,10 @@ UNIV_INLINE ulint rec_2_get_prev_field_end_info( /*==========================*/ - /* out: offset of the start of the PREVIOUS field, SQL + /* out: offset of the start of the PREVIOUS field, SQL null flag ORed */ - rec_t* rec, /* in: record */ - ulint n) /* in: field index */ + rec_t* rec, /* in: record */ + ulint n) /* in: field index */ { ut_ad(!rec_get_1byte_offs_flag(rec)); ut_ad(n <= rec_get_n_fields_old(rec)); @@ -1073,9 +1082,9 @@ UNIV_INLINE void rec_1_set_field_end_info( /*=====================*/ - rec_t* rec, /* in: record */ - ulint n, /* in: field index */ - ulint info) /* in: value to set */ + rec_t* rec, /* in: record */ + ulint n, /* in: field index */ + ulint info) /* in: value to set */ { ut_ad(rec_get_1byte_offs_flag(rec)); ut_ad(n < rec_get_n_fields_old(rec)); @@ -1090,9 +1099,9 @@ UNIV_INLINE void rec_2_set_field_end_info( /*=====================*/ - rec_t* rec, /* in: record */ - ulint n, /* in: field index */ - ulint info) /* in: value to set */ + rec_t* rec, /* in: record */ + ulint n, /* in: field index */ + ulint info) /* in: value to set */ { ut_ad(!rec_get_1byte_offs_flag(rec)); ut_ad(n < rec_get_n_fields_old(rec)); @@ -1107,9 +1116,9 @@ UNIV_INLINE ulint rec_1_get_field_start_offs( /*=======================*/ - /* out: offset of the start of the field */ - rec_t* rec, /* in: record */ - ulint n) /* in: field index */ + /* out: offset of the start of the field */ + rec_t* rec, /* in: record */ + ulint n) /* in: field index */ { ut_ad(rec_get_1byte_offs_flag(rec)); ut_ad(n <= rec_get_n_fields_old(rec)); @@ -1122,7 +1131,7 @@ rec_1_get_field_start_offs( return(rec_1_get_prev_field_end_info(rec, n) & ~REC_1BYTE_SQL_NULL_MASK); } - + /********************************************************** Returns the offset of nth field start if the record is stored in the 2-byte offsets form. */ @@ -1130,9 +1139,9 @@ UNIV_INLINE ulint rec_2_get_field_start_offs( /*=======================*/ - /* out: offset of the start of the field */ - rec_t* rec, /* in: record */ - ulint n) /* in: field index */ + /* out: offset of the start of the field */ + rec_t* rec, /* in: record */ + ulint n) /* in: field index */ { ut_ad(!rec_get_1byte_offs_flag(rec)); ut_ad(n <= rec_get_n_fields_old(rec)); @@ -1145,7 +1154,7 @@ rec_2_get_field_start_offs( return(rec_2_get_prev_field_end_info(rec, n) & ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK)); } - + /********************************************************** The following function is used to read the offset of the start of a data field in the record. The start of an SQL null field is the end offset of the @@ -1155,9 +1164,9 @@ UNIV_INLINE ulint rec_get_field_start_offs( /*=====================*/ - /* out: offset of the start of the field */ - rec_t* rec, /* in: record */ - ulint n) /* in: field index */ + /* out: offset of the start of the field */ + rec_t* rec, /* in: record */ + ulint n) /* in: field index */ { ut_ad(rec); ut_ad(n <= rec_get_n_fields_old(rec)); @@ -1184,8 +1193,8 @@ ulint rec_get_nth_field_size( /*===================*/ /* out: field size in bytes */ - rec_t* rec, /* in: record */ - ulint n) /* in: index of the field */ + rec_t* rec, /* in: record */ + ulint n) /* in: index of the field */ { ulint os; ulint next_os; @@ -1198,7 +1207,7 @@ rec_get_nth_field_size( return(next_os - os); } -/*************************************************************** +/*************************************************************** This is used to modify the value of an already existing field in a record. The previous value must have exactly the same size as the new value. If len is UNIV_SQL_NULL then the field is treated as an SQL null for old-style @@ -1243,7 +1252,7 @@ rec_set_nth_field( ut_memcpy(data2, data, len); } -/************************************************************** +/************************************************************** The following function returns the data size of an old-style physical record, that is the sum of field lengths. SQL null fields are counted as length 0 fields. The value returned by the function @@ -1260,7 +1269,7 @@ rec_get_data_size_old( return(rec_get_field_start_offs(rec, rec_get_n_fields_old(rec))); } -/************************************************************** +/************************************************************** The following function sets the number of fields in offsets. */ UNIV_INLINE void @@ -1327,7 +1336,7 @@ rec_offs_size( { return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets)); } - + /************************************************************** Returns a pointer to the end of the record. */ UNIV_INLINE @@ -1367,7 +1376,7 @@ rec_copy( { ulint extra_len; ulint data_len; - + ut_ad(rec && buf); ut_ad(rec_offs_validate((rec_t*) rec, NULL, offsets)); ut_ad(rec_validate((rec_t*) rec, offsets)); @@ -1434,7 +1443,7 @@ rec_get_converted_size( ? dict_index_get_n_unique_in_tree(index) + 1 : dict_index_get_n_fields(index))); - if (UNIV_LIKELY(index->table->comp)) { + if (dict_table_is_comp(index->table)) { return(rec_get_converted_size_new(index, dtuple)); } @@ -1478,15 +1487,15 @@ rec_fold( ut_ad(n_fields < n_fields_rec || n_bytes == 0); if (n_fields > n_fields_rec) { - n_fields = n_fields_rec; + n_fields = n_fields_rec; } if (n_fields == n_fields_rec) { - n_bytes = 0; + n_bytes = 0; } fold = ut_fold_dulint(tree_id); - + for (i = 0; i < n_fields; i++) { data = rec_get_nth_field(rec, offsets, i, &len); @@ -1503,7 +1512,7 @@ rec_fold( if (len > n_bytes) { len = n_bytes; } - + fold = ut_fold_ulint_pair(fold, ut_fold_binary(data, len)); } diff --git a/storage/innobase/include/row0ins.h b/storage/innobase/include/row0ins.h index a5b4b74e7fc..b4bcc8ac5ca 100644 --- a/storage/innobase/include/row0ins.h +++ b/storage/innobase/include/row0ins.h @@ -15,7 +15,7 @@ Created 4/20/1996 Heikki Tuuri #include "dict0types.h" #include "trx0types.h" #include "row0types.h" - + /******************************************************************* Checks if foreign key constraint fails for an index entry. Sets shared locks which lock either the success or the failure of the constraint. NOTE that @@ -45,7 +45,7 @@ ins_node_create( /*============*/ /* out, own: insert node struct */ ulint ins_type, /* in: INS_VALUES, ... */ - dict_table_t* table, /* in: table where to insert */ + dict_table_t* table, /* in: table where to insert */ mem_heap_t* heap); /* in: mem heap where created */ /************************************************************************* Sets a new row to insert for an INS_DIRECT node. This function is only used @@ -166,4 +166,4 @@ struct ins_node_struct{ #include "row0ins.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 4062179483d..8ff8a0476a1 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -154,7 +154,7 @@ row_update_prebuilt_trx( /************************************************************************* Unlocks an AUTO_INC type lock possibly reserved by trx. */ -void +void row_unlock_table_autoinc_for_mysql( /*===============================*/ trx_t* trx); /* in: transaction */ @@ -186,7 +186,7 @@ row_lock_table_for_mysql( prebuilt->select_lock_type */ ulint mode); /* in: lock mode of table (ignored if table==NULL) */ - + /************************************************************************* Does an insert for MySQL. */ @@ -489,7 +489,7 @@ struct mysql_row_templ_struct { length at the start of row in the MySQL format (NOTE that the MySQL key value format always uses 2 bytes for the data - len) */ + len) */ ulint charset; /* MySQL charset-collation code of the column, or zero */ ulint mbminlen; /* minimum length of a char, in bytes, @@ -523,10 +523,10 @@ struct row_prebuilt_struct { an SQL statement: we may have to set an intention lock on the table, create a consistent read view etc. */ - ibool mysql_has_locked; /* this is set TRUE when MySQL - calls external_lock on this handle - with a lock flag, and set FALSE when - with the F_UNLOCK flag */ + ibool mysql_has_locked; /* this is set TRUE when MySQL + calls external_lock on this handle + with a lock flag, and set FALSE when + with the F_UNLOCK flag */ ibool clust_index_was_generated; /* if the user did not define a primary key in MySQL, then Innobase @@ -549,7 +549,7 @@ struct row_prebuilt_struct { unique search from a clustered index, because HANDLER allows NEXT and PREV in such a situation */ - ulint template_type; /* ROW_MYSQL_WHOLE_ROW, + ulint template_type; /* ROW_MYSQL_WHOLE_ROW, ROW_MYSQL_REC_FIELDS, ROW_MYSQL_DUMMY_TEMPLATE, or ROW_MYSQL_NO_TEMPLATE */ @@ -625,12 +625,12 @@ struct row_prebuilt_struct { ('semi-consistent read'). Then, this field will be set to ROW_READ_DID_SEMI_CONSISTENT to - indicate that. If the row does not + indicate that. If the row does not match the WHERE condition, MySQL will invoke handler::unlock_row() to clear the flag back to ROW_READ_TRY_SEMI_CONSISTENT and - to simply skip the row. If + to simply skip the row. If the row matches, the next call to row_search_for_mysql() will lock the row. @@ -654,9 +654,9 @@ struct row_prebuilt_struct { allocated mem buf start, because there is a 4 byte magic number at the start and at the end */ - ibool keep_other_fields_on_keyread; /* when using fetch - cache with HA_EXTRA_KEYREAD, don't - overwrite other fields in mysql row + ibool keep_other_fields_on_keyread; /* when using fetch + cache with HA_EXTRA_KEYREAD, don't + overwrite other fields in mysql row row buffer.*/ ulint fetch_cache_first;/* position of the first not yet fetched row in fetch_cache */ @@ -687,9 +687,8 @@ struct row_prebuilt_struct { #define ROW_READ_TRY_SEMI_CONSISTENT 1 #define ROW_READ_DID_SEMI_CONSISTENT 2 - #ifndef UNIV_NONINL #include "row0mysql.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/row0purge.h b/storage/innobase/include/row0purge.h index 4c863441442..52dd2fce551 100644 --- a/storage/innobase/include/row0purge.h +++ b/storage/innobase/include/row0purge.h @@ -17,7 +17,7 @@ Created 3/14/1997 Heikki Tuuri #include "trx0types.h" #include "que0types.h" #include "row0types.h" - + /************************************************************************ Creates a purge node to a query graph. */ @@ -77,4 +77,4 @@ struct purge_node_struct{ #include "row0purge.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h index 782973d8f5d..22ad4cb4d6d 100644 --- a/storage/innobase/include/row0row.h +++ b/storage/innobase/include/row0row.h @@ -14,7 +14,7 @@ Created 4/20/1996 Heikki Tuuri #include "dict0types.h" #include "trx0types.h" #include "que0types.h" -#include "mtr0mtr.h" +#include "mtr0mtr.h" #include "rem0types.h" #include "read0types.h" #include "btr0types.h" @@ -67,9 +67,9 @@ dtuple_t* row_build_index_entry( /*==================*/ /* out: index entry which should be inserted */ - dtuple_t* row, /* in: row which should be inserted to the + dtuple_t* row, /* in: row which should be inserted to the table */ - dict_index_t* index, /* in: index on the table */ + dict_index_t* index, /* in: index on the table */ mem_heap_t* heap); /* in: memory heap from which the memory for the index entry is allocated */ /*********************************************************************** @@ -81,7 +81,7 @@ row_build( /*======*/ /* out, own: row built; see the NOTE below! */ ulint type, /* in: ROW_COPY_POINTERS, ROW_COPY_DATA, or - ROW_COPY_ALSO_EXTERNALS, + ROW_COPY_ALSO_EXTERNALS, the two last copy also the data fields to heap as the first only places pointers to data fields on the index page, and thus is @@ -232,7 +232,7 @@ row_search_index_entry( be closed by the caller */ mtr_t* mtr); /* in: mtr */ - + #define ROW_COPY_DATA 1 #define ROW_COPY_POINTERS 2 #define ROW_COPY_ALSO_EXTERNALS 3 @@ -249,4 +249,4 @@ However, the kernel mutex can be reserved while latches are owned. */ #include "row0row.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/row0row.ic b/storage/innobase/include/row0row.ic index 85410beacf0..7cf09d25eed 100644 --- a/storage/innobase/include/row0row.ic +++ b/storage/innobase/include/row0row.ic @@ -53,7 +53,7 @@ row_get_rec_trx_id( ut_ad(rec_offs_validate(rec, index, offsets)); offset = index->trx_id_offset; - + if (offset) { return(trx_read_trx_id(rec + offset)); } else { @@ -79,7 +79,7 @@ row_get_rec_roll_ptr( ut_ad(rec_offs_validate(rec, index, offsets)); offset = index->trx_id_offset; - + if (offset) { return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN)); } else { @@ -105,7 +105,7 @@ row_set_rec_trx_id( ut_ad(rec_offs_validate(rec, index, offsets)); offset = index->trx_id_offset; - + if (offset) { trx_write_trx_id(rec + offset, trx_id); } else { @@ -131,11 +131,11 @@ row_set_rec_roll_ptr( ut_ad(rec_offs_validate(rec, index, offsets)); offset = index->trx_id_offset; - + if (offset) { trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN, roll_ptr); } else { - row_set_rec_sys_field(DATA_ROLL_PTR, + row_set_rec_sys_field(DATA_ROLL_PTR, rec, index, offsets, roll_ptr); } } @@ -163,10 +163,10 @@ row_build_row_ref_fast( ulint ref_len; ulint field_no; ulint i; - + ut_ad(rec_offs_validate(rec, NULL, offsets)); ref_len = dtuple_get_n_fields(ref); - + for (i = 0; i < ref_len; i++) { dfield = dtuple_get_nth_field(ref, i); diff --git a/storage/innobase/include/row0sel.h b/storage/innobase/include/row0sel.h index 8d5187bfc1c..c9f2389d3dd 100644 --- a/storage/innobase/include/row0sel.h +++ b/storage/innobase/include/row0sel.h @@ -118,7 +118,7 @@ ulint row_search_for_mysql( /*=================*/ /* out: DB_SUCCESS, - DB_RECORD_NOT_FOUND, + DB_RECORD_NOT_FOUND, DB_END_OF_INDEX, DB_DEADLOCK, DB_LOCK_TABLE_FULL, or DB_TOO_BIG_RECORD */ @@ -133,7 +133,7 @@ row_search_for_mysql( the end of the index, depending on 'mode' */ ulint match_mode, /* in: 0 or ROW_SEL_EXACT or - ROW_SEL_EXACT_PREFIX */ + ROW_SEL_EXACT_PREFIX */ ulint direction); /* in: 0 or ROW_SEL_NEXT or ROW_SEL_PREV; NOTE: if this is != 0, then prebuilt must have a pcur @@ -238,8 +238,8 @@ struct plan_struct{ this pcur to search the clustered index */ mem_heap_t* old_vers_heap; /* memory heap used in building an old - version of a row, or NULL */ -}; + version of a row, or NULL */ +}; struct sel_node_struct{ que_common_t common; /* node type: QUE_NODE_SELECT */ @@ -296,7 +296,7 @@ struct sel_node_struct{ so that they do not change between fetches */ }; - + /* Select node states */ #define SEL_NODE_CLOSED 0 /* it is a declared cursor which is not currently open */ @@ -335,7 +335,7 @@ struct row_printf_node_struct{ #define ROW_SEL_PREV 2 #define ROW_SEL_EXACT 1 /* search using a complete key value */ -#define ROW_SEL_EXACT_PREFIX 2 /* search using a key prefix which +#define ROW_SEL_EXACT_PREFIX 2 /* search using a key prefix which must match to rows: the prefix may contain an incomplete field (the last field in prefix may be just @@ -345,4 +345,4 @@ struct row_printf_node_struct{ #include "row0sel.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/row0sel.ic b/storage/innobase/include/row0sel.ic index 600c6204571..d58daf79969 100644 --- a/storage/innobase/include/row0sel.ic +++ b/storage/innobase/include/row0sel.ic @@ -50,7 +50,7 @@ open_step( ulint err; ut_ad(thr); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_OPEN); @@ -74,15 +74,15 @@ open_step( err = DB_ERROR; } } - + if (UNIV_EXPECT(err, DB_SUCCESS) != DB_SUCCESS) { /* SQL error detected */ fprintf(stderr, "SQL error %lu\n", (ulong) err); ut_error; } - + thr->run_node = que_node_get_parent(node); - + return(thr); } diff --git a/storage/innobase/include/row0types.h b/storage/innobase/include/row0types.h index 79b864f4835..56ca8711848 100644 --- a/storage/innobase/include/row0types.h +++ b/storage/innobase/include/row0types.h @@ -27,7 +27,7 @@ typedef struct open_node_struct open_node_t; typedef struct fetch_node_struct fetch_node_t; -typedef struct row_printf_node_struct row_printf_node_t; +typedef struct row_printf_node_struct row_printf_node_t; typedef struct sel_buf_struct sel_buf_t; typedef struct undo_node_struct undo_node_t; diff --git a/storage/innobase/include/row0uins.h b/storage/innobase/include/row0uins.h index fc57881f691..e28d5363048 100644 --- a/storage/innobase/include/row0uins.h +++ b/storage/innobase/include/row0uins.h @@ -16,7 +16,7 @@ Created 2/25/1997 Heikki Tuuri #include "que0types.h" #include "row0types.h" #include "mtr0mtr.h" - + /*************************************************************** Undoes a fresh insert of a row to a table. A fresh insert means that the same clustered index unique key did not have any record, even delete @@ -33,4 +33,4 @@ row_undo_ins( #include "row0uins.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/row0umod.h b/storage/innobase/include/row0umod.h index 2c8e19a80ae..f22945e6f12 100644 --- a/storage/innobase/include/row0umod.h +++ b/storage/innobase/include/row0umod.h @@ -16,7 +16,7 @@ Created 2/27/1997 Heikki Tuuri #include "que0types.h" #include "row0types.h" #include "mtr0mtr.h" - + /*************************************************************** Undoes a modify operation on a row of a table. */ @@ -32,4 +32,4 @@ row_undo_mod( #include "row0umod.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/row0undo.h b/storage/innobase/include/row0undo.h index d64a00dcb8f..5e3f514ad8d 100644 --- a/storage/innobase/include/row0undo.h +++ b/storage/innobase/include/row0undo.h @@ -113,4 +113,4 @@ struct undo_node_struct{ #include "row0undo.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index 673e0511153..41cce851d87 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -18,7 +18,7 @@ Created 12/27/1996 Heikki Tuuri #include "que0types.h" #include "row0types.h" #include "pars0types.h" - + /************************************************************************* Creates an update vector object. */ UNIV_INLINE @@ -209,7 +209,7 @@ Checks if an update vector changes an ordering field of an index record. This function is fast if the update vector is short or the number of ordering fields in the index is small. Otherwise, this can be quadratic. NOTE: we compare the fields as binary strings! */ - + ibool row_upd_changes_ord_field_binary( /*=============================*/ @@ -410,7 +410,7 @@ struct upd_node_struct{ index record was changed, or this is a delete operation: should update all the secondary index records */ -#define UPD_NODE_UPDATE_SOME_SEC 5 /* secondary index entries should be +#define UPD_NODE_UPDATE_SOME_SEC 5 /* secondary index entries should be looked at and updated if an ordering field changed */ @@ -425,4 +425,4 @@ struct upd_node_struct{ #include "row0upd.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/row0upd.ic b/storage/innobase/include/row0upd.ic index acbb11aa1c7..d5a797df651 100644 --- a/storage/innobase/include/row0upd.ic +++ b/storage/innobase/include/row0upd.ic @@ -34,7 +34,7 @@ upd_create( for (i = 0; i < n; i++) { update->fields[i].extern_storage = 0; } - + return(update); } @@ -80,7 +80,7 @@ upd_field_set_field_no( index */ dict_index_t* index, /* in: index */ trx_t* trx) /* in: transaction */ -{ +{ upd_field->field_no = field_no; if (UNIV_UNLIKELY(field_no >= dict_index_get_n_fields(index))) { diff --git a/storage/innobase/include/row0vers.h b/storage/innobase/include/row0vers.h index fafbe9a2402..e1377112d2a 100644 --- a/storage/innobase/include/row0vers.h +++ b/storage/innobase/include/row0vers.h @@ -123,4 +123,4 @@ row_vers_build_for_semi_consistent_read( #include "row0vers.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 11347f430d4..906f0e3875c 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -34,6 +34,18 @@ extern ibool srv_lower_case_table_names; extern mutex_t srv_monitor_file_mutex; /* Temporary file for innodb monitor output */ extern FILE* srv_monitor_file; +/* Mutex for locking srv_dict_tmpfile. +This mutex has a very high rank; threads reserving it should not +be holding any InnoDB latches. */ +extern mutex_t srv_dict_tmpfile_mutex; +/* Temporary file for output from the data dictionary */ +extern FILE* srv_dict_tmpfile; +/* Mutex for locking srv_misc_tmpfile. +This mutex has a very low rank; threads reserving it should not +acquire any further latches or sleep before releasing this one. */ +extern mutex_t srv_misc_tmpfile_mutex; +/* Temporary file for miscellanous diagnostic output */ +extern FILE* srv_misc_tmpfile; /* Server parameters which are read from the initfile */ @@ -43,12 +55,12 @@ extern char* srv_arch_dir; #endif /* UNIV_LOG_ARCHIVE */ extern ibool srv_file_per_table; -extern ibool srv_locks_unsafe_for_binlog; +extern ibool srv_locks_unsafe_for_binlog; extern ulint srv_n_data_files; extern char** srv_data_file_names; extern ulint* srv_data_file_sizes; -extern ulint* srv_data_file_is_raw_partition; +extern ulint* srv_data_file_is_raw_partition; extern ibool srv_auto_extend_last_data_file; extern ulint srv_last_file_size_max; @@ -56,8 +68,8 @@ extern ulong srv_auto_extend_increment; extern ibool srv_created_new_raw; -#define SRV_NEW_RAW 1 -#define SRV_OLD_RAW 2 +#define SRV_NEW_RAW 1 +#define SRV_OLD_RAW 2 extern char** srv_log_group_home_dirs; @@ -84,9 +96,9 @@ extern dulint srv_archive_recovery_limit_lsn; extern ulint srv_lock_wait_timeout; -extern char* srv_file_flush_method_str; -extern ulint srv_unix_file_flush_method; -extern ulint srv_win_file_flush_method; +extern char* srv_file_flush_method_str; +extern ulint srv_unix_file_flush_method; +extern ulint srv_win_file_flush_method; extern ulint srv_max_n_open_files; @@ -100,7 +112,7 @@ extern ulint srv_max_n_threads; extern lint srv_conc_n_threads; -extern ulint srv_fast_shutdown; /* If this is 1, do not do a +extern ulint srv_fast_shutdown; /* If this is 1, do not do a purge and index buffer merge. If this 2, do not even flush the buffer pool to data files at the @@ -112,8 +124,8 @@ extern ibool srv_innodb_status; extern ibool srv_use_doublewrite_buf; extern ibool srv_use_checksums; -extern ibool srv_set_thread_priorities; -extern int srv_query_thread_priority; +extern ibool srv_set_thread_priorities; +extern int srv_query_thread_priority; extern ulong srv_max_buf_pool_modified_pct; extern ulong srv_max_purge_lag; @@ -127,20 +139,20 @@ extern ulint srv_n_rows_deleted; extern ulint srv_n_rows_read; extern ibool srv_print_innodb_monitor; -extern ibool srv_print_innodb_lock_monitor; -extern ibool srv_print_innodb_tablespace_monitor; -extern ibool srv_print_verbose_log; -extern ibool srv_print_innodb_table_monitor; +extern ibool srv_print_innodb_lock_monitor; +extern ibool srv_print_innodb_tablespace_monitor; +extern ibool srv_print_verbose_log; +extern ibool srv_print_innodb_table_monitor; extern ibool srv_lock_timeout_and_monitor_active; -extern ibool srv_error_monitor_active; +extern ibool srv_error_monitor_active; extern ulong srv_n_spin_wait_rounds; extern ulong srv_n_free_tickets_to_enter; extern ulong srv_thread_sleep_delay; extern ulint srv_spin_wait_delay; extern ibool srv_priority_boost; - + extern ulint srv_pool_size; extern ulint srv_mem_pool_size; extern ulint srv_lock_table_size; @@ -152,7 +164,7 @@ extern ibool srv_sim_disk_wait_by_wait; extern ibool srv_measure_contention; extern ibool srv_measure_by_spin; - + extern ibool srv_print_thread_releases; extern ibool srv_print_lock_waits; extern ibool srv_print_buf_io; @@ -183,8 +195,7 @@ extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs, #define kernel_mutex (*kernel_mutex_temp) #define SRV_MAX_N_IO_THREADS 100 -#define SRV_CONCURRENCY_THRESHOLD 20 - + /* Array of English strings describing the current state of an i/o handler thread */ extern const char* srv_io_thread_op_info[]; @@ -252,15 +263,17 @@ typedef struct srv_sys_struct srv_sys_t; /* The server system */ 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_O_DSYNC 2 -#define SRV_UNIX_LITTLESYNC 3 -#define SRV_UNIX_NOSYNC 4 -#define SRV_UNIX_O_DIRECT 5 +/* 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_O_DSYNC 2 +#define SRV_UNIX_LITTLESYNC 3 +#define SRV_UNIX_NOSYNC 4 +#define SRV_UNIX_O_DIRECT 5 /* Alternatives for file i/o in Windows */ #define SRV_WIN_IO_NORMAL 1 @@ -274,7 +287,7 @@ of lower numbers are included. */ #define SRV_FORCE_IGNORE_CORRUPT 1 /* let the server run even if it detects a corrupt page */ -#define SRV_FORCE_NO_BACKGROUND 2 /* prevent the main thread from +#define SRV_FORCE_NO_BACKGROUND 2 /* prevent the main thread from running: if a crash would occur in purge, this prevents it */ #define SRV_FORCE_NO_TRX_UNDO 3 /* do not run trx rollback after @@ -288,7 +301,7 @@ of lower numbers are included. */ as committed */ #define SRV_FORCE_NO_LOG_REDO 6 /* do not do the log roll-forward in connection with recovery */ - + /************************************************************************* Boots Innobase server. */ @@ -433,7 +446,7 @@ void srv_release_mysql_thread_if_suspended( /*==================================*/ que_thr_t* thr); /* in: query thread associated with the - MySQL OS thread */ + MySQL OS thread */ /************************************************************************* A thread which wakes up threads whose lock wait may have lasted too long. This also prints the info output by various InnoDB monitors. */ @@ -496,7 +509,7 @@ cleaning versions from the buffer pool. */ not currently in use */ #define SRV_INSERT 6 /* thread flushing the insert buffer to disk, not currently in use */ -#define SRV_MASTER 7 /* the master thread, (whose type number must +#define SRV_MASTER 7 /* the master thread, (whose type number must be biggest) */ /* Thread slot in the thread table */ @@ -507,49 +520,49 @@ typedef srv_slot_t srv_table_t; /* In this structure we store status variables to be passed to MySQL */ struct export_var_struct{ - ulint innodb_data_pending_reads; - ulint innodb_data_pending_writes; - ulint innodb_data_pending_fsyncs; - ulint innodb_data_fsyncs; - ulint innodb_data_read; - ulint innodb_data_writes; - ulint innodb_data_written; - ulint innodb_data_reads; - ulint innodb_buffer_pool_pages_total; - ulint innodb_buffer_pool_pages_data; - ulint innodb_buffer_pool_pages_dirty; - ulint innodb_buffer_pool_pages_misc; - ulint innodb_buffer_pool_pages_free; - ulint innodb_buffer_pool_pages_latched; - ulint innodb_buffer_pool_read_requests; - ulint innodb_buffer_pool_reads; - ulint innodb_buffer_pool_wait_free; - ulint innodb_buffer_pool_pages_flushed; - ulint innodb_buffer_pool_write_requests; - ulint innodb_buffer_pool_read_ahead_seq; - ulint innodb_buffer_pool_read_ahead_rnd; - ulint innodb_dblwr_pages_written; - ulint innodb_dblwr_writes; - ulint innodb_log_waits; - ulint innodb_log_write_requests; - ulint innodb_log_writes; - ulint innodb_os_log_written; - ulint innodb_os_log_fsyncs; - ulint innodb_os_log_pending_writes; - ulint innodb_os_log_pending_fsyncs; - ulint innodb_page_size; - ulint innodb_pages_created; - ulint innodb_pages_read; - ulint innodb_pages_written; - ulint innodb_row_lock_waits; - ulint innodb_row_lock_current_waits; - ib_longlong innodb_row_lock_time; - ulint innodb_row_lock_time_avg; - ulint innodb_row_lock_time_max; - ulint innodb_rows_read; - ulint innodb_rows_inserted; - ulint innodb_rows_updated; - ulint innodb_rows_deleted; + ulint innodb_data_pending_reads; + ulint innodb_data_pending_writes; + ulint innodb_data_pending_fsyncs; + ulint innodb_data_fsyncs; + ulint innodb_data_read; + ulint innodb_data_writes; + ulint innodb_data_written; + ulint innodb_data_reads; + ulint innodb_buffer_pool_pages_total; + ulint innodb_buffer_pool_pages_data; + ulint innodb_buffer_pool_pages_dirty; + ulint innodb_buffer_pool_pages_misc; + ulint innodb_buffer_pool_pages_free; + ulint innodb_buffer_pool_pages_latched; + ulint innodb_buffer_pool_read_requests; + ulint innodb_buffer_pool_reads; + ulint innodb_buffer_pool_wait_free; + ulint innodb_buffer_pool_pages_flushed; + ulint innodb_buffer_pool_write_requests; + ulint innodb_buffer_pool_read_ahead_seq; + ulint innodb_buffer_pool_read_ahead_rnd; + ulint innodb_dblwr_pages_written; + ulint innodb_dblwr_writes; + ulint innodb_log_waits; + ulint innodb_log_write_requests; + ulint innodb_log_writes; + ulint innodb_os_log_written; + ulint innodb_os_log_fsyncs; + ulint innodb_os_log_pending_writes; + ulint innodb_os_log_pending_fsyncs; + ulint innodb_page_size; + ulint innodb_pages_created; + ulint innodb_pages_read; + ulint innodb_pages_written; + ulint innodb_row_lock_waits; + ulint innodb_row_lock_current_waits; + ib_longlong innodb_row_lock_time; + ulint innodb_row_lock_time_avg; + ulint innodb_row_lock_time_max; + ulint innodb_rows_read; + ulint innodb_rows_inserted; + ulint innodb_rows_updated; + ulint innodb_rows_deleted; }; /* The server system struct */ diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h index d24f119c0b0..a04930d6516 100644 --- a/storage/innobase/include/srv0start.h +++ b/storage/innobase/include/srv0start.h @@ -89,18 +89,18 @@ void set_panic_flag_for_netware(void); extern ibool srv_have_fullfsync; #endif -extern ulint srv_sizeof_trx_t_in_ha_innodb_cc; +extern ulint srv_sizeof_trx_t_in_ha_innodb_cc; -extern ibool srv_is_being_started; +extern ibool srv_is_being_started; extern ibool srv_startup_is_before_trx_rollback_phase; extern ibool srv_is_being_shut_down; -extern ibool srv_start_raw_disk_in_use; +extern ibool srv_start_raw_disk_in_use; /* At a shutdown the value first climbs from 0 to SRV_SHUTDOWN_CLEANUP and then to SRV_SHUTDOWN_LAST_PHASE, and so on */ -extern ulint srv_shutdown_state; +extern ulint srv_shutdown_state; #define SRV_SHUTDOWN_CLEANUP 1 #define SRV_SHUTDOWN_LAST_PHASE 2 diff --git a/storage/innobase/include/sync0arr.h b/storage/innobase/include/sync0arr.h index fecd910683e..d4407e14dc4 100644 --- a/storage/innobase/include/sync0arr.h +++ b/storage/innobase/include/sync0arr.h @@ -14,7 +14,7 @@ Created 9/5/1995 Heikki Tuuri #include "ut0mem.h" #include "os0thread.h" -typedef struct sync_cell_struct sync_cell_t; +typedef struct sync_cell_struct sync_cell_t; typedef struct sync_array_struct sync_array_t; #define SYNC_ARRAY_OS_MUTEX 1 @@ -48,12 +48,12 @@ The event of the cell is reset to nonsignalled state. */ void sync_array_reserve_cell( /*====================*/ - sync_array_t* arr, /* in: wait array */ - void* object, /* in: pointer to the object to wait for */ - ulint type, /* in: lock request type */ + sync_array_t* arr, /* in: wait array */ + void* object, /* in: pointer to the object to wait for */ + ulint type, /* in: lock request type */ const char* file, /* in: file where requested */ - ulint line, /* in: line where requested */ - ulint* index); /* out: index of the reserved cell */ + ulint line, /* in: line where requested */ + ulint* index); /* out: index of the reserved cell */ /********************************************************************** This function should be called when a thread starts to wait on a wait array cell. In the debug version this function checks @@ -63,17 +63,17 @@ case prints info and asserts. */ void sync_array_wait_event( /*==================*/ - sync_array_t* arr, /* in: wait array */ - ulint index); /* in: index of the reserved cell */ + sync_array_t* arr, /* in: wait array */ + ulint index); /* in: index of the reserved cell */ /********************************************************************** -Frees the cell. NOTE! sync_array_wait_event frees the cell -automatically! */ +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( -/*=================*/ +sync_array_free_cell_protected( +/*===========================*/ sync_array_t* arr, /* in: wait array */ - ulint index); /* in: index of the cell in 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, diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h index 911c8ac3f4a..e6ca3258099 100644 --- a/storage/innobase/include/sync0rw.h +++ b/storage/innobase/include/sync0rw.h @@ -31,7 +31,7 @@ typedef struct rw_lock_debug_struct rw_lock_debug_t; typedef UT_LIST_BASE_NODE_T(rw_lock_t) rw_lock_list_t; -extern rw_lock_list_t rw_lock_list; +extern rw_lock_list_t rw_lock_list; extern mutex_t rw_lock_list_mutex; #ifdef UNIV_SYNC_DEBUG @@ -62,7 +62,7 @@ location (which must be appropriately aligned). The rw-lock is initialized to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free is necessary only if the memory block containing it is freed. */ #define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__, #L) - + /*=====================*/ /********************************************************************** Creates, or rather, initializes an rw-lock object in a specified memory @@ -75,7 +75,7 @@ rw_lock_create_func( /*================*/ rw_lock_t* lock, /* in: pointer to memory */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ + ulint cline, /* in: file line where created */ const char* cmutex_name); /* in: mutex name */ /********************************************************************** Calling this function is obligatory only if the memory buffer containing @@ -98,20 +98,20 @@ rw_lock_validate( NOTE! The following macros should be used in rw s-locking, not the corresponding function. */ -#define rw_lock_s_lock(M) rw_lock_s_lock_func(\ - (M), 0, __FILE__, __LINE__) +#define rw_lock_s_lock(M) rw_lock_s_lock_func(\ + (M), 0, __FILE__, __LINE__) /****************************************************************** NOTE! The following macros should be used in rw s-locking, not the corresponding function. */ -#define rw_lock_s_lock_gen(M, P) rw_lock_s_lock_func(\ - (M), (P), __FILE__, __LINE__) +#define rw_lock_s_lock_gen(M, P) rw_lock_s_lock_func(\ + (M), (P), __FILE__, __LINE__) /****************************************************************** NOTE! The following macros should be used in rw s-locking, not the corresponding function. */ -#define rw_lock_s_lock_nowait(M) rw_lock_s_lock_func_nowait(\ - (M), __FILE__, __LINE__) +#define rw_lock_s_lock_nowait(M) rw_lock_s_lock_func_nowait(\ + (M), __FILE__, __LINE__) /********************************************************************** NOTE! Use the corresponding macro, not directly this function, except if you supply the file name and line number. Lock an rw-lock in shared mode @@ -123,7 +123,7 @@ UNIV_INLINE void rw_lock_s_lock_func( /*================*/ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ ulint pass, /* in: pass value; != 0, if the lock will be passed to another thread to unlock */ const char* file_name,/* in: file name where lock requested */ @@ -137,7 +137,7 @@ ibool rw_lock_s_lock_func_nowait( /*=======================*/ /* out: TRUE if success */ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ const char* file_name,/* in: file name where lock requested */ ulint line); /* in: line where requested */ /********************************************************************** @@ -149,7 +149,7 @@ ibool rw_lock_x_lock_func_nowait( /*=======================*/ /* out: TRUE if success */ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ const char* file_name,/* in: file name where lock requested */ ulint line); /* in: line where requested */ /********************************************************************** @@ -168,36 +168,36 @@ rw_lock_s_unlock_func( Releases a shared mode lock. */ #ifdef UNIV_SYNC_DEBUG -#define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L, 0) +#define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L, 0) #else -#define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L) +#define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L) #endif /*********************************************************************** Releases a shared mode lock. */ #ifdef UNIV_SYNC_DEBUG -#define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L, P) +#define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L, P) #else -#define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L) +#define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L) #endif /****************************************************************** NOTE! The following macro should be used in rw x-locking, not the corresponding function. */ -#define rw_lock_x_lock(M) rw_lock_x_lock_func(\ - (M), 0, __FILE__, __LINE__) +#define rw_lock_x_lock(M) rw_lock_x_lock_func(\ + (M), 0, __FILE__, __LINE__) /****************************************************************** NOTE! The following macro should be used in rw x-locking, not the corresponding function. */ -#define rw_lock_x_lock_gen(M, P) rw_lock_x_lock_func(\ - (M), (P), __FILE__, __LINE__) +#define rw_lock_x_lock_gen(M, P) rw_lock_x_lock_func(\ + (M), (P), __FILE__, __LINE__) /****************************************************************** NOTE! The following macros should be used in rw x-locking, not the corresponding function. */ -#define rw_lock_x_lock_nowait(M) rw_lock_x_lock_func_nowait(\ - (M), __FILE__, __LINE__) +#define rw_lock_x_lock_nowait(M) rw_lock_x_lock_func_nowait(\ + (M), __FILE__, __LINE__) /********************************************************************** NOTE! Use the corresponding macro, not directly this function! Lock an rw-lock in exclusive mode for the current thread. If the rw-lock is locked @@ -211,7 +211,7 @@ an s-lock, locking does not succeed! */ void rw_lock_x_lock_func( /*================*/ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ ulint pass, /* in: pass value; != 0, if the lock will be passed to another thread to unlock */ const char* file_name,/* in: file name where lock requested */ @@ -232,17 +232,17 @@ rw_lock_x_unlock_func( Releases an exclusive mode lock. */ #ifdef UNIV_SYNC_DEBUG -#define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L, 0) +#define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L, 0) #else -#define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L) +#define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L) #endif /*********************************************************************** Releases an exclusive mode lock. */ #ifdef UNIV_SYNC_DEBUG -#define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L, P) +#define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L, P) #else -#define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L) +#define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L) #endif /********************************************************************** Low-level function which locks an rw-lock in s-mode when we know that it @@ -413,7 +413,7 @@ field. Then no new readers are allowed in. */ struct rw_lock_struct { 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 + ulint writer; /* This field is set to RW_LOCK_EX if there is a writer owning the lock (in exclusive mode), RW_LOCK_WAIT_EX if a writer is queueing for the lock, and @@ -424,7 +424,7 @@ struct rw_lock_struct { recursively locked the lock in the exclusive mode */ mutex_t mutex; /* The mutex protecting rw_lock_struct */ - ulint pass; /* Default value 0. This is set to some + ulint pass; /* Default value 0. This is set to some value != 0 given by the caller of an x-lock operation, if the x-lock is to be passed to another thread to unlock (which happens in diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic index b1ae636010a..37dc22f1fe5 100644 --- a/storage/innobase/include/sync0rw.ic +++ b/storage/innobase/include/sync0rw.ic @@ -15,7 +15,7 @@ waiting for the lock before suspending the thread. */ void rw_lock_s_lock_spin( /*================*/ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ ulint pass, /* in: pass value; != 0, if the lock will be passed to another thread to unlock */ const char* file_name,/* in: file name where lock requested */ @@ -126,9 +126,9 @@ ibool rw_lock_s_lock_low( /*===============*/ /* out: TRUE if success */ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ ulint pass __attribute__((unused)), - /* in: pass value; != 0, if the lock will be + /* in: pass value; != 0, if the lock will be passed to another thread to unlock */ const char* file_name, /* in: file name where lock requested */ ulint line) /* in: line where requested */ @@ -169,7 +169,7 @@ rw_lock_s_lock_direct( { ut_ad(lock->writer == RW_LOCK_NOT_LOCKED); ut_ad(rw_lock_get_reader_count(lock) == 0); - + /* Set the shared lock by incrementing the reader count */ lock->reader_count++; @@ -193,7 +193,7 @@ rw_lock_x_lock_direct( const char* file_name, /* in: file name where requested */ ulint line) /* in: line where lock requested */ { - ut_ad(rw_lock_validate(lock)); + ut_ad(rw_lock_validate(lock)); ut_ad(rw_lock_get_reader_count(lock) == 0); ut_ad(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED); @@ -201,7 +201,7 @@ rw_lock_x_lock_direct( lock->writer_thread = os_thread_get_curr_id(); lock->writer_count++; lock->pass = 0; - + lock->last_x_file_name = file_name; lock->last_x_line = line; @@ -220,7 +220,7 @@ UNIV_INLINE void rw_lock_s_lock_func( /*================*/ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ ulint pass, /* in: pass value; != 0, if the lock will be passed to another thread to unlock */ const char* file_name,/* in: file name where lock requested */ @@ -236,7 +236,7 @@ rw_lock_s_lock_func( safe recursive s-locking, we should keep in a list the thread ids of the threads which have s-locked a latch. This would use some CPU time. */ - + #ifdef UNIV_SYNC_DEBUG ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */ #endif /* UNIV_SYNC_DEBUG */ @@ -266,7 +266,7 @@ ibool rw_lock_s_lock_func_nowait( /*=======================*/ /* out: TRUE if success */ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ const char* file_name,/* in: file name where lock requested */ ulint line) /* in: line where requested */ { @@ -285,7 +285,7 @@ rw_lock_s_lock_func_nowait( lock->last_s_file_name = file_name; lock->last_s_line = line; - + success = TRUE; } @@ -303,7 +303,7 @@ ibool rw_lock_x_lock_func_nowait( /*=======================*/ /* out: TRUE if success */ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ const char* file_name,/* in: file name where lock requested */ ulint line) /* in: line where requested */ { @@ -313,13 +313,13 @@ rw_lock_x_lock_func_nowait( if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) { } else if (UNIV_LIKELY(rw_lock_get_writer(lock) - == RW_LOCK_NOT_LOCKED)) { + == RW_LOCK_NOT_LOCKED)) { rw_lock_set_writer(lock, RW_LOCK_EX); lock->writer_thread = curr_thread; lock->pass = 0; relock: lock->writer_count++; - + #ifdef UNIV_SYNC_DEBUG rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line); #endif @@ -336,7 +336,7 @@ rw_lock_x_lock_func_nowait( mutex_exit(rw_lock_get_mutex(lock)); - ut_ad(rw_lock_validate(lock)); + ut_ad(rw_lock_validate(lock)); return(success); } @@ -355,9 +355,9 @@ rw_lock_s_unlock_func( ) { mutex_t* mutex = &(lock->mutex); - ibool sg = FALSE; + ibool sg = FALSE; - /* Acquire the mutex protecting the rw-lock fields */ + /* Acquire the mutex protecting the rw-lock fields */ mutex_enter(mutex); /* Reset the shared lock by decrementing the reader count */ @@ -368,24 +368,24 @@ rw_lock_s_unlock_func( #ifdef UNIV_SYNC_DEBUG rw_lock_remove_debug_info(lock, pass, RW_LOCK_SHARED); #endif - + /* If there may be waiters and this was the last s-lock, signal the object */ if (UNIV_UNLIKELY(lock->waiters) && lock->reader_count == 0) { - sg = TRUE; + sg = TRUE; rw_lock_set_waiters(lock, 0); } - + mutex_exit(mutex); if (UNIV_UNLIKELY(sg)) { sync_array_signal_object(sync_primary_wait_array, lock); } - ut_ad(rw_lock_validate(lock)); + ut_ad(rw_lock_validate(lock)); #ifdef UNIV_SYNC_PERF_STAT rw_s_exit_count++; @@ -412,7 +412,7 @@ rw_lock_s_unlock_direct( #endif ut_ad(!lock->waiters); - ut_ad(rw_lock_validate(lock)); + ut_ad(rw_lock_validate(lock)); #ifdef UNIV_SYNC_PERF_STAT rw_s_exit_count++; #endif @@ -431,9 +431,9 @@ rw_lock_x_unlock_func( #endif ) { - ibool sg = FALSE; + ibool sg = FALSE; - /* Acquire the mutex protecting the rw-lock fields */ + /* Acquire the mutex protecting the rw-lock fields */ mutex_enter(&(lock->mutex)); /* Reset the exclusive lock if this thread no longer has an x-mode @@ -450,22 +450,22 @@ rw_lock_x_unlock_func( #ifdef UNIV_SYNC_DEBUG rw_lock_remove_debug_info(lock, pass, RW_LOCK_EX); #endif - + /* If there may be waiters, signal the lock */ if (UNIV_UNLIKELY(lock->waiters) && lock->writer_count == 0) { - sg = TRUE; + sg = TRUE; rw_lock_set_waiters(lock, 0); } - + mutex_exit(&(lock->mutex)); if (UNIV_UNLIKELY(sg)) { sync_array_signal_object(sync_primary_wait_array, lock); } - ut_ad(rw_lock_validate(lock)); + ut_ad(rw_lock_validate(lock)); #ifdef UNIV_SYNC_PERF_STAT rw_x_exit_count++; @@ -497,7 +497,7 @@ rw_lock_x_unlock_direct( #endif ut_ad(!lock->waiters); - ut_ad(rw_lock_validate(lock)); + ut_ad(rw_lock_validate(lock)); #ifdef UNIV_SYNC_PERF_STAT rw_x_exit_count++; diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h index 5955ab9a06a..0a233843b50 100644 --- a/storage/innobase/include/sync0sync.h +++ b/storage/innobase/include/sync0sync.h @@ -18,7 +18,7 @@ Created 9/5/1995 Heikki Tuuri #include "sync0arr.h" #ifndef UNIV_HOTBACKUP -extern my_bool timed_mutexes; +extern my_bool timed_mutexes; #endif /* UNIV_HOTBACKUP */ /********************************************************************** @@ -52,7 +52,7 @@ mutex_create_func( /*==============*/ mutex_t* mutex, /* in: pointer to memory */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ + ulint cline, /* in: file line where created */ const char* cmutex_name); /* in: mutex name */ /********************************************************************** Calling this function is obligatory only if the memory buffer containing @@ -68,7 +68,7 @@ mutex_free( NOTE! The following macro should be used in mutex locking, not the corresponding function. */ -#define mutex_enter(M) mutex_enter_func((M), __FILE__, __LINE__) +#define mutex_enter(M) mutex_enter_func((M), __FILE__, __LINE__) /********************************************************************** A noninlined function that reserves a mutex. In ha_innodb.cc we have disabled inlining of InnoDB functions, and no inlined functions should be called from @@ -84,8 +84,8 @@ corresponding function. */ /* NOTE! currently same as mutex_enter! */ -#define mutex_enter_fast(M) mutex_enter_func((M), __FILE__, __LINE__) -#define mutex_enter_fast_func mutex_enter_func; +#define mutex_enter_fast(M) mutex_enter_func((M), __FILE__, __LINE__) +#define mutex_enter_fast_func mutex_enter_func; /********************************************************************** NOTE! Use the corresponding macro in the header file, not this function directly. Locks a mutex for the current thread. If the mutex is reserved @@ -96,7 +96,7 @@ void mutex_enter_func( /*=============*/ mutex_t* mutex, /* in: pointer to mutex */ - const char* file_name, /* in: file name where locked */ + const char* file_name, /* in: file name where locked */ ulint line); /* in: line where locked */ /************************************************************************ Tries to lock the mutex for the current thread. If the lock is not acquired @@ -172,7 +172,7 @@ sync_thread_add_level( /*==================*/ void* latch, /* in: pointer to a mutex or an rw-lock */ ulint level); /* in: level in the latching order; if SYNC_LEVEL_NONE, - nothing is done */ + nothing is done */ /********************************************************************** Removes a latch from the thread level array if it is found there. */ @@ -253,7 +253,7 @@ UNIV_INLINE ulint mutex_get_waiters( /*==============*/ - /* out: value to set */ + /* out: value to set */ mutex_t* mutex); /* in: mutex */ #endif /* UNIV_SYNC_DEBUG */ @@ -269,7 +269,7 @@ central memory object latch or mutex. Synchronization object Notes ---------------------- ----- - + Dictionary mutex If we have a pointer to a dictionary | object, e.g., a table, it can be | accessed without reserving the @@ -281,7 +281,7 @@ Dictionary mutex If we have a pointer to a dictionary V Dictionary header | -V +V Secondary index tree latch The tree latch protects also all | the B-tree non-leaf pages. These V can be read with the page only @@ -293,7 +293,7 @@ Secondary index non-leaf bufferfixed to save CPU time, | it is allowed to latch non-leaf pages | even after it has acquired the fsp | latch. -V +V Secondary index leaf The latch on the secondary index leaf | can be kept while accessing the | clustered index, to save CPU time. @@ -301,7 +301,7 @@ V Clustered index tree latch To increase concurrency, the tree | latch is usually released when the | leaf page latch has been acquired. -V +V Clustered index non-leaf | V @@ -319,7 +319,7 @@ Transaction undo mutex The undo log entry must be written | trx undo mutex reserved, it is allowed | to latch the undo log pages in any | order, and also after it has acquired -| the fsp latch. +| the fsp latch. V Rollback segment mutex The rollback segment mutex must be | reserved, if, e.g., a new page must @@ -412,7 +412,7 @@ or row lock! */ #define SYNC_EXTERN_STORAGE 500 #define SYNC_FSP 400 #define SYNC_FSP_PAGE 395 -/*------------------------------------- Insert buffer headers */ +/*------------------------------------- Insert buffer headers */ /*------------------------------------- ibuf_mutex */ /*------------------------------------- Insert buffer tree */ #define SYNC_IBUF_BITMAP_MUTEX 351 @@ -441,7 +441,7 @@ or row lock! */ #define SYNC_MEM_POOL 130 /* Codes used to designate lock operations */ -#define RW_LOCK_NOT_LOCKED 350 +#define RW_LOCK_NOT_LOCKED 350 #define RW_LOCK_EX 351 #define RW_LOCK_EXCLUSIVE 351 #define RW_LOCK_SHARED 352 @@ -485,8 +485,8 @@ struct mutex_struct { ulong count_os_yield; /* count of os_wait */ ulonglong lspent_time; /* mutex os_wait timer msec */ ulonglong lmax_spent_time; /* mutex os_wait timer msec */ - const char* cmutex_name;/* mutex name */ - ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */ + const char* cmutex_name;/* mutex name */ + ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */ #endif /* !UNIV_HOTBACKUP */ }; @@ -512,7 +512,7 @@ to 20 microseconds. */ /* The number of system calls made in this module. Intended for performance monitoring. */ -extern ulint mutex_system_call_count; +extern ulint mutex_system_call_count; extern ulint mutex_exit_count; /* Latching order checks start when this is set TRUE */ diff --git a/storage/innobase/include/sync0sync.ic b/storage/innobase/include/sync0sync.ic index b3fde61db5e..f384e43779f 100644 --- a/storage/innobase/include/sync0sync.ic +++ b/storage/innobase/include/sync0sync.ic @@ -13,7 +13,7 @@ void mutex_set_waiters( /*==============*/ mutex_t* mutex, /* in: mutex */ - ulint n); /* in: value to set */ + ulint n); /* in: value to set */ /********************************************************************** Reserves a mutex for the current thread. If the mutex is reserved, the function spins a preset time (controlled by SYNC_SPIN_ROUNDS) waiting @@ -22,9 +22,10 @@ for the mutex before suspending the thread. */ void mutex_spin_wait( /*============*/ - mutex_t* mutex, /* in: pointer to mutex */ - const char* file_name,/* in: file name where mutex requested */ - ulint line); /* in: line where requested */ + mutex_t* mutex, /* in: pointer to mutex */ + const char* file_name, /* in: file name where mutex + requested */ + ulint line); /* in: line where requested */ #ifdef UNIV_SYNC_DEBUG /********************************************************************** Sets the debug information for a reserved mutex. */ @@ -64,10 +65,10 @@ mutex_test_and_set( lw = &(mutex->lock_word); - __asm MOV ECX, lw - __asm MOV EDX, 1 - __asm XCHG EDX, DWORD PTR [ECX] - __asm MOV res, EDX + __asm MOV ECX, lw + __asm MOV EDX, 1 + __asm XCHG EDX, DWORD PTR [ECX] + __asm MOV res, EDX /* The fence below would prevent this thread from reading the data structure protected by the mutex before the test-and-set operation is @@ -97,8 +98,8 @@ mutex_test_and_set( code, and the second line tells the input to the asm code. */ asm volatile("movl $1, %%eax; xchgl (%%ecx), %%eax" : - "=eax" (res), "=m" (*lw) : - "ecx" (lw)); + "=eax" (res), "=m" (*lw) : + "ecx" (lw)); return(res); #else ibool ret; @@ -133,9 +134,9 @@ mutex_reset_lock_word( lw = &(mutex->lock_word); - __asm MOV EDX, 0 - __asm MOV ECX, lw - __asm XCHG EDX, DWORD PTR [ECX] + __asm MOV EDX, 0 + __asm MOV ECX, lw + __asm XCHG EDX, DWORD PTR [ECX] #elif defined(not_defined) && defined(__GNUC__) && defined(UNIV_INTEL_X86) ulint* lw; @@ -146,11 +147,11 @@ mutex_reset_lock_word( syntax. The 'l' after the mnemonics denotes a 32-bit operation. */ asm volatile("movl $0, %%eax; xchgl (%%ecx), %%eax" : - "=m" (*lw) : - "ecx" (lw) : - "eax"); /* gcc does not seem to understand - that our asm code resets eax: tell it - explicitly that after the third ':' */ + "=m" (*lw) : + "ecx" (lw) : + "eax"); /* gcc does not seem to understand that our asm code + resets eax: tell it explicitly that after the third + ':' */ #else mutex->lock_word = 0; @@ -181,7 +182,7 @@ UNIV_INLINE ulint mutex_get_waiters( /*==============*/ - /* out: value to set */ + /* out: value to set */ mutex_t* mutex) /* in: mutex */ { volatile ulint* ptr; /* declared volatile to ensure that @@ -208,7 +209,7 @@ mutex_exit( mutex->thread_id = ULINT_UNDEFINED; sync_thread_reset_level(mutex); -#endif +#endif mutex_reset_lock_word(mutex); /* A problem: we assume that mutex_reset_lock word @@ -224,10 +225,10 @@ mutex_exit( they are missed in mutex_signal_object. */ if (mutex_get_waiters(mutex) != 0) { - + mutex_signal_object(mutex); } - + #ifdef UNIV_SYNC_PERF_STAT mutex_exit_count++; #endif @@ -242,7 +243,7 @@ void mutex_enter_func( /*=============*/ mutex_t* mutex, /* in: pointer to mutex */ - const char* file_name, /* in: file name where locked */ + const char* file_name, /* in: file name where locked */ ulint line) /* in: line where locked */ { ut_ad(mutex_validate(mutex)); @@ -253,9 +254,8 @@ mutex_enter_func( #ifndef UNIV_HOTBACKUP mutex->count_using++; #endif /* UNIV_HOTBACKUP */ - - if (!mutex_test_and_set(mutex)) - { + + if (!mutex_test_and_set(mutex)) { #ifdef UNIV_SYNC_DEBUG mutex_set_debug_info(mutex, file_name, line); #endif @@ -263,5 +263,4 @@ mutex_enter_func( } mutex_spin_wait(mutex, file_name, line); - } diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 049c79aec9b..c4aab91a93a 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -166,4 +166,4 @@ struct trx_purge_struct{ #include "trx0purge.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/trx0purge.ic b/storage/innobase/include/trx0purge.ic index 451e8ca31d0..9f1c0ed96f8 100644 --- a/storage/innobase/include/trx0purge.ic +++ b/storage/innobase/include/trx0purge.ic @@ -22,5 +22,5 @@ trx_purge_get_log_from_hist( node_addr.boffset -= TRX_UNDO_HISTORY_NODE; return(node_addr); -} +} diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h index 4387ce1a61e..6447b6a2e35 100644 --- a/storage/innobase/include/trx0rec.h +++ b/storage/innobase/include/trx0rec.h @@ -300,4 +300,4 @@ record */ #include "trx0rec.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h index 944142a299d..7b450f9da39 100644 --- a/storage/innobase/include/trx0roll.h +++ b/storage/innobase/include/trx0roll.h @@ -89,7 +89,7 @@ trx_undo_rec_release( trx_t* trx, /* in: transaction */ dulint undo_no);/* in: undo number */ /************************************************************************* -Starts a rollback operation. */ +Starts a rollback operation. */ void trx_rollback( @@ -104,7 +104,7 @@ trx_rollback( /*********************************************************************** Rollback or clean up transactions which have no user session. If the transaction already was committed, then we clean up a possible insert -undo log. If the transaction was not yet committed, then we roll it back. +undo log. If the transaction was not yet committed, then we roll it back. Note: this is done in a background thread. */ #ifndef __WIN__ @@ -114,10 +114,10 @@ ulint #endif trx_rollback_or_clean_all_without_sess( /*===================================*/ - /* out: a dummy parameter */ - void* arg __attribute__((unused))); - /* in: a dummy parameter required by - os_thread_create */ + /* out: a dummy parameter */ + void* arg __attribute__((unused))); + /* in: a dummy parameter required by + os_thread_create */ /******************************************************************** Finishes a transaction rollback. */ @@ -129,7 +129,7 @@ trx_finish_rollback_off_kernel( que_thr_t** next_thr);/* in/out: next query thread to run; if the value which is passed in is a pointer to a NULL pointer, then the - calling function can start running + calling function can start running a new query thread; if this parameter is NULL, it is ignored */ /******************************************************************** @@ -190,7 +190,7 @@ trx_general_rollback_for_mysql( Rolls back a transaction back to a named savepoint. Modifications after the savepoint are undone but InnoDB does NOT release the corresponding locks which are stored in memory. If a lock is 'implicit', that is, a new inserted -row holds a lock where the lock information is carried by the trx id stored in +row holds a lock where the lock information is carried by the trx id stored in the row, these locks are naturally released in the rollback. Savepoints which were set after this savepoint are deleted. */ @@ -225,14 +225,14 @@ trx_savepoint_for_mysql( position corresponding to this connection at the time of the savepoint */ - + /*********************************************************************** Releases a named savepoint. Savepoints which were set after this savepoint are deleted. */ ulint trx_release_savepoint_for_mysql( -/*================================*/ +/*============================*/ /* out: if no savepoint of the name found then DB_NO_SAVEPOINT, @@ -303,4 +303,4 @@ struct trx_named_savept_struct{ #include "trx0roll.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h index fd64612ab3f..46ba010bd1d 100644 --- a/storage/innobase/include/trx0rseg.h +++ b/storage/innobase/include/trx0rseg.h @@ -118,13 +118,13 @@ trx_rseg_create( /* The rollback segment memory object */ struct trx_rseg_struct{ /*--------------------------------------------------------*/ - ulint id; /* rollback segment id == the index of + ulint id; /* rollback segment id == the index of its slot in the trx system file copy */ mutex_t mutex; /* mutex protecting the fields in this struct except id; NOTE that the latching order must always be kernel mutex -> rseg mutex */ - ulint space; /* space where the rollback segment is + ulint space; /* space where the rollback segment is header is placed */ ulint page_no;/* page number of the rollback segment header */ @@ -190,4 +190,4 @@ struct trx_rseg_struct{ #include "trx0rseg.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/trx0rseg.ic b/storage/innobase/include/trx0rseg.ic index c9ac50ebf16..4de7a4ab144 100644 --- a/storage/innobase/include/trx0rseg.ic +++ b/storage/innobase/include/trx0rseg.ic @@ -109,7 +109,7 @@ trx_rsegf_undo_find_free( { ulint i; ulint page_no; - + for (i = 0; i < TRX_RSEG_N_SLOTS; i++) { page_no = trx_rsegf_get_nth_undo(rsegf, i, mtr); diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 31e8607f8a0..a8da5cd51a3 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -29,7 +29,7 @@ file name and position here. We have successfully got the updates to InnoDB up to this position. If .._pos is -1, it means no crash recovery was needed, or there was no master log position info inside InnoDB. */ -extern char trx_sys_mysql_master_log_name[]; +extern char trx_sys_mysql_master_log_name[]; extern ib_longlong trx_sys_mysql_master_log_pos; /* If this MySQL server uses binary logging, after InnoDB has been inited @@ -37,7 +37,7 @@ and if it has done a crash recovery, we store the binlog file name and position here. If .._pos is -1, it means there was no binlog position info inside InnoDB. */ -extern char trx_sys_mysql_bin_log_name[]; +extern char trx_sys_mysql_bin_log_name[]; extern ib_longlong trx_sys_mysql_bin_log_pos; /* The transaction system */ @@ -320,7 +320,7 @@ trx_sys_print_mysql_master_log_pos(void); #define TRX_SYS_FSEG_HEADER 8 /* segment header for the tablespace segment the trx system is created into */ -#define TRX_SYS_RSEGS (8 + FSEG_HEADER_SIZE) +#define TRX_SYS_RSEGS (8 + FSEG_HEADER_SIZE) /* the start of the array of rollback segment specification slots */ /*-------------------------------------------------------------*/ @@ -352,10 +352,10 @@ this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */ /* The offset of the doublewrite buffer header on the trx system header page */ #define TRX_SYS_DOUBLEWRITE (UNIV_PAGE_SIZE - 200) /*-------------------------------------------------------------*/ -#define TRX_SYS_DOUBLEWRITE_FSEG 0 /* fseg header of the fseg +#define TRX_SYS_DOUBLEWRITE_FSEG 0 /* fseg header of the fseg containing the doublewrite buffer */ -#define TRX_SYS_DOUBLEWRITE_MAGIC FSEG_HEADER_SIZE +#define TRX_SYS_DOUBLEWRITE_MAGIC FSEG_HEADER_SIZE /* 4-byte magic number which shows if we already have created the doublewrite @@ -390,7 +390,7 @@ this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */ #define TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N 1783657386 -#define TRX_SYS_DOUBLEWRITE_BLOCK_SIZE FSP_EXTENT_SIZE +#define TRX_SYS_DOUBLEWRITE_BLOCK_SIZE FSP_EXTENT_SIZE /* Doublewrite control struct */ struct trx_doublewrite_struct{ @@ -401,7 +401,7 @@ struct trx_doublewrite_struct{ ulint block2; /* page number of the second block */ ulint first_free; /* first free position in write_buf measured in units of UNIV_PAGE_SIZE */ - byte* write_buf; /* write buffer used in writing to the + byte* write_buf; /* write buffer used in writing to the doublewrite buffer, aligned to an address divisible by UNIV_PAGE_SIZE (which is required by Windows aio) */ @@ -450,4 +450,4 @@ page is updated */ #include "trx0sys.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/trx0sys.ic b/storage/innobase/include/trx0sys.ic index 24610bef827..e0653609b36 100644 --- a/storage/innobase/include/trx0sys.ic +++ b/storage/innobase/include/trx0sys.ic @@ -11,12 +11,14 @@ Created 3/26/1996 Heikki Tuuri #include "data0type.h" /* The typedef for rseg slot in the file copy */ -typedef byte trx_sysf_rseg_t; +typedef byte trx_sysf_rseg_t; /* Rollback segment specification slot offsets */ /*-------------------------------------------------------------*/ #define TRX_SYS_RSEG_SPACE 0 /* space where the the segment - header is placed */ + header is placed; starting with + MySQL/InnoDB 5.1.7, this is + UNIV_UNDEFINED if the slot is unused */ #define TRX_SYS_RSEG_PAGE_NO 4 /* page number where the the segment header is placed; this is FIL_NULL if the slot is unused */ @@ -96,7 +98,7 @@ trx_sysf_get( trx_sysf_t* header; ut_ad(mtr); - + header = TRX_SYS + buf_page_get(TRX_SYS_SPACE, TRX_SYS_PAGE_NO, RW_X_LATCH, mtr); @@ -217,7 +219,7 @@ trx_write_trx_id( dulint id) /* in: id */ { ut_ad(DATA_TRX_ID_LEN == 6); - + mach_write_to_6(ptr, id); } @@ -233,7 +235,7 @@ trx_read_trx_id( byte* ptr) /* in: pointer to memory from where to read */ { ut_ad(DATA_TRX_ID_LEN == 6); - + return(mach_read_from_6(ptr)); } @@ -325,8 +327,8 @@ trx_is_active( } trx = trx_get_on_id(trx_id); - if (trx && (trx->conc_state == TRX_ACTIVE || - trx->conc_state == TRX_PREPARED)) { + if (trx && (trx->conc_state == TRX_ACTIVE || + trx->conc_state == TRX_PREPARED)) { return(TRUE); } @@ -354,13 +356,13 @@ trx_sys_get_new_trx_id(void) and the value for trx id will be written to disk-based header! Thus trx id values will not overlap when the database is repeatedly started! */ - + if (ut_dulint_get_low(trx_sys->max_trx_id) % TRX_SYS_TRX_ID_WRITE_MARGIN == 0) { trx_sys_flush_max_trx_id(); } - + id = trx_sys->max_trx_id; UT_DULINT_INC(trx_sys->max_trx_id); diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 0dc82893ad1..4278d602675 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -55,7 +55,7 @@ Releases the search latch if trx has reserved it. */ void trx_search_latch_release_if_reserved( /*=================================*/ - trx_t* trx); /* in: transaction */ + trx_t* trx); /* in: transaction */ /********************************************************************** Set detailed error message for the transaction. */ void @@ -78,8 +78,8 @@ Retrieves the error_info field from a trx. */ void* trx_get_error_info( /*===============*/ - /* out: the error info */ - trx_t* trx); /* in: trx object */ + /* out: the error info */ + trx_t* trx); /* in: trx object */ /******************************************************************** Creates and initializes a transaction object. */ @@ -141,7 +141,7 @@ trx_start( /*======*/ /* out: TRUE if success, FALSE if the rollback segment could not support this many transactions */ - trx_t* trx, /* in: transaction */ + trx_t* trx, /* in: transaction */ ulint rseg_id);/* in: rollback segment id; if ULINT_UNDEFINED is passed, the system chooses the rollback segment automatically in a round-robin fashion */ @@ -152,7 +152,7 @@ ibool trx_start_low( /*==========*/ /* out: TRUE */ - trx_t* trx, /* in: transaction */ + trx_t* trx, /* in: transaction */ ulint rseg_id);/* in: rollback segment id; if ULINT_UNDEFINED is passed, the system chooses the rollback segment automatically in a round-robin fashion */ @@ -207,7 +207,7 @@ Does the transaction prepare for MySQL. */ ulint trx_prepare_for_mysql( -/*=================*/ +/*==================*/ /* out: 0 or error number */ trx_t* trx); /* in: trx handle */ /************************************************************************** @@ -218,7 +218,7 @@ int trx_recover_for_mysql( /*==================*/ /* out: number of prepared transactions */ - XID* xid_list, /* in/out: prepared transactions */ + XID* xid_list, /* in/out: prepared transactions */ ulint len); /* in: number of slots in xid_list */ /*********************************************************************** This function is used to find one X/Open XA distributed transaction @@ -278,7 +278,7 @@ trx_sig_send( que_thr_t* receiver_thr, /* in: query thread which wants the reply, or NULL; if type is TRX_SIG_END_WAIT, this must be NULL */ - trx_savept_t* savept, /* in: possible rollback savepoint, or + trx_savept_t* savept, /* in: possible rollback savepoint, or NULL */ que_thr_t** next_thr); /* in/out: next query thread to run; if the value which is passed in is @@ -357,7 +357,7 @@ trx_print( /*======*/ FILE* f, /* in: output stream */ trx_t* trx, /* in: transaction */ - uint max_query_len); /* in: max query length to print, or 0 to + ulint max_query_len); /* in: max query length to print, or 0 to use the default max length */ #ifndef UNIV_HOTBACKUP @@ -411,9 +411,9 @@ struct trx_struct{ of view of concurrency control: TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY, ... */ - time_t start_time; /* time the trx object was created - or the state last time became - TRX_ACTIVE */ + time_t start_time; /* time the trx object was created + or the state last time became + TRX_ACTIVE */ ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */ ibool check_foreigns; /* normally TRUE, but if the user wants to suppress foreign key checks, @@ -427,8 +427,8 @@ struct trx_struct{ if we can use the insert buffer for them, we set this FALSE */ dulint id; /* transaction id */ - XID xid; /* X/Open XA transaction - identification to identify a + XID xid; /* X/Open XA transaction + identification to identify a transaction branch */ ibool support_xa; /* normally we do the XA two-phase commit steps, but by setting this to @@ -436,7 +436,7 @@ struct trx_struct{ 150 bytes in the undo log size as then we skip XA steps */ dulint no; /* transaction serialization number == - max trx id when the transaction is + max trx id when the transaction is moved to COMMITTED_IN_MEMORY state */ ibool flush_log_later;/* when we commit the transaction in MySQL's binlog write, we will @@ -451,7 +451,7 @@ struct trx_struct{ dulint commit_lsn; /* lsn at the time of the commit */ ibool dict_operation; /* TRUE if the trx is used to create a table, create an index, or drop a - table. This is a hint that the table + table. This is a hint that the table may need to be dropped in crash recovery. */ dulint table_id; /* table id if the preceding field is @@ -459,8 +459,8 @@ struct trx_struct{ /*------------------------------*/ int active_trans; /* 1 - if a transaction in MySQL is active. 2 - if prepare_commit_mutex - was taken */ - void* mysql_thd; /* MySQL thread handle corresponding + was taken */ + void* mysql_thd; /* MySQL thread handle corresponding to this trx, or NULL */ char** mysql_query_str;/* pointer to the field in mysqld_thd which contains the pointer to the @@ -507,17 +507,17 @@ struct trx_struct{ ulint n_mysql_tables_in_use; /* number of Innobase tables used in the processing of the current SQL statement in MySQL */ - ulint mysql_n_tables_locked; - /* how many tables the current SQL + ulint mysql_n_tables_locked; + /* how many tables the current SQL statement uses, except those in consistent read */ ibool dict_operation_lock_mode; /* 0, RW_S_LATCH, or RW_X_LATCH: the latch mode trx currently holds on dict_operation_lock */ - ibool has_search_latch; - /* TRUE if this trx has latched the - search system latch in S-mode */ + ibool has_search_latch; + /* TRUE if this trx has latched the + search system latch in S-mode */ ulint search_latch_timeout; /* If we notice that someone is waiting for our S-lock on the search @@ -538,7 +538,7 @@ struct trx_struct{ /* this can be > 0 only when declared_to_... is TRUE; when we come to srv_conc_innodb_enter, if the value - here is > 0, we decrement this by 1 */ + here is > 0, we decrement this by 1 */ /*------------------------------*/ lock_t* auto_inc_lock; /* possible auto-inc lock reserved by the transaction; note that it is also @@ -570,7 +570,7 @@ struct trx_struct{ duplicate key error, a pointer to the problematic index is stored here */ sess_t* sess; /* session of the trx, NULL if none */ - ulint que_state; /* TRX_QUE_RUNNING, TRX_QUE_LOCK_WAIT, + ulint que_state; /* TRX_QUE_RUNNING, TRX_QUE_LOCK_WAIT, ... */ que_t* graph; /* query currently run in the session, or NULL if none; NOTE that the query @@ -608,7 +608,7 @@ struct trx_struct{ if another transaction chooses this transaction as a victim in deadlock resolution, it sets this to TRUE */ - time_t wait_started; /* lock wait started at this time */ + time_t wait_started; /* lock wait started at this time */ UT_LIST_BASE_NODE_T(que_thr_t) wait_thrs; /* query threads belonging to this trx that are in the QUE_THR_LOCK_WAIT @@ -618,23 +618,23 @@ struct trx_struct{ /*------------------------------*/ mem_heap_t* lock_heap; /* memory heap for the locks of the transaction */ - UT_LIST_BASE_NODE_T(lock_t) + UT_LIST_BASE_NODE_T(lock_t) trx_locks; /* locks reserved by the transaction */ /*------------------------------*/ - mem_heap_t* global_read_view_heap; - /* memory heap for the global read + mem_heap_t* global_read_view_heap; + /* memory heap for the global read view */ read_view_t* global_read_view; /* consistent read view associated to a transaction or NULL */ read_view_t* read_view; /* consistent read view used in the transaction or NULL, this read view - if defined can be normal read view - associated to a transaction (i.e. + if defined can be normal read view + associated to a transaction (i.e. same as global_read_view) or read view associated to a cursor */ /*------------------------------*/ - UT_LIST_BASE_NODE_T(trx_named_savept_t) + UT_LIST_BASE_NODE_T(trx_named_savept_t) trx_savepoints; /* savepoints set with SAVEPOINT ..., oldest first */ /*------------------------------*/ @@ -654,9 +654,9 @@ struct trx_struct{ trx_rseg_t* rseg; /* rollback segment assigned to the transaction, or NULL if not assigned yet */ - trx_undo_t* insert_undo; /* pointer to the insert undo log, or + trx_undo_t* insert_undo; /* pointer to the insert undo log, or NULL if no inserts performed yet */ - trx_undo_t* update_undo; /* pointer to the update undo log, or + trx_undo_t* update_undo; /* pointer to the update undo log, or NULL if no update performed yet */ dulint roll_limit; /* least undo number to undo during a rollback */ @@ -743,7 +743,7 @@ struct trx_struct{ /* Signal states */ #define TRX_SIG_WAITING 1 #define TRX_SIG_BEING_HANDLED 2 - + /* Commit command node in a query graph */ struct commit_node_struct{ que_common_t common; /* node type: QUE_NODE_COMMIT */ @@ -759,4 +759,4 @@ struct commit_node_struct{ #include "trx0trx.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/trx0trx.ic b/storage/innobase/include/trx0trx.ic index 54cf2ff331f..3992225ed8b 100644 --- a/storage/innobase/include/trx0trx.ic +++ b/storage/innobase/include/trx0trx.ic @@ -13,7 +13,7 @@ void trx_start_if_not_started( /*=====================*/ trx_t* trx) /* in: transaction */ -{ +{ ut_ad(trx->conc_state != TRX_COMMITTED_IN_MEMORY); if (trx->conc_state == TRX_NOT_STARTED) { @@ -30,7 +30,7 @@ void trx_start_if_not_started_low( /*=========================*/ trx_t* trx) /* in: transaction */ -{ +{ ut_ad(trx->conc_state != TRX_COMMITTED_IN_MEMORY); if (trx->conc_state == TRX_NOT_STARTED) { @@ -94,5 +94,5 @@ trx_new_rec_locks_contain( dict_index_t* index) /* in: index */ { return(trx->new_rec_locks[0] == index - || trx->new_rec_locks[1] == index); + || trx->new_rec_locks[1] == index); } diff --git a/storage/innobase/include/trx0types.h b/storage/innobase/include/trx0types.h index 2965eb4451f..0e6ee79498c 100644 --- a/storage/innobase/include/trx0types.h +++ b/storage/innobase/include/trx0types.h @@ -42,4 +42,4 @@ typedef byte trx_upagef_t; /* Undo log record */ typedef byte trx_undo_rec_t; -#endif +#endif diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h index bd7337e4f90..83f022cc2c5 100644 --- a/storage/innobase/include/trx0undo.h +++ b/storage/innobase/include/trx0undo.h @@ -71,7 +71,7 @@ Gets an undo log page and x-latches it. */ UNIV_INLINE page_t* trx_undo_page_get( -/*===============*/ +/*==============*/ /* out: pointer to page x-latched */ ulint space, /* in: space where placed */ ulint page_no, /* in: page number */ @@ -81,7 +81,7 @@ Gets an undo log page and s-latches it. */ UNIV_INLINE page_t* trx_undo_page_get_s_latched( -/*=========================*/ +/*========================*/ /* out: pointer to page s-latched */ ulint space, /* in: space where placed */ ulint page_no, /* in: page number */ @@ -162,7 +162,7 @@ trx_undo_get_first_rec( /*===================*/ /* out: undo log record, the page latched, NULL if none */ - ulint space, /* in: undo log header space */ + ulint space, /* in: undo log header space */ ulint page_no,/* in: undo log header page number */ ulint offset, /* in: undo log header offset on page */ ulint mode, /* in: latching mode: RW_S_LATCH or RW_X_LATCH */ @@ -217,7 +217,7 @@ trx_undo_lists_init( /*================*/ /* out: the combined size of undo log segments in pages */ - trx_rseg_t* rseg); /* in: rollback segment memory object */ + trx_rseg_t* rseg); /* in: rollback segment memory object */ /************************************************************************** Assigns an undo log for a transaction. A new undo log is created or a cached undo log reused. */ @@ -278,7 +278,7 @@ Parses the redo log entry of an undo log page initialization. */ byte* trx_undo_parse_page_init( -/*======================*/ +/*=====================*/ /* out: end of log record or NULL */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ @@ -322,7 +322,7 @@ trx_undo_parse_discard_latest( #define TRX_UNDO_TO_PURGE 4 /* update undo segment will not be reused: it can be freed in purge when all undo data in it is removed */ -#define TRX_UNDO_PREPARED 5 /* contains an undo log of an +#define TRX_UNDO_PREPARED 5 /* contains an undo log of an prepared transaction */ /* Transaction undo log memory object; this is protected by the undo_mutex @@ -346,7 +346,7 @@ struct trx_undo_struct{ field */ dulint trx_id; /* id of the trx assigned to the undo log */ - XID xid; /* X/Open XA transaction + XID xid; /* X/Open XA transaction identification */ ibool dict_operation; /* TRUE if a dict operation trx */ dulint table_id; /* if a dict operation, then the table @@ -482,7 +482,7 @@ is not needed by the user. The XID wastes about 150 bytes of space in every undo log. In the history list we may have millions of undo logs, which means quite a large overhead. */ -/* X/Open XA Transaction Identification (XID) */ +/* X/Open XA Transaction Identification (XID) */ #define TRX_UNDO_XA_FORMAT (TRX_UNDO_LOG_OLD_HDR_SIZE) #define TRX_UNDO_XA_TRID_LEN (TRX_UNDO_XA_FORMAT + 4) @@ -496,4 +496,4 @@ quite a large overhead. */ #include "trx0undo.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/trx0undo.ic b/storage/innobase/include/trx0undo.ic index a04b234b495..1678b292590 100644 --- a/storage/innobase/include/trx0undo.ic +++ b/storage/innobase/include/trx0undo.ic @@ -20,7 +20,9 @@ trx_undo_build_roll_ptr( ulint page_no, /* in: page number */ ulint offset) /* in: offset of the undo entry within page */ { - ut_ad(DATA_ROLL_PTR_LEN == 7); +#if DATA_ROLL_PTR_LEN != 7 +# error "DATA_ROLL_PTR_LEN != 7" +#endif ut_ad(rseg_id < 128); return(ut_dulint_create(is_insert * 128 * 256 * 256 @@ -44,13 +46,15 @@ trx_undo_decode_roll_ptr( { ulint low; ulint high; - - ut_ad(DATA_ROLL_PTR_LEN == 7); - ut_ad(TRUE == 1); - +#if DATA_ROLL_PTR_LEN != 7 +# error "DATA_ROLL_PTR_LEN != 7" +#endif +#if TRUE != 1 +# error "TRUE != 1" +#endif high = ut_dulint_get_high(roll_ptr); low = ut_dulint_get_low(roll_ptr); - + *offset = low % (256 * 256); *is_insert = high / (256 * 256 * 128); /* TRUE == 1 */ @@ -70,12 +74,14 @@ trx_undo_roll_ptr_is_insert( dulint roll_ptr) /* in: roll pointer */ { ulint high; - - ut_ad(DATA_ROLL_PTR_LEN == 7); - ut_ad(TRUE == 1); - +#if DATA_ROLL_PTR_LEN != 7 +# error "DATA_ROLL_PTR_LEN != 7" +#endif +#if TRUE != 1 +# error "TRUE != 1" +#endif high = ut_dulint_get_high(roll_ptr); - + return(high / (256 * 256 * 128)); } @@ -91,7 +97,7 @@ trx_write_roll_ptr( dulint roll_ptr) /* in: roll ptr */ { ut_ad(DATA_ROLL_PTR_LEN == 7); - + mach_write_to_7(ptr, roll_ptr); } @@ -106,8 +112,9 @@ trx_read_roll_ptr( /* out: roll ptr */ byte* ptr) /* in: pointer to memory from where to read */ { - ut_ad(DATA_ROLL_PTR_LEN == 7); - +#if DATA_ROLL_PTR_LEN != 7 +# error "DATA_ROLL_PTR_LEN != 7" +#endif return(mach_read_from_7(ptr)); } @@ -116,14 +123,14 @@ Gets an undo log page and x-latches it. */ UNIV_INLINE page_t* trx_undo_page_get( -/*===============*/ +/*==============*/ /* out: pointer to page x-latched */ ulint space, /* in: space where placed */ ulint page_no, /* in: page number */ mtr_t* mtr) /* in: mtr */ { page_t* page; - + page = buf_page_get(space, page_no, RW_X_LATCH, mtr); #ifdef UNIV_SYNC_DEBUG @@ -138,14 +145,14 @@ Gets an undo log page and s-latches it. */ UNIV_INLINE page_t* trx_undo_page_get_s_latched( -/*=========================*/ +/*========================*/ /* out: pointer to page s-latched */ ulint space, /* in: space where placed */ ulint page_no, /* in: page number */ mtr_t* mtr) /* in: mtr */ { page_t* page; - + page = buf_page_get(space, page_no, RW_S_LATCH, mtr); #ifdef UNIV_SYNC_DEBUG @@ -168,7 +175,7 @@ trx_undo_page_get_start( ulint offset) /* in: undo log header offset on page */ { ulint start; - + if (page_no == buf_frame_get_page_no(undo_page)) { start = mach_read_from_2(offset + undo_page @@ -194,7 +201,7 @@ trx_undo_page_get_end( { trx_ulogf_t* log_hdr; ulint end; - + if (page_no == buf_frame_get_page_no(undo_page)) { log_hdr = undo_page + offset; @@ -259,14 +266,14 @@ trx_undo_page_get_next_rec( undo_page = buf_frame_align(rec); end = trx_undo_page_get_end(undo_page, page_no, offset); - + next = mach_read_from_2(rec); if (next == end) { return(NULL); } - + return(undo_page + next); } @@ -285,9 +292,9 @@ trx_undo_page_get_last_rec( ulint start; ulint end; - start = trx_undo_page_get_start(undo_page, page_no, offset); - end = trx_undo_page_get_end(undo_page, page_no, offset); - + start = trx_undo_page_get_start(undo_page, page_no, offset); + end = trx_undo_page_get_end(undo_page, page_no, offset); + if (start == end) { return(NULL); @@ -311,9 +318,9 @@ trx_undo_page_get_first_rec( ulint start; ulint end; - start = trx_undo_page_get_start(undo_page, page_no, offset); - end = trx_undo_page_get_end(undo_page, page_no, offset); - + start = trx_undo_page_get_start(undo_page, page_no, offset); + end = trx_undo_page_get_end(undo_page, page_no, offset); + if (start == end) { return(NULL); diff --git a/storage/innobase/include/trx0xa.h b/storage/innobase/include/trx0xa.h index 34b7a2f95a8..e90ce47ffcf 100644 --- a/storage/innobase/include/trx0xa.h +++ b/storage/innobase/include/trx0xa.h @@ -52,27 +52,27 @@ struct xa_switch_t { long flags; /* resource manager specific options */ long version; /* must be 0 */ int (*xa_open_entry) /* xa_open function pointer */ - __P((char *, int, long)); + __P((char *, int, long)); int (*xa_close_entry) /* xa_close function pointer */ - __P((char *, int, long)); + __P((char *, int, long)); int (*xa_start_entry) /* xa_start function pointer */ - __P((XID *, int, long)); + __P((XID *, int, long)); int (*xa_end_entry) /* xa_end function pointer */ - __P((XID *, int, long)); + __P((XID *, int, long)); int (*xa_rollback_entry) /* xa_rollback function pointer */ - __P((XID *, int, long)); + __P((XID *, int, long)); int (*xa_prepare_entry) /* xa_prepare function pointer */ - __P((XID *, int, long)); + __P((XID *, int, long)); int (*xa_commit_entry) /* xa_commit function pointer */ - __P((XID *, int, long)); + __P((XID *, int, long)); int (*xa_recover_entry) /* xa_recover function pointer */ - __P((XID *, long, int, long)); + __P((XID *, long, int, long)); int (*xa_forget_entry) /* xa_forget function pointer */ - __P((XID *, int, long)); + __P((XID *, int, long)); int (*xa_complete_entry) /* xa_complete function pointer */ - __P((int *, int *, int, long)); + __P((int *, int *, int, long)); }; -#endif /* NOTDEFINED */ +#endif /* NOTDEFINED */ /* diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index dd4862b3808..7b021087163 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -163,7 +163,7 @@ management to ensure correct alignment for doubles etc. */ #define UNIV_PAGE_SIZE (2 * 8192) /* NOTE! Currently, this has to be a power of 2 */ /* The 2-logarithm of UNIV_PAGE_SIZE: */ -#define UNIV_PAGE_SIZE_SHIFT 14 +#define UNIV_PAGE_SIZE_SHIFT 14 /* Maximum number of parallel threads in a parallelized operation */ #define UNIV_MAX_PARALLELISM 32 @@ -232,7 +232,7 @@ of a field is a 32-bit integer when we store it, for example, to an undo log on disk, we must have also this number fit in 32 bits, also in 64-bit computers! */ -#define UNIV_SQL_NULL ULINT32_UNDEFINED +#define UNIV_SQL_NULL ULINT32_UNDEFINED /* Lengths which are not UNIV_SQL_NULL, but bigger than the following number indicate that a field contains a reference to an externally @@ -265,6 +265,9 @@ it is read or written. */ /* Tell the compiler that cond is unlikely to hold */ #define UNIV_UNLIKELY(cond) UNIV_EXPECT(cond, FALSE) +/* Compile-time constant of the given array's size. */ +#define UT_ARR_SIZE(a) (sizeof(a) / sizeof((a)[0])) + #include <stdio.h> #include "ut0dbg.h" #include "ut0ut.h" diff --git a/storage/innobase/include/usr0sess.h b/storage/innobase/include/usr0sess.h index c7bcfb20fed..3ed1ea21a4d 100644 --- a/storage/innobase/include/usr0sess.h +++ b/storage/innobase/include/usr0sess.h @@ -58,4 +58,4 @@ struct sess_struct{ #include "usr0sess.ic" #endif -#endif +#endif diff --git a/storage/innobase/include/usr0types.h b/storage/innobase/include/usr0types.h index 29359425169..311471c1a0e 100644 --- a/storage/innobase/include/usr0types.h +++ b/storage/innobase/include/usr0types.h @@ -11,4 +11,4 @@ Created 6/25/1996 Heikki Tuuri typedef struct sess_struct sess_t; -#endif +#endif diff --git a/storage/innobase/include/ut0byte.h b/storage/innobase/include/ut0byte.h index 22d488abeaf..6533f1166ca 100644 --- a/storage/innobase/include/ut0byte.h +++ b/storage/innobase/include/ut0byte.h @@ -78,7 +78,7 @@ int ut_dulint_cmp( /*==========*/ /* out: -1 if a < b, 0 if a == b, - 1 if a > b */ + 1 if a > b */ dulint a, /* in: dulint */ dulint b); /* in: dulint */ /*********************************************************** @@ -135,8 +135,8 @@ dulint ut_dulint_align_down( /*=================*/ /* out: rounded value */ - dulint n, /* in: number to be rounded */ - ulint align_no); /* in: align by this number which must be a + dulint n, /* in: number to be rounded */ + ulint align_no); /* in: align by this number which must be a power of 2 */ /************************************************************ Rounds a dulint upward to a multiple of a power of 2. */ @@ -145,8 +145,8 @@ dulint ut_dulint_align_up( /*===============*/ /* out: rounded value */ - dulint n, /* in: number to be rounded */ - ulint align_no); /* in: align by this number which must be a + dulint n, /* in: number to be rounded */ + ulint align_no); /* in: align by this number which must be a power of 2 */ /*********************************************************** Increments a dulint variable by 1. */ @@ -177,8 +177,8 @@ ulint ut_calc_align( /*==========*/ /* out: rounded value */ - ulint n, /* in: number to be rounded */ - ulint align_no); /* in: align by this number */ + ulint n, /* in: number to be rounded */ + ulint align_no); /* in: align by this number */ /************************************************************ The following function calculates the value of an integer n rounded to the biggest product of align_no which is <= n. align_no has to be a @@ -188,8 +188,8 @@ ulint ut_calc_align_down( /*===============*/ /* out: rounded value */ - ulint n, /* in: number to be rounded */ - ulint align_no); /* in: align by this number */ + ulint n, /* in: number to be rounded */ + ulint align_no); /* in: align by this number */ /************************************************************* The following function rounds up a pointer to the nearest aligned address. */ UNIV_INLINE @@ -197,8 +197,8 @@ void* ut_align( /*=====*/ /* out: aligned pointer */ - void* ptr, /* in: pointer */ - ulint align_no); /* in: align by this number */ + void* ptr, /* in: pointer */ + ulint align_no); /* in: align by this number */ /************************************************************* The following function rounds down a pointer to the nearest aligned address. */ @@ -207,8 +207,8 @@ void* ut_align_down( /*==========*/ /* out: aligned pointer */ - void* ptr, /* in: pointer */ - ulint align_no) /* in: align by this number */ + void* ptr, /* in: pointer */ + ulint align_no) /* in: align by this number */ __attribute__((const)); /************************************************************* The following function computes the offset of a pointer from the nearest @@ -216,7 +216,7 @@ aligned address. */ UNIV_INLINE ulint ut_align_offset( -/*==========*/ +/*============*/ /* out: distance from aligned pointer */ const void* ptr, /* in: pointer */ diff --git a/storage/innobase/include/ut0byte.ic b/storage/innobase/include/ut0byte.ic index e141de3aa3f..9829b3a2c46 100644 --- a/storage/innobase/include/ut0byte.ic +++ b/storage/innobase/include/ut0byte.ic @@ -22,7 +22,7 @@ ut_dulint_create( ut_ad(low <= 0xFFFFFFFF); res.high = high; - res.low = low; + res.low = low; return(res); } @@ -89,7 +89,7 @@ int ut_dulint_cmp( /*==========*/ /* out: -1 if a < b, 0 if a == b, - 1 if a > b */ + 1 if a > b */ dulint a, /* in: dulint */ dulint b) /* in: dulint */ { @@ -186,7 +186,7 @@ ut_dulint_subtract( a.low = 0xFFFFFFFFUL - b; ut_ad(a.high > 0); - + a.high--; return(a); @@ -218,9 +218,9 @@ ut_dulint_minus( diff += 1 + a.low; ut_ad(diff > a.low); - + return(diff); -} +} /************************************************************ Rounds a dulint downward to a multiple of a power of 2. */ @@ -229,8 +229,8 @@ dulint ut_dulint_align_down( /*=================*/ /* out: rounded value */ - dulint n, /* in: number to be rounded */ - ulint align_no) /* in: align by this number which must be a + dulint n, /* in: number to be rounded */ + ulint align_no) /* in: align by this number which must be a power of 2 */ { ulint low, high; @@ -240,7 +240,7 @@ ut_dulint_align_down( low = ut_dulint_get_low(n); high = ut_dulint_get_high(n); - + low = low & ~(align_no - 1); return(ut_dulint_create(high, low)); @@ -253,8 +253,8 @@ dulint ut_dulint_align_up( /*===============*/ /* out: rounded value */ - dulint n, /* in: number to be rounded */ - ulint align_no) /* in: align by this number which must be a + dulint n, /* in: number to be rounded */ + ulint align_no) /* in: align by this number which must be a power of 2 */ { return(ut_dulint_align_down(ut_dulint_add(n, align_no - 1), align_no)); @@ -269,8 +269,8 @@ ulint ut_calc_align( /*==========*/ /* out: rounded value */ - ulint n, /* in: number to be rounded */ - ulint align_no) /* in: align by this number */ + ulint n, /* in: number to be rounded */ + ulint align_no) /* in: align by this number */ { ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); @@ -285,8 +285,8 @@ void* ut_align( /*=====*/ /* out: aligned pointer */ - void* ptr, /* in: pointer */ - ulint align_no) /* in: align by this number */ + void* ptr, /* in: pointer */ + ulint align_no) /* in: align by this number */ { ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); @@ -306,8 +306,8 @@ ulint ut_calc_align_down( /*===============*/ /* out: rounded value */ - ulint n, /* in: number to be rounded */ - ulint align_no) /* in: align by this number */ + ulint n, /* in: number to be rounded */ + ulint align_no) /* in: align by this number */ { ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); @@ -323,8 +323,8 @@ void* ut_align_down( /*==========*/ /* out: aligned pointer */ - void* ptr, /* in: pointer */ - ulint align_no) /* in: align by this number */ + void* ptr, /* in: pointer */ + ulint align_no) /* in: align by this number */ { ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); @@ -344,8 +344,8 @@ ut_align_offset( /*============*/ /* out: distance from aligned pointer */ - const void* ptr, /* in: pointer */ - ulint align_no) /* in: align by this number */ + const void* ptr, /* in: pointer */ + ulint align_no) /* in: align by this number */ { ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); @@ -368,8 +368,9 @@ ut_bit_get_nth( ulint n) /* in: nth bit requested */ { ut_ad(n < 8 * sizeof(ulint)); - ut_ad(TRUE == 1); - +#if TRUE != 1 +# error "TRUE != 1" +#endif return(1 & (a >> n)); } @@ -385,8 +386,9 @@ ut_bit_set_nth( ibool val) /* in: value for the bit to set */ { ut_ad(n < 8 * sizeof(ulint)); - ut_ad(TRUE == 1); - +#if TRUE != 1 +# error "TRUE != 1" +#endif if (val) { return((1 << n) | a); } else { diff --git a/storage/innobase/include/ut0dbg.h b/storage/innobase/include/ut0dbg.h index bc3f852626a..55e8c8ef88c 100644 --- a/storage/innobase/include/ut0dbg.h +++ b/storage/innobase/include/ut0dbg.h @@ -74,7 +74,7 @@ ut_dbg_stop_thread( __FILE__, (ulint) __LINE__); \ UT_DBG_PANIC; \ } \ - UT_DBG_STOP; \ + UT_DBG_STOP; \ } while (0) /* Abort execution. */ @@ -84,7 +84,7 @@ ut_dbg_stop_thread( } while (0) #ifdef UNIV_DEBUG -#define ut_ad(EXPR) ut_a(EXPR) +#define ut_ad(EXPR) ut_a(EXPR) #define ut_d(EXPR) do {EXPR;} while (0) #else #define ut_ad(EXPR) diff --git a/storage/innobase/include/ut0lst.h b/storage/innobase/include/ut0lst.h index d290c476963..819f2e770ba 100644 --- a/storage/innobase/include/ut0lst.h +++ b/storage/innobase/include/ut0lst.h @@ -192,9 +192,9 @@ TYPE is the node type, and BASE is the base node (not a pointer to it). */ ut_list_node_313 = (BASE).start;\ \ for (ut_list_i_313 = 0; ut_list_i_313 < (BASE).count;\ - ut_list_i_313++) {\ - ut_a(ut_list_node_313);\ - ut_list_node_313 = (ut_list_node_313->NAME).next;\ + ut_list_i_313++) {\ + ut_a(ut_list_node_313);\ + ut_list_node_313 = (ut_list_node_313->NAME).next;\ }\ \ ut_a(ut_list_node_313 == NULL);\ @@ -202,14 +202,14 @@ TYPE is the node type, and BASE is the base node (not a pointer to it). */ ut_list_node_313 = (BASE).end;\ \ for (ut_list_i_313 = 0; ut_list_i_313 < (BASE).count;\ - ut_list_i_313++) {\ - ut_a(ut_list_node_313);\ - ut_list_node_313 = (ut_list_node_313->NAME).prev;\ + ut_list_i_313++) {\ + ut_a(ut_list_node_313);\ + ut_list_node_313 = (ut_list_node_313->NAME).prev;\ }\ \ ut_a(ut_list_node_313 == NULL);\ }\ - + #endif diff --git a/storage/innobase/include/ut0mem.h b/storage/innobase/include/ut0mem.h index b9bbe0b5c92..6e4a265349f 100644 --- a/storage/innobase/include/ut0mem.h +++ b/storage/innobase/include/ut0mem.h @@ -36,12 +36,13 @@ defined and set_to_zero is TRUE. */ void* ut_malloc_low( /*==========*/ - /* out, own: allocated memory */ - ulint n, /* in: number of bytes to allocate */ - ibool set_to_zero, /* in: TRUE if allocated memory should be set - to zero if UNIV_SET_MEM_TO_ZERO is defined */ - ibool assert_on_error); /* in: if TRUE, we crash mysqld if the memory - cannot be allocated */ + /* out, own: allocated memory */ + ulint n, /* in: number of bytes to allocate */ + ibool set_to_zero, /* in: TRUE if allocated memory + should be set to zero if + UNIV_SET_MEM_TO_ZERO is defined */ + ibool assert_on_error); /* in: if TRUE, we crash mysqld if + the memory cannot be allocated */ /************************************************************************** Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is defined. */ @@ -49,8 +50,8 @@ defined. */ void* ut_malloc( /*======*/ - /* out, own: allocated memory */ - ulint n); /* in: number of bytes to allocate */ + /* out, own: allocated memory */ + ulint n); /* in: number of bytes to allocate */ /************************************************************************** Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs out. It cannot be used if we want to return an error message. Prints to @@ -78,10 +79,10 @@ man realloc in Linux, 2004: realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated mem - ory will be uninitialized. If ptr is NULL, the call is + ory will be uninitialized. If ptr is NULL, the call is equivalent to malloc(size); if size is equal to zero, the - call is equivalent to free(ptr). Unless ptr is NULL, it - must have been returned by an earlier call to malloc(), + call is equivalent to free(ptr). Unless ptr is NULL, it + must have been returned by an earlier call to malloc(), calloc() or realloc(). RETURN VALUE @@ -89,8 +90,8 @@ RETURN VALUE which is suitably aligned for any kind of variable and may be different from ptr, or NULL if the request fails. If size was equal to 0, either NULL or a pointer suitable to - be passed to free() is returned. If realloc() fails the - original block is left untouched - it is not freed or + be passed to free() is returned. If realloc() fails the + original block is left untouched - it is not freed or moved. */ void* @@ -154,7 +155,7 @@ ut_strlenq( char q); /* in: the quote character */ /************************************************************************** -Make a quoted copy of a NUL-terminated string. Leading and trailing +Make a quoted copy of a NUL-terminated string. Leading and trailing quotes will not be included; only embedded quotes will be escaped. See also ut_strlenq() and ut_memcpyq(). */ diff --git a/storage/innobase/include/ut0mem.ic b/storage/innobase/include/ut0mem.ic index 76c721112a0..e0253ebf618 100644 --- a/storage/innobase/include/ut0mem.ic +++ b/storage/innobase/include/ut0mem.ic @@ -10,7 +10,7 @@ UNIV_INLINE void* ut_memcpy(void* dest, const void* sour, ulint n) { - return(memcpy(dest, sour, n)); + return(memcpy(dest, sour, n)); } UNIV_INLINE diff --git a/storage/innobase/include/ut0rnd.h b/storage/innobase/include/ut0rnd.h index aeec5d2f6eb..3f3fce1075c 100644 --- a/storage/innobase/include/ut0rnd.h +++ b/storage/innobase/include/ut0rnd.h @@ -15,7 +15,7 @@ Created 1/20/1994 Heikki Tuuri /* The 'character code' for end of field or string (used in folding records */ -#define UT_END_OF_FIELD 257 +#define UT_END_OF_FIELD 257 /************************************************************ This is used to set the random number seed. */ @@ -23,7 +23,7 @@ UNIV_INLINE void ut_rnd_set_seed( /*============*/ - ulint seed); /* in: seed */ + ulint seed); /* in: seed */ /************************************************************ The following function generates a series of 'random' ulint integers. */ UNIV_INLINE @@ -65,10 +65,10 @@ random number to work reliably. */ UNIV_INLINE ulint ut_hash_ulint( -/*=========*/ +/*==========*/ /* out: hash value */ - ulint key, /* in: value to be hashed */ - ulint table_size); /* in: hash table size */ + ulint key, /* in: value to be hashed */ + ulint table_size); /* in: hash table size */ /***************************************************************** Folds a pair of ulints. */ UNIV_INLINE @@ -93,7 +93,7 @@ ulint ut_fold_string( /*===========*/ /* out: folded value */ - const char* str); /* in: null-terminated string */ + const char* str); /* in: null-terminated string */ /***************************************************************** Folds a binary string. */ UNIV_INLINE @@ -111,7 +111,7 @@ ulint ut_find_prime( /*==========*/ /* out: prime */ - ulint n); /* in: positive number > 100 */ + ulint n); /* in: positive number > 100 */ #ifndef UNIV_NONINL diff --git a/storage/innobase/include/ut0rnd.ic b/storage/innobase/include/ut0rnd.ic index d2ab087d491..455007c7d9b 100644 --- a/storage/innobase/include/ut0rnd.ic +++ b/storage/innobase/include/ut0rnd.ic @@ -6,19 +6,19 @@ Random numbers and hashing Created 5/30/1994 Heikki Tuuri *******************************************************************/ -#define UT_HASH_RANDOM_MASK 1463735687 -#define UT_HASH_RANDOM_MASK2 1653893711 -#define UT_RND1 151117737 -#define UT_RND2 119785373 -#define UT_RND3 85689495 -#define UT_RND4 76595339 -#define UT_SUM_RND2 98781234 -#define UT_SUM_RND3 126792457 -#define UT_SUM_RND4 63498502 -#define UT_XOR_RND1 187678878 -#define UT_XOR_RND2 143537923 - -extern ulint ut_rnd_ulint_counter; +#define UT_HASH_RANDOM_MASK 1463735687 +#define UT_HASH_RANDOM_MASK2 1653893711 +#define UT_RND1 151117737 +#define UT_RND2 119785373 +#define UT_RND3 85689495 +#define UT_RND4 76595339 +#define UT_SUM_RND2 98781234 +#define UT_SUM_RND3 126792457 +#define UT_SUM_RND4 63498502 +#define UT_XOR_RND1 187678878 +#define UT_XOR_RND2 143537923 + +extern ulint ut_rnd_ulint_counter; /************************************************************ This is used to set the random number seed. */ @@ -26,7 +26,7 @@ UNIV_INLINE void ut_rnd_set_seed( /*============*/ - ulint seed) /* in: seed */ + ulint seed) /* in: seed */ { ut_rnd_ulint_counter = seed; } @@ -66,7 +66,7 @@ ut_rnd_gen_ulint(void) /*==================*/ /* out: the 'random' number */ { - ulint rnd; + ulint rnd; ulint n_bits; n_bits = 8 * sizeof(ulint); @@ -111,7 +111,7 @@ ut_rnd_gen_ibool(void) /*=================*/ /* out: the random value */ { - ulint x; + ulint x; x = ut_rnd_gen_ulint(); @@ -121,7 +121,7 @@ ut_rnd_gen_ibool(void) } return(FALSE); -} +} /*********************************************************** The following function generates a hash value for a ulint integer @@ -130,10 +130,10 @@ or some random number for the hash table to work reliably. */ UNIV_INLINE ulint ut_hash_ulint( -/*=========*/ +/*==========*/ /* out: hash value */ - ulint key, /* in: value to be hashed */ - ulint table_size) /* in: hash table size */ + ulint key, /* in: value to be hashed */ + ulint table_size) /* in: hash table size */ { key = key ^ UT_HASH_RANDOM_MASK2; @@ -152,7 +152,7 @@ ut_fold_ulint_pair( { return(((((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1) ^ UT_HASH_RANDOM_MASK) + n2); -} +} /***************************************************************** Folds a dulint. */ @@ -165,7 +165,7 @@ ut_fold_dulint( { return(ut_fold_ulint_pair(ut_dulint_get_low(d), ut_dulint_get_high(d))); -} +} /***************************************************************** Folds a character string ending in the null character. */ @@ -174,7 +174,7 @@ ulint ut_fold_string( /*===========*/ /* out: folded value */ - const char* str) /* in: null-terminated string */ + const char* str) /* in: null-terminated string */ { #ifdef UNIV_DEBUG ulint i = 0; @@ -196,7 +196,7 @@ ut_fold_string( return(fold); } - + /***************************************************************** Folds a binary string. */ UNIV_INLINE diff --git a/storage/innobase/include/ut0sort.h b/storage/innobase/include/ut0sort.h index d0a3d34e79e..87d30dee6f2 100644 --- a/storage/innobase/include/ut0sort.h +++ b/storage/innobase/include/ut0sort.h @@ -40,20 +40,20 @@ see test program in tsut.c. */ ulint ut_sort_low77;\ ulint ut_sort_high77;\ \ - ut_ad((LOW) < (HIGH));\ - ut_ad(ARR);\ - ut_ad(AUX_ARR);\ + ut_ad((LOW) < (HIGH));\ + ut_ad(ARR);\ + ut_ad(AUX_ARR);\ \ - if ((LOW) == (HIGH) - 1) {\ - return;\ - } else if ((LOW) == (HIGH) - 2) {\ - if (CMP_FUN((ARR)[LOW], (ARR)[(HIGH) - 1]) > 0) {\ - (AUX_ARR)[LOW] = (ARR)[LOW];\ - (ARR)[LOW] = (ARR)[(HIGH) - 1];\ - (ARR)[(HIGH) - 1] = (AUX_ARR)[LOW];\ - }\ - return;\ - }\ + if ((LOW) == (HIGH) - 1) {\ + return;\ + } else if ((LOW) == (HIGH) - 2) {\ + if (CMP_FUN((ARR)[LOW], (ARR)[(HIGH) - 1]) > 0) {\ + (AUX_ARR)[LOW] = (ARR)[LOW];\ + (ARR)[LOW] = (ARR)[(HIGH) - 1];\ + (ARR)[(HIGH) - 1] = (AUX_ARR)[LOW];\ + }\ + return;\ + }\ \ ut_sort_mid77 = ((LOW) + (HIGH)) / 2;\ \ @@ -63,29 +63,29 @@ see test program in tsut.c. */ ut_sort_low77 = (LOW);\ ut_sort_high77 = ut_sort_mid77;\ \ - for (ut_sort_i77 = (LOW); ut_sort_i77 < (HIGH); ut_sort_i77++) {\ + for (ut_sort_i77 = (LOW); ut_sort_i77 < (HIGH); ut_sort_i77++) {\ \ - if (ut_sort_low77 >= ut_sort_mid77) {\ - (AUX_ARR)[ut_sort_i77] = (ARR)[ut_sort_high77];\ - ut_sort_high77++;\ - } else if (ut_sort_high77 >= (HIGH)) {\ - (AUX_ARR)[ut_sort_i77] = (ARR)[ut_sort_low77];\ - ut_sort_low77++;\ - } else if (CMP_FUN((ARR)[ut_sort_low77],\ + if (ut_sort_low77 >= ut_sort_mid77) {\ + (AUX_ARR)[ut_sort_i77] = (ARR)[ut_sort_high77];\ + ut_sort_high77++;\ + } else if (ut_sort_high77 >= (HIGH)) {\ + (AUX_ARR)[ut_sort_i77] = (ARR)[ut_sort_low77];\ + ut_sort_low77++;\ + } else if (CMP_FUN((ARR)[ut_sort_low77],\ (ARR)[ut_sort_high77]) > 0) {\ - (AUX_ARR)[ut_sort_i77] = (ARR)[ut_sort_high77];\ - ut_sort_high77++;\ + (AUX_ARR)[ut_sort_i77] = (ARR)[ut_sort_high77];\ + ut_sort_high77++;\ } else {\ - (AUX_ARR)[ut_sort_i77] = (ARR)[ut_sort_low77];\ - ut_sort_low77++;\ + (AUX_ARR)[ut_sort_i77] = (ARR)[ut_sort_low77];\ + ut_sort_low77++;\ }\ }\ \ - for (ut_sort_i77 = (LOW); ut_sort_i77 < (HIGH); ut_sort_i77++) {\ - (ARR)[ut_sort_i77] = (AUX_ARR)[ut_sort_i77];\ - }\ + for (ut_sort_i77 = (LOW); ut_sort_i77 < (HIGH); ut_sort_i77++) {\ + (ARR)[ut_sort_i77] = (AUX_ARR)[ut_sort_i77];\ + }\ }\ - + #endif diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index 8938957cd12..8f1be212fbf 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -34,8 +34,8 @@ ulint ut_min( /*===*/ /* out: minimum */ - ulint n1, /* in: first number */ - ulint n2); /* in: second number */ + ulint n1, /* in: first number */ + ulint n2); /* in: second number */ /********************************************************** Calculates the maximum of two ulints. */ UNIV_INLINE @@ -43,8 +43,8 @@ ulint ut_max( /*===*/ /* out: maximum */ - ulint n1, /* in: first number */ - ulint n2); /* in: second number */ + ulint n1, /* in: first number */ + ulint n2); /* in: second number */ /******************************************************************** Calculates minimum of two ulint-pairs. */ UNIV_INLINE @@ -73,7 +73,7 @@ int ut_pair_cmp( /*========*/ /* out: -1 if a < b, 0 if a == b, - 1 if a > b */ + 1 if a > b */ ulint a1, /* in: more significant part of first pair */ ulint a2, /* in: less significant part of first pair */ ulint b1, /* in: more significant part of second pair */ @@ -202,7 +202,7 @@ void ut_print_buf( /*=========*/ FILE* file, /* in: file where to print */ - const byte* buf, /* in: memory buffer */ + const void* buf, /* in: memory buffer */ ulint len); /* in: length of the buffer */ /************************************************************************** @@ -231,7 +231,7 @@ Outputs a fixed-length string, quoted as an SQL identifier. */ void ut_print_namel( -/*==========*/ +/*===========*/ FILE* f, /* in: output stream */ struct trx_struct*trx, /* in: transaction (NULL=no quotes) */ const char* name, /* in: name to print */ diff --git a/storage/innobase/include/ut0ut.ic b/storage/innobase/include/ut0ut.ic index 9a0ef1c0d5b..7b080216117 100644 --- a/storage/innobase/include/ut0ut.ic +++ b/storage/innobase/include/ut0ut.ic @@ -13,8 +13,8 @@ ulint ut_min( /*===*/ /* out: minimum */ - ulint n1, /* in: first number */ - ulint n2) /* in: second number */ + ulint n1, /* in: first number */ + ulint n2) /* in: second number */ { return((n1 <= n2) ? n1 : n2); } @@ -26,8 +26,8 @@ ulint ut_max( /*===*/ /* out: maximum */ - ulint n1, /* in: first number */ - ulint n2) /* in: second number */ + ulint n1, /* in: first number */ + ulint n2) /* in: second number */ { return((n1 <= n2) ? n2 : n1); } @@ -44,7 +44,7 @@ ut_pair_min( ulint b1, /* in: less significant part of first pair */ ulint a2, /* in: more significant part of second pair */ ulint b2) /* in: less significant part of second pair */ -{ +{ if (a1 == a2) { *a = a1; *b = ut_min(b1, b2); @@ -82,7 +82,7 @@ UNIV_INLINE int ut_pair_cmp( /*========*/ - /* out: -1 if a < b, 0 if a == b, 1 if a > b */ + /* out: -1 if a < b, 0 if a == b, 1 if a > b */ ulint a1, /* in: more significant part of first pair */ ulint a2, /* in: less significant part of first pair */ ulint b1, /* in: more significant part of second pair */ diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index a3d388f981d..1152e0c89ea 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -64,7 +64,7 @@ bitmap */ /* An explicit record lock affects both the record and the gap before it. An implicit x-lock does not affect the gap, it only locks the index -record from read or update. +record from read or update. If a transaction has modified or inserted an index record, then it owns an implicit x-lock on the record. On a secondary index record, @@ -298,11 +298,11 @@ locks on the inserted record. */ /* LOCK COMPATIBILITY MATRIX * IS IX S X AI - * IS + + + - + - * IX + + - - + - * S + - + - - - * X - - - - - - * AI + + - - - + * IS + + + - + + * IX + + - - + + * S + - + - - + * X - - - - - + * AI + + - - - * * Note that for rows, InnoDB only acquires S or X locks. * For tables, InnoDB normally acquires IS or IX locks. @@ -324,7 +324,7 @@ typedef struct lock_table_struct lock_table_t; struct lock_table_struct{ dict_table_t* table; /* database table in dictionary cache */ UT_LIST_NODE_T(lock_t) - locks; /* list of locks on the same table */ + locks; /* list of locks on the same table */ }; /* Record lock for a page */ @@ -340,7 +340,7 @@ struct lock_rec_struct{ /* Lock struct */ struct lock_struct{ trx_t* trx; /* transaction owning the lock */ - UT_LIST_NODE_T(lock_t) + UT_LIST_NODE_T(lock_t) trx_locks; /* list of the locks of the transaction */ ulint type_mode; /* lock type, mode, LOCK_GAP or @@ -396,7 +396,7 @@ lock_deadlock_recursive( ulint* cost, /* in/out: number of calculation steps thus far: if this exceeds LOCK_MAX_N_STEPS_... we return LOCK_VICTIM_IS_START */ - uint depth); /* in: recursion depth: if this exceeds + ulint depth); /* in: recursion depth: if this exceeds LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we return LOCK_VICTIM_IS_START */ @@ -442,7 +442,7 @@ lock_rec_get_nth_bit( b = (ulint)*((byte*)lock + sizeof(lock_t) + byte_index); return(ut_bit_get_nth(b, bit_index)); -} +} /*************************************************************************/ @@ -464,7 +464,7 @@ lock_check_trx_id_sanity( kernel mutex */ { ibool is_ok = TRUE; - + ut_ad(rec_offs_validate(rec, index, offsets)); if (!has_kernel_mutex) { @@ -485,14 +485,14 @@ lock_check_trx_id_sanity( fprintf(stderr, "\n" "InnoDB: is %lu %lu which is higher than the global trx id counter %lu %lu!\n" "InnoDB: The table is corrupt. You have to do dump + drop + reimport.\n", - (ulong) ut_dulint_get_high(trx_id), - (ulong) ut_dulint_get_low(trx_id), - (ulong) ut_dulint_get_high(trx_sys->max_trx_id), - (ulong) ut_dulint_get_low(trx_sys->max_trx_id)); + (ulong) ut_dulint_get_high(trx_id), + (ulong) ut_dulint_get_low(trx_id), + (ulong) ut_dulint_get_high(trx_sys->max_trx_id), + (ulong) ut_dulint_get_low(trx_sys->max_trx_id)); is_ok = FALSE; } - + if (!has_kernel_mutex) { mutex_exit(&kernel_mutex); } @@ -525,7 +525,7 @@ lock_clust_rec_cons_read_sees( kernel mutex here! */ trx_id = row_get_rec_trx_id(rec, index, offsets); - + return(read_view_sees_trx_id(view, trx_id)); } @@ -549,9 +549,9 @@ lock_sec_rec_cons_read_sees( read_view_t* view) /* in: consistent read view */ { dulint max_trx_id; - + UT_NOT_USED(index); - + ut_ad(!(index->type & DICT_CLUSTERED)); ut_ad(page_rec_is_user_rec(rec)); @@ -675,7 +675,7 @@ lock_get_src_table( /* This presumably is the source table. */ src = tab_lock->table; if (UT_LIST_GET_LEN(src->locks) != 1 || - UT_LIST_GET_FIRST(src->locks) != lock) { + UT_LIST_GET_FIRST(src->locks) != lock) { /* We only support the case when there is only one lock on this table. */ return(NULL); @@ -769,9 +769,9 @@ lock_set_lock_and_trx_wait( { ut_ad(lock); ut_ad(trx->wait_lock == NULL); - + trx->wait_lock = lock; - lock->type_mode = lock->type_mode | LOCK_WAIT; + lock->type_mode = lock->type_mode | LOCK_WAIT; } /************************************************************************** @@ -789,7 +789,7 @@ lock_reset_lock_and_trx_wait( /* Reset the back pointer in trx to this waiting lock request */ (lock->trx)->wait_lock = NULL; - lock->type_mode = lock->type_mode & ~LOCK_WAIT; + lock->type_mode = lock->type_mode & ~LOCK_WAIT; } /************************************************************************* @@ -914,18 +914,18 @@ lock_mode_compatible( return(FALSE); } else if (mode1 == LOCK_AUTO_INC && (mode2 == LOCK_IS - || mode2 == LOCK_IX)) { + || mode2 == LOCK_IX)) { return(TRUE); } else if (mode1 == LOCK_IS && (mode2 == LOCK_IS - || mode2 == LOCK_IX - || mode2 == LOCK_AUTO_INC - || mode2 == LOCK_S)) { + || mode2 == LOCK_IX + || mode2 == LOCK_AUTO_INC + || mode2 == LOCK_S)) { return(TRUE); } else if (mode1 == LOCK_IX && (mode2 == LOCK_IS - || mode2 == LOCK_AUTO_INC - || mode2 == LOCK_IX)) { + || mode2 == LOCK_AUTO_INC + || mode2 == LOCK_IX)) { return(TRUE); } @@ -956,23 +956,23 @@ lock_rec_has_to_wait( ut_ad(lock_get_type(lock2) == LOCK_REC); if (trx != lock2->trx - && !lock_mode_compatible(LOCK_MODE_MASK & type_mode, - lock_get_mode(lock2))) { + && !lock_mode_compatible(LOCK_MODE_MASK & type_mode, + lock_get_mode(lock2))) { /* We have somewhat complex rules when gap type record locks cause waits */ if ((lock_is_on_supremum || (type_mode & LOCK_GAP)) - && !(type_mode & LOCK_INSERT_INTENTION)) { + && !(type_mode & LOCK_INSERT_INTENTION)) { /* Gap type locks without LOCK_INSERT_INTENTION flag - do not need to wait for anything. This is because - different users can have conflicting lock types + do not need to wait for anything. This is because + different users can have conflicting lock types on gaps. */ - + return(FALSE); } - + if (!(type_mode & LOCK_INSERT_INTENTION) && lock_rec_get_gap(lock2)) { @@ -984,7 +984,7 @@ lock_rec_has_to_wait( if ((type_mode & LOCK_GAP) && lock_rec_get_rec_not_gap(lock2)) { - + /* Lock on gap does not need to wait for a LOCK_REC_NOT_GAP type lock */ @@ -1003,7 +1003,7 @@ lock_rec_has_to_wait( Also, insert intention locks do not disturb each other. */ - + return(FALSE); } @@ -1030,13 +1030,13 @@ lock_has_to_wait( if (lock1->trx != lock2->trx && !lock_mode_compatible(lock_get_mode(lock1), - lock_get_mode(lock2))) { + lock_get_mode(lock2))) { if (lock_get_type(lock1) == LOCK_REC) { ut_ad(lock_get_type(lock2) == LOCK_REC); /* If this lock request is for a supremum record then the second bit on the lock bitmap is set */ - + return(lock_rec_has_to_wait(lock1->trx, lock1->type_mode, lock2, lock_rec_get_nth_bit(lock1,1))); @@ -1067,7 +1067,7 @@ Sets the nth bit of a record lock to TRUE. */ UNIV_INLINE void lock_rec_set_nth_bit( -/*==================*/ +/*=================*/ lock_t* lock, /* in: record lock */ ulint i) /* in: index of the bit */ { @@ -1075,22 +1075,22 @@ lock_rec_set_nth_bit( ulint bit_index; byte* ptr; ulint b; - + ut_ad(lock); ut_ad(lock_get_type(lock) == LOCK_REC); ut_ad(i < lock->un_member.rec_lock.n_bits); - + byte_index = i / 8; bit_index = i % 8; ptr = (byte*)lock + sizeof(lock_t) + byte_index; - + b = (ulint)*ptr; b = ut_bit_set_nth(b, bit_index, TRUE); *ptr = (byte)b; -} +} /************************************************************************** Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED, @@ -1130,22 +1130,22 @@ lock_rec_reset_nth_bit( ulint bit_index; byte* ptr; ulint b; - + ut_ad(lock); ut_ad(lock_get_type(lock) == LOCK_REC); ut_ad(i < lock->un_member.rec_lock.n_bits); - + byte_index = i / 8; bit_index = i % 8; ptr = (byte*)lock + sizeof(lock_t) + byte_index; - + b = (ulint)*ptr; b = ut_bit_set_nth(b, bit_index, FALSE); *ptr = (byte)b; -} +} /************************************************************************* Gets the first or next record lock on a page. */ @@ -1166,7 +1166,7 @@ lock_rec_get_next_on_page( space = lock->un_member.rec_lock.space; page_no = lock->un_member.rec_lock.page_no; - + for (;;) { lock = HASH_GET_NEXT(hash, lock); @@ -1175,13 +1175,13 @@ lock_rec_get_next_on_page( break; } - if ((lock->un_member.rec_lock.space == space) - && (lock->un_member.rec_lock.page_no == page_no)) { + if ((lock->un_member.rec_lock.space == space) + && (lock->un_member.rec_lock.page_no == page_no)) { break; } } - + return(lock); } @@ -1205,8 +1205,8 @@ lock_rec_get_first_on_page_addr( lock = HASH_GET_FIRST(lock_sys->rec_hash, lock_rec_hash(space, page_no)); while (lock) { - if ((lock->un_member.rec_lock.space == space) - && (lock->un_member.rec_lock.page_no == page_no)) { + if ((lock->un_member.rec_lock.space == space) + && (lock->un_member.rec_lock.page_no == page_no)) { break; } @@ -1216,7 +1216,7 @@ lock_rec_get_first_on_page_addr( return(lock); } - + /************************************************************************* Returns TRUE if there are explicit record locks on a page. */ @@ -1239,7 +1239,7 @@ lock_rec_expl_exist_on_page( } mutex_exit(&kernel_mutex); - + return(ret); } @@ -1261,7 +1261,7 @@ lock_rec_get_first_on_page( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - + hash = buf_frame_get_lock_hash_val(ptr); lock = HASH_GET_FIRST(lock_sys->rec_hash, hash); @@ -1270,8 +1270,8 @@ lock_rec_get_first_on_page( space = buf_frame_get_space_id(ptr); page_no = buf_frame_get_page_no(ptr); - if ((lock->un_member.rec_lock.space == space) - && (lock->un_member.rec_lock.page_no == page_no)) { + if ((lock->un_member.rec_lock.space == space) + && (lock->un_member.rec_lock.page_no == page_no)) { break; } @@ -1363,7 +1363,7 @@ lock_rec_bitmap_reset( n_bytes = lock_rec_get_n_bits(lock) / 8; ut_ad((lock_rec_get_n_bits(lock) % 8) == 0); - + for (i = 0; i < n_bytes; i++) { *ptr = 0; @@ -1386,7 +1386,7 @@ lock_rec_copy( ut_ad(lock_get_type(lock) == LOCK_REC); - size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8; + size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8; dupl_lock = mem_heap_alloc(heap, size); @@ -1409,7 +1409,7 @@ lock_rec_get_prev( lock_t* lock; ulint space; ulint page_no; - lock_t* found_lock = NULL; + lock_t* found_lock = NULL; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); @@ -1423,7 +1423,7 @@ lock_rec_get_prev( for (;;) { ut_ad(lock); - + if (lock == in_lock) { return(found_lock); @@ -1435,7 +1435,7 @@ lock_rec_get_prev( } lock = lock_rec_get_next_on_page(lock); - } + } } /*============= FUNCTIONS FOR ANALYZING TABLE LOCK QUEUE ================*/ @@ -1464,12 +1464,12 @@ lock_table_has( while (lock != NULL) { if (lock->trx == trx - && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) { + && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) { - /* The same trx already has locked the table in + /* The same trx already has locked the table in a mode stronger or equal to the mode given */ - ut_ad(!lock_get_wait(lock)); + ut_ad(!lock_get_wait(lock)); return(lock); } @@ -1479,7 +1479,7 @@ lock_table_has( return(NULL); } - + /*============= FUNCTIONS FOR ANALYZING RECORD LOCK QUEUE ================*/ /************************************************************************* @@ -1503,25 +1503,25 @@ lock_rec_has_expl( ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad((precise_mode & LOCK_MODE_MASK) == LOCK_S - || (precise_mode & LOCK_MODE_MASK) == LOCK_X); + || (precise_mode & LOCK_MODE_MASK) == LOCK_X); ut_ad(!(precise_mode & LOCK_INSERT_INTENTION)); - + lock = lock_rec_get_first(rec); while (lock) { if (lock->trx == trx - && lock_mode_stronger_or_eq(lock_get_mode(lock), - precise_mode & LOCK_MODE_MASK) - && !lock_get_wait(lock) - && (!lock_rec_get_rec_not_gap(lock) - || (precise_mode & LOCK_REC_NOT_GAP) - || page_rec_is_supremum(rec)) - && (!lock_rec_get_gap(lock) + && lock_mode_stronger_or_eq(lock_get_mode(lock), + precise_mode & LOCK_MODE_MASK) + && !lock_get_wait(lock) + && (!lock_rec_get_rec_not_gap(lock) + || (precise_mode & LOCK_REC_NOT_GAP) + || page_rec_is_supremum(rec)) + && (!lock_rec_get_gap(lock) || (precise_mode & LOCK_GAP) || page_rec_is_supremum(rec)) - && (!lock_rec_get_insert_intention(lock))) { + && (!lock_rec_get_insert_intention(lock))) { - return(lock); + return(lock); } lock = lock_rec_get_next(rec, lock); @@ -1529,7 +1529,8 @@ lock_rec_has_expl( return(NULL); } - + +#ifndef UNIV_HOTBACKUP /************************************************************************* Checks if some other transaction has a lock request in the queue. */ static @@ -1542,12 +1543,12 @@ lock_rec_other_has_expl_req( into account, or 0 if not */ ulint wait, /* in: LOCK_WAIT if also waiting locks are taken into account, or 0 if not */ - rec_t* rec, /* in: record to look at */ + rec_t* rec, /* in: record to look at */ trx_t* trx) /* in: transaction, or NULL if requests by all transactions are taken into account */ { lock_t* lock; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ @@ -1559,12 +1560,12 @@ lock_rec_other_has_expl_req( while (lock) { if (lock->trx != trx - && (gap || - !(lock_rec_get_gap(lock) || page_rec_is_supremum(rec))) - && (wait || !lock_get_wait(lock)) - && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) { + && (gap || + !(lock_rec_get_gap(lock) || page_rec_is_supremum(rec))) + && (wait || !lock_get_wait(lock)) + && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) { - return(lock); + return(lock); } lock = lock_rec_get_next(rec, lock); @@ -1572,6 +1573,7 @@ lock_rec_other_has_expl_req( return(NULL); } +#endif /* !UNIV_HOTBACKUP */ /************************************************************************* Checks if some other transaction has a conflicting explicit lock request @@ -1584,7 +1586,7 @@ lock_rec_other_has_conflicting( ulint mode, /* in: LOCK_S or LOCK_X, possibly ORed to LOCK_GAP or LOC_REC_NOT_GAP, LOCK_INSERT_INTENTION */ - rec_t* rec, /* in: record to look at */ + rec_t* rec, /* in: record to look at */ trx_t* trx) /* in: our transaction */ { lock_t* lock; @@ -1600,7 +1602,7 @@ lock_rec_other_has_conflicting( return(lock); } - + lock = lock_rec_get_next(rec, lock); } @@ -1632,12 +1634,12 @@ lock_rec_find_similar_on_page( while (lock != NULL) { if (lock->trx == trx - && lock->type_mode == type_mode - && lock_rec_get_n_bits(lock) > heap_no) { - + && lock->type_mode == type_mode + && lock_rec_get_n_bits(lock) > heap_no) { + return(lock); } - + lock = lock_rec_get_next_on_page(lock); } @@ -1658,7 +1660,7 @@ lock_sec_rec_some_has_impl_off_kernel( const ulint* offsets)/* in: rec_get_offsets(rec, index) */ { page_t* page; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ @@ -1676,18 +1678,18 @@ lock_sec_rec_some_has_impl_off_kernel( if (!(ut_dulint_cmp(page_get_max_trx_id(page), trx_list_get_min_trx_id()) >= 0) - && !recv_recovery_is_on()) { + && !recv_recovery_is_on()) { return(NULL); } /* Ok, in this case it is possible that some transaction has an implicit x-lock. We have to look in the clustered index. */ - + if (!lock_check_trx_id_sanity(page_get_max_trx_id(page), rec, index, offsets, TRUE)) { buf_page_print(page); - + /* The page is corrupt: try to avoid a crash by returning NULL */ return(NULL); @@ -1719,7 +1721,7 @@ lock_rec_create( ulint space; ulint n_bits; ulint n_bytes; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ @@ -1729,7 +1731,7 @@ lock_rec_create( page_no = buf_frame_get_page_no(page); heap_no = rec_get_heap_no(rec, page_is_comp(page)); - ut_ad(!!page_is_comp(page) == index->table->comp); + ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); /* If rec is the supremum record, then we reset the gap and LOCK_REC_NOT_GAP bits, as all locks on the supremum are @@ -1753,7 +1755,7 @@ lock_rec_create( lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; lock->index = index; - + lock->un_member.rec_lock.space = space; lock->un_member.rec_lock.page_no = page_no; lock->un_member.rec_lock.n_bits = n_bytes * 8; @@ -1772,7 +1774,7 @@ lock_rec_create( lock_set_lock_and_trx_wait(lock, trx); } - + return(lock); } @@ -1801,7 +1803,7 @@ lock_rec_enqueue_waiting( { lock_t* lock; trx_t* trx; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ @@ -1816,7 +1818,7 @@ lock_rec_enqueue_waiting( return(DB_QUE_THR_SUSPENDED); } - + trx = thr_get_trx(thr); if (trx->dict_operation) { @@ -1829,13 +1831,13 @@ lock_rec_enqueue_waiting( "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); } - + /* Enqueue the lock request that will wait to be granted */ lock = lock_rec_create(type_mode | LOCK_WAIT, rec, index, trx); /* Check if a deadlock occurs: if yes, remove the lock request and return an error code */ - + if (lock_deadlock_occurs(lock, trx)) { lock_reset_lock_and_trx_wait(lock); @@ -1866,8 +1868,8 @@ lock_rec_enqueue_waiting( ut_print_name(stderr, trx, index->name); } #endif /* UNIV_DEBUG */ - - return(DB_LOCK_WAIT); + + return(DB_LOCK_WAIT); } /************************************************************************* @@ -1892,18 +1894,18 @@ lock_rec_add_to_queue( lock_t* similar_lock = NULL; ulint heap_no; ibool somebody_waits = FALSE; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP)) - || ((type_mode & LOCK_MODE_MASK) != LOCK_S) - || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT, - rec, trx)); + || ((type_mode & LOCK_MODE_MASK) != LOCK_S) + || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT, + rec, trx)); ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP)) - || ((type_mode & LOCK_MODE_MASK) != LOCK_X) - || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT, - rec, trx)); + || ((type_mode & LOCK_MODE_MASK) != LOCK_X) + || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT, + rec, trx)); type_mode = type_mode | LOCK_REC; @@ -1917,7 +1919,7 @@ lock_rec_add_to_queue( /* There should never be LOCK_REC_NOT_GAP on a supremum record, but let us play safe */ - + type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP); } @@ -1970,11 +1972,11 @@ lock_rec_lock_fast( ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */ rec_t* rec, /* in: record */ dict_index_t* index, /* in: index of record */ - que_thr_t* thr) /* in: query thread */ + que_thr_t* thr) /* in: query thread */ { lock_t* lock; ulint heap_no; - trx_t* trx; + trx_t* trx; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); @@ -1988,9 +1990,9 @@ lock_rec_lock_fast( ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); - + heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); - + lock = lock_rec_get_first_on_page(rec); trx = thr_get_trx(thr); @@ -1998,25 +2000,25 @@ lock_rec_lock_fast( if (lock == NULL) { if (!impl) { lock_rec_create(mode, rec, index, trx); - + if (srv_locks_unsafe_for_binlog) { trx_register_new_rec_lock(trx, index); } } - + return(TRUE); } - + if (lock_rec_get_next_on_page(lock)) { return(FALSE); } if (lock->trx != trx - || lock->type_mode != (mode | LOCK_REC) - || lock_rec_get_n_bits(lock) <= heap_no) { + || lock->type_mode != (mode | LOCK_REC) + || lock_rec_get_n_bits(lock) <= heap_no) { - return(FALSE); + return(FALSE); } if (!impl) { @@ -2052,7 +2054,7 @@ lock_rec_lock_slow( ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */ rec_t* rec, /* in: record */ dict_index_t* index, /* in: index of record */ - que_thr_t* thr) /* in: query thread */ + que_thr_t* thr) /* in: query thread */ { trx_t* trx; ulint err; @@ -2069,9 +2071,9 @@ lock_rec_lock_slow( ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); - + trx = thr_get_trx(thr); - + if (lock_rec_has_expl(mode, rec, trx)) { /* The trx already has a strong enough lock on rec: do nothing */ @@ -2082,7 +2084,7 @@ lock_rec_lock_slow( /* If another transaction has a non-gap conflicting request in the queue, as this transaction does not have a lock strong enough already granted on the record, we have to wait. */ - + err = lock_rec_enqueue_waiting(mode, rec, index, thr); if (srv_locks_unsafe_for_binlog) { @@ -2124,7 +2126,7 @@ lock_rec_lock( ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */ rec_t* rec, /* in: record */ dict_index_t* index, /* in: index of record */ - que_thr_t* thr) /* in: query thread */ + que_thr_t* thr) /* in: query thread */ { ulint err; @@ -2140,7 +2142,7 @@ lock_rec_lock( ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP || mode - (LOCK_MODE_MASK & mode) == 0); - + if (lock_rec_lock_fast(impl, mode, rec, index, thr)) { /* We try a simplified and faster subroutine for the most @@ -2171,9 +2173,9 @@ lock_rec_has_to_wait_in_queue( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - ut_ad(lock_get_wait(wait_lock)); + ut_ad(lock_get_wait(wait_lock)); ut_ad(lock_get_type(wait_lock) == LOCK_REC); - + space = wait_lock->un_member.rec_lock.space; page_no = wait_lock->un_member.rec_lock.page_no; heap_no = lock_rec_find_set_bit(wait_lock); @@ -2183,9 +2185,9 @@ lock_rec_has_to_wait_in_queue( while (lock != wait_lock) { if (lock_rec_get_nth_bit(lock, heap_no) - && lock_has_to_wait(wait_lock, lock)) { + && lock_has_to_wait(wait_lock, lock)) { - return(TRUE); + return(TRUE); } lock = lock_rec_get_next_on_page(lock); @@ -2209,23 +2211,23 @@ lock_grant( lock_reset_lock_and_trx_wait(lock); - if (lock_get_mode(lock) == LOCK_AUTO_INC) { + if (lock_get_mode(lock) == LOCK_AUTO_INC) { - if (lock->trx->auto_inc_lock != NULL) { - fprintf(stderr, - "InnoDB: Error: trx already had an AUTO-INC lock!\n"); - } + if (lock->trx->auto_inc_lock != NULL) { + fprintf(stderr, + "InnoDB: Error: trx already had an AUTO-INC lock!\n"); + } - /* Store pointer to lock to trx so that we know to - release it at the end of the SQL statement */ + /* Store pointer to lock to trx so that we know to + release it at the end of the SQL statement */ - lock->trx->auto_inc_lock = lock; - } + lock->trx->auto_inc_lock = lock; + } #ifdef UNIV_DEBUG if (lock_print_waits) { fprintf(stderr, "Lock wait for trx %lu ends\n", - (ulong) ut_dulint_get_low(lock->trx->id)); + (ulong) ut_dulint_get_low(lock->trx->id)); } #endif /* UNIV_DEBUG */ @@ -2233,8 +2235,8 @@ lock_grant( as a victim, then our original transaction may not be in the TRX_QUE_LOCK_WAIT state, and there is no need to end the lock wait for it */ - - if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + + if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) { trx_end_lock_wait(lock->trx); } } @@ -2265,7 +2267,7 @@ lock_rec_cancel( trx_end_lock_wait(lock->trx); } - + /***************************************************************** Removes a record lock request, waiting or granted, from the queue and grants locks to other transactions in the queue if they now are entitled @@ -2283,7 +2285,7 @@ lock_rec_dequeue_from_page( ulint page_no; lock_t* lock; trx_t* trx; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ @@ -2304,7 +2306,7 @@ lock_rec_dequeue_from_page( lock = lock_rec_get_first_on_page_addr(space, page_no); - while (lock != NULL) { + while (lock != NULL) { if (lock_get_wait(lock) && !lock_rec_has_to_wait_in_queue(lock)) { @@ -2314,7 +2316,7 @@ lock_rec_dequeue_from_page( lock = lock_rec_get_next_on_page(lock); } -} +} /***************************************************************** Removes a record lock request, waiting or granted, from the queue. */ @@ -2328,14 +2330,14 @@ lock_rec_discard( ulint space; ulint page_no; trx_t* trx; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad(lock_get_type(in_lock) == LOCK_REC); trx = in_lock->trx; - + space = in_lock->un_member.rec_lock.space; page_no = in_lock->un_member.rec_lock.page_no; @@ -2359,11 +2361,11 @@ lock_rec_free_all_from_discard_page( ulint page_no; lock_t* lock; lock_t* next_lock; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - + space = buf_frame_get_space_id(page); page_no = buf_frame_get_page_no(page); @@ -2374,12 +2376,12 @@ lock_rec_free_all_from_discard_page( ut_ad(!lock_get_wait(lock)); next_lock = lock_rec_get_next_on_page(lock); - + lock_rec_discard(lock); - + lock = next_lock; } -} +} /*============= RECORD LOCK MOVING AND INHERITING ===================*/ @@ -2400,7 +2402,7 @@ lock_rec_reset_and_release_wait( #endif /* UNIV_SYNC_DEBUG */ heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); - + lock = lock_rec_get_first(rec); while (lock != NULL) { @@ -2412,7 +2414,7 @@ lock_rec_reset_and_release_wait( lock = lock_rec_get_next(rec, lock); } -} +} /***************************************************************** Makes a record to inherit the locks (except LOCK_INSERT_INTENTION type) @@ -2431,7 +2433,7 @@ lock_rec_inherit_to_gap( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - + lock = lock_rec_get_first(rec); /* If srv_locks_unsafe_for_binlog is TRUE, we do not want locks set @@ -2441,17 +2443,17 @@ lock_rec_inherit_to_gap( while (lock != NULL) { if (!lock_rec_get_insert_intention(lock) - && !(srv_locks_unsafe_for_binlog - && lock_get_mode(lock) == LOCK_X)) { - + && !(srv_locks_unsafe_for_binlog + && lock_get_mode(lock) == LOCK_X)) { + lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock) - | LOCK_GAP, - heir, lock->index, lock->trx); - } - + | LOCK_GAP, + heir, lock->index, lock->trx); + } + lock = lock_rec_get_next(rec, lock); } -} +} /***************************************************************** Makes a record to inherit the gap locks (except LOCK_INSERT_INTENTION type) @@ -2469,22 +2471,22 @@ lock_rec_inherit_to_gap_if_gap_lock( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - + lock = lock_rec_get_first(rec); while (lock != NULL) { if (!lock_rec_get_insert_intention(lock) - && (page_rec_is_supremum(rec) - || !lock_rec_get_rec_not_gap(lock))) { - + && (page_rec_is_supremum(rec) + || !lock_rec_get_rec_not_gap(lock))) { + lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock) - | LOCK_GAP, - heir, lock->index, lock->trx); - } + | LOCK_GAP, + heir, lock->index, lock->trx); + } lock = lock_rec_get_next(rec, lock); } -} +} /***************************************************************** Moves the locks of a record to another record and resets the lock bits of @@ -2501,25 +2503,25 @@ lock_rec_move( lock_t* lock; ulint heap_no; ulint type_mode; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ heap_no = rec_get_heap_no(donator, comp); - + lock = lock_rec_get_first(donator); ut_ad(lock_rec_get_first(receiver) == NULL); while (lock != NULL) { type_mode = lock->type_mode; - + lock_rec_reset_nth_bit(lock, heap_no); if (lock_get_wait(lock)) { lock_reset_lock_and_trx_wait(lock); - } + } /* Note that we FIRST reset the bit, and then set the lock: the function works also if donator == receiver */ @@ -2530,7 +2532,7 @@ lock_rec_move( } ut_ad(lock_rec_get_first(donator) == NULL); -} +} /***************************************************************** Updates the lock table when we have reorganized a page. NOTE: we copy @@ -2565,13 +2567,13 @@ lock_move_reorganize_page( } heap = mem_heap_create(256); - + /* Copy first all the locks on the page to heap and reset the bitmaps in the original locks; chain the copies of the locks using the trx_locks field in them. */ UT_LIST_INIT(old_locks); - + while (lock != NULL) { /* Make a copy of the lock */ @@ -2584,13 +2586,13 @@ lock_move_reorganize_page( if (lock_get_wait(lock)) { lock_reset_lock_and_trx_wait(lock); - } + } lock = lock_rec_get_next_on_page(lock); } sup = page_get_supremum_rec(page); - + lock = UT_LIST_GET_FIRST(old_locks); comp = page_is_comp(page); @@ -2601,7 +2603,7 @@ lock_move_reorganize_page( supremum of the page; the infimum may carry locks if an update of a record is occurring on the page, and its locks were temporarily stored on the infimum */ - + page_cur_set_before_first(page, &cur1); page_cur_set_before_first(old_page, &cur2); @@ -2649,9 +2651,9 @@ lock_move_reorganize_page( mem_heap_free(heap); -/* ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page), +/* ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page), buf_frame_get_page_no(page))); */ -} +} /***************************************************************** Moves the explicit locks on user records to another page if a record @@ -2683,13 +2685,13 @@ lock_move_rec_list_end( does not reuse locks if there are waiters in the queue. */ sup = page_get_supremum_rec(page); - + lock = lock_rec_get_first_on_page(page); comp = page_is_comp(page); while (lock != NULL) { - + page_cur_position(rec, &cur1); if (page_cur_is_before_first(&cur1)) { @@ -2698,7 +2700,7 @@ lock_move_rec_list_end( page_cur_set_before_first(new_page, &cur2); page_cur_move_to_next(&cur2); - + /* Copy lock requests on user records to new page and reset the lock bits on the old */ @@ -2717,7 +2719,7 @@ lock_move_rec_list_end( if (lock_get_wait(lock)) { lock_reset_lock_and_trx_wait(lock); - } + } lock_rec_add_to_queue(type_mode, page_cur_get_rec(&cur2), @@ -2730,14 +2732,14 @@ lock_move_rec_list_end( lock = lock_rec_get_next_on_page(lock); } - + lock_mutex_exit_kernel(); /* ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page), buf_frame_get_page_no(page))); ut_ad(lock_rec_validate_page(buf_frame_get_space_id(new_page), buf_frame_get_page_no(new_page))); */ -} +} /***************************************************************** Moves the explicit locks on user records to another page if a record @@ -2770,7 +2772,7 @@ lock_move_rec_list_start( ut_ad(page == buf_frame_align(rec)); while (lock != NULL) { - + page_cur_set_before_first(page, &cur1); page_cur_move_to_next(&cur1); @@ -2795,7 +2797,7 @@ lock_move_rec_list_start( if (lock_get_wait(lock)) { lock_reset_lock_and_trx_wait(lock); - } + } lock_rec_add_to_queue(type_mode, page_cur_get_rec(&cur2), @@ -2808,14 +2810,14 @@ lock_move_rec_list_start( lock = lock_rec_get_next_on_page(lock); } - + lock_mutex_exit_kernel(); /* ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page), buf_frame_get_page_no(page))); ut_ad(lock_rec_validate_page(buf_frame_get_space_id(new_page), buf_frame_get_page_no(new_page))); */ -} +} /***************************************************************** Updates the lock table when a page is split to the right. */ @@ -2836,7 +2838,7 @@ lock_update_split_right( lock_rec_move(page_get_supremum_rec(right_page), page_get_supremum_rec(left_page), comp); - + /* Inherit the locks to the supremum of left page from the successor of the infimum on right page */ @@ -2844,7 +2846,7 @@ lock_update_split_right( page_rec_get_next(page_get_infimum_rec(right_page))); lock_mutex_exit_kernel(); -} +} /***************************************************************** Updates the lock table when a page is merged to the right. */ @@ -2858,7 +2860,7 @@ lock_update_merge_right( discarded */ { lock_mutex_enter_kernel(); - + /* Inherit the locks from the supremum of the left page to the original successor of infimum on the right page, to which the left page was merged */ @@ -2869,7 +2871,7 @@ lock_update_merge_right( waiting transactions */ lock_rec_reset_and_release_wait(page_get_supremum_rec(left_page)); - + lock_rec_free_all_from_discard_page(left_page); lock_mutex_exit_kernel(); @@ -2937,7 +2939,7 @@ lock_update_split_left( page_t* left_page) /* in: left page */ { lock_mutex_enter_kernel(); - + /* Inherit the locks to the supremum of the left page from the successor of the infimum on the right page */ @@ -2985,7 +2987,7 @@ lock_update_merge_left( /* Move the locks from the supremum of right page to the supremum of the left page */ - + lock_rec_move(left_supremum, page_get_supremum_rec(right_page), comp); lock_rec_free_all_from_discard_page(right_page); @@ -3003,13 +3005,13 @@ lock_rec_reset_and_inherit_gap_locks( rec_t* heir, /* in: heir record */ rec_t* rec) /* in: record */ { - mutex_enter(&kernel_mutex); + mutex_enter(&kernel_mutex); lock_rec_reset_and_release_wait(heir); - + lock_rec_inherit_to_gap(heir, rec); - mutex_exit(&kernel_mutex); + mutex_exit(&kernel_mutex); } /***************************************************************** @@ -3024,7 +3026,7 @@ lock_update_discard( rec_t* rec; lock_mutex_enter_kernel(); - + if (NULL == lock_rec_get_first_on_page(page)) { /* No locks exist on page, nothing to do */ @@ -3032,7 +3034,7 @@ lock_update_discard( return; } - + /* Inherit all the locks on the page to the record and reset all the locks on the page */ @@ -3049,7 +3051,7 @@ lock_update_discard( break; } - + rec = page_rec_get_next(rec); } @@ -3092,11 +3094,11 @@ lock_update_delete( /* Reset the lock bits on rec and release waiting transactions */ - lock_rec_reset_and_release_wait(rec); + lock_rec_reset_and_release_wait(rec); lock_mutex_exit_kernel(); } - + /************************************************************************* Stores on the page infimum record the explicit locks of another record. This function is used to store the lock state of a record when it is @@ -3116,10 +3118,10 @@ lock_rec_store_on_page_infimum( ut_ad(page == buf_frame_align(rec)); lock_mutex_enter_kernel(); - + lock_rec_move(page_get_infimum_rec(page), rec, page_is_comp(page)); - lock_mutex_exit_kernel(); + lock_mutex_exit_kernel(); } /************************************************************************* @@ -3132,7 +3134,7 @@ lock_rec_restore_from_page_infimum( rec_t* rec, /* in: record whose lock state is restored */ page_t* page) /* in: page (rec is not necessarily on this page) whose infimum stored the lock state; lock bits are - reset on the infimum */ + reset on the infimum */ { ulint comp; lock_mutex_enter_kernel(); @@ -3140,7 +3142,7 @@ lock_rec_restore_from_page_infimum( ut_ad(!comp == !page_rec_is_comp(rec)); lock_rec_move(rec, page_get_infimum_rec(page), comp); - + lock_mutex_exit_kernel(); } @@ -3206,7 +3208,7 @@ retry: return(TRUE); } - + return(FALSE); } @@ -3230,7 +3232,7 @@ lock_deadlock_recursive( ulint* cost, /* in/out: number of calculation steps thus far: if this exceeds LOCK_MAX_N_STEPS_... we return LOCK_VICTIM_IS_START */ - uint depth) /* in: recursion depth: if this exceeds + ulint depth) /* in: recursion depth: if this exceeds LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we return LOCK_VICTIM_IS_START */ { @@ -3238,12 +3240,12 @@ lock_deadlock_recursive( ulint bit_no = ULINT_UNDEFINED; trx_t* lock_trx; ulint ret; - + ut_a(trx && start && wait_lock); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - + if (trx->deadlock_mark == 1) { /* We have already exhaustively searched the subtree starting from this trx */ @@ -3296,7 +3298,7 @@ lock_deadlock_recursive( /* We came back to the recursion starting point: a deadlock detected */ FILE* ef = lock_latest_err_file; - + rewind(ef); ut_print_timestamp(ef); @@ -3306,28 +3308,28 @@ lock_deadlock_recursive( fputs( "*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n", ef); - + if (lock_get_type(wait_lock) == LOCK_REC) { lock_rec_print(ef, wait_lock); } else { lock_table_print(ef, wait_lock); } - + fputs("*** (2) TRANSACTION:\n", ef); trx_print(ef, lock->trx, 3000); fputs("*** (2) HOLDS THE LOCK(S):\n", ef); - + if (lock_get_type(lock) == LOCK_REC) { lock_rec_print(ef, lock); } else { lock_table_print(ef, lock); } - + fputs( "*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n", ef); - + if (lock_get_type(start->wait_lock) == LOCK_REC) { lock_rec_print(ef, start->wait_lock); @@ -3347,20 +3349,20 @@ lock_deadlock_recursive( back it */ return(LOCK_VICTIM_IS_START); - } + } lock_deadlock_found = TRUE; /* Let us choose the transaction of wait_lock as a victim to try to avoid deadlocking our recursion starting point transaction */ - + fputs("*** WE ROLL BACK TRANSACTION (1)\n", ef); - + wait_lock->trx->was_chosen_as_deadlock_victim = TRUE; - + lock_cancel_waiting_and_release(wait_lock); /* Since trx and wait_lock are no longer @@ -3372,7 +3374,7 @@ lock_deadlock_recursive( return(LOCK_VICTIM_IS_OTHER); } - + if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) { /* Another trx ahead has requested lock in an @@ -3468,7 +3470,7 @@ lock_table_remove_low( UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock); UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock); -} +} /************************************************************************* Enqueues a waiting request for a table lock which cannot be granted @@ -3490,11 +3492,11 @@ lock_table_enqueue_waiting( { lock_t* lock; trx_t* trx; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - + /* Test if there already is some other reason to suspend thread: we do not enqueue a lock request if the query thread should be stopped anyway */ @@ -3517,7 +3519,7 @@ lock_table_enqueue_waiting( "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); } - + /* Enqueue the lock request that will wait to be granted */ lock = lock_table_create(table, mode | LOCK_WAIT, trx); @@ -3536,10 +3538,10 @@ lock_table_enqueue_waiting( if (trx->wait_lock == NULL) { /* Deadlock resolution chose another transaction as a victim, and we accidentally got our lock granted! */ - + return(DB_SUCCESS); } - + trx->que_state = TRX_QUE_LOCK_WAIT; trx->was_chosen_as_deadlock_victim = FALSE; trx->wait_started = time(NULL); @@ -3573,11 +3575,11 @@ lock_table_other_has_incompatible( while (lock != NULL) { - if ((lock->trx != trx) - && (!lock_mode_compatible(lock_get_mode(lock), mode)) - && (wait || !(lock_get_wait(lock)))) { + if ((lock->trx != trx) + && (!lock_mode_compatible(lock_get_mode(lock), mode)) + && (wait || !(lock_get_wait(lock)))) { - return(TRUE); + return(TRUE); } lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock); @@ -3603,7 +3605,7 @@ lock_table( { trx_t* trx; ulint err; - + ut_ad(table && thr); if (flags & BTR_NO_LOCKING_FLAG) { @@ -3630,12 +3632,12 @@ lock_table( other transactions have in the table lock queue. */ if (lock_table_other_has_incompatible(trx, LOCK_WAIT, table, mode)) { - + /* Another trx has a request on the table in an incompatible mode: this trx may have to wait */ err = lock_table_enqueue_waiting(mode | flags, table, thr); - + lock_mutex_exit_kernel(); return(err); @@ -3688,8 +3690,8 @@ lock_table_has_to_wait_in_queue( dict_table_t* table; lock_t* lock; - ut_ad(lock_get_wait(wait_lock)); - + ut_ad(lock_get_wait(wait_lock)); + table = wait_lock->un_member.tab_lock.table; lock = UT_LIST_GET_FIRST(table->locks); @@ -3698,7 +3700,7 @@ lock_table_has_to_wait_in_queue( if (lock_has_to_wait(wait_lock, lock)) { - return(TRUE); + return(TRUE); } lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock); @@ -3720,7 +3722,7 @@ lock_table_dequeue( they are now qualified to it */ { lock_t* lock; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ @@ -3744,7 +3746,7 @@ lock_table_dequeue( lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock); } -} +} /*=========================== LOCK RELEASE ==============================*/ @@ -3756,13 +3758,14 @@ to a lock. */ void lock_rec_unlock( /*============*/ - trx_t* trx, /* in: transaction that has set a record + trx_t* trx, /* in: transaction that has set a record lock */ rec_t* rec, /* in: record */ ulint lock_mode) /* in: LOCK_S or LOCK_X */ { - lock_t* lock; - ulint heap_no; + lock_t* lock; + lock_t* release_lock = NULL; + ulint heap_no; ut_ad(trx && rec); @@ -3772,21 +3775,23 @@ lock_rec_unlock( lock = lock_rec_get_first(rec); - /* Remove the record lock */ + /* Find the last lock with the same lock_mode and transaction + from the record. */ while (lock != NULL) { if (lock->trx == trx && lock_get_mode(lock) == lock_mode) { + release_lock = lock; ut_a(!lock_get_wait(lock)); - - lock_rec_reset_nth_bit(lock, heap_no); - - break; } lock = lock_rec_get_next(rec, lock); } - if (UNIV_UNLIKELY(lock == NULL)) { + /* If a record lock is found, release the record lock */ + + if (UNIV_LIKELY(release_lock != NULL)) { + lock_rec_reset_nth_bit(release_lock, heap_no); + } else { mutex_exit(&kernel_mutex); ut_print_timestamp(stderr); fprintf(stderr, @@ -3812,7 +3817,7 @@ lock_rec_unlock( } mutex_exit(&kernel_mutex); -} +} /************************************************************************* Releases a table lock. @@ -3866,7 +3871,7 @@ lock_release_off_kernel( #endif /* UNIV_SYNC_DEBUG */ lock = UT_LIST_GET_LAST(trx->trx_locks); - + count = 0; while (lock != NULL) { @@ -3874,21 +3879,21 @@ lock_release_off_kernel( count++; if (lock_get_type(lock) == LOCK_REC) { - + lock_rec_dequeue_from_page(lock); } else { ut_ad(lock_get_type(lock) & LOCK_TABLE); if (lock_get_mode(lock) != LOCK_IS - && 0 != ut_dulint_cmp(trx->undo_no, - ut_dulint_zero)) { + && 0 != ut_dulint_cmp(trx->undo_no, + ut_dulint_zero)) { - /* The trx may have modified the table. - We block the use of the MySQL query cache - for all currently active transactions. */ + /* The trx may have modified the table. We + block the use of the MySQL query cache for + all currently active transactions. */ table = lock->un_member.tab_lock.table; - + table->query_cache_inv_trx_id = trx_sys->max_trx_id; } @@ -3905,7 +3910,7 @@ lock_release_off_kernel( lock_mutex_enter_kernel(); count = 0; - } + } lock = UT_LIST_GET_LAST(trx->trx_locks); } @@ -3929,7 +3934,7 @@ lock_cancel_waiting_and_release( #endif /* UNIV_SYNC_DEBUG */ if (lock_get_type(lock) == LOCK_REC) { - + lock_rec_dequeue_from_page(lock); } else { ut_ad(lock_get_type(lock) & LOCK_TABLE); @@ -3964,20 +3969,20 @@ lock_reset_all_on_table_for_trx( #endif /* UNIV_SYNC_DEBUG */ lock = UT_LIST_GET_LAST(trx->trx_locks); - + while (lock != NULL) { prev_lock = UT_LIST_GET_PREV(trx_locks, lock); - + if (lock_get_type(lock) == LOCK_REC && lock->index->table == table) { ut_a(!lock_get_wait(lock)); - + lock_rec_discard(lock); } else if (lock_get_type(lock) & LOCK_TABLE && lock->un_member.tab_lock.table == table) { ut_a(!lock_get_wait(lock)); - + lock_table_remove_low(lock); } @@ -4000,7 +4005,7 @@ lock_reset_all_on_table( lock = UT_LIST_GET_FIRST(table->locks); - while (lock) { + while (lock) { ut_a(!lock_get_wait(lock)); lock_reset_all_on_table_for_trx(table, lock->trx); @@ -4051,8 +4056,8 @@ lock_table_print( } putc('\n', file); -} - +} + /************************************************************************* Prints info of a record lock. */ @@ -4078,15 +4083,15 @@ lock_rec_print( ut_a(lock_get_type(lock) == LOCK_REC); space = lock->un_member.rec_lock.space; - page_no = lock->un_member.rec_lock.page_no; + page_no = lock->un_member.rec_lock.page_no; fprintf(file, "RECORD LOCKS space id %lu page no %lu n bits %lu ", - (ulong) space, (ulong) page_no, - (ulong) lock_rec_get_n_bits(lock)); + (ulong) space, (ulong) page_no, + (ulong) lock_rec_get_n_bits(lock)); dict_index_name_print(file, lock->trx, lock->index); fprintf(file, " trx id %lu %lu", - (ulong) (lock->trx)->id.high, - (ulong) (lock->trx)->id.low); + (ulong) (lock->trx)->id.high, + (ulong) (lock->trx)->id.low); if (lock_get_mode(lock) == LOCK_S) { fputs(" lock mode S", file); @@ -4119,7 +4124,7 @@ lock_rec_print( /* If the page is not in the buffer pool, we cannot load it because we have the kernel mutex and ibuf operations would break the latching order */ - + page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL, BUF_GET_IF_IN_POOL, __FILE__, __LINE__, &mtr); @@ -4130,12 +4135,12 @@ lock_rec_print( /* Let us try to get an X-latch. If the current thread is holding an X-latch on the page, we cannot get an S-latch. */ - + page = buf_page_get_nowait(space, page_no, RW_X_LATCH, &mtr); } } - + if (page) { #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK); @@ -4166,6 +4171,7 @@ lock_rec_print( } } +#ifndef UNIV_HOTBACKUP /************************************************************************* Calculates the number of record lock structs in the record lock hash table. */ static @@ -4195,7 +4201,6 @@ lock_get_n_rec_locks(void) return(n_locks); } -#ifndef UNIV_HOTBACKUP /************************************************************************* Prints info of locks for all transactions. */ @@ -4213,7 +4218,7 @@ lock_print_info_summary( if (lock_deadlock_found) { fputs( -"------------------------\n" +"------------------------\n" "LATEST DETECTED DEADLOCK\n" "------------------------\n", file); @@ -4221,13 +4226,13 @@ lock_print_info_summary( } fputs( -"------------\n" +"------------\n" "TRANSACTIONS\n" "------------\n", file); fprintf(file, "Trx id counter %lu %lu\n", - (ulong) ut_dulint_get_high(trx_sys->max_trx_id), - (ulong) ut_dulint_get_low(trx_sys->max_trx_id)); + (ulong) ut_dulint_get_high(trx_sys->max_trx_id), + (ulong) ut_dulint_get_low(trx_sys->max_trx_id)); fprintf(file, "Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n", @@ -4274,7 +4279,7 @@ lock_print_info_all_transactions( fputs("---", file); trx_print(file, trx, 600); } - + trx = UT_LIST_GET_NEXT(mysql_trx_list, trx); } @@ -4287,7 +4292,7 @@ loop: reading a database page in below, variable trx may be obsolete now and we must loop through the trx list to get probably the same trx, or some other trx. */ - + while (trx && (i < nth_trx)) { trx = UT_LIST_GET_NEXT(trx_list, trx); i++; @@ -4305,15 +4310,15 @@ loop: if (nth_lock == 0) { fputs("---", file); trx_print(file, trx, 600); - - if (trx->read_view) { + + if (trx->read_view) { fprintf(file, - "Trx read view will not see trx with id >= %lu %lu, sees < %lu %lu\n", - (ulong) ut_dulint_get_high(trx->read_view->low_limit_id), - (ulong) ut_dulint_get_low(trx->read_view->low_limit_id), - (ulong) ut_dulint_get_high(trx->read_view->up_limit_id), - (ulong) ut_dulint_get_low(trx->read_view->up_limit_id)); - } +"Trx read view will not see trx with id >= %lu %lu, sees < %lu %lu\n", + (ulong) ut_dulint_get_high(trx->read_view->low_limit_id), + (ulong) ut_dulint_get_low(trx->read_view->low_limit_id), + (ulong) ut_dulint_get_high(trx->read_view->up_limit_id), + (ulong) ut_dulint_get_low(trx->read_view->up_limit_id)); + } if (trx->que_state == TRX_QUE_LOCK_WAIT) { fprintf(file, @@ -4331,17 +4336,17 @@ loop: } if (!srv_print_innodb_lock_monitor) { - nth_trx++; - goto loop; + nth_trx++; + goto loop; } i = 0; /* Look at the note about the trx loop above why we loop here: lock may be an obsolete pointer now. */ - + lock = UT_LIST_GET_FIRST(trx->trx_locks); - + while (lock && (i < nth_lock)) { lock = UT_LIST_GET_NEXT(trx_locks, lock); i++; @@ -4356,14 +4361,14 @@ loop: if (lock_get_type(lock) == LOCK_REC) { space = lock->un_member.rec_lock.space; - page_no = lock->un_member.rec_lock.page_no; + page_no = lock->un_member.rec_lock.page_no; - if (load_page_first) { + if (load_page_first) { lock_mutex_exit_kernel(); innobase_mysql_end_print_arbitrary_thd(); mtr_start(&mtr); - + page = buf_page_get_with_no_latch(space, page_no, &mtr); mtr_commit(&mtr); @@ -4375,11 +4380,11 @@ loop: goto loop; } - + lock_rec_print(file, lock); } else { ut_ad(lock_get_type(lock) & LOCK_TABLE); - + lock_table_print(file, lock); } @@ -4391,7 +4396,7 @@ loop: fputs( "10 LOCKS PRINTED FOR THIS TRX: SUPPRESSING FURTHER PRINTS\n", file); - + nth_trx++; nth_lock = 0; @@ -4423,13 +4428,13 @@ lock_table_queue_validate( while (lock) { ut_a(((lock->trx)->conc_state == TRX_ACTIVE) - || ((lock->trx)->conc_state == TRX_PREPARED) - || ((lock->trx)->conc_state == TRX_COMMITTED_IN_MEMORY)); - + || ((lock->trx)->conc_state == TRX_PREPARED) + || ((lock->trx)->conc_state == TRX_COMMITTED_IN_MEMORY)); + if (!lock_get_wait(lock)) { ut_a(!is_waiting); - + ut_a(!lock_table_other_has_incompatible(lock->trx, 0, table, lock_get_mode(lock))); } else { @@ -4455,7 +4460,7 @@ lock_rec_queue_validate( dict_index_t* index, /* in: index, or NULL if not known */ const ulint* offsets)/* in: rec_get_offsets(rec, index) */ { - trx_t* impl_trx; + trx_t* impl_trx; lock_t* lock; ut_a(rec); @@ -4470,12 +4475,11 @@ lock_rec_queue_validate( while (lock) { ut_a(lock->trx->conc_state == TRX_ACTIVE - || lock->trx->conc_state == TRX_PREPARED - || lock->trx->conc_state - == TRX_COMMITTED_IN_MEMORY); - + || lock->trx->conc_state == TRX_PREPARED + || lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY); + ut_a(trx_in_trx_list(lock->trx)); - + if (lock_get_wait(lock)) { ut_a(lock_rec_has_to_wait_in_queue(lock)); } @@ -4489,11 +4493,11 @@ lock_rec_queue_validate( lock_mutex_exit_kernel(); - return(TRUE); + return(TRUE); } if (index && (index->type & DICT_CLUSTERED)) { - + impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets); if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0, @@ -4505,11 +4509,11 @@ lock_rec_queue_validate( } if (index && !(index->type & DICT_CLUSTERED)) { - + /* The kernel mutex may get released temporarily in the next function call: we have to release lock table mutex to obey the latching order */ - + impl_trx = lock_sec_rec_some_has_impl_off_kernel( rec, index, offsets); @@ -4525,10 +4529,10 @@ lock_rec_queue_validate( while (lock) { ut_a(lock->trx->conc_state == TRX_ACTIVE - || lock->trx->conc_state == TRX_PREPARED - || lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY); + || lock->trx->conc_state == TRX_PREPARED + || lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY); ut_a(trx_in_trx_list(lock->trx)); - + if (index) { ut_a(lock->index == index); } @@ -4536,7 +4540,7 @@ lock_rec_queue_validate( if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) { ulint mode; - + if (lock_get_mode(lock) == LOCK_S) { mode = LOCK_X; } else { @@ -4586,14 +4590,14 @@ lock_rec_validate_page( #endif /* UNIV_SYNC_DEBUG */ mtr_start(&mtr); - + page = buf_page_get(space, page_no, RW_X_LATCH, &mtr); #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK); #endif /* UNIV_SYNC_DEBUG */ lock_mutex_enter_kernel(); -loop: +loop: lock = lock_rec_get_first_on_page_addr(space, page_no); if (!lock) { @@ -4611,9 +4615,9 @@ loop: ut_a(trx_in_trx_list(lock->trx)); ut_a(lock->trx->conc_state == TRX_ACTIVE - || lock->trx->conc_state == TRX_PREPARED - || lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY); - + || lock->trx->conc_state == TRX_PREPARED + || lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY); + for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) { if (i == 1 || lock_rec_get_nth_bit(lock, i)) { @@ -4652,8 +4656,8 @@ function_exit: mem_heap_free(heap); } return(TRUE); -} - +} + /************************************************************************* Validates the lock system. */ @@ -4670,22 +4674,22 @@ lock_validate(void) ulint i; lock_mutex_enter_kernel(); - + trx = UT_LIST_GET_FIRST(trx_sys->trx_list); while (trx) { lock = UT_LIST_GET_FIRST(trx->trx_locks); - + while (lock) { if (lock_get_type(lock) & LOCK_TABLE) { - + lock_table_queue_validate( lock->un_member.tab_lock.table); } - + lock = UT_LIST_GET_NEXT(trx_locks, lock); } - + trx = UT_LIST_GET_NEXT(trx_list, trx); } @@ -4701,7 +4705,7 @@ lock_validate(void) space = lock->un_member.rec_lock.space; page_no = lock->un_member.rec_lock.page_no; - + if (ut_dulint_cmp( ut_dulint_create(space, page_no), limit) >= 0) { @@ -4715,7 +4719,7 @@ lock_validate(void) break; } - + lock_mutex_exit_kernel(); lock_rec_validate_page(space, page_no); @@ -4788,7 +4792,7 @@ lock_rec_insert_check_and_lock( page_update_max_trx_id(buf_frame_align(rec), thr_get_trx(thr)->id); } - + return(DB_SUCCESS); } @@ -4879,8 +4883,7 @@ lock_rec_convert_impl_to_expl( impl_trx)) { lock_rec_add_to_queue(LOCK_REC | LOCK_X - | LOCK_REC_NOT_GAP, rec, index, - impl_trx); + | LOCK_REC_NOT_GAP, rec, index, impl_trx); } } } @@ -4952,7 +4955,7 @@ lock_sec_rec_modify_check_and_lock( que_thr_t* thr) /* in: query thread */ { ulint err; - + if (flags & BTR_NO_LOCKING_FLAG) { return(DB_SUCCESS); @@ -5036,9 +5039,9 @@ lock_sec_rec_read_check_and_lock( lock_mutex_enter_kernel(); ut_ad(mode != LOCK_X - || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); + || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); ut_ad(mode != LOCK_S - || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS)); + || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS)); /* Some transaction may have an implicit x-lock on the record only if the max trx id for the page >= min trx id for the trx list or a @@ -5046,10 +5049,10 @@ lock_sec_rec_read_check_and_lock( if (((ut_dulint_cmp(page_get_max_trx_id(buf_frame_align(rec)), trx_list_get_min_trx_id()) >= 0) - || recv_recovery_is_on()) - && !page_rec_is_supremum(rec)) { + || recv_recovery_is_on()) + && !page_rec_is_supremum(rec)) { - lock_rec_convert_impl_to_expl(rec, index, offsets); + lock_rec_convert_impl_to_expl(rec, index, offsets); } err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr); @@ -5104,12 +5107,12 @@ lock_clust_rec_read_check_and_lock( lock_mutex_enter_kernel(); ut_ad(mode != LOCK_X - || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); + || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); ut_ad(mode != LOCK_S - || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS)); - + || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS)); + if (!page_rec_is_supremum(rec)) { - + lock_rec_convert_impl_to_expl(rec, index, offsets); } diff --git a/storage/innobase/log/log0log.c b/storage/innobase/log/log0log.c index 2f76bf450db..ea3b74c00f9 100644 --- a/storage/innobase/log/log0log.c +++ b/storage/innobase/log/log0log.c @@ -34,8 +34,8 @@ to the InnoDB redo log. 2) Normally these changes are performed using a mlog_write_ulint() or similar function. -3) In some page level operations only a code number of a -c-function and its parameters are written to the log to +3) In some page level operations only a code number of a +c-function and its parameters are written to the log to reduce the size of the log. 3a) You should not add parameters to these kind of functions @@ -75,7 +75,7 @@ byte log_archive_io; #endif /* UNIV_LOG_ARCHIVE */ /* A margin for free space in the log buffer before a log entry is catenated */ -#define LOG_BUF_WRITE_MARGIN (4 * OS_FILE_LOG_BLOCK_SIZE) +#define LOG_BUF_WRITE_MARGIN (4 * OS_FILE_LOG_BLOCK_SIZE) /* Margins for free space in the log buffer after a log entry is catenated */ #define LOG_BUF_FLUSH_RATIO 2 @@ -147,7 +147,7 @@ log_fsp_current_free_limit_set_and_checkpoint( mutex_exit(&(log_sys->mutex)); /* Try to make a synchronous checkpoint */ - + success = FALSE; while (!success) { @@ -202,7 +202,7 @@ log_reserve_and_open( ut_a(len < log->buf_size / 2); loop: mutex_enter(&(log->mutex)); - + /* Calculate an upper limit for the space the string may take in the log buffer */ @@ -217,7 +217,7 @@ loop: log_buffer_flush_to_disk(); - srv_log_waits++; + srv_log_waits++; ut_ad(++count < 50); @@ -226,22 +226,22 @@ loop: #ifdef UNIV_LOG_ARCHIVE if (log->archiving_state != LOG_ARCH_OFF) { - + archived_lsn_age = ut_dulint_minus(log->lsn, log->archived_lsn); if (archived_lsn_age + len_upper_limit > log->max_archived_lsn_age) { /* Not enough free archived space in log groups: do a synchronous archive write batch: */ - + mutex_exit(&(log->mutex)); - + ut_ad(len_upper_limit <= log->max_archived_lsn_age); - + log_archive_do(TRUE, &dummy); - + ut_ad(++count < 50); - + goto loop; } } @@ -250,7 +250,7 @@ loop: #ifdef UNIV_LOG_DEBUG log->old_buf_free = log->buf_free; log->old_lsn = log->lsn; -#endif +#endif return(log->lsn); } @@ -279,15 +279,15 @@ part_loop: if (data_len <= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) { - /* The string fits within the current log block */ - - len = str_len; + /* The string fits within the current log block */ + + len = str_len; } else { data_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; - - len = OS_FILE_LOG_BLOCK_SIZE + + len = OS_FILE_LOG_BLOCK_SIZE - (log->buf_free % OS_FILE_LOG_BLOCK_SIZE) - - LOG_BLOCK_TRL_SIZE; + - LOG_BLOCK_TRL_SIZE; } ut_memcpy(log->buf + log->buf_free, str, len); @@ -321,8 +321,8 @@ part_loop: if (str_len > 0) { goto part_loop; } - - srv_log_write_requests++; + + srv_log_write_requests++; } /**************************************************************** @@ -345,7 +345,7 @@ log_close(void) #endif /* UNIV_SYNC_DEBUG */ lsn = log->lsn; - + log_block = ut_align_down(log->buf + log->buf_free, OS_FILE_LOG_BLOCK_SIZE); first_rec_group = log_block_get_first_rec_group(log_block); @@ -356,7 +356,7 @@ log_close(void) will start within this block at the offset data_len */ log_block_set_first_rec_group(log_block, - log_block_get_data_len(log_block)); + log_block_get_data_len(log_block)); } if (log->buf_free > log->max_buf_free) { @@ -374,12 +374,12 @@ log_close(void) big_rec operations, but other operations are smaller. */ if (!log_has_printed_chkp_warning - || difftime(time(NULL), log_last_warning_time) > 15) { + || difftime(time(NULL), log_last_warning_time) > 15) { - log_has_printed_chkp_warning = TRUE; + log_has_printed_chkp_warning = TRUE; log_last_warning_time = time(NULL); - - ut_print_timestamp(stderr); + + ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: ERROR: the age of the last checkpoint is %lu,\n" "InnoDB: which exceeds the log group capacity %lu.\n" @@ -399,9 +399,9 @@ log_close(void) oldest_lsn = buf_pool_get_oldest_modification(); if (ut_dulint_is_zero(oldest_lsn) - || (ut_dulint_minus(lsn, oldest_lsn) - > log->max_modified_age_async) - || checkpoint_age > log->max_checkpoint_age_async) { + || (ut_dulint_minus(lsn, oldest_lsn) + > log->max_modified_age_async) + || checkpoint_age > log->max_checkpoint_age_async) { log->check_flush_or_checkpoint = TRUE; } @@ -428,7 +428,7 @@ log_pad_current_log_block(void) ulint pad_length; ulint i; dulint lsn; - + /* We retrieve lsn only because otherwise gcc crashed on HP-UX */ lsn = log_reserve_and_open(OS_FILE_LOG_BLOCK_SIZE); @@ -441,7 +441,7 @@ log_pad_current_log_block(void) } lsn = log_sys->lsn; - + log_close(); log_release(); @@ -464,7 +464,7 @@ log_group_get_capacity( ut_ad(mutex_own(&(log_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ - return((group->file_size - LOG_FILE_HDR_SIZE) * group->n_files); + return((group->file_size - LOG_FILE_HDR_SIZE) * group->n_files); } /********************************************************** @@ -515,12 +515,12 @@ log_group_calc_lsn_offset( group->lsn */ log_group_t* group) /* in: log group */ { - dulint gr_lsn; - ib_longlong gr_lsn_size_offset; + dulint gr_lsn; + ib_longlong gr_lsn_size_offset; ib_longlong difference; ib_longlong group_size; ib_longlong offset; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(log_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -531,12 +531,12 @@ log_group_calc_lsn_offset( gr_lsn = group->lsn; gr_lsn_size_offset = (ib_longlong) - log_group_calc_size_offset(group->lsn_offset, group); + log_group_calc_size_offset(group->lsn_offset, group); group_size = (ib_longlong) log_group_get_capacity(group); if (ut_dulint_cmp(lsn, gr_lsn) >= 0) { - + difference = (ib_longlong) ut_dulint_minus(lsn, gr_lsn); } else { difference = (ib_longlong) ut_dulint_minus(gr_lsn, lsn); @@ -552,7 +552,7 @@ log_group_calc_lsn_offset( /* fprintf(stderr, "Offset is %lu gr_lsn_offset is %lu difference is %lu\n", - (ulint)offset,(ulint)gr_lsn_size_offset, (ulint)difference); + (ulint)offset,(ulint)gr_lsn_size_offset, (ulint)difference); */ return(log_group_calc_real_offset((ulint)offset, group)); @@ -581,7 +581,7 @@ log_calc_where_lsn_is( ib_longlong capacity = log_file_size - LOG_FILE_HDR_SIZE; ulint file_no; ib_longlong add_this_many; - + ib_lsn = ut_conv_dulint_to_longlong(lsn); ib_first_header_lsn = ut_conv_dulint_to_longlong(first_header_lsn); @@ -589,11 +589,11 @@ log_calc_where_lsn_is( add_this_many = 1 + (ib_first_header_lsn - ib_lsn) / (capacity * (ib_longlong)n_log_files); ib_lsn += add_this_many - * capacity * (ib_longlong)n_log_files; + * capacity * (ib_longlong)n_log_files; } ut_a(ib_lsn >= ib_first_header_lsn); - + file_no = ((ulint)((ib_lsn - ib_first_header_lsn) / capacity)) % n_log_files; *log_file_offset = (ib_lsn - ib_first_header_lsn) % capacity; @@ -634,7 +634,7 @@ log_calc_max_ages(void) ulint margin; ulint free; ibool success = TRUE; - ulint smallest_capacity; + ulint smallest_capacity; ulint archive_margin; ulint smallest_archive_margin; @@ -665,10 +665,10 @@ log_calc_max_ages(void) smallest_archive_margin = archive_margin; } - + group = UT_LIST_GET_NEXT(log_groups, group); } - + /* Add extra safety */ smallest_capacity = smallest_capacity - smallest_capacity / 10; @@ -676,7 +676,7 @@ log_calc_max_ages(void) smallest log group that it can accommodate the log entries produced by single query steps: running out of free log space is a serious system error which requires rebooting the database. */ - + free = LOG_CHECKPOINT_FREE_PER_THREAD * (10 + srv_thread_concurrency) + LOG_CHECKPOINT_EXTRA_FREE; if (free >= smallest_capacity / 2) { @@ -748,7 +748,7 @@ log_init(void) /* Start the lsn from one log block from zero: this way every log record has a start lsn != zero, a fact which we will use */ - + log_sys->lsn = LOG_START_LSN; ut_a(LOG_BUFFER_SIZE >= 16 * OS_FILE_LOG_BLOCK_SIZE); @@ -766,12 +766,12 @@ log_init(void) log_sys->check_flush_or_checkpoint = TRUE; UT_LIST_INIT(log_sys->log_groups); - log_sys->n_log_ios = 0; + log_sys->n_log_ios = 0; log_sys->n_log_ios_old = log_sys->n_log_ios; log_sys->last_printout_time = time(NULL); /*----------------------------*/ - + log_sys->buf_next_to_write = 0; log_sys->write_lsn = ut_dulint_zero; @@ -780,7 +780,7 @@ log_init(void) log_sys->written_to_some_lsn = log_sys->lsn; log_sys->written_to_all_lsn = log_sys->lsn; - + log_sys->n_pending_writes = 0; log_sys->no_flush_event = os_event_create(NULL); @@ -796,7 +796,7 @@ log_init(void) log_sys->next_checkpoint_no = ut_dulint_zero; log_sys->last_checkpoint_lsn = log_sys->lsn; - log_sys->n_pending_checkpoint_writes = 0; + log_sys->n_pending_checkpoint_writes = 0; rw_lock_create(&(log_sys->checkpoint_lock)); rw_lock_set_level(&(log_sys->checkpoint_lock), SYNC_NO_ORDER_CHECK); @@ -838,7 +838,7 @@ log_init(void) log_sys->buf_free = LOG_BLOCK_HDR_SIZE; log_sys->lsn = ut_dulint_add(LOG_START_LSN, LOG_BLOCK_HDR_SIZE); - + mutex_exit(&(log_sys->mutex)); #ifdef UNIV_LOG_DEBUG @@ -873,7 +873,7 @@ log_group_init( used */ { ulint i; - + log_group_t* group; group = mem_alloc(sizeof(log_group_t)); @@ -908,7 +908,7 @@ log_group_init( LOG_FILE_HDR_SIZE); #endif /* UNIV_LOG_ARCHIVE */ } - + #ifdef UNIV_LOG_ARCHIVE group->archive_space_id = archive_space_id; @@ -919,14 +919,14 @@ log_group_init( group->checkpoint_buf = ut_align( mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE), OS_FILE_LOG_BLOCK_SIZE); - + memset(group->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE); UT_LIST_ADD_LAST(log_groups, log_sys->log_groups, group); ut_a(log_calc_max_ages()); -} - +} + /********************************************************************** Does the unlockings needed in flush i/o completion. */ UNIV_INLINE @@ -949,7 +949,7 @@ log_flush_do_unlocks( this function would erroneously signal the NEW flush as completed. Thus, the changes in the state of these events are performed atomically in conjunction with the changes in the state of - log_sys->n_pending_writes etc. */ + log_sys->n_pending_writes etc. */ if (code & LOG_UNLOCK_NONE_FLUSHED_LOCK) { os_event_set(log_sys->one_flushed_event); @@ -1012,7 +1012,7 @@ log_sys_check_flush_completion(void) #endif /* UNIV_SYNC_DEBUG */ if (log_sys->n_pending_writes == 0) { - + log_sys->written_to_all_lsn = log_sys->write_lsn; log_sys->buf_next_to_write = log_sys->write_end_offset; @@ -1029,7 +1029,7 @@ log_sys_check_flush_completion(void) ut_memmove(log_sys->buf, log_sys->buf + move_start, move_end - move_start); log_sys->buf_free -= move_start; - + log_sys->buf_next_to_write -= move_start; } @@ -1065,8 +1065,8 @@ log_io_complete( if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC && srv_unix_file_flush_method != SRV_UNIX_NOSYNC) { - - fil_flush(group->space_id); + + fil_flush(group->space_id); } #ifdef UNIV_DEBUG @@ -1085,23 +1085,23 @@ log_io_complete( logs and cannot end up here! */ if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC - && srv_unix_file_flush_method != SRV_UNIX_NOSYNC - && srv_flush_log_at_trx_commit != 2) { + && srv_unix_file_flush_method != SRV_UNIX_NOSYNC + && srv_flush_log_at_trx_commit != 2) { - fil_flush(group->space_id); + fil_flush(group->space_id); } mutex_enter(&(log_sys->mutex)); ut_a(group->n_pending_writes > 0); ut_a(log_sys->n_pending_writes > 0); - + group->n_pending_writes--; log_sys->n_pending_writes--; unlock = log_group_check_flush_completion(group); unlock = unlock | log_sys_check_flush_completion(); - + log_flush_do_unlocks(unlock); mutex_exit(&(log_sys->mutex)); @@ -1145,17 +1145,17 @@ log_group_file_header_flush( } #endif /* UNIV_DEBUG */ if (log_do_write) { - log_sys->n_log_ios++; - - srv_os_log_pending_writes++; - + log_sys->n_log_ios++; + + srv_os_log_pending_writes++; + fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id, dest_offset / UNIV_PAGE_SIZE, dest_offset % UNIV_PAGE_SIZE, OS_FILE_LOG_BLOCK_SIZE, buf, group); - srv_os_log_pending_writes--; + srv_os_log_pending_writes--; } } @@ -1171,7 +1171,7 @@ log_block_store_checksum( { log_block_set_checksum(block, log_block_calc_checksum(block)); } - + /********************************************************** Writes a buffer to a log file group. */ @@ -1194,7 +1194,7 @@ log_group_write_buf( ibool write_header; ulint next_offset; ulint i; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(log_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -1215,13 +1215,13 @@ loop: next_offset = log_group_calc_lsn_offset(start_lsn, group); if ((next_offset % group->file_size == LOG_FILE_HDR_SIZE) - && write_header) { + && write_header) { /* We start to write a new log file instance in the group */ log_group_file_header_flush(group, next_offset / group->file_size, start_lsn); - srv_os_log_written+= OS_FILE_LOG_BLOCK_SIZE; - srv_log_writes++; + srv_os_log_written+= OS_FILE_LOG_BLOCK_SIZE; + srv_log_writes++; } if ((next_offset % group->file_size) + len > group->file_size) { @@ -1240,7 +1240,7 @@ loop: "start lsn %lu %lu\n" "First block n:o %lu last block n:o %lu\n", (ulong) group->id, (ulong) next_offset, - (ulong) write_len, + (ulong) write_len, (ulong) ut_dulint_get_high(start_lsn), (ulong) ut_dulint_get_low(start_lsn), (ulong) log_block_get_hdr_no(buf), @@ -1248,7 +1248,7 @@ loop: buf + write_len - OS_FILE_LOG_BLOCK_SIZE)); ut_a(log_block_get_hdr_no(buf) == log_block_convert_lsn_to_no(start_lsn)); - + for (i = 0; i < write_len / OS_FILE_LOG_BLOCK_SIZE; i++) { ut_a(log_block_get_hdr_no(buf) + i @@ -1265,18 +1265,18 @@ loop: } if (log_do_write) { - log_sys->n_log_ios++; + log_sys->n_log_ios++; + + srv_os_log_pending_writes++; - srv_os_log_pending_writes++; - fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id, next_offset / UNIV_PAGE_SIZE, next_offset % UNIV_PAGE_SIZE, write_len, buf, group); - srv_os_log_pending_writes--; + srv_os_log_pending_writes--; - srv_os_log_written+= write_len; - srv_log_writes++; + srv_os_log_written+= write_len; + srv_log_writes++; } if (write_len < len) { @@ -1331,46 +1331,48 @@ loop: if (loop_count > 2) { /* fprintf(stderr, "Log loop count %lu\n", loop_count); */ } - + mutex_enter(&(log_sys->mutex)); if (flush_to_disk - && ut_dulint_cmp(log_sys->flushed_to_disk_lsn, lsn) >= 0) { - + && ut_dulint_cmp(log_sys->flushed_to_disk_lsn, lsn) >= 0) { + mutex_exit(&(log_sys->mutex)); return; } if (!flush_to_disk - && (ut_dulint_cmp(log_sys->written_to_all_lsn, lsn) >= 0 - || (ut_dulint_cmp(log_sys->written_to_some_lsn, lsn) >= 0 - && wait != LOG_WAIT_ALL_GROUPS))) { + && (ut_dulint_cmp(log_sys->written_to_all_lsn, lsn) >= 0 + || (ut_dulint_cmp(log_sys->written_to_some_lsn, lsn) + >= 0 + && wait != LOG_WAIT_ALL_GROUPS))) { mutex_exit(&(log_sys->mutex)); return; } - + if (log_sys->n_pending_writes > 0) { /* A write (+ possibly flush to disk) is running */ if (flush_to_disk - && ut_dulint_cmp(log_sys->current_flush_lsn, lsn) >= 0) { + && ut_dulint_cmp(log_sys->current_flush_lsn, lsn) + >= 0) { /* The write + flush will write enough: wait for it to complete */ - + goto do_waits; } if (!flush_to_disk - && ut_dulint_cmp(log_sys->write_lsn, lsn) >= 0) { + && ut_dulint_cmp(log_sys->write_lsn, lsn) >= 0) { /* The write will write enough: wait for it to complete */ goto do_waits; } - + mutex_exit(&(log_sys->mutex)); /* Wait for the write to complete and try to start a new @@ -1403,7 +1405,7 @@ loop: log_sys->n_pending_writes++; group = UT_LIST_GET_FIRST(log_sys->log_groups); - group->n_pending_writes++; /* We assume here that we have only + group->n_pending_writes++; /* We assume here that we have only one log group! */ os_event_reset(log_sys->no_flush_event); @@ -1424,16 +1426,16 @@ loop: } log_sys->one_flushed = FALSE; - + log_block_set_flush_bit(log_sys->buf + area_start, TRUE); log_block_set_checkpoint_no( log_sys->buf + area_end - OS_FILE_LOG_BLOCK_SIZE, log_sys->next_checkpoint_no); - + /* Copy the last, incompletely written, log block a log block length up, so that when the flush operation writes from the log buffer, the segment to write will not be changed by writers to the log */ - + ut_memcpy(log_sys->buf + area_end, log_sys->buf + area_end - OS_FILE_LOG_BLOCK_SIZE, OS_FILE_LOG_BLOCK_SIZE); @@ -1454,7 +1456,7 @@ loop: start_offset - area_start); log_group_set_fields(group, log_sys->write_lsn); - + group = UT_LIST_GET_NEXT(log_groups, group); } @@ -1470,7 +1472,7 @@ loop: group = UT_LIST_GET_FIRST(log_sys->log_groups); - fil_flush(group->space_id); + fil_flush(group->space_id); log_sys->flushed_to_disk_lsn = log_sys->write_lsn; } @@ -1480,19 +1482,19 @@ loop: ut_a(group->n_pending_writes == 1); ut_a(log_sys->n_pending_writes == 1); - + group->n_pending_writes--; log_sys->n_pending_writes--; unlock = log_group_check_flush_completion(group); unlock = unlock | log_sys_check_flush_completion(); - + log_flush_do_unlocks(unlock); mutex_exit(&(log_sys->mutex)); return; - + do_waits: mutex_exit(&(log_sys->mutex)); @@ -1502,7 +1504,7 @@ do_waits: os_event_wait(log_sys->no_flush_event); } else { ut_ad(wait == LOG_NO_WAIT); - } + } } /******************************************************************** @@ -1538,7 +1540,7 @@ log_flush_margin(void) mutex_enter(&(log->mutex)); if (log->buf_free > log->max_buf_free) { - + if (log->n_pending_writes > 0) { /* A flush is running: hope that it will provide enough free space */ @@ -1582,7 +1584,7 @@ log_preflush_pool_modified_pages( not know how up-to-date the disk version of the database is, and we could not make a new checkpoint on the basis of the info on the buffer pool only. */ - + recv_apply_hashed_log_recs(TRUE); } @@ -1630,13 +1632,13 @@ log_io_complete_checkpoint(void) mutex_enter(&(log_sys->mutex)); ut_ad(log_sys->n_pending_checkpoint_writes > 0); - + log_sys->n_pending_checkpoint_writes--; if (log_sys->n_pending_checkpoint_writes == 0) { log_complete_checkpoint(); - } - + } + mutex_exit(&(log_sys->mutex)); } @@ -1699,10 +1701,12 @@ log_group_checkpoint( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(log_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ - ut_a(LOG_CHECKPOINT_SIZE <= OS_FILE_LOG_BLOCK_SIZE); - +#if LOG_CHECKPOINT_SIZE > OS_FILE_LOG_BLOCK_SIZE +# error "LOG_CHECKPOINT_SIZE > OS_FILE_LOG_BLOCK_SIZE" +#endif + buf = group->checkpoint_buf; - + mach_write_to_8(buf + LOG_CHECKPOINT_NO, log_sys->next_checkpoint_no); mach_write_to_8(buf + LOG_CHECKPOINT_LSN, log_sys->next_checkpoint_lsn); @@ -1710,7 +1714,7 @@ log_group_checkpoint( mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET, log_group_calc_lsn_offset( log_sys->next_checkpoint_lsn, group)); - + mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, log_sys->buf_size); #ifdef UNIV_LOG_ARCHIVE @@ -1723,7 +1727,7 @@ log_group_checkpoint( log_sys->next_archived_lsn)) { next_archived_lsn = log_sys->next_archived_lsn; /* For debugging only */ - } + } } mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, archived_lsn); @@ -1734,7 +1738,7 @@ log_group_checkpoint( for (i = 0; i < LOG_MAX_N_GROUPS; i++) { log_checkpoint_set_nth_group_info(buf, i, 0, 0); } - + group2 = UT_LIST_GET_FIRST(log_sys->log_groups); while (group2) { @@ -1768,16 +1772,16 @@ log_group_checkpoint( /* We alternate the physical place of the checkpoint info in the first log file */ - + if (ut_dulint_get_low(log_sys->next_checkpoint_no) % 2 == 0) { write_offset = LOG_CHECKPOINT_1; } else { write_offset = LOG_CHECKPOINT_2; } - + if (log_do_write) { if (log_sys->n_pending_checkpoint_writes == 0) { - + rw_lock_x_lock_gen(&(log_sys->checkpoint_lock), LOG_CHECKPOINT); } @@ -1785,11 +1789,11 @@ log_group_checkpoint( log_sys->n_pending_checkpoint_writes++; log_sys->n_log_ios++; - + /* We send as the last parameter the group machine address added with 1, as we want to distinguish between a normal log file write and a checkpoint field write */ - + fil_io(OS_FILE_WRITE | OS_FILE_LOG, FALSE, group->space_id, write_offset / UNIV_PAGE_SIZE, write_offset % UNIV_PAGE_SIZE, @@ -1816,7 +1820,7 @@ log_reset_first_header_and_checkpoint( ulint fold; byte* buf; dulint lsn; - + mach_write_to_4(hdr_buf + LOG_GROUP_ID, 0); mach_write_to_8(hdr_buf + LOG_FILE_START_LSN, start); @@ -1829,13 +1833,13 @@ log_reset_first_header_and_checkpoint( (char*) hdr_buf + (LOG_FILE_WAS_CREATED_BY_HOT_BACKUP + (sizeof "ibbackup ") - 1)); buf = hdr_buf + LOG_CHECKPOINT_1; - + mach_write_to_8(buf + LOG_CHECKPOINT_NO, ut_dulint_zero); mach_write_to_8(buf + LOG_CHECKPOINT_LSN, lsn); mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET, LOG_FILE_HDR_SIZE + LOG_BLOCK_HDR_SIZE); - + mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, 2 * 1024 * 1024); mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, ut_dulint_max); @@ -1866,7 +1870,7 @@ log_group_read_checkpoint_info( #endif /* UNIV_SYNC_DEBUG */ log_sys->n_log_ios++; - + fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, group->space_id, field / UNIV_PAGE_SIZE, field % UNIV_PAGE_SIZE, OS_FILE_LOG_BLOCK_SIZE, log_sys->checkpoint_buf, NULL); @@ -1921,7 +1925,7 @@ log_checkpoint( } if (srv_unix_file_flush_method != SRV_UNIX_NOSYNC) { - fil_flush_file_spaces(FIL_TABLESPACE); + fil_flush_file_spaces(FIL_TABLESPACE); } mutex_enter(&(log_sys->mutex)); @@ -1951,7 +1955,7 @@ log_checkpoint( } ut_ad(ut_dulint_cmp(log_sys->written_to_all_lsn, oldest_lsn) >= 0); - + if (log_sys->n_pending_checkpoint_writes > 0) { /* A checkpoint write is running */ @@ -2011,13 +2015,13 @@ log_make_checkpoint_at( /* Preflush pages synchronously */ success = FALSE; - + while (!success) { success = log_preflush_pool_modified_pages(lsn, TRUE); } success = FALSE; - + while (!success) { success = log_checkpoint(TRUE, write_always); } @@ -2053,12 +2057,12 @@ loop: mutex_exit(&(log->mutex)); return; - } + } oldest_lsn = log_buf_pool_get_oldest_modification(); age = ut_dulint_minus(log->lsn, oldest_lsn); - + if (age > log->max_modified_age_sync) { /* A flush is urgent: we have to do a synchronous preflush */ @@ -2077,7 +2081,7 @@ loop: if (checkpoint_age > log->max_checkpoint_age) { /* A checkpoint is urgent: we do it synchronously */ - + checkpoint_sync = TRUE; do_checkpoint = TRUE; @@ -2091,7 +2095,7 @@ loop: } else { log->check_flush_or_checkpoint = FALSE; } - + mutex_exit(&(log->mutex)); if (advance) { @@ -2109,7 +2113,7 @@ loop: mutex_enter(&(log->mutex)); log->check_flush_or_checkpoint = TRUE; - + mutex_exit(&(log->mutex)); goto loop; } @@ -2164,13 +2168,13 @@ loop: #ifdef UNIV_LOG_ARCHIVE if (type == LOG_ARCHIVE) { - + log_sys->n_pending_archive_ios++; } #endif /* UNIV_LOG_ARCHIVE */ log_sys->n_log_ios++; - + fil_io(OS_FILE_READ | OS_FILE_LOG, sync, group->space_id, source_offset / UNIV_PAGE_SIZE, source_offset % UNIV_PAGE_SIZE, len, buf, NULL); @@ -2233,7 +2237,7 @@ log_group_archive_file_header_write( dest_offset = nth_file * group->file_size; log_sys->n_log_ios++; - + fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->archive_space_id, dest_offset / UNIV_PAGE_SIZE, dest_offset % UNIV_PAGE_SIZE, @@ -2268,7 +2272,7 @@ log_group_archive_completed_header_write( dest_offset = nth_file * group->file_size + LOG_FILE_ARCH_COMPLETED; log_sys->n_log_ios++; - + fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->archive_space_id, dest_offset / UNIV_PAGE_SIZE, dest_offset % UNIV_PAGE_SIZE, @@ -2295,7 +2299,7 @@ log_group_archive( ulint next_offset; ulint n_files; ulint open_mode; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(log_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -2313,9 +2317,9 @@ log_group_archive( n_files = 0; next_offset = group->archived_offset; -loop: +loop: if ((next_offset % group->file_size == 0) - || (fil_space_get_size(group->archive_space_id) == 0)) { + || (fil_space_get_size(group->archive_space_id) == 0)) { /* Add the file to the archive file space; create or open the file */ @@ -2325,7 +2329,7 @@ loop: } else { open_mode = OS_FILE_OPEN; } - + log_archived_file_name_gen(name, group->id, group->archived_file_no + n_files); @@ -2354,11 +2358,11 @@ loop: #endif /* UNIV_DEBUG */ ret = os_file_close(file_handle); - + ut_a(ret); - + /* Add the archive file as a node to the space */ - + fil_node_create(name, group->file_size / UNIV_PAGE_SIZE, group->archive_space_id, FALSE); @@ -2368,7 +2372,7 @@ loop: start_lsn); next_offset += LOG_FILE_HDR_SIZE; - } + } } len = ut_dulint_minus(end_lsn, start_lsn); @@ -2391,7 +2395,7 @@ loop: log_sys->n_pending_archive_ios++; log_sys->n_log_ios++; - + fil_io(OS_FILE_WRITE | OS_FILE_LOG, FALSE, group->archive_space_id, next_offset / UNIV_PAGE_SIZE, next_offset % UNIV_PAGE_SIZE, ut_calc_align(len, OS_FILE_LOG_BLOCK_SIZE), buf, @@ -2406,7 +2410,7 @@ loop: } if (ut_dulint_cmp(end_lsn, start_lsn) != 0) { - + goto loop; } @@ -2464,14 +2468,14 @@ log_archive_write_complete_groups(void) file, or if it has been written full, all files */ n_files = (UNIV_PAGE_SIZE - * fil_space_get_size(group->archive_space_id)) - / group->file_size; + * fil_space_get_size(group->archive_space_id)) + / group->file_size; ut_ad(n_files > 0); - + end_offset = group->archived_offset; if (end_offset % group->file_size == 0) { - + trunc_files = n_files; } else { trunc_files = n_files - 1; @@ -2491,7 +2495,7 @@ log_archive_write_complete_groups(void) + trunc_files * (group->file_size - LOG_FILE_HDR_SIZE)); end_lsn = start_lsn; - + for (i = 0; i < trunc_files; i++) { end_lsn = ut_dulint_add(end_lsn, @@ -2502,7 +2506,7 @@ log_archive_write_complete_groups(void) log_group_archive_completed_header_write(group, i, end_lsn); } - + fil_space_truncate_start(group->archive_space_id, trunc_files * group->file_size); @@ -2533,22 +2537,22 @@ log_archive_check_completion_low(void) } #endif /* UNIV_DEBUG */ - /* Archive buffer has now been read in: start archive writes */ + /* Archive buffer has now been read in: start archive writes */ log_sys->archiving_phase = LOG_ARCHIVE_WRITE; log_archive_groups(); - } + } if (log_sys->n_pending_archive_ios == 0 && log_sys->archiving_phase == LOG_ARCHIVE_WRITE) { - log_archive_write_complete_groups(); + log_archive_write_complete_groups(); log_sys->archived_lsn = log_sys->next_archived_lsn; rw_lock_x_unlock_gen(&(log_sys->archive_lock), LOG_ARCHIVE); - } + } } /********************************************************** @@ -2567,11 +2571,11 @@ log_io_complete_archive(void) mutex_exit(&(log_sys->mutex)); fil_flush(group->archive_space_id); - + mutex_enter(&(log_sys->mutex)); - + ut_ad(log_sys->n_pending_archive_ios > 0); - + log_sys->n_pending_archive_ios--; log_archive_check_completion_low(); @@ -2594,9 +2598,9 @@ log_archive_do( ibool calc_new_limit; dulint start_lsn; dulint limit_lsn; - + calc_new_limit = TRUE; -loop: +loop: mutex_enter(&(log_sys->mutex)); if (log_sys->archiving_state == LOG_ARCH_OFF) { @@ -2607,26 +2611,26 @@ loop: return(TRUE); } else if (log_sys->archiving_state == LOG_ARCH_STOPPED - || log_sys->archiving_state == LOG_ARCH_STOPPING2) { + || log_sys->archiving_state == LOG_ARCH_STOPPING2) { mutex_exit(&(log_sys->mutex)); - + os_event_wait(log_sys->archiving_on); mutex_enter(&(log_sys->mutex)); goto loop; } - + start_lsn = log_sys->archived_lsn; - + if (calc_new_limit) { - ut_a(log_sys->archive_buf_size % OS_FILE_LOG_BLOCK_SIZE == 0); + ut_a(log_sys->archive_buf_size % OS_FILE_LOG_BLOCK_SIZE == 0); limit_lsn = ut_dulint_add(start_lsn, log_sys->archive_buf_size); *n_bytes = log_sys->archive_buf_size; - + if (ut_dulint_cmp(limit_lsn, log_sys->lsn) >= 0) { limit_lsn = ut_dulint_align_down(log_sys->lsn, @@ -2639,21 +2643,21 @@ loop: mutex_exit(&(log_sys->mutex)); *n_bytes = 0; - + return(TRUE); } if (ut_dulint_cmp(log_sys->written_to_all_lsn, limit_lsn) < 0) { mutex_exit(&(log_sys->mutex)); - + log_write_up_to(limit_lsn, LOG_WAIT_ALL_GROUPS, TRUE); calc_new_limit = FALSE; goto loop; } - + if (log_sys->n_pending_archive_ios > 0) { /* An archiving operation is running */ @@ -2667,7 +2671,7 @@ loop: *n_bytes = log_sys->archive_buf_size; return(FALSE); - } + } rw_lock_x_lock_gen(&(log_sys->archive_lock), LOG_ARCHIVE); @@ -2687,7 +2691,7 @@ loop: #endif /* UNIV_DEBUG */ /* Read the log segment to the archive buffer */ - + log_group_read_log_seg(LOG_ARCHIVE, log_sys->archive_buf, UT_LIST_GET_FIRST(log_sys->log_groups), start_lsn, limit_lsn); @@ -2700,7 +2704,7 @@ loop: } *n_bytes = log_sys->archive_buf_size; - + return(TRUE); } @@ -2714,7 +2718,7 @@ log_archive_all(void) { dulint present_lsn; ulint dummy; - + mutex_enter(&(log_sys->mutex)); if (log_sys->archiving_state == LOG_ARCH_OFF) { @@ -2728,22 +2732,22 @@ log_archive_all(void) mutex_exit(&(log_sys->mutex)); log_pad_current_log_block(); - + for (;;) { mutex_enter(&(log_sys->mutex)); if (ut_dulint_cmp(present_lsn, log_sys->archived_lsn) <= 0) { - + mutex_exit(&(log_sys->mutex)); return; } - + mutex_exit(&(log_sys->mutex)); log_archive_do(TRUE, &dummy); } -} +} /********************************************************* Closes the possible open archive log file (for each group) the first group, @@ -2770,10 +2774,10 @@ log_archive_close_groups( group = UT_LIST_GET_FIRST(log_sys->log_groups); trunc_len = UNIV_PAGE_SIZE - * fil_space_get_size(group->archive_space_id); + * fil_space_get_size(group->archive_space_id); if (trunc_len > 0) { ut_a(trunc_len == group->file_size); - + /* Write a notice to the headers of archived log files that the file write has been completed */ @@ -2792,7 +2796,7 @@ log_archive_close_groups( fprintf(stderr, "Incrementing arch file no to %lu in log group %lu\n", (ulong) group->archived_file_no + 2, - (ulong) group->id); + (ulong) group->id); } #endif /* UNIV_DEBUG */ } @@ -2818,10 +2822,10 @@ log_archive_stop(void) mutex_exit(&(log_sys->mutex)); return(DB_ERROR); - } + } log_sys->archiving_state = LOG_ARCH_STOPPING; - + mutex_exit(&(log_sys->mutex)); log_archive_all(); @@ -2834,7 +2838,7 @@ log_archive_stop(void) mutex_exit(&(log_sys->mutex)); /* Wait for a possible archiving operation to end */ - + rw_lock_s_lock(&(log_sys->archive_lock)); rw_lock_s_unlock(&(log_sys->archive_lock)); @@ -2851,7 +2855,7 @@ log_archive_stop(void) of new archived log files will start from the right value */ success = FALSE; - + while (!success) { success = log_checkpoint(TRUE, TRUE); } @@ -2859,7 +2863,7 @@ log_archive_stop(void) mutex_enter(&(log_sys->mutex)); log_sys->archiving_state = LOG_ARCH_STOPPED; - + mutex_exit(&(log_sys->mutex)); return(DB_SUCCESS); @@ -2880,8 +2884,8 @@ log_archive_start(void) mutex_exit(&(log_sys->mutex)); return(DB_ERROR); - } - + } + log_sys->archiving_state = LOG_ARCH_ON; os_event_set(log_sys->archiving_on); @@ -2903,24 +2907,24 @@ loop: mutex_enter(&(log_sys->mutex)); if (log_sys->archiving_state == LOG_ARCH_STOPPED - || log_sys->archiving_state == LOG_ARCH_OFF) { + || log_sys->archiving_state == LOG_ARCH_OFF) { log_sys->archiving_state = LOG_ARCH_OFF; - + os_event_set(log_sys->archiving_on); mutex_exit(&(log_sys->mutex)); return(DB_SUCCESS); - } + } mutex_exit(&(log_sys->mutex)); log_archive_stop(); os_thread_sleep(500000); - - goto loop; + + goto loop; } /******************************************************************** @@ -2942,11 +2946,11 @@ log_archive_archivelog(void) mutex_exit(&(log_sys->mutex)); return(DB_SUCCESS); - } + } mutex_exit(&(log_sys->mutex)); - return(DB_ERROR); + return(DB_ERROR); } /******************************************************************** @@ -2972,17 +2976,17 @@ loop: } age = ut_dulint_minus(log->lsn, log->archived_lsn); - + if (age > log->max_archived_lsn_age) { /* An archiving is urgent: we have to do synchronous i/o */ sync = TRUE; - + } else if (age > log->max_archived_lsn_age_async) { /* An archiving is not urgent: we do asynchronous i/o */ - + sync = FALSE; } else { /* No archiving required yet */ @@ -3024,7 +3028,7 @@ loop: #endif /* UNIV_LOG_ARCHIVE */ mutex_enter(&(log_sys->mutex)); - + if (log_sys->check_flush_or_checkpoint) { mutex_exit(&(log_sys->mutex)); @@ -3049,8 +3053,8 @@ logs_empty_and_mark_files_at_shutdown(void) ulint arch_log_no; if (srv_print_verbose_log) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Starting shutdown...\n"); + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Starting shutdown...\n"); } /* Wait until the master thread and all other operations are idle: our algorithm only works if the server is idle at shutdown */ @@ -3061,32 +3065,32 @@ loop: mutex_enter(&kernel_mutex); - /* Check that there are no longer transactions. We need this wait even - for the 'very fast' shutdown, because the InnoDB layer may have - committed or prepared transactions and we don't want to lose them. */ + /* Check that there are no longer transactions. We need this wait + even for the 'very fast' shutdown, because the InnoDB layer may have + committed or prepared transactions and we don't want to lose + them. */ if (trx_n_mysql_transactions > 0 || UT_LIST_GET_LEN(trx_sys->trx_list) > 0) { - + mutex_exit(&kernel_mutex); - + goto loop; } - if (srv_fast_shutdown == 2) { - /* In this fastest shutdown we do not flush the buffer pool: - it is essentially a 'crash' of the InnoDB server. - Make sure that the log is all flushed to disk, so that - we can recover all committed transactions in a crash - recovery. - We must not write the lsn stamps to the data files, since at a - startup InnoDB deduces from the stamps if the previous - shutdown was clean. */ + if (srv_fast_shutdown == 2) { + /* In this fastest shutdown we do not flush the buffer pool: + it is essentially a 'crash' of the InnoDB server. Make sure + that the log is all flushed to disk, so that we can recover + all committed transactions in a crash recovery. We must not + write the lsn stamps to the data files, since at a startup + InnoDB deduces from the stamps if the previous shutdown was + clean. */ - log_buffer_flush_to_disk(); - return; /* We SKIP ALL THE REST !! */ - } + log_buffer_flush_to_disk(); + return; /* We SKIP ALL THE REST !! */ + } /* Check that the master thread is suspended */ @@ -3098,7 +3102,7 @@ loop: } mutex_exit(&kernel_mutex); - + mutex_enter(&(log_sys->mutex)); if ( @@ -3107,12 +3111,12 @@ loop: #endif /* UNIV_LOG_ARCHIVE */ log_sys->n_pending_checkpoint_writes || log_sys->n_pending_writes) { - + mutex_exit(&(log_sys->mutex)); goto loop; - } - + } + mutex_exit(&(log_sys->mutex)); if (!buf_pool_check_no_pending_io()) { @@ -3130,19 +3134,20 @@ loop: lsn = log_sys->lsn; - if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0) + if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0) #ifdef UNIV_LOG_ARCHIVE - || (srv_log_archive_on - && ut_dulint_cmp(lsn, - ut_dulint_add(log_sys->archived_lsn, LOG_BLOCK_HDR_SIZE)) - != 0) + || (srv_log_archive_on + && ut_dulint_cmp(lsn, + ut_dulint_add(log_sys->archived_lsn, + LOG_BLOCK_HDR_SIZE)) + != 0) #endif /* UNIV_LOG_ARCHIVE */ ) { - mutex_exit(&(log_sys->mutex)); + mutex_exit(&(log_sys->mutex)); - goto loop; - } + goto loop; + } arch_log_no = 0; @@ -3179,7 +3184,7 @@ loop: completely flushed to disk! (We do not call fil_write... if the 'very fast' shutdown is enabled.) */ - if (!buf_all_freed()) { + if (!buf_all_freed()) { goto loop; } @@ -3192,7 +3197,7 @@ loop: } /* We now let also the InnoDB error monitor thread to exit */ - + srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE; if (srv_error_monitor_active) { @@ -3202,7 +3207,7 @@ loop: /* Make some checks that the server really is quiet */ ut_a(srv_n_threads_active[SRV_MASTER] == 0); - ut_a(buf_all_freed()); + ut_a(buf_all_freed()); ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn)); if (ut_dulint_cmp(lsn, srv_start_lsn) < 0) { @@ -3225,7 +3230,7 @@ loop: /* Make some checks that the server really is quiet */ ut_a(srv_n_threads_active[SRV_MASTER] == 0); - ut_a(buf_all_freed()); + ut_a(buf_all_freed()); ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn)); } @@ -3256,7 +3261,7 @@ log_check_log_recs( return(TRUE); } - + start = ut_align_down(buf, OS_FILE_LOG_BLOCK_SIZE); end = ut_align(buf + len, OS_FILE_LOG_BLOCK_SIZE); @@ -3264,10 +3269,10 @@ log_check_log_recs( scan_buf = ut_align(buf1, OS_FILE_LOG_BLOCK_SIZE); ut_memcpy(scan_buf, start, end - start); - + recv_scan_log_recs(TRUE, (buf_pool->n_frames - - recv_n_pool_free_frames) * UNIV_PAGE_SIZE, + recv_n_pool_free_frames) * UNIV_PAGE_SIZE, FALSE, scan_buf, end - start, ut_dulint_align_down(buf_start_lsn, OS_FILE_LOG_BLOCK_SIZE), @@ -3278,7 +3283,7 @@ log_check_log_recs( ut_a(ut_dulint_cmp(recv_sys->recovered_lsn, scanned_lsn) == 0); mem_free(buf1); - + return(TRUE); } @@ -3293,7 +3298,7 @@ log_peek_lsn( dulint* lsn) /* out: if returns TRUE, current lsn is here */ { if (0 == mutex_enter_nowait(&(log_sys->mutex), __FILE__, __LINE__)) { - *lsn = log_sys->lsn; + *lsn = log_sys->lsn; mutex_exit(&(log_sys->mutex)); @@ -3318,8 +3323,8 @@ log_print( fprintf(file, "Log sequence number %lu %lu\n" - "Log flushed up to %lu %lu\n" - "Last checkpoint at %lu %lu\n", + "Log flushed up to %lu %lu\n" + "Last checkpoint at %lu %lu\n", (ulong) ut_dulint_get_high(log_sys->lsn), (ulong) ut_dulint_get_low(log_sys->lsn), (ulong) ut_dulint_get_high(log_sys->flushed_to_disk_lsn), @@ -3328,7 +3333,7 @@ log_print( (ulong) ut_dulint_get_low(log_sys->last_checkpoint_lsn)); current_time = time(NULL); - + time_elapsed = 0.001 + difftime(current_time, log_sys->last_printout_time); fprintf(file, diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c index 42e854398ba..f210afe6b5d 100644 --- a/storage/innobase/log/log0recv.c +++ b/storage/innobase/log/log0recv.c @@ -90,7 +90,7 @@ the log and store the scanned log records in the buffer pool: we will use these free frames to read in pages when we start applying the log records to the database. */ -ulint recv_n_pool_free_frames = 256; +ulint recv_n_pool_free_frames = 256; /* The maximum lsn we see for a page during the recovery process. If this is bigger than the lsn we are able to scan up to, that is an indication that @@ -149,7 +149,7 @@ recv_sys_init( recv_sys->addr_hash = hash_create(available_memory / 64); recv_sys->n_addrs = 0; - + recv_sys->apply_log_recs = FALSE; recv_sys->apply_batch_on = FALSE; @@ -178,11 +178,11 @@ recv_sys_empty_hash(void) fprintf(stderr, "InnoDB: Error: %lu pages with log records were left unprocessed!\n" "InnoDB: Maximum page number with log records on it %lu\n", - (ulong) recv_sys->n_addrs, + (ulong) recv_sys->n_addrs, (ulong) recv_max_parsed_page_no); ut_error; } - + hash_table_free(recv_sys->addr_hash); mem_heap_empty(recv_sys->heap); @@ -197,7 +197,7 @@ recv_sys_free(void) /*===============*/ { mutex_enter(&(recv_sys->mutex)); - + hash_table_free(recv_sys->addr_hash); mem_heap_free(recv_sys->heap); ut_free(recv_sys->buf); @@ -241,7 +241,7 @@ recv_truncate_group( finish_lsn1 = ut_dulint_add(ut_dulint_align_down(archived_lsn, OS_FILE_LOG_BLOCK_SIZE), log_group_get_capacity(group)); - + finish_lsn2 = ut_dulint_add(ut_dulint_align_up(recovered_lsn, OS_FILE_LOG_BLOCK_SIZE), recv_sys->last_log_buf_size); @@ -255,8 +255,8 @@ recv_truncate_group( /* It is enough to erase the length of the log buffer */ finish_lsn = ut_dulint_get_min(finish_lsn1, finish_lsn2); } - - ut_a(RECV_SCAN_SIZE <= log_sys->buf_size); + + ut_a(RECV_SCAN_SIZE <= log_sys->buf_size); /* Write the log buffer full of zeros */ for (i = 0; i < RECV_SCAN_SIZE; i++) { @@ -266,7 +266,7 @@ recv_truncate_group( start_lsn = ut_dulint_align_down(recovered_lsn, OS_FILE_LOG_BLOCK_SIZE); - + if (ut_dulint_cmp(start_lsn, recovered_lsn) != 0) { /* Copy the last incomplete log block to the log buffer and edit its data length: */ @@ -276,22 +276,22 @@ recv_truncate_group( log_block_set_data_len(log_sys->buf, ut_dulint_minus(recovered_lsn, start_lsn)); } - + if (ut_dulint_cmp(start_lsn, finish_lsn) >= 0) { return; } - for (;;) { + for (;;) { end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE); - + if (ut_dulint_cmp(end_lsn, finish_lsn) > 0) { end_lsn = finish_lsn; } len = ut_dulint_minus(end_lsn, start_lsn); - + log_group_write_buf(group, log_sys->buf, len, start_lsn, 0); if (ut_dulint_cmp(end_lsn, finish_lsn) >= 0) { @@ -330,14 +330,14 @@ recv_copy_group( return; } - + ut_a(RECV_SCAN_SIZE <= log_sys->buf_size); start_lsn = ut_dulint_align_down(group->scanned_lsn, OS_FILE_LOG_BLOCK_SIZE); - for (;;) { + for (;;) { end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE); - + if (ut_dulint_cmp(end_lsn, recovered_lsn) > 0) { end_lsn = ut_dulint_align_up(recovered_lsn, OS_FILE_LOG_BLOCK_SIZE); @@ -347,9 +347,9 @@ recv_copy_group( up_to_date_group, start_lsn, end_lsn); len = ut_dulint_minus(end_lsn, start_lsn); - + log_group_write_buf(group, log_sys->buf, len, start_lsn, 0); - + if (ut_dulint_cmp(end_lsn, recovered_lsn) >= 0) { return; @@ -441,7 +441,7 @@ recv_check_cp_is_consistent( fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1); if ((fold & 0xFFFFFFFFUL) != mach_read_from_4(buf - + LOG_CHECKPOINT_CHECKSUM_1)) { + + LOG_CHECKPOINT_CHECKSUM_1)) { return(FALSE); } @@ -472,32 +472,32 @@ recv_find_max_checkpoint( dulint checkpoint_no; ulint field; byte* buf; - + group = UT_LIST_GET_FIRST(log_sys->log_groups); max_no = ut_dulint_zero; *max_group = NULL; *max_field = 0; - + buf = log_sys->checkpoint_buf; - + while (group) { group->state = LOG_GROUP_CORRUPTED; - + for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { - + log_group_read_checkpoint_info(group, field); if (!recv_check_cp_is_consistent(buf)) { #ifdef UNIV_DEBUG if (log_debug_writes) { - fprintf(stderr, - "InnoDB: Checkpoint in group %lu at %lu invalid, %lu\n", - (ulong) group->id, - (ulong) field, - (ulong) mach_read_from_4(buf - + LOG_CHECKPOINT_CHECKSUM_1)); + fprintf(stderr, + "InnoDB: Checkpoint in group %lu at %lu invalid, %lu\n", + (ulong) group->id, + (ulong) field, + (ulong) mach_read_from_4(buf + + LOG_CHECKPOINT_CHECKSUM_1)); } #endif /* UNIV_DEBUG */ @@ -515,7 +515,7 @@ recv_find_max_checkpoint( #ifdef UNIV_DEBUG if (log_debug_writes) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Checkpoint number %lu found in group %lu\n", (ulong) ut_dulint_get_low(checkpoint_no), (ulong) group->id); @@ -591,21 +591,21 @@ recv_read_cp_info_for_backup( } cp_buf = hdr + max_cp; - + *lsn = mach_read_from_8(cp_buf + LOG_CHECKPOINT_LSN); *offset = mach_read_from_4(cp_buf + LOG_CHECKPOINT_OFFSET); /* If the user is running a pre-3.23.50 version of InnoDB, its checkpoint data does not contain the fsp limit info */ if (mach_read_from_4(cp_buf + LOG_CHECKPOINT_FSP_MAGIC_N) - == LOG_CHECKPOINT_FSP_MAGIC_N_VAL) { - + == LOG_CHECKPOINT_FSP_MAGIC_N_VAL) { + *fsp_limit = mach_read_from_4( cp_buf + LOG_CHECKPOINT_FSP_FREE_LIMIT); if (*fsp_limit == 0) { *fsp_limit = 1000000000; - } + } } else { *fsp_limit = 1000000000; } @@ -678,16 +678,16 @@ recv_scan_log_seg_for_backup( ulint no; *n_bytes_scanned = 0; - + for (log_block = buf; log_block < buf + buf_len; log_block += OS_FILE_LOG_BLOCK_SIZE) { - + no = log_block_get_hdr_no(log_block); /* fprintf(stderr, "Log block header no %lu\n", no); */ if (no != log_block_convert_lsn_to_no(*scanned_lsn) - || !log_block_checksum_is_ok_or_old_format(log_block)) { + || !log_block_checksum_is_ok_or_old_format(log_block)) { /* fprintf(stderr, "Log block n:o %lu, scanned lsn n:o %lu\n", @@ -700,16 +700,16 @@ recv_scan_log_seg_for_backup( fprintf(stderr, "Next log block n:o %lu\n", log_block_get_hdr_no(log_block)); -*/ +*/ break; } if (*scanned_checkpoint_no > 0 - && log_block_get_checkpoint_no(log_block) - < *scanned_checkpoint_no - && *scanned_checkpoint_no + && log_block_get_checkpoint_no(log_block) + < *scanned_checkpoint_no + && *scanned_checkpoint_no - log_block_get_checkpoint_no(log_block) - > 0x80000000UL) { + > 0x80000000UL) { /* Garbage from a log buffer flush which was made before the most recent database recovery */ @@ -729,7 +729,7 @@ recv_scan_log_seg_for_backup( *scanned_lsn = ut_dulint_add(*scanned_lsn, data_len); *n_bytes_scanned += data_len; - + if (data_len < OS_FILE_LOG_BLOCK_SIZE) { /* Log data ends here */ @@ -769,7 +769,8 @@ recv_parse_or_apply_log_rec_body( if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_INSERT, &index))) { ut_a(!page - || (ibool)!!page_is_comp(page)==index->table->comp); + || (ibool)!!page_is_comp(page) + == dict_table_is_comp(index->table)); ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr, index, page, mtr); } @@ -778,7 +779,8 @@ recv_parse_or_apply_log_rec_body( if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_CLUST_DELETE_MARK, &index))) { ut_a(!page - || (ibool)!!page_is_comp(page)==index->table->comp); + || (ibool)!!page_is_comp(page) + == dict_table_is_comp(index->table)); ptr = btr_cur_parse_del_mark_set_clust_rec(ptr, end_ptr, index, page); } @@ -799,7 +801,8 @@ recv_parse_or_apply_log_rec_body( if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_UPDATE_IN_PLACE, &index))) { ut_a(!page - || (ibool)!!page_is_comp(page)==index->table->comp); + || (ibool)!!page_is_comp(page) + == dict_table_is_comp(index->table)); ptr = btr_cur_parse_update_in_place(ptr, end_ptr, page, index); } @@ -810,7 +813,8 @@ recv_parse_or_apply_log_rec_body( type == MLOG_COMP_LIST_END_DELETE || type == MLOG_COMP_LIST_START_DELETE, &index))) { ut_a(!page - || (ibool)!!page_is_comp(page)==index->table->comp); + || (ibool)!!page_is_comp(page) + == dict_table_is_comp(index->table)); ptr = page_parse_delete_rec_list(type, ptr, end_ptr, index, page, mtr); } @@ -819,7 +823,8 @@ recv_parse_or_apply_log_rec_body( if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_LIST_END_COPY_CREATED, &index))) { ut_a(!page - || (ibool)!!page_is_comp(page)==index->table->comp); + || (ibool)!!page_is_comp(page) + == dict_table_is_comp(index->table)); ptr = page_parse_copy_rec_list_to_created_page(ptr, end_ptr, index, page, mtr); } @@ -828,7 +833,8 @@ recv_parse_or_apply_log_rec_body( if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_PAGE_REORGANIZE, &index))) { ut_a(!page - || (ibool)!!page_is_comp(page)==index->table->comp); + || (ibool)!!page_is_comp(page) + == dict_table_is_comp(index->table)); ptr = btr_parse_page_reorganize(ptr, end_ptr, index, page, mtr); } @@ -862,7 +868,8 @@ recv_parse_or_apply_log_rec_body( if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_DELETE, &index))) { ut_a(!page - || (ibool)!!page_is_comp(page)==index->table->comp); + || (ibool)!!page_is_comp(page) + == dict_table_is_comp(index->table)); ptr = page_cur_parse_delete_rec(ptr, end_ptr, index, page, mtr); } @@ -894,7 +901,7 @@ recv_parse_or_apply_log_rec_body( mutex_free(&(table->autoinc_mutex)); mem_heap_free(table->heap); } - + return(ptr); } @@ -973,7 +980,7 @@ recv_add_to_hash_table( recv_data_t* recv_data; recv_data_t** prev_field; recv_addr_t* recv_addr; - + if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { /* The tablespace does not exist any more: do not store the log record */ @@ -990,7 +997,7 @@ recv_add_to_hash_table( recv->end_lsn = end_lsn; recv_addr = recv_get_fil_addr_struct(space, page_no); - + if (recv_addr == NULL) { recv_addr = mem_heap_alloc(recv_sys->heap, sizeof(recv_addr_t)); @@ -1015,15 +1022,15 @@ recv_add_to_hash_table( /* Store the log record body in chunks of less than UNIV_PAGE_SIZE: recv_sys->heap grows into the buffer pool, and bigger chunks could not be allocated */ - + while (rec_end > body) { len = rec_end - body; - + if (len > RECV_DATA_BLOCK_SIZE) { len = RECV_DATA_BLOCK_SIZE; } - + recv_data = mem_heap_alloc(recv_sys->heap, sizeof(recv_data_t) + len); *prev_field = recv_data; @@ -1105,17 +1112,17 @@ recv_recover_page( if (recv_sys->apply_log_recs == FALSE) { /* Log records should not be applied now */ - + mutex_exit(&(recv_sys->mutex)); return; } - + recv_addr = recv_get_fil_addr_struct(space, page_no); if ((recv_addr == NULL) - || (recv_addr->state == RECV_BEING_PROCESSED) - || (recv_addr->state == RECV_PROCESSED)) { + || (recv_addr->state == RECV_BEING_PROCESSED) + || (recv_addr->state == RECV_PROCESSED)) { mutex_exit(&(recv_sys->mutex)); @@ -1125,13 +1132,13 @@ recv_recover_page( /* fprintf(stderr, "Recovering space %lu, page %lu\n", space, page_no); */ recv_addr->state = RECV_BEING_PROCESSED; - + mutex_exit(&(recv_sys->mutex)); mtr_start(&mtr); mtr_set_log_mode(&mtr, MTR_LOG_NONE); - if (!recover_backup) { + if (!recover_backup) { block = buf_block_align(page); if (just_read_in) { @@ -1160,11 +1167,11 @@ recv_recover_page( if (!recover_backup) { /* It may be that the page has been modified in the buffer pool: read the newest modification lsn there */ - + page_newest_lsn = buf_frame_get_newest_modification(page); if (!ut_dulint_is_zero(page_newest_lsn)) { - + page_lsn = page_newest_lsn; } } else { @@ -1178,10 +1185,10 @@ recv_recover_page( start_lsn = end_lsn = ut_dulint_zero; recv = UT_LIST_GET_FIRST(recv_addr->rec_list); - + while (recv) { end_lsn = recv->end_lsn; - + if (recv->len > RECV_DATA_BLOCK_SIZE) { /* We have to copy the record body to a separate buffer */ @@ -1200,19 +1207,19 @@ recv_recover_page( - FIL_PAGE_END_LSN_OLD_CHKSUM, ut_dulint_zero); mach_write_to_8(page + FIL_PAGE_LSN, ut_dulint_zero); } - + if (ut_dulint_cmp(recv->start_lsn, page_lsn) >= 0) { if (!modification_to_page) { - + modification_to_page = TRUE; start_lsn = recv->start_lsn; } #ifdef UNIV_DEBUG if (log_debug_writes) { - fprintf(stderr, - "InnoDB: Applying log rec type %lu len %lu to space %lu page no %lu\n", + fprintf(stderr, + "InnoDB: Applying log rec type %lu len %lu to space %lu page no %lu\n", (ulong) recv->type, (ulong) recv->len, (ulong) recv_addr->space, (ulong) recv_addr->page_no); @@ -1229,7 +1236,7 @@ recv_recover_page( ut_dulint_add(recv->start_lsn, recv->len)); } - + if (recv->len > RECV_DATA_BLOCK_SIZE) { mem_free(buf); } @@ -1238,7 +1245,7 @@ recv_recover_page( } mutex_enter(&(recv_sys->mutex)); - + if (ut_dulint_cmp(recv_max_page_lsn, page_lsn) < 0) { recv_max_page_lsn = page_lsn; } @@ -1249,19 +1256,19 @@ recv_recover_page( recv_sys->n_addrs--; mutex_exit(&(recv_sys->mutex)); - + if (!recover_backup && modification_to_page) { ut_a(block); buf_flush_recv_note_modification(block, start_lsn, end_lsn); } - + /* Make sure that committing mtr does not change the modification lsn values of page */ - + mtr.modifications = FALSE; - - mtr_commit(&mtr); + + mtr_commit(&mtr); } /*********************************************************************** @@ -1294,12 +1301,12 @@ recv_read_in_area( if (recv_addr->state == RECV_NOT_PROCESSED) { recv_addr->state = RECV_BEING_READ; - + page_nos[n] = page_no; n++; } - + mutex_exit(&(recv_sys->mutex)); } } @@ -1310,7 +1317,7 @@ recv_read_in_area( */ return(n); } - + /*********************************************************************** Empties the hash table of stored log records, applying them to appropriate pages. */ @@ -1359,7 +1366,7 @@ loop: recv_sys->apply_batch_on = TRUE; for (i = 0; i < hash_get_n_cells(recv_sys->addr_hash); i++) { - + recv_addr = HASH_GET_FIRST(recv_sys->addr_hash, i); while (recv_addr) { @@ -1368,13 +1375,13 @@ loop: if (recv_addr->state == RECV_NOT_PROCESSED) { if (!has_printed) { - ut_print_timestamp(stderr); - fputs( + ut_print_timestamp(stderr); + fputs( " InnoDB: Starting an apply batch of log records to the database...\n" "InnoDB: Progress in percents: ",stderr); has_printed = TRUE; } - + mutex_exit(&(recv_sys->mutex)); if (buf_page_peek(space, page_no)) { @@ -1402,11 +1409,11 @@ loop: } if (has_printed - && (i * 100) / hash_get_n_cells(recv_sys->addr_hash) - != ((i + 1) * 100) - / hash_get_n_cells(recv_sys->addr_hash)) { + && (i * 100) / hash_get_n_cells(recv_sys->addr_hash) + != ((i + 1) * 100) + / hash_get_n_cells(recv_sys->addr_hash)) { - fprintf(stderr, "%lu ", + fprintf(stderr, "%lu ", (ulong) ((i * 100) / hash_get_n_cells(recv_sys->addr_hash))); } } @@ -1420,11 +1427,11 @@ loop: os_thread_sleep(500000); mutex_enter(&(recv_sys->mutex)); - } + } if (has_printed) { - fprintf(stderr, "\n"); + fprintf(stderr, "\n"); } if (!allow_ibuf) { @@ -1437,7 +1444,7 @@ loop: n_pages = buf_flush_batch(BUF_FLUSH_LIST, ULINT_MAX, ut_dulint_max); ut_a(n_pages != ULINT_UNDEFINED); - + buf_flush_wait_batch_end(BUF_FLUSH_LIST); buf_pool_invalidate(); @@ -1450,7 +1457,7 @@ loop: recv_sys->apply_log_recs = FALSE; recv_sys->apply_batch_on = FALSE; - + recv_sys_empty_hash(); if (has_printed) { @@ -1491,11 +1498,11 @@ recv_apply_log_recs_for_backup(void) fputs( "InnoDB: Starting an apply batch of log records to the database...\n" "InnoDB: Progress in percents: ", stderr); - + n_hash_cells = hash_get_n_cells(recv_sys->addr_hash); for (i = 0; i < n_hash_cells; i++) { - /* The address hash table is externally chained */ + /* The address hash table is externally chained */ recv_addr = hash_get_nth_cell(recv_sys->addr_hash, i)->node; while (recv_addr != NULL) { @@ -1505,7 +1512,7 @@ recv_apply_log_recs_for_backup(void) fprintf(stderr, "InnoDB: Warning: cannot apply log record to tablespace %lu page %lu,\n" "InnoDB: because tablespace with that id does not exist.\n", - recv_addr->space, recv_addr->page_no); +recv_addr->space, recv_addr->page_no); */ recv_addr->state = RECV_PROCESSED; @@ -1535,10 +1542,11 @@ recv_apply_log_recs_for_backup(void) recv_addr->space, recv_addr->page_no + 1); if (!success) { - fprintf(stderr, -"InnoDB: Fatal error: cannot extend tablespace %lu to hold %lu pages\n", - recv_addr->space, recv_addr->page_no); - + fprintf(stderr, + "InnoDB: Fatal error: cannot extend" + " tablespace %lu to hold %lu pages\n", + recv_addr->space, recv_addr->page_no); + exit(1); } @@ -1549,16 +1557,18 @@ recv_apply_log_recs_for_backup(void) recv_addr->page_no, 0, UNIV_PAGE_SIZE, page, NULL); if (error != DB_SUCCESS) { - fprintf(stderr, -"InnoDB: Fatal error: cannot read from tablespace %lu page number %lu\n", - (ulong) recv_addr->space, (ulong) recv_addr->page_no); - + fprintf(stderr, + "InnoDB: Fatal error: cannot read from tablespace" + " %lu page number %lu\n", + (ulong) recv_addr->space, + (ulong) recv_addr->page_no); + exit(1); } /* Apply the log records to this page */ recv_recover_page(TRUE, FALSE, page, recv_addr->space, - recv_addr->page_no); + recv_addr->page_no); /* Write the page back to the tablespace file using the fil0fil.c routines */ @@ -1577,7 +1587,7 @@ skip_this_recv_addr: if ((100 * i) / n_hash_cells != (100 * (i + 1)) / n_hash_cells) { fprintf(stderr, "%lu ", - (ulong) ((100 * i) / n_hash_cells)); + (ulong) ((100 * i) / n_hash_cells)); fflush(stderr); } } @@ -1612,7 +1622,7 @@ recv_update_replicate( #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(replica, SYNC_NO_ORDER_CHECK); #endif /* UNIV_SYNC_DEBUG */ - + ptr = recv_parse_or_apply_log_rec_body(type, body, end_ptr, replica, &mtr); ut_a(ptr == end_ptr); @@ -1624,7 +1634,7 @@ recv_update_replicate( /* Make sure that committing mtr does not call log routines, as we currently own the log mutex */ - + mtr.modifications = FALSE; mtr_commit(&mtr); @@ -1654,8 +1664,8 @@ recv_check_identical( ut_error; } } -} - +} + /*********************************************************************** In the debug version, checks that the replica of a file page is identical to the original page. */ @@ -1715,7 +1725,7 @@ recv_compare_spaces( page = buf_frame_alloc(); for (page_no = 0; page_no < n_pages; page_no++) { - + mtr_start(&mtr); frame = buf_page_get_gen(space1, page_no, RW_S_LATCH, NULL, @@ -1747,7 +1757,7 @@ recv_compare_spaces( fil_io(OS_FILE_READ, TRUE, space2, page_no, 0, UNIV_PAGE_SIZE, replica, NULL); } - + recv_check_identical(page + FIL_PAGE_DATA, replica + FIL_PAGE_DATA, PAGE_HEADER + PAGE_MAX_TRX_ID - FIL_PAGE_DATA); @@ -1780,7 +1790,7 @@ recv_compare_spaces_low( mutex_enter(&(log_sys->mutex)); recv_apply_hashed_log_recs(FALSE); - + mutex_exit(&(log_sys->mutex)); recv_compare_spaces(space1, space2, n_pages); @@ -1812,7 +1822,7 @@ recv_parse_log_rec( } if (*ptr == MLOG_MULTI_REC_END) { - + *type = *ptr; return(1); @@ -1832,7 +1842,7 @@ recv_parse_log_rec( if (UNIV_UNLIKELY(!new_ptr)) { - return(0); + return(0); } /* Check that page_no is sensible */ @@ -1854,7 +1864,7 @@ recv_parse_log_rec( if (*page_no > recv_max_parsed_page_no) { recv_max_parsed_page_no = *page_no; } - + return(new_ptr - ptr); } @@ -1870,15 +1880,15 @@ recv_calc_lsn_on_data_add( { ulint frag_len; ulint lsn_len; - + frag_len = (ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE) - - LOG_BLOCK_HDR_SIZE; + - LOG_BLOCK_HDR_SIZE; ut_ad(frag_len < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE - - LOG_BLOCK_TRL_SIZE); + - LOG_BLOCK_TRL_SIZE); lsn_len = len + ((len + frag_len) - / (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE - - LOG_BLOCK_TRL_SIZE)) - * (LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE); + / (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE + - LOG_BLOCK_TRL_SIZE)) + * (LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE); return(ut_dulint_add(lsn, lsn_len)); } @@ -1898,12 +1908,12 @@ recv_check_incomplete_log_recs( ulint space; ulint page_no; byte* body; - + for (i = 0; i < len; i++) { ut_a(0 == recv_parse_log_rec(ptr, ptr + i, &type, &space, &page_no, &body)); } -} +} /*********************************************************** Prints diagnostic info of corrupt log. */ @@ -1922,29 +1932,29 @@ recv_report_corrupt_log( "InnoDB: Log parsing proceeded successfully up to %lu %lu\n" "InnoDB: Previous log record type %lu, is multi %lu\n" "InnoDB: Recv offset %lu, prev %lu\n", - (ulong) type, (ulong) space, (ulong) page_no, - (ulong) ut_dulint_get_high(recv_sys->recovered_lsn), - (ulong) ut_dulint_get_low(recv_sys->recovered_lsn), - (ulong) recv_previous_parsed_rec_type, - (ulong) recv_previous_parsed_rec_is_multi, - (ulong) (ptr - recv_sys->buf), - (ulong) recv_previous_parsed_rec_offset); + (ulong) type, (ulong) space, (ulong) page_no, + (ulong) ut_dulint_get_high(recv_sys->recovered_lsn), + (ulong) ut_dulint_get_low(recv_sys->recovered_lsn), + (ulong) recv_previous_parsed_rec_type, + (ulong) recv_previous_parsed_rec_is_multi, + (ulong) (ptr - recv_sys->buf), + (ulong) recv_previous_parsed_rec_offset); if ((ulint)(ptr - recv_sys->buf + 100) - > recv_previous_parsed_rec_offset - && (ulint)(ptr - recv_sys->buf + 100 - - recv_previous_parsed_rec_offset) - < 200000) { + > recv_previous_parsed_rec_offset + && (ulint)(ptr - recv_sys->buf + 100 + - recv_previous_parsed_rec_offset) + < 200000) { fputs( "InnoDB: Hex dump of corrupt log starting 100 bytes before the start\n" "InnoDB: of the previous log rec,\n" "InnoDB: and ending 100 bytes after the start of the corrupt rec:\n", stderr); - + ut_print_buf(stderr, - recv_sys->buf + recv_previous_parsed_rec_offset - 100, - ptr - recv_sys->buf + 200 - - recv_previous_parsed_rec_offset); + recv_sys->buf + recv_previous_parsed_rec_offset - 100, + ptr - recv_sys->buf + 200 - + recv_previous_parsed_rec_offset); putc('\n', stderr); } @@ -1984,7 +1994,7 @@ recv_parse_log_recs( ulint page_no; byte* body; ulint n_recs; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(log_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -2018,7 +2028,7 @@ loop: recv_report_corrupt_log(ptr, type, space, page_no); } - + return(FALSE); } @@ -2032,7 +2042,7 @@ loop: return(FALSE); } - + recv_previous_parsed_rec_type = (ulint)type; recv_previous_parsed_rec_offset = recv_sys->recovered_offset; recv_previous_parsed_rec_is_multi = 0; @@ -2042,7 +2052,7 @@ loop: #ifdef UNIV_DEBUG if (log_debug_writes) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Parsed a single log rec type %lu len %lu space %lu page no %lu\n", (ulong) type, (ulong) len, (ulong) space, (ulong) page_no); @@ -2051,10 +2061,10 @@ loop: if (type == MLOG_DUMMY_RECORD) { /* Do nothing */ - + } else if (store_to_hash && (type == MLOG_FILE_CREATE - || type == MLOG_FILE_RENAME - || type == MLOG_FILE_DELETE)) { + || type == MLOG_FILE_RENAME + || type == MLOG_FILE_DELETE)) { #ifdef UNIV_HOTBACKUP if (recv_replay_file_ops) { @@ -2062,7 +2072,7 @@ loop: operation, if possible; note that fil_path_to_mysql_datadir is set in ibbackup to point to the datadir we should use there */ - + if (NULL == fil_op_log_parse_or_replay(body, end_ptr, type, TRUE, space)) { fprintf(stderr, @@ -2099,19 +2109,19 @@ loop: total_len = 0; n_recs = 0; - + for (;;) { len = recv_parse_log_rec(ptr, end_ptr, &type, &space, &page_no, &body); if (len == 0 || recv_sys->found_corrupt_log) { - if (recv_sys->found_corrupt_log) { + if (recv_sys->found_corrupt_log) { recv_report_corrupt_log(ptr, type, space, page_no); - } + } - return(FALSE); + return(FALSE); } recv_previous_parsed_rec_type = (ulint)type; @@ -2133,7 +2143,7 @@ loop: #ifdef UNIV_DEBUG if (log_debug_writes) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Parsed a multi log rec type %lu len %lu space %lu page no %lu\n", (ulong) type, (ulong) len, (ulong) space, (ulong) page_no); @@ -2204,11 +2214,11 @@ loop: recv_compare_replicate(space, page_no); #endif /* UNIV_LOG_REPLICATE */ } - + ptr += len; } } - + goto loop; } @@ -2247,7 +2257,7 @@ recv_sys_add_to_parsing_buf( } else if (ut_dulint_cmp(recv_sys->scanned_lsn, scanned_lsn) >= 0) { return(FALSE); - + } else if (ut_dulint_cmp(recv_sys->parse_start_lsn, recv_sys->scanned_lsn) > 0) { more_len = ut_dulint_minus(scanned_lsn, @@ -2260,7 +2270,7 @@ recv_sys_add_to_parsing_buf( return(FALSE); } - + ut_ad(data_len >= more_len); start_offset = data_len - more_len; @@ -2295,7 +2305,7 @@ static void recv_sys_justify_left_parsing_buf(void) /*===================================*/ -{ +{ ut_memmove(recv_sys->buf, recv_sys->buf + recv_sys->recovered_offset, recv_sys->len - recv_sys->recovered_offset); @@ -2343,13 +2353,13 @@ recv_scan_log_recs( ut_ad(len > 0); ut_a(apply_automatically <= TRUE); ut_a(store_to_hash <= TRUE); - + finished = FALSE; - + log_block = buf; scanned_lsn = start_lsn; more_data = FALSE; - + while (log_block < buf + len && !finished) { no = log_block_get_hdr_no(log_block); @@ -2360,11 +2370,11 @@ recv_scan_log_recs( log_block_convert_lsn_to_no(scanned_lsn)); */ if (no != log_block_convert_lsn_to_no(scanned_lsn) - || !log_block_checksum_is_ok_or_old_format(log_block)) { + || !log_block_checksum_is_ok_or_old_format(log_block)) { if (no == log_block_convert_lsn_to_no(scanned_lsn) - && !log_block_checksum_is_ok_or_old_format( - log_block)) { + && !log_block_checksum_is_ok_or_old_format( + log_block)) { fprintf(stderr, "InnoDB: Log block no %lu at lsn %lu %lu has\n" "InnoDB: ok header, but checksum field contains %lu, should be %lu\n", @@ -2398,14 +2408,14 @@ recv_scan_log_recs( data_len = log_block_get_data_len(log_block); if ((store_to_hash || (data_len == OS_FILE_LOG_BLOCK_SIZE)) - && (ut_dulint_cmp(ut_dulint_add(scanned_lsn, data_len), - recv_sys->scanned_lsn) > 0) - && (recv_sys->scanned_checkpoint_no > 0) - && (log_block_get_checkpoint_no(log_block) - < recv_sys->scanned_checkpoint_no) - && (recv_sys->scanned_checkpoint_no - - log_block_get_checkpoint_no(log_block) - > 0x80000000UL)) { + && (ut_dulint_cmp(ut_dulint_add(scanned_lsn, data_len), + recv_sys->scanned_lsn) > 0) + && (recv_sys->scanned_checkpoint_no > 0) + && (log_block_get_checkpoint_no(log_block) + < recv_sys->scanned_checkpoint_no) + && (recv_sys->scanned_checkpoint_no + - log_block_get_checkpoint_no(log_block) + > 0x80000000UL)) { /* Garbage from a log buffer flush which was made before the most recent database recovery */ @@ -2418,8 +2428,8 @@ recv_scan_log_recs( ut_error; #endif break; - } - + } + if (ut_dulint_is_zero(recv_sys->parse_start_lsn) && (log_block_get_first_rec_group(log_block) > 0)) { @@ -2457,7 +2467,7 @@ recv_scan_log_recs( recv_sys->scanned_checkpoint_no = log_block_get_checkpoint_no(log_block); } - + if (data_len < OS_FILE_LOG_BLOCK_SIZE) { /* Log data for this group ends here */ @@ -2470,12 +2480,12 @@ recv_scan_log_recs( *group_scanned_lsn = scanned_lsn; if (recv_needed_recovery - || (recv_is_from_backup && !recv_is_making_a_backup)) { + || (recv_is_from_backup && !recv_is_making_a_backup)) { recv_scan_print_counter++; if (finished || (recv_scan_print_counter % 80 == 0)) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Doing recovery: scanned up to log sequence number %lu %lu\n", (ulong) ut_dulint_get_high(*group_scanned_lsn), (ulong) ut_dulint_get_low(*group_scanned_lsn)); @@ -2488,27 +2498,27 @@ recv_scan_log_recs( recv_parse_log_recs(store_to_hash); if (store_to_hash && mem_heap_get_size(recv_sys->heap) - > available_memory - && apply_automatically) { - + > available_memory + && apply_automatically) { + /* Hash table of log records has grown too big: empty it; FALSE means no ibuf operations allowed, as we cannot add new records to the log yet: they would be produced by ibuf operations */ - + recv_apply_hashed_log_recs(FALSE); - } + } if (recv_sys->recovered_offset > RECV_PARSING_BUF_SIZE / 4) { /* Move parsing buffer data to the buffer start */ recv_sys_justify_left_parsing_buf(); - } + } } return(finished); -} +} /*********************************************************** Scans log from a buffer and stores new log data to the parsing buffer. Parses @@ -2517,7 +2527,7 @@ static void recv_group_scan_log_recs( /*=====================*/ - log_group_t* group, /* in: log group */ + log_group_t* group, /* in: log group */ dulint* contiguous_lsn, /* in/out: it is known that all log groups contain contiguous log data up to this lsn */ dulint* group_scanned_lsn)/* out: scanning succeeded up to this lsn */ @@ -2525,20 +2535,20 @@ recv_group_scan_log_recs( ibool finished; dulint start_lsn; dulint end_lsn; - + finished = FALSE; start_lsn = *contiguous_lsn; - - while (!finished) { + + while (!finished) { end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE); log_group_read_log_seg(LOG_RECOVER, log_sys->buf, group, start_lsn, end_lsn); finished = recv_scan_log_recs(TRUE, - (buf_pool->n_frames - - recv_n_pool_free_frames) * UNIV_PAGE_SIZE, + (buf_pool->n_frames + - recv_n_pool_free_frames) * UNIV_PAGE_SIZE, TRUE, log_sys->buf, RECV_SCAN_SIZE, start_lsn, contiguous_lsn, group_scanned_lsn); @@ -2588,7 +2598,7 @@ recv_recovery_from_checkpoint_start( ut_ad((type != LOG_CHECKPOINT) || (ut_dulint_cmp(limit_lsn, ut_dulint_max) == 0)); - + if (type == LOG_CHECKPOINT) { recv_sys_create(); recv_sys_init(FALSE, buf_pool_get_curr_size()); @@ -2599,7 +2609,7 @@ recv_recovery_from_checkpoint_start( "InnoDB: The user has set SRV_FORCE_NO_LOG_REDO on\n"); fprintf(stderr, "InnoDB: Skipping log redo\n"); - + return(DB_SUCCESS); } @@ -2610,7 +2620,7 @@ recv_recovery_from_checkpoint_start( mutex_enter(&(log_sys->mutex)); /* Look for the latest checkpoint from any of the log groups */ - + err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field); if (err != DB_SUCCESS) { @@ -2619,7 +2629,7 @@ recv_recovery_from_checkpoint_start( return(err); } - + log_group_read_checkpoint_info(max_cp_group, max_cp_field); buf = log_sys->checkpoint_buf; @@ -2630,7 +2640,7 @@ recv_recovery_from_checkpoint_start( /* Read the first log file header to print a note if this is a recovery from a restored InnoDB Hot Backup */ - + fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, max_cp_group->space_id, 0, 0, LOG_FILE_HDR_SIZE, log_hdr_buf, max_cp_group); @@ -2645,7 +2655,7 @@ recv_recovery_from_checkpoint_start( "InnoDB: %s\n", log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP); fprintf(stderr, "InnoDB: NOTE: the following crash recovery is part of a normal restore.\n"); - + /* Wipe over the label now */ memset(log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, @@ -2657,7 +2667,7 @@ recv_recovery_from_checkpoint_start( log_hdr_buf, max_cp_group); } -#ifdef UNIV_LOG_ARCHIVE +#ifdef UNIV_LOG_ARCHIVE group = UT_LIST_GET_FIRST(log_sys->log_groups); while (group) { @@ -2684,9 +2694,9 @@ recv_recovery_from_checkpoint_start( /* NOTE: we always do a 'recovery' at startup, but only if there is something wrong we will print a message to the user about recovery: */ - + if (ut_dulint_cmp(checkpoint_lsn, max_flushed_lsn) != 0 - || ut_dulint_cmp(checkpoint_lsn, min_flushed_lsn) != 0) { + || ut_dulint_cmp(checkpoint_lsn, min_flushed_lsn) != 0) { if (ut_dulint_cmp(checkpoint_lsn, max_flushed_lsn) < 0) { @@ -2708,11 +2718,11 @@ recv_recovery_from_checkpoint_start( (ulong) ut_dulint_get_low(max_flushed_lsn)); } - recv_needed_recovery = TRUE; - + recv_needed_recovery = TRUE; + ut_print_timestamp(stderr); - fprintf(stderr, + fprintf(stderr, " InnoDB: Database was not shut down normally!\n" "InnoDB: Starting crash recovery.\n"); @@ -2725,9 +2735,9 @@ recv_recovery_from_checkpoint_start( check if there are half-written pages in data files, and restore them from the doublewrite buffer if possible */ - + if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { - + fprintf(stderr, "InnoDB: Restoring possible half-written data pages from the doublewrite\n" "InnoDB: buffer...\n"); @@ -2737,10 +2747,10 @@ recv_recovery_from_checkpoint_start( ut_print_timestamp(stderr); - fprintf(stderr, + fprintf(stderr, " InnoDB: Starting log scan based on checkpoint at\n" "InnoDB: log sequence number %lu %lu.\n", - (ulong) ut_dulint_get_high(checkpoint_lsn), + (ulong) ut_dulint_get_high(checkpoint_lsn), (ulong) ut_dulint_get_low(checkpoint_lsn)); } else { /* Init the doublewrite buffer memory structure */ @@ -2751,7 +2761,7 @@ recv_recovery_from_checkpoint_start( contiguous_lsn = ut_dulint_align_down(recv_sys->scanned_lsn, OS_FILE_LOG_BLOCK_SIZE); if (type == LOG_ARCHIVE) { - /* Try to recover the remaining part from logs: first from + /* Try to recover the remaining part from logs: first from the logs of the archived group */ group = recv_sys->archive_group; @@ -2769,7 +2779,7 @@ recv_recovery_from_checkpoint_start( return(DB_ERROR); } - + recv_group_scan_log_recs(group, &contiguous_lsn, &group_scanned_lsn); if (ut_dulint_cmp(recv_sys->scanned_lsn, checkpoint_lsn) < 0) { @@ -2795,25 +2805,25 @@ recv_recovery_from_checkpoint_start( if ((type == LOG_ARCHIVE) && (group == recv_sys->archive_group)) { group = UT_LIST_GET_NEXT(log_groups, group); - } + } - while (group) { + while (group) { old_scanned_lsn = recv_sys->scanned_lsn; recv_group_scan_log_recs(group, &contiguous_lsn, &group_scanned_lsn); group->scanned_lsn = group_scanned_lsn; - + if (ut_dulint_cmp(old_scanned_lsn, group_scanned_lsn) < 0) { /* We found a more up-to-date group */ up_to_date_group = group; } - + if ((type == LOG_ARCHIVE) && (group == recv_sys->archive_group)) { group = UT_LIST_GET_NEXT(log_groups, group); - } + } group = UT_LIST_GET_NEXT(log_groups, group); } @@ -2856,7 +2866,7 @@ recv_recovery_from_checkpoint_start( return(DB_ERROR); } - + /* Synchronize the uncorrupted log groups to the most up-to-date log group; we also copy checkpoint info to groups */ @@ -2866,7 +2876,7 @@ recv_recovery_from_checkpoint_start( #ifdef UNIV_LOG_ARCHIVE log_sys->archived_lsn = archived_lsn; #endif /* UNIV_LOG_ARCHIVE */ - + recv_synchronize_groups(up_to_date_group); if (!recv_needed_recovery) { @@ -2883,7 +2893,7 @@ recv_recovery_from_checkpoint_start( } else { srv_start_lsn = recv_sys->recovered_lsn; } - + log_sys->lsn = recv_sys->recovered_lsn; ut_memcpy(log_sys->buf, recv_sys->last_block, OS_FILE_LOG_BLOCK_SIZE); @@ -2895,9 +2905,9 @@ recv_recovery_from_checkpoint_start( log_sys->written_to_all_lsn = log_sys->lsn; log_sys->last_checkpoint_lsn = checkpoint_lsn; - + log_sys->next_checkpoint_no = ut_dulint_add(checkpoint_no, 1); - + #ifdef UNIV_LOG_ARCHIVE if (ut_dulint_cmp(archived_lsn, ut_dulint_max) == 0) { @@ -2906,11 +2916,11 @@ recv_recovery_from_checkpoint_start( #endif /* UNIV_LOG_ARCHIVE */ mutex_enter(&(recv_sys->mutex)); - + recv_sys->apply_log_recs = TRUE; - mutex_exit(&(recv_sys->mutex)); - + mutex_exit(&(recv_sys->mutex)); + mutex_exit(&(log_sys->mutex)); recv_lsn_checks_on = TRUE; @@ -2929,11 +2939,11 @@ void recv_recovery_from_checkpoint_finish(void) /*======================================*/ { - int i; + int i; os_thread_id_t recovery_thread_id; /* Apply the hashed log records to the respective file pages */ - + if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { recv_apply_hashed_log_recs(TRUE); @@ -3007,7 +3017,7 @@ recv_reset_logs( group->lsn = log_sys->lsn; group->lsn_offset = LOG_FILE_HDR_SIZE; #ifdef UNIV_LOG_ARCHIVE - group->archived_file_no = arch_log_no; + group->archived_file_no = arch_log_no; group->archived_offset = 0; #endif /* UNIV_LOG_ARCHIVE */ @@ -3015,7 +3025,7 @@ recv_reset_logs( recv_truncate_group(group, group->lsn, group->lsn, group->lsn, group->lsn); } - + group = UT_LIST_GET_NEXT(log_groups, group); } @@ -3029,20 +3039,20 @@ recv_reset_logs( #ifdef UNIV_LOG_ARCHIVE log_sys->archived_lsn = log_sys->lsn; #endif /* UNIV_LOG_ARCHIVE */ - + log_block_init(log_sys->buf, log_sys->lsn); log_block_set_first_rec_group(log_sys->buf, LOG_BLOCK_HDR_SIZE); log_sys->buf_free = LOG_BLOCK_HDR_SIZE; log_sys->lsn = ut_dulint_add(log_sys->lsn, LOG_BLOCK_HDR_SIZE); - + mutex_exit(&(log_sys->mutex)); /* Reset the checkpoint fields in logs */ - + log_make_checkpoint_at(ut_dulint_max, TRUE); log_make_checkpoint_at(ut_dulint_max, TRUE); - + mutex_enter(&(log_sys->mutex)); } @@ -3064,22 +3074,22 @@ recv_reset_log_files_for_backup( byte* buf; ulint i; ulint log_dir_len; - char* name; - static const - char logfilename[] = "ib_logfile"; + char name[5000]; + static const char ib_logfile_basename[] = "ib_logfile"; log_dir_len = strlen(log_dir); - /* reserve space for log_dir, "ib_logfile" and a number */ - name = memcpy(mem_alloc(log_dir_len + ((sizeof logfilename) + 11)), - log_dir, log_dir_len); - memcpy(name + log_dir_len, logfilename, sizeof logfilename); + /* full path name of ib_logfile consists of log dir path + basename + + number. This must fit in the name buffer. + */ + ut_a(log_dir_len + strlen(ib_logfile_basename) + 11 < sizeof(name)); buf = ut_malloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE); - memset(buf, '\0', LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE); + memset(buf, '\0', LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE); for (i = 0; i < n_log_files; i++) { - sprintf(name + log_dir_len + sizeof logfilename, "%lu", (ulong) i); + sprintf(name, "%s%s%lu", log_dir, + ib_logfile_basename, (ulong)i); log_file = os_file_create_simple(name, OS_FILE_CREATE, OS_FILE_READ_WRITE, &success); @@ -3111,13 +3121,13 @@ recv_reset_log_files_for_backup( } /* We pretend there is a checkpoint at lsn + LOG_BLOCK_HDR_SIZE */ - + log_reset_first_header_and_checkpoint(buf, lsn); - + log_block_init_in_old_format(buf + LOG_FILE_HDR_SIZE, lsn); log_block_set_first_rec_group(buf + LOG_FILE_HDR_SIZE, LOG_BLOCK_HDR_SIZE); - strcpy(name + log_dir_len + sizeof logfilename, "0"); + sprintf(name, "%s%s%lu", log_dir, ib_logfile_basename, (ulong)0); log_file = os_file_create_simple(name, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success); @@ -3132,7 +3142,6 @@ recv_reset_log_files_for_backup( os_file_flush(log_file); os_file_close(log_file); - mem_free(name); ut_free(buf); } #endif /* UNIV_HOTBACKUP */ @@ -3164,11 +3173,11 @@ log_group_recover_from_archive_file( ut_a(0); -try_open_again: +try_open_again: buf = log_sys->buf; /* Add the file to the archive file space; open the file */ - + log_archived_file_name_gen(name, group->id, group->archived_file_no); file_handle = os_file_create(name, OS_FILE_OPEN, @@ -3176,12 +3185,12 @@ try_open_again: if (ret == FALSE) { ask_again: - fprintf(stderr, + fprintf(stderr, "InnoDB: Do you want to copy additional archived log files\n" "InnoDB: to the directory\n"); - fprintf(stderr, + fprintf(stderr, "InnoDB: or were these all the files needed in recovery?\n"); - fprintf(stderr, + fprintf(stderr, "InnoDB: (Y == copy more files; N == this is all)?"); input_char = getchar(); @@ -3201,25 +3210,27 @@ ask_again: ut_a(ret); ut_a(file_size_high == 0); - + fprintf(stderr, "InnoDB: Opened archived log file %s\n", name); - + ret = os_file_close(file_handle); - + if (file_size < LOG_FILE_HDR_SIZE) { fprintf(stderr, "InnoDB: Archive file header incomplete %s\n", name); - + return(TRUE); } ut_a(ret); - + /* Add the archive file as a node to the space */ - + fil_node_create(name, 1 + file_size / UNIV_PAGE_SIZE, - group->archive_space_id, FALSE); - ut_a(RECV_SCAN_SIZE >= LOG_FILE_HDR_SIZE); + group->archive_space_id, FALSE); +#if RECV_SCAN_SIZE < LOG_FILE_HDR_SIZE +# error "RECV_SCAN_SIZE < LOG_FILE_HDR_SIZE" +#endif /* Read the archive file header */ fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, group->archive_space_id, 0, 0, @@ -3228,11 +3239,11 @@ ask_again: /* Check if the archive file header is consistent */ if (mach_read_from_4(buf + LOG_GROUP_ID) != group->id - || mach_read_from_4(buf + LOG_FILE_NO) - != group->archived_file_no) { + || mach_read_from_4(buf + LOG_FILE_NO) + != group->archived_file_no) { fprintf(stderr, "InnoDB: Archive file header inconsistent %s\n", name); - + return(TRUE); } @@ -3242,22 +3253,22 @@ ask_again: return(TRUE); } - + start_lsn = mach_read_from_8(buf + LOG_FILE_START_LSN); file_end_lsn = mach_read_from_8(buf + LOG_FILE_END_LSN); if (ut_dulint_is_zero(recv_sys->scanned_lsn)) { if (ut_dulint_cmp(recv_sys->parse_start_lsn, start_lsn) < 0) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Archive log file %s starts from too big a lsn\n", - name); + name); return(TRUE); } - + recv_sys->scanned_lsn = start_lsn; } - + if (ut_dulint_cmp(recv_sys->scanned_lsn, start_lsn) != 0) { fprintf(stderr, @@ -3267,7 +3278,7 @@ ask_again: } read_offset = LOG_FILE_HDR_SIZE; - + for (;;) { len = RECV_SCAN_SIZE; @@ -3280,10 +3291,10 @@ ask_again: break; } - + #ifdef UNIV_DEBUG if (log_debug_writes) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Archive read starting at lsn %lu %lu, len %lu from file %s\n", (ulong) ut_dulint_get_high(start_lsn), (ulong) ut_dulint_get_low(start_lsn), @@ -3296,8 +3307,8 @@ ask_again: read_offset % UNIV_PAGE_SIZE, len, buf, NULL); ret = recv_scan_log_recs(TRUE, - (buf_pool->n_frames - - recv_n_pool_free_frames) * UNIV_PAGE_SIZE, + (buf_pool->n_frames - + recv_n_pool_free_frames) * UNIV_PAGE_SIZE, TRUE, buf, len, start_lsn, &dummy_lsn, &scanned_lsn); @@ -3309,10 +3320,10 @@ ask_again: if (ret) { fprintf(stderr, "InnoDB: Archive log file %s does not scan right\n", - name); + name); return(TRUE); } - + read_offset += len; start_lsn = ut_dulint_add(start_lsn, len); @@ -3342,12 +3353,12 @@ recv_recovery_from_archive_start( ulint trunc_len; ibool ret; ulint err; - + ut_a(0); recv_sys_create(); recv_sys_init(FALSE, buf_pool_get_curr_size()); - + recv_recovery_on = TRUE; recv_recovery_from_backup_on = TRUE; @@ -3360,9 +3371,9 @@ recv_recovery_from_archive_start( while (group) { if (group->id == group_id) { - break; + break; } - + group = UT_LIST_GET_NEXT(log_groups, group); } @@ -3384,7 +3395,7 @@ recv_recovery_from_archive_start( recv_sys->archive_group = group; ret = FALSE; - + mutex_enter(&(log_sys->mutex)); while (!ret) { @@ -3392,9 +3403,9 @@ recv_recovery_from_archive_start( /* Close and truncate a possible processed archive file from the file space */ - + trunc_len = UNIV_PAGE_SIZE - * fil_space_get_size(group->archive_space_id); + * fil_space_get_size(group->archive_space_id); if (trunc_len > 0) { fil_space_truncate_start(group->archive_space_id, trunc_len); diff --git a/storage/innobase/mach/mach0data.c b/storage/innobase/mach/mach0data.c index ff7265b34f4..b92293fd037 100644 --- a/storage/innobase/mach/mach0data.c +++ b/storage/innobase/mach/mach0data.c @@ -1,6 +1,6 @@ /********************************************************************** Utilities for converting data from the database file -to the machine format. +to the machine format. (c) 1995 Innobase Oy @@ -21,9 +21,9 @@ mach_parse_compressed( /*==================*/ /* out: pointer to end of the stored field, NULL if not complete */ - byte* ptr, /* in: pointer to buffer from where to read */ + byte* ptr, /* in: pointer to buffer from where to read */ byte* end_ptr,/* in: pointer to end of the buffer */ - ulint* val) /* out: read value (< 2^32) */ + ulint* val) /* out: read value (< 2^32) */ { ulint flag; @@ -39,21 +39,21 @@ mach_parse_compressed( if (flag < 0x80UL) { *val = flag; return(ptr + 1); - + } else if (flag < 0xC0UL) { if (end_ptr < ptr + 2) { return(NULL); } - + *val = mach_read_from_2(ptr) & 0x7FFFUL; return(ptr + 2); - + } else if (flag < 0xE0UL) { if (end_ptr < ptr + 3) { return(NULL); } - + *val = mach_read_from_3(ptr) & 0x3FFFFFUL; return(ptr + 3); @@ -61,7 +61,7 @@ mach_parse_compressed( if (end_ptr < ptr + 4) { return(NULL); } - + *val = mach_read_from_4(ptr) & 0x1FFFFFFFUL; return(ptr + 4); @@ -85,9 +85,9 @@ mach_dulint_parse_compressed( /*=========================*/ /* out: pointer to end of the stored field, NULL if not complete */ - byte* ptr, /* in: pointer to buffer from where to read */ + byte* ptr, /* in: pointer to buffer from where to read */ byte* end_ptr,/* in: pointer to end of the buffer */ - dulint* val) /* out: read value */ + dulint* val) /* out: read value */ { ulint high; ulint low; @@ -115,5 +115,5 @@ mach_dulint_parse_compressed( *val = ut_dulint_create(high, low); - return(ptr + 4); + return(ptr + 4); } diff --git a/storage/innobase/mem/mem0dbg.c b/storage/innobase/mem/mem0dbg.c index 7c0be818948..86d5beb9c80 100644 --- a/storage/innobase/mem/mem0dbg.c +++ b/storage/innobase/mem/mem0dbg.c @@ -17,8 +17,8 @@ mutex_t mem_hash_mutex; /* The mutex which protects in the extent of memory allocations. Only used in the debug version. Protected by mem_hash_mutex above. */ -static ulint mem_n_created_heaps = 0; -static ulint mem_n_allocations = 0; +static ulint mem_n_created_heaps = 0; +static ulint mem_n_allocations = 0; static ulint mem_total_allocated_memory = 0; ulint mem_current_allocated_memory = 0; static ulint mem_max_allocated_memory = 0; @@ -130,7 +130,7 @@ mem_init( } UT_LIST_INIT(mem_all_list_base); - + mem_hash_initialized = TRUE; #endif @@ -150,17 +150,17 @@ mem_field_init( byte* usr_buf; usr_buf = buf + MEM_FIELD_HEADER_SIZE; - - /* In the debug version write the length field and the + + /* In the debug version write the length field and the check fields to the start and the end of the allocated storage. The field header consists of a length field and a random number field, in this order. The field trailer contains the same random number as a check field. */ mem_field_header_set_len(usr_buf, n); - + rnd = ut_rnd_gen_ulint(); - + mem_field_header_set_check(usr_buf, rnd); mem_field_trailer_set_check(usr_buf, rnd); @@ -202,7 +202,7 @@ mem_field_erase( #ifdef UNIV_MEM_DEBUG mutex_enter(&mem_hash_mutex); - mem_current_allocated_memory -= n; + mem_current_allocated_memory -= n; mutex_exit(&mem_hash_mutex); /* Check that the field lengths agree */ @@ -223,10 +223,10 @@ Used to initialize allocated memory. */ void mem_init_buf( /*=========*/ - byte* buf, /* in: pointer to buffer */ - ulint n) /* in: length of buffer */ + byte* buf, /* in: pointer to buffer */ + ulint n) /* in: length of buffer */ { - byte* ptr; + byte* ptr; for (ptr = buf; ptr < buf + n; ptr++) { @@ -245,10 +245,10 @@ Used to erase freed memory.*/ void mem_erase_buf( /*==========*/ - byte* buf, /* in: pointer to buffer */ - ulint n) /* in: length of buffer */ + byte* buf, /* in: pointer to buffer */ + ulint n) /* in: length of buffer */ { - byte* ptr; + byte* ptr; for (ptr = buf; ptr < buf + n; ptr++) { if (ut_rnd_gen_ibool()) { @@ -276,7 +276,7 @@ mem_hash_insert( ut_ad(mem_heap_check(heap)); mutex_enter(&mem_hash_mutex); - + cell_no = ut_hash_ulint((ulint)heap, MEM_HASH_SIZE); /* Allocate a new node to the list */ @@ -292,7 +292,7 @@ mem_hash_insert( UT_LIST_ADD_LAST(all_list, mem_all_list_base, new_node); - mem_n_created_heaps++; + mem_n_created_heaps++; mutex_exit(&mem_hash_mutex); } @@ -317,14 +317,14 @@ mem_hash_remove( ulint cell_no; ibool error; ulint size; - + ut_ad(mem_heap_check(heap)); mutex_enter(&mem_hash_mutex); cell_no = ut_hash_ulint((ulint)heap, MEM_HASH_SIZE); - /* Look for the heap in the hash table list */ + /* Look for the heap in the hash table list */ node = UT_LIST_GET_FIRST(*mem_hash_get_nth_cell(cell_no)); while (node != NULL) { @@ -335,10 +335,10 @@ mem_hash_remove( node = UT_LIST_GET_NEXT(list, node); } - + if (node == NULL) { fprintf(stderr, - "Memory heap or buffer freed in %s line %lu did not exist.\n", + "Memory heap or buffer freed in %s line %lu did not exist.\n", file_name, (ulong) line); ut_error; } @@ -384,16 +384,16 @@ of blocks. */ void mem_heap_validate_or_print( /*=======================*/ - mem_heap_t* heap, /* in: memory heap */ - byte* top __attribute__((unused)), - /* in: calculate and validate only until + mem_heap_t* heap, /* in: memory heap */ + byte* top __attribute__((unused)), + /* in: calculate and validate only until this top pointer in the heap is reached, if this pointer is NULL, ignored */ ibool print, /* in: if TRUE, prints the contents of the heap; works only in the debug version */ ibool* error, /* out: TRUE if error */ - ulint* us_size,/* out: allocated memory + ulint* us_size,/* out: allocated memory (for the user) in the heap, if a NULL pointer is passed as this argument, it is ignored; in the @@ -406,7 +406,7 @@ mem_heap_validate_or_print( argument, it is ignored */ { mem_block_t* block; - ulint total_len = 0; + ulint total_len = 0; ulint block_count = 0; ulint phys_len = 0; #ifdef UNIV_MEM_DEBUG @@ -417,19 +417,19 @@ mem_heap_validate_or_print( #endif /* Pessimistically, we set the parameters to error values */ - if (us_size != NULL) { + if (us_size != NULL) { *us_size = 0; } - if (ph_size != NULL) { + if (ph_size != NULL) { *ph_size = 0; } if (n_blocks != NULL) { *n_blocks = 0; - } + } *error = TRUE; block = heap; - + if (block->magic_n != MEM_BLOCK_MAGIC_N) { return; } @@ -438,18 +438,18 @@ mem_heap_validate_or_print( fputs("Memory heap:", stderr); } - while (block != NULL) { + while (block != NULL) { phys_len += mem_block_get_len(block); if ((block->type == MEM_HEAP_BUFFER) - && (mem_block_get_len(block) > UNIV_PAGE_SIZE)) { + && (mem_block_get_len(block) > UNIV_PAGE_SIZE)) { fprintf(stderr, "InnoDB: Error: mem block %p length %lu > UNIV_PAGE_SIZE\n", block, (ulong) mem_block_get_len(block)); - /* error */ + /* error */ - return; + return; } #ifdef UNIV_MEM_DEBUG @@ -470,20 +470,20 @@ mem_heap_validate_or_print( /* Calculate the pointer to the storage which was given to the user */ - + user_field = field + MEM_FIELD_HEADER_SIZE; - - len = mem_field_header_get_len(user_field); - + + len = mem_field_header_get_len(user_field); + if (print) { ut_print_buf(stderr, user_field, len); } - + total_len += len; check_field = mem_field_header_get_check(user_field); - - if (check_field != - mem_field_trailer_get_check(user_field)) { + + if (check_field != + mem_field_trailer_get_check(user_field)) { /* error */ fprintf(stderr, @@ -492,7 +492,7 @@ mem_heap_validate_or_print( (ulint)field, len, check_field, mem_field_trailer_get_check(user_field)); - return; + return; } /* Move to next field */ @@ -526,16 +526,16 @@ mem_heap_validate_or_print( } #ifdef UNIV_MEM_DEBUG completed: -#endif - if (us_size != NULL) { +#endif + if (us_size != NULL) { *us_size = total_len; } - if (ph_size != NULL) { + if (ph_size != NULL) { *ph_size = phys_len; } if (n_blocks != NULL) { *n_blocks = block_count; - } + } *error = FALSE; } @@ -547,14 +547,14 @@ mem_heap_print( /*===========*/ mem_heap_t* heap) /* in: memory heap */ { - ibool error; + ibool error; ulint us_size; ulint phys_size; ulint n_blocks; ut_ad(mem_heap_check(heap)); - mem_heap_validate_or_print(heap, NULL, TRUE, &error, + mem_heap_validate_or_print(heap, NULL, TRUE, &error, &us_size, &phys_size, &n_blocks); fprintf(stderr, "\nheap type: %lu; size: user size %lu; physical size %lu; blocks %lu.\n", @@ -586,7 +586,7 @@ mem_heap_validate( /* out: TRUE if ok */ mem_heap_t* heap) /* in: memory heap */ { - ibool error; + ibool error; ulint us_size; ulint phys_size; ulint n_blocks; @@ -651,10 +651,10 @@ mem_validate_no_assert(void) /* out: TRUE if error */ { mem_hash_node_t* node; - ulint n_heaps = 0; + ulint n_heaps = 0; ulint allocated_mem; ulint ph_size; - ulint total_allocated_mem = 0; + ulint total_allocated_mem = 0; ibool error = FALSE; ulint n_blocks; ulint i; @@ -671,7 +671,7 @@ mem_validate_no_assert(void) n_heaps++; mem_heap_validate_or_print(node->heap, NULL, - FALSE, &error, &allocated_mem, + FALSE, &error, &allocated_mem, &ph_size, &n_blocks); if (error) { @@ -690,11 +690,11 @@ mem_validate_no_assert(void) node = UT_LIST_GET_NEXT(list, node); } } - + if ((n_heaps == 0) && (mem_current_allocated_memory != 0)) { error = TRUE; } - + if (mem_total_allocated_memory < mem_current_allocated_memory) { error = TRUE; } @@ -702,13 +702,13 @@ mem_validate_no_assert(void) if (mem_max_allocated_memory > mem_total_allocated_memory) { error = TRUE; } - + if (mem_n_created_heaps < n_heaps) { error = TRUE; } - + mutex_exit(&mem_hash_mutex); - + return(error); } @@ -733,41 +733,41 @@ the neighborhood of a given pointer. */ void mem_analyze_corruption( /*===================*/ - byte* ptr) /* in: pointer to place of possible corruption */ + void* ptr) /* in: pointer to place of possible corruption */ { byte* p; ulint i; ulint dist; fputs("InnoDB: Apparent memory corruption: mem dump ", stderr); - ut_print_buf(stderr, ptr - 250, 500); + ut_print_buf(stderr, (byte*)ptr - 250, 500); fputs("\nInnoDB: Scanning backward trying to find previous allocated mem blocks\n", stderr); - p = ptr; + p = (byte*)ptr; dist = 0; - + for (i = 0; i < 10; i++) { for (;;) { if (((ulint)p) % 4 == 0) { - if (*((ulint*)p) == MEM_BLOCK_MAGIC_N) { - fprintf(stderr, - "Mem block at - %lu, file %s, line %lu\n", + if (*((ulint*)p) == MEM_BLOCK_MAGIC_N) { + fprintf(stderr, + "Mem block at - %lu, file %s, line %lu\n", (ulong) dist, (p + sizeof(ulint)), (ulong) (*(ulint*)(p + 8 + sizeof(ulint)))); - break; - } + break; + } - if (*((ulint*)p) == MEM_FREED_BLOCK_MAGIC_N) { - fprintf(stderr, - "Freed mem block at - %lu, file %s, line %lu\n", + if (*((ulint*)p) == MEM_FREED_BLOCK_MAGIC_N) { + fprintf(stderr, + "Freed mem block at - %lu, file %s, line %lu\n", (ulong) dist, (p + sizeof(ulint)), (ulong) (*(ulint*)(p + 8 + sizeof(ulint)))); - break; - } + break; + } } p--; @@ -781,30 +781,30 @@ mem_analyze_corruption( fprintf(stderr, "InnoDB: Scanning forward trying to find next allocated mem blocks\n"); - p = ptr; + p = (byte*)ptr; dist = 0; - + for (i = 0; i < 10; i++) { for (;;) { if (((ulint)p) % 4 == 0) { - if (*((ulint*)p) == MEM_BLOCK_MAGIC_N) { - fprintf(stderr, - "Mem block at + %lu, file %s, line %lu\n", + if (*((ulint*)p) == MEM_BLOCK_MAGIC_N) { + fprintf(stderr, + "Mem block at + %lu, file %s, line %lu\n", (ulong) dist, (p + sizeof(ulint)), (ulong) (*(ulint*)(p + 8 + sizeof(ulint)))); - break; - } + break; + } - if (*((ulint*)p) == MEM_FREED_BLOCK_MAGIC_N) { - fprintf(stderr, - "Freed mem block at + %lu, file %s, line %lu\n", + if (*((ulint*)p) == MEM_FREED_BLOCK_MAGIC_N) { + fprintf(stderr, + "Freed mem block at + %lu, file %s, line %lu\n", (ulong) dist, (p + sizeof(ulint)), (ulong) (*(ulint*)(p + 8 + sizeof(ulint)))); - break; - } + break; + } } p++; @@ -823,26 +823,26 @@ static void mem_print_info_low( /*===============*/ - ibool print_all) /* in: if TRUE, all heaps are printed, + ibool print_all) /* in: if TRUE, all heaps are printed, else only the heaps allocated after the - previous call of this function */ + previous call of this function */ { #ifdef UNIV_MEM_DEBUG mem_hash_node_t* node; - ulint n_heaps = 0; + ulint n_heaps = 0; ulint allocated_mem; ulint ph_size; - ulint total_allocated_mem = 0; + ulint total_allocated_mem = 0; ibool error; ulint n_blocks; #endif FILE* outfile; - + /* outfile = fopen("ibdebug", "a"); */ outfile = stdout; - - fprintf(outfile, "\n"); + + fprintf(outfile, "\n"); fprintf(outfile, "________________________________________________________\n"); fprintf(outfile, "MEMORY ALLOCATION INFORMATION\n\n"); @@ -852,16 +852,16 @@ mem_print_info_low( UT_NOT_USED(print_all); mem_pool_print_info(outfile, mem_comm_pool); - + fprintf(outfile, "Sorry, non-debug version cannot give more memory info\n"); /* fclose(outfile); */ - + return; #else mutex_enter(&mem_hash_mutex); - + fprintf(outfile, "LIST OF CREATED HEAPS AND ALLOCATED BUFFERS: \n\n"); if (!print_all) { @@ -872,39 +872,39 @@ mem_print_info_low( while (node != NULL) { n_heaps++; - + if (!print_all && node->nth_heap < mem_last_print_info) { goto next_heap; - } + } - mem_heap_validate_or_print(node->heap, NULL, - FALSE, &error, &allocated_mem, + mem_heap_validate_or_print(node->heap, NULL, + FALSE, &error, &allocated_mem, &ph_size, &n_blocks); total_allocated_mem += allocated_mem; fprintf(outfile, "%lu: file %s line %lu of size %lu phys.size %lu with %lu blocks, type %lu\n", - node->nth_heap, node->file_name, node->line, + node->nth_heap, node->file_name, node->line, allocated_mem, ph_size, n_blocks, (node->heap)->type); next_heap: node = UT_LIST_GET_NEXT(all_list, node); } - + fprintf(outfile, "\n"); - fprintf(outfile, "Current allocated memory : %lu\n", + fprintf(outfile, "Current allocated memory : %lu\n", mem_current_allocated_memory); - fprintf(outfile, "Current allocated heaps and buffers : %lu\n", + fprintf(outfile, "Current allocated heaps and buffers : %lu\n", n_heaps); - fprintf(outfile, "Cumulative allocated memory : %lu\n", + fprintf(outfile, "Cumulative allocated memory : %lu\n", mem_total_allocated_memory); - fprintf(outfile, "Maximum allocated memory : %lu\n", + fprintf(outfile, "Maximum allocated memory : %lu\n", mem_max_allocated_memory); - fprintf(outfile, "Cumulative created heaps and buffers : %lu\n", + fprintf(outfile, "Cumulative created heaps and buffers : %lu\n", mem_n_created_heaps); - fprintf(outfile, "Cumulative number of allocations : %lu\n", + fprintf(outfile, "Cumulative number of allocations : %lu\n", mem_n_allocations); mem_last_print_info = mem_n_created_heaps; @@ -912,10 +912,10 @@ mem_print_info_low( mutex_exit(&mem_hash_mutex); mem_pool_print_info(outfile, mem_comm_pool); - + /* mem_validate(); */ -/* fclose(outfile); */ +/* fclose(outfile); */ #endif } diff --git a/storage/innobase/mem/mem0mem.c b/storage/innobase/mem/mem0mem.c index e1911097ca5..90d3f4fa6b1 100644 --- a/storage/innobase/mem/mem0mem.c +++ b/storage/innobase/mem/mem0mem.c @@ -35,7 +35,7 @@ When we use a memory heap, we can allocate larger blocks of memory at a time and thus reduce overhead. Slightly more efficient the method is when we allocate the memory from the index page buffer pool, as we can -claim a new page fast. This is called buffer allocation. +claim a new page fast. This is called buffer allocation. When we allocate the memory from the dynamic memory of the C environment, that is called dynamic allocation. @@ -44,13 +44,13 @@ First, when the heap is created, an initial block of memory is allocated. In dynamic allocation this may be about 50 bytes. If more space is needed, additional blocks are allocated and they are put into a linked list. -After the initial block, each allocated block is twice the size of the +After the initial block, each allocated block is twice the size of the previous, until a threshold is attained, after which the sizes of the blocks stay the same. An exception is, of course, the case where the caller requests a memory buffer whose size is bigger than the threshold. In that case a block big enough must be allocated. - + The heap is physically arranged so that if the current block becomes full, a new block is allocated and always inserted in the chain of blocks as the last block. @@ -75,18 +75,18 @@ After freeing, all the blocks in the heap are set to random bytes to help us discover errors which result from the use of buffers in an already freed heap. */ -#ifdef MEM_PERIODIC_CHECK +#ifdef MEM_PERIODIC_CHECK ibool mem_block_list_inited; /* List of all mem blocks allocated; protected by the mem_comm_pool mutex */ UT_LIST_BASE_NODE_T(mem_block_t) mem_block_list; #endif - + /******************************************************************* NOTE: Use the corresponding macro instead of this function. Allocates a single buffer of memory from the dynamic memory of -the C compiler. Is like malloc of C. The buffer must be freed +the C compiler. Is like malloc of C. The buffer must be freed with mem_free. */ void* @@ -97,7 +97,7 @@ mem_alloc_func_noninline( const char* file_name, /* in: file name where created */ ulint line) /* in: line where created */ { - return(mem_alloc_func(n, file_name, line)); + return(mem_alloc_func(n, file_name, line)); } /************************************************************************** @@ -136,12 +136,12 @@ mem_heap_create_block( { mem_block_t* block; ulint len; - + ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER) || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH)); if (heap && heap->magic_n != MEM_BLOCK_MAGIC_N) { - mem_analyze_corruption((byte*)heap); + mem_analyze_corruption(heap); } /* In dynamic allocation, calculate the size: block header + data. */ @@ -191,14 +191,14 @@ mem_heap_create_block( ut_strlcpy_rev(block->file_name, file_name, sizeof(block->file_name)); block->line = line; -#ifdef MEM_PERIODIC_CHECK +#ifdef MEM_PERIODIC_CHECK mem_pool_mutex_enter(); if (!mem_block_list_inited) { mem_block_list_inited = TRUE; UT_LIST_INIT(mem_block_list); } - + UT_LIST_ADD_LAST(mem_block_list, mem_block_list, block); mem_pool_mutex_exit(); @@ -225,11 +225,11 @@ mem_heap_add_block( /* out: created block, NULL if did not succeed (only possible for MEM_HEAP_BTR_SEARCH type heaps)*/ - mem_heap_t* heap, /* in: memory heap */ + mem_heap_t* heap, /* in: memory heap */ ulint n) /* in: number of bytes user needs */ { - mem_block_t* block; - mem_block_t* new_block; + mem_block_t* block; + mem_block_t* new_block; ulint new_size; ut_ad(mem_heap_check(heap)); @@ -239,7 +239,7 @@ mem_heap_add_block( /* We have to allocate a new block. The size is always at least doubled until the standard size is reached. After that the size stays the same, except in cases where the caller needs more space. */ - + new_size = 2 * mem_block_get_len(block); if (heap->type != MEM_HEAP_DYNAMIC) { @@ -257,7 +257,7 @@ mem_heap_add_block( if (new_size < n) { new_size = n; } - + new_block = mem_heap_create_block(heap, new_size, NULL, heap->type, heap->file_name, heap->line); if (new_block == NULL) { @@ -283,15 +283,15 @@ mem_heap_block_free( { ulint type; ulint len; - ibool init_block; + ibool init_block; if (block->magic_n != MEM_BLOCK_MAGIC_N) { - mem_analyze_corruption((byte*)block); + mem_analyze_corruption(block); } UT_LIST_REMOVE(list, heap->base, block); - -#ifdef MEM_PERIODIC_CHECK + +#ifdef MEM_PERIODIC_CHECK mem_pool_mutex_enter(); UT_LIST_REMOVE(mem_block_list, mem_block_list, block); @@ -302,7 +302,7 @@ mem_heap_block_free( len = block->len; init_block = block->init_block; block->magic_n = MEM_FREED_BLOCK_MAGIC_N; - + #ifdef UNIV_MEM_DEBUG /* In the debug version we set the memory to a random combination of hex 0xDE and 0xAD. */ @@ -361,7 +361,7 @@ mem_validate_all_blocks(void) while (block) { if (block->magic_n != MEM_BLOCK_MAGIC_N) { - mem_analyze_corruption((byte*)block); + mem_analyze_corruption(block); } block = UT_LIST_GET_NEXT(mem_block_list, block); diff --git a/storage/innobase/mem/mem0pool.c b/storage/innobase/mem/mem0pool.c index cb891a03092..a61ab1ce170 100644 --- a/storage/innobase/mem/mem0pool.c +++ b/storage/innobase/mem/mem0pool.c @@ -157,8 +157,9 @@ mem_area_get_free( /* out: TRUE if free */ mem_area_t* area) /* in: area */ { - ut_ad(TRUE == MEM_AREA_FREE); - +#if TRUE != MEM_AREA_FREE +# error "TRUE != MEM_AREA_FREE" +#endif return(area->size_and_free & MEM_AREA_FREE); } @@ -171,8 +172,9 @@ mem_area_set_free( mem_area_t* area, /* in: area */ ibool free) /* in: free bit value */ { - ut_ad(TRUE == MEM_AREA_FREE); - +#if TRUE != MEM_AREA_FREE +# error "TRUE != MEM_AREA_FREE" +#endif area->size_and_free = (area->size_and_free & ~MEM_AREA_FREE) | free; } @@ -192,7 +194,7 @@ mem_pool_create( ulint used; ut_a(size > 10000); - + pool = ut_malloc(sizeof(mem_pool_t)); /* We do not set the memory to zero (FALSE) in the pool, @@ -221,7 +223,7 @@ mem_pool_create( if (ut_2_exp(i) > size - used) { /* ut_2_log rounds upward */ - + i--; } @@ -238,7 +240,7 @@ mem_pool_create( ut_ad(size >= used); pool->reserved = 0; - + return(pool); } @@ -264,17 +266,17 @@ mem_pool_fill_free_list( if (i >= 63) { /* We come here when we have run out of space in the memory pool: */ - + return(FALSE); } area = UT_LIST_GET_FIRST(pool->free_list[i + 1]); if (area == NULL) { - if (UT_LIST_GET_LEN(pool->free_list[i + 1]) > 0) { - ut_print_timestamp(stderr); + if (UT_LIST_GET_LEN(pool->free_list[i + 1]) > 0) { + ut_print_timestamp(stderr); - fprintf(stderr, + fprintf(stderr, " InnoDB: Error: mem pool free list %lu length is %lu\n" "InnoDB: though the list is empty!\n", (ulong) i + 1, @@ -292,7 +294,7 @@ mem_pool_fill_free_list( } if (UT_LIST_GET_LEN(pool->free_list[i + 1]) == 0) { - mem_analyze_corruption((byte*)area); + mem_analyze_corruption(area); ut_error; } @@ -305,14 +307,14 @@ mem_pool_fill_free_list( mem_area_set_free(area2, TRUE); UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area2); - + mem_area_set_size(area, ut_2_exp(i)); UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area); return(TRUE); } - + /************************************************************************ Allocates memory from a pool. NOTE: This low-level function should only be used in mem0mem.*! */ @@ -356,19 +358,19 @@ mem_area_alloc( } if (!mem_area_get_free(area)) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: Removing element from mem pool free list %lu though the\n" "InnoDB: element is not marked free!\n", (ulong) n); - mem_analyze_corruption((byte*)area); + mem_analyze_corruption(area); /* Try to analyze a strange assertion failure reported at mysql@lists.mysql.com where the free bit IS 1 in the hex dump above */ if (mem_area_get_free(area)) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Probably a race condition because now the area is marked free!\n"); } @@ -376,29 +378,29 @@ mem_area_alloc( } if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: Removing element from mem pool free list %lu\n" "InnoDB: though the list length is 0!\n", (ulong) n); - mem_analyze_corruption((byte*)area); + mem_analyze_corruption(area); ut_error; } - ut_ad(mem_area_get_size(area) == ut_2_exp(n)); + ut_ad(mem_area_get_size(area) == ut_2_exp(n)); mem_area_set_free(area, FALSE); - + UT_LIST_REMOVE(free_list, pool->free_list[n], area); pool->reserved += mem_area_get_size(area); - + mem_n_threads_inside--; mutex_exit(&(pool->mutex)); ut_ad(mem_pool_validate(pool)); - - return((void*)(MEM_AREA_EXTRA_SIZE + ((byte*)area))); + + return((void*)(MEM_AREA_EXTRA_SIZE + ((byte*)area))); } /************************************************************************ @@ -417,7 +419,7 @@ mem_area_get_buddy( ut_ad(size != 0); if (((((byte*)area) - pool->buf) % (2 * size)) == 0) { - + /* The buddy is in a higher address */ buddy = (mem_area_t*)(((byte*)area) + size); @@ -456,7 +458,7 @@ mem_area_free( void* new_ptr; ulint size; ulint n; - + /* It may be that the area was really allocated from the OS with regular malloc: check if ptr points within our memory pool */ @@ -468,27 +470,27 @@ mem_area_free( area = (mem_area_t*) (((byte*)ptr) - MEM_AREA_EXTRA_SIZE); - if (mem_area_get_free(area)) { - fprintf(stderr, + if (mem_area_get_free(area)) { + fprintf(stderr, "InnoDB: Error: Freeing element to mem pool free list though the\n" "InnoDB: element is marked free!\n"); - mem_analyze_corruption((byte*)area); + mem_analyze_corruption(area); ut_error; } size = mem_area_get_size(area); - - if (size == 0) { - fprintf(stderr, + + if (size == 0) { + fprintf(stderr, "InnoDB: Error: Mem area size is 0. Possibly a memory overrun of the\n" "InnoDB: previous allocated area!\n"); - mem_analyze_corruption((byte*)area); + mem_analyze_corruption(area); ut_error; } -#ifdef UNIV_LIGHT_MEM_DEBUG +#ifdef UNIV_LIGHT_MEM_DEBUG if (((byte*)area) + size < pool->buf + pool->size) { ulint next_size; @@ -496,20 +498,20 @@ mem_area_free( next_size = mem_area_get_size( (mem_area_t*)(((byte*)area) + size)); if (ut_2_power_up(next_size) != next_size) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: Memory area size %lu, next area size %lu not a power of 2!\n" "InnoDB: Possibly a memory overrun of the buffer being freed here.\n", (ulong) size, (ulong) next_size); - mem_analyze_corruption((byte*)area); + mem_analyze_corruption(area); ut_error; } } #endif buddy = mem_area_get_buddy(area, size, pool); - + n = ut_2_log(size); - + mutex_enter(&(pool->mutex)); mem_n_threads_inside++; @@ -532,7 +534,7 @@ mem_area_free( } /* Remove the buddy from its free list and merge it to area */ - + UT_LIST_REMOVE(free_list, pool->free_list[n], buddy); pool->reserved += ut_2_exp(n); @@ -552,7 +554,7 @@ mem_area_free( pool->reserved -= size; } - + mem_n_threads_inside--; mutex_exit(&(pool->mutex)); @@ -576,9 +578,9 @@ mem_pool_validate( mutex_enter(&(pool->mutex)); free = 0; - + for (i = 0; i < 64; i++) { - + UT_LIST_VALIDATE(free_list, mem_area_t, pool->free_list[i]); area = UT_LIST_GET_FIRST(pool->free_list[i]); @@ -590,7 +592,7 @@ mem_pool_validate( buddy = mem_area_get_buddy(area, ut_2_exp(i), pool); ut_a(!buddy || !mem_area_get_free(buddy) - || (ut_2_exp(i) != mem_area_get_size(buddy))); + || (ut_2_exp(i) != mem_area_get_size(buddy))); area = UT_LIST_GET_NEXT(free_list, area); @@ -611,7 +613,7 @@ Prints info of a memory pool. */ void mem_pool_print_info( /*================*/ - FILE* outfile,/* in: output file to write to */ + FILE* outfile,/* in: output file to write to */ mem_pool_t* pool) /* in: memory pool */ { ulint i; @@ -629,11 +631,11 @@ mem_pool_print_info( "Free list length %lu for blocks of size %lu\n", (ulong) UT_LIST_GET_LEN(pool->free_list[i]), (ulong) ut_2_exp(i)); - } + } } fprintf(outfile, "Pool size %lu, reserved %lu.\n", (ulong) pool->size, - (ulong) pool->reserved); + (ulong) pool->reserved); mutex_exit(&(pool->mutex)); } @@ -651,7 +653,7 @@ mem_pool_get_reserved( mutex_enter(&(pool->mutex)); reserved = pool->reserved; - + mutex_exit(&(pool->mutex)); return(reserved); diff --git a/storage/innobase/mtr/mtr0log.c b/storage/innobase/mtr/mtr0log.c index 0308619073a..c47c73e188b 100644 --- a/storage/innobase/mtr/mtr0log.c +++ b/storage/innobase/mtr/mtr0log.c @@ -74,7 +74,7 @@ mlog_write_initial_log_record( log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr); mlog_close(mtr, log_ptr); -} +} /************************************************************ Parses an initial log record written by mlog_write_initial_log_record. */ @@ -143,7 +143,7 @@ mlog_parse_nbytes( offset = mach_read_from_2(ptr); ptr += 2; - + if (offset >= UNIV_PAGE_SIZE) { recv_sys->found_corrupt_log = TRUE; @@ -219,7 +219,7 @@ mlog_write_ulint( mtr_t* mtr) /* in: mini-transaction handle */ { byte* log_ptr; - + if (ptr < buf_pool->frame_zero || ptr >= buf_pool->high_end) { fprintf(stderr, "InnoDB: Error: trying to write to a stray memory location %p\n", ptr); @@ -236,7 +236,7 @@ mlog_write_ulint( } log_ptr = mlog_open(mtr, 11 + 2 + 5); - + /* If no logging is requested, we may return now */ if (log_ptr == NULL) { @@ -247,7 +247,7 @@ mlog_write_ulint( mach_write_to_2(log_ptr, ptr - buf_frame_align(ptr)); log_ptr += 2; - + log_ptr += mach_write_compressed(log_ptr, val); mlog_close(mtr, log_ptr); @@ -277,7 +277,7 @@ mlog_write_dulint( mach_write_to_8(ptr, val); log_ptr = mlog_open(mtr, 11 + 2 + 9); - + /* If no logging is requested, we may return now */ if (log_ptr == NULL) { @@ -289,7 +289,7 @@ mlog_write_dulint( mach_write_to_2(log_ptr, ptr - buf_frame_align(ptr)); log_ptr += 2; - + log_ptr += mach_dulint_write_compressed(log_ptr, val); mlog_close(mtr, log_ptr); @@ -310,7 +310,7 @@ mlog_write_string( byte* log_ptr; if (UNIV_UNLIKELY(ptr < buf_pool->frame_zero) - || UNIV_UNLIKELY(ptr >= buf_pool->high_end)) { + || UNIV_UNLIKELY(ptr >= buf_pool->high_end)) { fprintf(stderr, "InnoDB: Error: trying to write to a stray memory location %p\n", ptr); ut_error; @@ -321,7 +321,7 @@ mlog_write_string( ut_memcpy(ptr, str, len); log_ptr = mlog_open(mtr, 30); - + /* If no logging is requested, we may return now */ if (log_ptr == NULL) { @@ -332,7 +332,7 @@ mlog_write_string( log_ptr, mtr); mach_write_to_2(log_ptr, ptr - buf_frame_align(ptr)); log_ptr += 2; - + mach_write_to_2(log_ptr, len); log_ptr += 2; @@ -407,7 +407,7 @@ mlog_open_and_write_index( const byte* log_start; const byte* log_end; - ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); if (!page_rec_is_comp(rec)) { log_start = log_ptr = mlog_open(mtr, 11 + size); @@ -518,7 +518,8 @@ mlog_parse_index( } else { n = n_uniq = 1; } - table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n, comp); + table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n, + comp ? DICT_TF_COMPACT : 0); ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY", DICT_HDR_SPACE, 0, n); ind->table = table; @@ -541,7 +542,7 @@ mlog_parse_index( len & 0x8000 ? DATA_NOT_NULL : 0, len & 0x7fff, 0); dict_index_add_col(ind, - dict_table_get_nth_col(table, i), 0, 0); + dict_table_get_nth_col(table, i), 0); } ptr += 2; } diff --git a/storage/innobase/mtr/mtr0mtr.c b/storage/innobase/mtr/mtr0mtr.c index da045be1f62..c27a97f6028 100644 --- a/storage/innobase/mtr/mtr0mtr.c +++ b/storage/innobase/mtr/mtr0mtr.c @@ -18,7 +18,7 @@ Created 11/26/1995 Heikki Tuuri #include "log0log.h" /******************************************************************* -Starts a mini-transaction and creates a mini-transaction handle +Starts a mini-transaction and creates a mini-transaction handle and buffer in the memory buffer given by the caller. */ mtr_t* @@ -94,11 +94,11 @@ mtr_memo_pop_all( memo = &(mtr->memo); offset = dyn_array_get_data_size(memo); - + while (offset > 0) { offset -= sizeof(mtr_memo_slot_t); slot = dyn_array_get_element(memo, offset); - + mtr_memo_slot_release(mtr, slot); } } @@ -128,7 +128,7 @@ mtr_log_reserve_and_write( } else { *first_data = (byte)((ulint)*first_data | MLOG_SINGLE_REC_FLAG); } - + if (mlog->heap == NULL) { mtr->end_lsn = log_reserve_and_write_fast(first_data, dyn_block_get_used(mlog), @@ -142,7 +142,7 @@ mtr_log_reserve_and_write( data_size = dyn_array_get_data_size(mlog); /* Open the database log for log_write_low */ - mtr->start_lsn = log_reserve_and_open(data_size); + mtr->start_lsn = log_reserve_and_open(data_size); if (mtr->log_mode == MTR_LOG_ALL) { @@ -155,7 +155,7 @@ mtr_log_reserve_and_write( } } else { ut_ad(mtr->log_mode == MTR_LOG_NONE); - /* Do nothing */ + /* Do nothing */ } mtr->end_lsn = log_close(); @@ -186,7 +186,7 @@ mtr_commit( at the oldest modification of any page in the buffer pool. It is also required when we insert modified buffer pages in to the flush list which must be sorted on oldest_modification. */ - + mtr_memo_pop_all(mtr); if (mtr->modifications) { @@ -198,7 +198,7 @@ mtr_commit( #endif dyn_array_free(&(mtr->memo)); dyn_array_free(&(mtr->log)); -} +} /************************************************************** Releases the latches stored in an mtr memo down to a savepoint. @@ -223,7 +223,7 @@ mtr_rollback_to_savepoint( offset = dyn_array_get_data_size(memo); ut_ad(offset >= savepoint); - + while (offset > savepoint) { offset -= sizeof(mtr_memo_slot_t); @@ -254,7 +254,7 @@ mtr_memo_release( memo = &(mtr->memo); - offset = dyn_array_get_data_size(memo); + offset = dyn_array_get_data_size(memo); while (offset > 0) { offset -= sizeof(mtr_memo_slot_t); @@ -280,13 +280,13 @@ mtr_read_ulint( byte* ptr, /* in: pointer from where to read */ ulint type, /* in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */ mtr_t* mtr __attribute__((unused))) - /* in: mini-transaction handle */ + /* in: mini-transaction handle */ { ut_ad(mtr->state == MTR_ACTIVE); - ut_ad(mtr_memo_contains(mtr, buf_block_align(ptr), - MTR_MEMO_PAGE_S_FIX) || - mtr_memo_contains(mtr, buf_block_align(ptr), - MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr_memo_contains(mtr, buf_block_align(ptr), + MTR_MEMO_PAGE_S_FIX) || + mtr_memo_contains(mtr, buf_block_align(ptr), + MTR_MEMO_PAGE_X_FIX)); if (type == MLOG_1BYTE) { return(mach_read_from_1(ptr)); } else if (type == MLOG_2BYTES) { @@ -302,18 +302,18 @@ Reads 8 bytes from a file page buffered in the buffer pool. */ dulint mtr_read_dulint( -/*===========*/ +/*============*/ /* out: value read */ byte* ptr, /* in: pointer from where to read */ mtr_t* mtr __attribute__((unused))) - /* in: mini-transaction handle */ + /* in: mini-transaction handle */ { ut_ad(mtr->state == MTR_ACTIVE); ut_ad(ptr && mtr); - ut_ad(mtr_memo_contains(mtr, buf_block_align(ptr), - MTR_MEMO_PAGE_S_FIX) || - mtr_memo_contains(mtr, buf_block_align(ptr), - MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr_memo_contains(mtr, buf_block_align(ptr), + MTR_MEMO_PAGE_S_FIX) || + mtr_memo_contains(mtr, buf_block_align(ptr), + MTR_MEMO_PAGE_X_FIX)); return(mach_read_from_8(ptr)); } diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index 20a3303d12d..d10bdccbd2b 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -93,7 +93,7 @@ struct os_aio_slot_struct{ which pending aio operation was completed */ #ifdef WIN_ASYNC_IO - os_event_t event; /* event object we need in the + os_event_t event; /* event object we need in the OVERLAPPED struct */ OVERLAPPED control; /* Windows control block for the aio request */ @@ -121,9 +121,9 @@ struct os_aio_array_struct{ separately for any one of the segments. */ ulint n_reserved;/* Number of reserved slots in the aio array outside the ibuf segment */ - os_aio_slot_t* slots; /* Pointer to the slots in the array */ + os_aio_slot_t* slots; /* Pointer to the slots in the array */ #ifdef __WIN__ - os_native_event_t* native_events; + os_native_event_t* native_events; /* Pointer to an array of OS native event handles where we copied the handles from slots, in the same order. This can be used @@ -160,15 +160,12 @@ time_t os_last_printout; ibool os_has_said_disk_full = FALSE; -/* The mutex protecting the following counts of pending pread and pwrite -operations */ +/* The mutex protecting the following counts of pending I/O operations */ static os_mutex_t os_file_count_mutex; ulint os_file_n_pending_preads = 0; ulint os_file_n_pending_pwrites = 0; - -/* These are not protected by any mutex */ -ulint os_n_pending_writes = 0; -ulint os_n_pending_reads = 0; +ulint os_n_pending_writes = 0; +ulint os_n_pending_reads = 0; /*************************************************************************** Gets the operating system version. Currently works only on Windows. */ @@ -176,33 +173,33 @@ Gets the operating system version. Currently works only on Windows. */ ulint os_get_os_version(void) /*===================*/ - /* out: OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */ + /* out: OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */ { #ifdef __WIN__ - OSVERSIONINFO os_info; + OSVERSIONINFO os_info; - os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); ut_a(GetVersionEx(&os_info)); - if (os_info.dwPlatformId == VER_PLATFORM_WIN32s) { - return(OS_WIN31); - } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { - return(OS_WIN95); - } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT) { + if (os_info.dwPlatformId == VER_PLATFORM_WIN32s) { + return(OS_WIN31); + } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { + return(OS_WIN95); + } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT) { if (os_info.dwMajorVersion <= 4) { - return(OS_WINNT); - } else { + return(OS_WINNT); + } else { return(OS_WIN2000); - } - } else { - ut_error; - return(0); - } + } + } else { + ut_error; + return(0); + } #else - ut_error; + ut_error; - return(0); + return(0); #endif } @@ -227,10 +224,10 @@ os_file_get_last_error( err = (ulint) GetLastError(); if (report_all_errors - || (err != ERROR_DISK_FULL && err != ERROR_FILE_EXISTS)) { + || (err != ERROR_DISK_FULL && err != ERROR_FILE_EXISTS)) { ut_print_timestamp(stderr); - fprintf(stderr, + fprintf(stderr, " InnoDB: Operating system error number %lu in a file operation.\n", (ulong) err); if (err == ERROR_PATH_NOT_FOUND) { @@ -246,7 +243,7 @@ os_file_get_last_error( fprintf(stderr, "InnoDB: The error means mysqld does not have the access rights to\n" "InnoDB: the directory. It may also be you have created a subdirectory\n" - "InnoDB: of the same name as a data file.\n"); + "InnoDB: of the same name as a data file.\n"); } else { fprintf(stderr, "InnoDB: Some operating system error numbers are described at\n" @@ -270,16 +267,16 @@ os_file_get_last_error( err = (ulint) errno; if (report_all_errors - || (err != ENOSPC && err != EEXIST)) { + || (err != ENOSPC && err != EEXIST)) { ut_print_timestamp(stderr); - fprintf(stderr, + fprintf(stderr, " InnoDB: Operating system error number %lu in a file operation.\n", (ulong) err); if (err == ENOENT) { fprintf(stderr, "InnoDB: The error means the system cannot find the path specified.\n"); - + if (srv_is_being_started) { fprintf(stderr, "InnoDB: If you are installing InnoDB, remember that you must create\n" @@ -314,6 +311,8 @@ os_file_get_last_error( return(OS_FILE_NOT_FOUND); } else if (err == EEXIST) { return(OS_FILE_ALREADY_EXISTS); + } else if (err == EXDEV || err == ENOTDIR || err == EISDIR) { + return(OS_FILE_PATH_ERROR); } else { return(100 + err); } @@ -334,7 +333,7 @@ os_file_handle_error( ulint err; err = os_file_get_last_error(FALSE); - + if (err == OS_FILE_DISK_FULL) { /* We only print a warning about disk full once */ @@ -342,7 +341,7 @@ os_file_handle_error( return(FALSE); } - + if (name) { ut_print_timestamp(stderr); fprintf(stderr, @@ -350,7 +349,7 @@ os_file_handle_error( } ut_print_timestamp(stderr); - fprintf(stderr, + fprintf(stderr, " InnoDB: Disk is full. Try to clean the disk to free space.\n"); os_has_said_disk_full = TRUE; @@ -363,16 +362,17 @@ os_file_handle_error( return(TRUE); - } else if (err == OS_FILE_ALREADY_EXISTS) { + } else if (err == OS_FILE_ALREADY_EXISTS + || err == OS_FILE_PATH_ERROR) { return(FALSE); } else { - if (name) { - fprintf(stderr, "InnoDB: File name %s\n", name); - } - + if (name) { + fprintf(stderr, "InnoDB: File name %s\n", name); + } + fprintf(stderr, "InnoDB: File operation call: '%s'.\n", - operation); + operation); fprintf(stderr, "InnoDB: Cannot continue operation.\n"); fflush(stderr); @@ -380,7 +380,7 @@ os_file_handle_error( exit(1); } - return(FALSE); + return(FALSE); } #undef USE_FILE_LOCK @@ -438,7 +438,7 @@ os_file_handle_error_no_exit( ulint err; err = os_file_get_last_error(FALSE); - + if (err == OS_FILE_DISK_FULL) { /* We only print a warning about disk full once */ @@ -446,7 +446,7 @@ os_file_handle_error_no_exit( return(FALSE); } - + if (name) { ut_print_timestamp(stderr); fprintf(stderr, @@ -454,7 +454,7 @@ os_file_handle_error_no_exit( } ut_print_timestamp(stderr); - fprintf(stderr, + fprintf(stderr, " InnoDB: Disk is full. Try to clean the disk to free space.\n"); os_has_said_disk_full = TRUE; @@ -467,16 +467,17 @@ os_file_handle_error_no_exit( return(TRUE); - } else if (err == OS_FILE_ALREADY_EXISTS) { + } else if (err == OS_FILE_ALREADY_EXISTS + || err == OS_FILE_PATH_ERROR) { return(FALSE); } else { - if (name) { - fprintf(stderr, "InnoDB: File name %s\n", name); - } - + if (name) { + fprintf(stderr, "InnoDB: File name %s\n", name); + } + fprintf(stderr, "InnoDB: File operation call: '%s'.\n", - operation); + operation); return (FALSE); } @@ -501,7 +502,8 @@ os_io_init_simple(void) #if !defined(UNIV_HOTBACKUP) && !defined(__NETWARE__) /************************************************************************* -Creates a temporary file. This function is defined in ha_innodb.cc. */ +Creates a temporary file that will be deleted on close. +This function is defined in ha_innodb.cc. */ int innobase_mysql_tmpfile(void); @@ -510,68 +512,46 @@ innobase_mysql_tmpfile(void); #endif /* !UNIV_HOTBACKUP && !__NETWARE__ */ /*************************************************************************** -Creates a temporary file. */ +Creates a temporary file. This function is like tmpfile(3), but +the temporary file is created in the MySQL temporary directory. +On Netware, this function is like tmpfile(3), because the C run-time +library of Netware does not expose the delete-on-close flag. */ FILE* os_file_create_tmpfile(void) /*========================*/ /* out: temporary file handle, or NULL on error */ { -#ifdef __NETWARE__ +#ifdef UNIV_HOTBACKUP + ut_error; + + return(NULL); +#else +# ifdef __NETWARE__ FILE* file = tmpfile(); -#else /* __NETWARE__ */ +# else /* __NETWARE__ */ FILE* file = NULL; - int fd = -1; -# ifdef UNIV_HOTBACKUP - int tries; - for (tries = 10; tries--; ) { - char* name = tempnam(fil_path_to_mysql_datadir, "ib"); - if (!name) { - break; - } - - fd = open(name, -# ifdef __WIN__ - O_SEQUENTIAL | O_SHORT_LIVED | O_TEMPORARY | -# endif /* __WIN__ */ - O_CREAT | O_EXCL | O_RDWR, - S_IREAD | S_IWRITE); - if (fd >= 0) { -# ifndef __WIN__ - unlink(name); -# endif /* !__WIN__ */ - free(name); - break; - } - - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Warning: " - "unable to create temporary file %s, retrying\n", - name); - free(name); - } -# else /* UNIV_HOTBACKUP */ - fd = innobase_mysql_tmpfile(); -# endif /* UNIV_HOTBACKUP */ + int fd = innobase_mysql_tmpfile(); if (fd >= 0) { file = fdopen(fd, "w+b"); } -#endif /* __NETWARE__ */ +# endif /* __NETWARE__ */ if (!file) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: unable to create temporary file;" " errno: %d\n", errno); -#ifndef __NETWARE__ +# ifndef __NETWARE__ if (fd >= 0) { close(fd); } -#endif /* !__NETWARE__ */ +# endif /* !__NETWARE__ */ } return(file); +#endif /* UNIV_HOTBACKUP */ } /*************************************************************************** @@ -595,7 +575,7 @@ os_file_opendir( { os_file_dir_t dir; #ifdef __WIN__ - LPWIN32_FIND_DATA lpFindFileData; + LPWIN32_FIND_DATA lpFindFileData; char path[OS_FILE_MAX_PATH + 3]; ut_a(strlen(dirname) < OS_FILE_MAX_PATH); @@ -616,18 +596,18 @@ os_file_opendir( if (dir == INVALID_HANDLE_VALUE) { if (error_is_fatal) { - os_file_handle_error(dirname, "opendir"); + os_file_handle_error(dirname, "opendir"); } return(NULL); } - return(dir); + return(dir); #else dir = opendir(dirname); if (dir == NULL && error_is_fatal) { - os_file_handle_error(dirname, "opendir"); + os_file_handle_error(dirname, "opendir"); } return(dir); @@ -649,19 +629,19 @@ os_file_closedir( ret = FindClose(dir); if (!ret) { - os_file_handle_error_no_exit(NULL, "closedir"); - + os_file_handle_error_no_exit(NULL, "closedir"); + return(-1); } - + return(0); #else int ret; - + ret = closedir(dir); if (ret) { - os_file_handle_error_no_exit(NULL, "closedir"); + os_file_handle_error_no_exit(NULL, "closedir"); } return(ret); @@ -690,18 +670,18 @@ next_file: ret = FindNextFile(dir, lpFindFileData); if (ret) { - ut_a(strlen((char *) lpFindFileData->cFileName) < OS_FILE_MAX_PATH); + ut_a(strlen((char *) lpFindFileData->cFileName) < OS_FILE_MAX_PATH); if (strcmp((char *) lpFindFileData->cFileName, ".") == 0 - || strcmp((char *) lpFindFileData->cFileName, "..") == 0) { + || strcmp((char *) lpFindFileData->cFileName, "..") == 0) { - goto next_file; + goto next_file; } strcpy(info->name, (char *) lpFindFileData->cFileName); info->size = (ib_longlong)(lpFindFileData->nFileSizeLow) - + (((ib_longlong)(lpFindFileData->nFileSizeHigh)) << 32); + + (((ib_longlong)(lpFindFileData->nFileSizeHigh)) << 32); if (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { @@ -712,7 +692,7 @@ http://www.mysql.com/doc/en/Windows_symbolic_links.html */ info->type = OS_FILE_TYPE_LINK; } else if (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - info->type = OS_FILE_TYPE_DIR; + info->type = OS_FILE_TYPE_DIR; } else { /* It is probably safest to assume that all other file types are normal. Better to check them rather @@ -761,7 +741,7 @@ next_file: if (ent == NULL) { /* End of directory */ - + return(1); } @@ -784,7 +764,7 @@ next_file: strcpy(info->name, ent->d_name); full_path = ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10); - + sprintf(full_path, "%s/%s", dirname, ent->d_name); ret = stat(full_path, &statinfo); @@ -802,13 +782,13 @@ next_file: if (S_ISDIR(statinfo.st_mode)) { info->type = OS_FILE_TYPE_DIR; } else if (S_ISLNK(statinfo.st_mode)) { - info->type = OS_FILE_TYPE_LINK; + info->type = OS_FILE_TYPE_LINK; } else if (S_ISREG(statinfo.st_mode)) { - info->type = OS_FILE_TYPE_FILE; + info->type = OS_FILE_TYPE_FILE; } else { - info->type = OS_FILE_TYPE_UNKNOWN; + info->type = OS_FILE_TYPE_UNKNOWN; } - + ut_free(full_path); return(0); @@ -833,7 +813,7 @@ os_file_create_directory( { #ifdef __WIN__ BOOL rcode; - + rcode = CreateDirectory((LPCTSTR) pathname, NULL); if (!(rcode != 0 || (GetLastError() == ERROR_ALREADY_EXISTS && !fail_if_exists))) { @@ -842,7 +822,7 @@ os_file_create_directory( return(FALSE); } - + return (TRUE); #else int rcode; @@ -855,9 +835,9 @@ os_file_create_directory( return(FALSE); } - + return (TRUE); -#endif +#endif } /******************************************************************** @@ -875,7 +855,7 @@ os_file_create_simple( opened (if does not exist, error), or OS_FILE_CREATE if a new file is created (if exists, error), or - OS_FILE_CREATE_PATH if new file + OS_FILE_CREATE_PATH if new file (if exists, error) and subdirectories along its path are created (if needed)*/ ulint access_type,/* in: OS_FILE_READ_ONLY or @@ -888,22 +868,22 @@ os_file_create_simple( DWORD access; DWORD attributes = 0; ibool retry; - -try_again: + +try_again: ut_a(name); if (create_mode == OS_FILE_OPEN) { create_flag = OPEN_EXISTING; } else if (create_mode == OS_FILE_CREATE) { create_flag = CREATE_NEW; - } else if (create_mode == OS_FILE_CREATE_PATH) { - /* create subdirs along the path if needed */ - *success = os_file_create_subdirs_if_needed(name); - if (!*success) { - ut_error; - } - create_flag = CREATE_NEW; - create_mode = OS_FILE_CREATE; + } else if (create_mode == OS_FILE_CREATE_PATH) { + /* create subdirs along the path if needed */ + *success = os_file_create_subdirs_if_needed(name); + if (!*success) { + ut_error; + } + create_flag = CREATE_NEW; + create_mode = OS_FILE_CREATE; } else { create_flag = 0; ut_error; @@ -946,8 +926,8 @@ try_again: os_file_t file; int create_flag; ibool retry; - -try_again: + +try_again: ut_a(name); if (create_mode == OS_FILE_OPEN) { @@ -958,26 +938,26 @@ try_again: } } else if (create_mode == OS_FILE_CREATE) { create_flag = O_RDWR | O_CREAT | O_EXCL; - } else if (create_mode == OS_FILE_CREATE_PATH) { - /* create subdirs along the path if needed */ - *success = os_file_create_subdirs_if_needed(name); - if (!*success) { - return (-1); - } - create_flag = O_RDWR | O_CREAT | O_EXCL; - create_mode = OS_FILE_CREATE; + } else if (create_mode == OS_FILE_CREATE_PATH) { + /* create subdirs along the path if needed */ + *success = os_file_create_subdirs_if_needed(name); + if (!*success) { + return (-1); + } + create_flag = O_RDWR | O_CREAT | O_EXCL; + create_mode = OS_FILE_CREATE; } else { create_flag = 0; ut_error; } if (create_mode == OS_FILE_CREATE) { - file = open(name, create_flag, S_IRUSR | S_IWUSR + file = open(name, create_flag, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - } else { - file = open(name, create_flag); - } - + } else { + file = open(name, create_flag); + } + if (file == -1) { *success = FALSE; @@ -998,7 +978,7 @@ try_again: *success = TRUE; } - return(file); + return(file); #endif /* __WIN__ */ } @@ -1029,7 +1009,7 @@ os_file_create_simple_no_error_handling( DWORD access; DWORD attributes = 0; DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE; - + ut_a(name); if (create_mode == OS_FILE_OPEN) { @@ -1048,7 +1028,7 @@ os_file_create_simple_no_error_handling( } else if (access_type == OS_FILE_READ_ALLOW_DELETE) { access = GENERIC_READ; share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ - | FILE_SHARE_WRITE; /* A backup program has to give + | FILE_SHARE_WRITE; /* A backup program has to give mysqld the maximum freedom to do what it likes with the file */ @@ -1075,7 +1055,7 @@ os_file_create_simple_no_error_handling( #else /* __WIN__ */ os_file_t file; int create_flag; - + ut_a(name); if (create_mode == OS_FILE_OPEN) { @@ -1092,12 +1072,12 @@ os_file_create_simple_no_error_handling( } if (create_mode == OS_FILE_CREATE) { - file = open(name, create_flag, S_IRUSR | S_IWUSR + file = open(name, create_flag, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - } else { - file = open(name, create_flag); - } - + } else { + file = open(name, create_flag); + } + if (file == -1) { *success = FALSE; #ifdef USE_FILE_LOCK @@ -1111,7 +1091,7 @@ os_file_create_simple_no_error_handling( *success = TRUE; } - return(file); + return(file); #endif /* __WIN__ */ } @@ -1150,7 +1130,7 @@ os_file_create( DWORD create_flag; DWORD attributes; ibool retry; -try_again: +try_again: ut_a(name); if (create_mode == OS_FILE_OPEN_RAW) { @@ -1176,27 +1156,27 @@ try_again: if (os_aio_use_native_aio) { attributes = attributes | FILE_FLAG_OVERLAPPED; } -#endif +#endif #ifdef UNIV_NON_BUFFERED_IO if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) { - /* Do not use unbuffered i/o to log files because - value 2 denotes that we do not flush the log at every - commit, but only once per second */ + /* Do not use unbuffered i/o to log files because + value 2 denotes that we do not flush the log at every + commit, but only once per second */ } else if (srv_win_file_flush_method == - SRV_WIN_IO_UNBUFFERED) { - attributes = attributes | FILE_FLAG_NO_BUFFERING; + SRV_WIN_IO_UNBUFFERED) { + attributes = attributes | FILE_FLAG_NO_BUFFERING; } #endif } else if (purpose == OS_FILE_NORMAL) { - attributes = 0; + attributes = 0; #ifdef UNIV_NON_BUFFERED_IO if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) { - /* Do not use unbuffered i/o to log files because - value 2 denotes that we do not flush the log at every - commit, but only once per second */ + /* Do not use unbuffered i/o to log files because + value 2 denotes that we do not flush the log at every + commit, but only once per second */ } else if (srv_win_file_flush_method == - SRV_WIN_IO_UNBUFFERED) { - attributes = attributes | FILE_FLAG_NO_BUFFERING; + SRV_WIN_IO_UNBUFFERED) { + attributes = attributes | FILE_FLAG_NO_BUFFERING; } #endif } else { @@ -1207,7 +1187,7 @@ try_again: file = CreateFile((LPCTSTR) name, GENERIC_READ | GENERIC_WRITE, /* read and write access */ - share_mode, /* File can be read also by other + share_mode, /* File can be read also by other processes; we must give the read permission because of ibbackup. We do not give the write permission to @@ -1244,8 +1224,8 @@ try_again: const char* mode_str = NULL; const char* type_str = NULL; const char* purpose_str = NULL; - -try_again: + +try_again: ut_a(name); if (create_mode == OS_FILE_OPEN || create_mode == OS_FILE_OPEN_RAW @@ -1268,47 +1248,47 @@ try_again: } else if (type == OS_DATA_FILE) { type_str = "DATA"; } else { - ut_error; + ut_error; } - + if (purpose == OS_FILE_AIO) { purpose_str = "AIO"; } else if (purpose == OS_FILE_NORMAL) { purpose_str = "NORMAL"; } else { - ut_error; + ut_error; } /* fprintf(stderr, "Opening file %s, mode %s, type %s, purpose %s\n", - name, mode_str, type_str, purpose_str); */ + name, mode_str, type_str, purpose_str); */ #ifdef O_SYNC - /* We let O_SYNC only affect log files; note that we map O_DSYNC to + /* We let O_SYNC only affect log files; note that we map O_DSYNC to O_SYNC because the datasync options seemed to corrupt files in 2001 in both Linux and Solaris */ if (type == OS_LOG_FILE - && srv_unix_file_flush_method == SRV_UNIX_O_DSYNC) { + && srv_unix_file_flush_method == SRV_UNIX_O_DSYNC) { /* fprintf(stderr, "Using O_SYNC for file %s\n", name); */ - create_flag = create_flag | O_SYNC; + create_flag = create_flag | O_SYNC; } #endif #ifdef O_DIRECT - /* We let O_DIRECT only affect data files */ + /* We let O_DIRECT only affect data files */ if (type != OS_LOG_FILE - && srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) { + && srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) { /* fprintf(stderr, "Using O_DIRECT for file %s\n", name); */ - create_flag = create_flag | O_DIRECT; + create_flag = create_flag | O_DIRECT; } #endif if (create_mode == OS_FILE_CREATE) { - file = open(name, create_flag, os_innodb_umask); - } else { - file = open(name, create_flag); - } - + file = open(name, create_flag, os_innodb_umask); + } else { + file = open(name, create_flag); + } + if (file == -1) { *success = FALSE; @@ -1345,7 +1325,7 @@ try_again: *success = TRUE; } - return(file); + return(file); #endif /* __WIN__ */ } @@ -1383,7 +1363,7 @@ loop: fprintf(stderr, "InnoDB: Warning: cannot delete file %s\n" "InnoDB: Are you running ibbackup to back up the file?\n", name); - + os_file_get_last_error(TRUE); /* print error information */ } @@ -1445,7 +1425,7 @@ loop: fprintf(stderr, "InnoDB: Warning: cannot delete file %s\n" "InnoDB: Are you running ibbackup to back up the file?\n", name); - + os_file_get_last_error(TRUE); /* print error information */ } @@ -1620,16 +1600,16 @@ os_file_get_size( return(FALSE); } - + if (sizeof(off_t) > 4) { - *size = (ulint)(offs & 0xFFFFFFFFUL); + *size = (ulint)(offs & 0xFFFFFFFFUL); *size_high = (ulint)(offs >> 32); } else { *size = (ulint) offs; *size_high = 0; } - - return(TRUE); + + return(TRUE); #endif } @@ -1673,8 +1653,8 @@ os_file_set_size( ib_longlong current_size; ib_longlong desired_size; ibool ret; - byte* buf; - byte* buf2; + byte* buf; + byte* buf2; ulint buf_size; ut_a(size == (size & 0xFFFFFFFF)); @@ -1694,7 +1674,7 @@ os_file_set_size( memset(buf, 0, buf_size); if (desired_size >= (ib_longlong)(100 * 1024 * 1024)) { - + fprintf(stderr, "InnoDB: Progress in MB:"); } @@ -1707,29 +1687,29 @@ os_file_set_size( n_bytes = buf_size; } - ret = os_file_write(name, file, buf, - (ulint)(current_size & 0xFFFFFFFF), - (ulint)(current_size >> 32), - n_bytes); - if (!ret) { + ret = os_file_write(name, file, buf, + (ulint)(current_size & 0xFFFFFFFF), + (ulint)(current_size >> 32), + n_bytes); + if (!ret) { ut_free(buf2); - goto error_handling; - } - + goto error_handling; + } + /* Print about progress for each 100 MB written */ if ((current_size + n_bytes) / (ib_longlong)(100 * 1024 * 1024) - != current_size / (ib_longlong)(100 * 1024 * 1024)) { + != current_size / (ib_longlong)(100 * 1024 * 1024)) { - fprintf(stderr, " %lu00", + fprintf(stderr, " %lu00", (ulong) ((current_size + n_bytes) / (ib_longlong)(100 * 1024 * 1024))); } - - current_size += n_bytes; + + current_size += n_bytes; } if (desired_size >= (ib_longlong)(100 * 1024 * 1024)) { - + fprintf(stderr, "\n"); } @@ -1738,7 +1718,7 @@ os_file_set_size( ret = os_file_flush(file); if (ret) { - return(TRUE); + return(TRUE); } error_handling: @@ -1790,7 +1770,7 @@ os_file_flush( if (srv_start_raw_disk_in_use && GetLastError() == ERROR_INVALID_FUNCTION) { - return(TRUE); + return(TRUE); } os_file_handle_error(NULL, "flush"); @@ -1817,7 +1797,7 @@ os_file_flush( if (!srv_have_fullfsync) { /* If we are not on an operating system that supports this, - then fall back to a plain fsync. */ + then fall back to a plain fsync. */ ret = fsync(file); } else { @@ -1825,7 +1805,7 @@ os_file_flush( if (ret) { /* If we are not on a file system that supports this, - then fall back to a plain fsync. */ + then fall back to a plain fsync. */ ret = fsync(file); } } @@ -1840,17 +1820,17 @@ os_file_flush( if (ret == 0) { return(TRUE); } - + /* Since Linux returns EINVAL if the 'file' is actually a raw device, we choose to ignore that error if we are using raw disks */ if (srv_start_raw_disk_in_use && errno == EINVAL) { - return(TRUE); + return(TRUE); } ut_print_timestamp(stderr); - + fprintf(stderr, " InnoDB: Error: the OS said file flush did not succeed\n"); @@ -1874,44 +1854,46 @@ os_file_pread( /* out: number of bytes read, -1 if error */ os_file_t file, /* in: handle to a file */ void* buf, /* in: buffer where to read */ - ulint n, /* in: number of bytes to read */ + ulint n, /* in: number of bytes to read */ ulint offset, /* in: least significant 32 bits of file offset from where to read */ ulint offset_high) /* in: most significant 32 bits of offset */ { - off_t offs; + off_t offs; ssize_t n_bytes; ut_a((offset & 0xFFFFFFFFUL) == offset); - - /* If off_t is > 4 bytes in size, then we assume we can pass a + + /* If off_t is > 4 bytes in size, then we assume we can pass a 64-bit address */ - if (sizeof(off_t) > 4) { - offs = (off_t)offset + (((off_t)offset_high) << 32); - - } else { - offs = (off_t)offset; + if (sizeof(off_t) > 4) { + offs = (off_t)offset + (((off_t)offset_high) << 32); + + } else { + offs = (off_t)offset; - if (offset_high > 0) { - fprintf(stderr, + if (offset_high > 0) { + fprintf(stderr, "InnoDB: Error: file read at offset > 4 GB\n"); } - } + } os_n_file_reads++; #if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD) - os_mutex_enter(os_file_count_mutex); + os_mutex_enter(os_file_count_mutex); os_file_n_pending_preads++; - os_mutex_exit(os_file_count_mutex); + os_n_pending_reads++; + os_mutex_exit(os_file_count_mutex); - n_bytes = pread(file, buf, (ssize_t)n, offs); + n_bytes = pread(file, buf, (ssize_t)n, offs); - os_mutex_enter(os_file_count_mutex); + os_mutex_enter(os_file_count_mutex); os_file_n_pending_preads--; - os_mutex_exit(os_file_count_mutex); + os_n_pending_reads--; + os_mutex_exit(os_file_count_mutex); return(n_bytes); #else @@ -1920,23 +1902,29 @@ os_file_pread( ssize_t ret; ulint i; + os_mutex_enter(os_file_count_mutex); + os_n_pending_reads++; + os_mutex_exit(os_file_count_mutex); + /* Protect the seek / read operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; - + os_mutex_enter(os_file_seek_mutexes[i]); ret_offset = lseek(file, offs, SEEK_SET); if (ret_offset < 0) { - os_mutex_exit(os_file_seek_mutexes[i]); - - return(-1); + ret = -1; + } else { + ret = read(file, buf, (ssize_t)n); } - - ret = read(file, buf, (ssize_t)n); os_mutex_exit(os_file_seek_mutexes[i]); + os_mutex_enter(os_file_count_mutex); + os_n_pending_reads--; + os_mutex_exit(os_file_count_mutex); + return(ret); } #endif @@ -1951,93 +1939,104 @@ os_file_pwrite( /* out: number of bytes written, -1 if error */ os_file_t file, /* in: handle to a file */ const void* buf, /* in: buffer from where to write */ - ulint n, /* in: number of bytes to write */ + ulint n, /* in: number of bytes to write */ ulint offset, /* in: least significant 32 bits of file offset where to write */ ulint offset_high) /* in: most significant 32 bits of offset */ { ssize_t ret; - off_t offs; + off_t offs; ut_a((offset & 0xFFFFFFFFUL) == offset); - /* If off_t is > 4 bytes in size, then we assume we can pass a + /* If off_t is > 4 bytes in size, then we assume we can pass a 64-bit address */ - if (sizeof(off_t) > 4) { - offs = (off_t)offset + (((off_t)offset_high) << 32); - } else { - offs = (off_t)offset; + if (sizeof(off_t) > 4) { + offs = (off_t)offset + (((off_t)offset_high) << 32); + } else { + offs = (off_t)offset; - if (offset_high > 0) { - fprintf(stderr, + if (offset_high > 0) { + fprintf(stderr, "InnoDB: Error: file write at offset > 4 GB\n"); } - } + } os_n_file_writes++; #if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD) - os_mutex_enter(os_file_count_mutex); + os_mutex_enter(os_file_count_mutex); os_file_n_pending_pwrites++; - os_mutex_exit(os_file_count_mutex); + os_n_pending_writes++; + os_mutex_exit(os_file_count_mutex); ret = pwrite(file, buf, (ssize_t)n, offs); - os_mutex_enter(os_file_count_mutex); + os_mutex_enter(os_file_count_mutex); os_file_n_pending_pwrites--; - os_mutex_exit(os_file_count_mutex); + os_n_pending_writes--; + os_mutex_exit(os_file_count_mutex); # ifdef UNIV_DO_FLUSH if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC - && srv_unix_file_flush_method != SRV_UNIX_NOSYNC - && !os_do_not_call_flush_at_each_write) { - - /* Always do fsync to reduce the probability that when - the OS crashes, a database page is only partially - physically written to disk. */ + && srv_unix_file_flush_method != SRV_UNIX_NOSYNC + && !os_do_not_call_flush_at_each_write) { - ut_a(TRUE == os_file_flush(file)); + /* Always do fsync to reduce the probability that when + the OS crashes, a database page is only partially + physically written to disk. */ + + ut_a(TRUE == os_file_flush(file)); } # endif /* UNIV_DO_FLUSH */ - return(ret); + return(ret); #else { off_t ret_offset; ulint i; + os_mutex_enter(os_file_count_mutex); + os_n_pending_writes++; + os_mutex_exit(os_file_count_mutex); + /* Protect the seek / write operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; - + os_mutex_enter(os_file_seek_mutexes[i]); ret_offset = lseek(file, offs, SEEK_SET); if (ret_offset < 0) { - os_mutex_exit(os_file_seek_mutexes[i]); + ret = -1; - return(-1); + goto func_exit; } - + ret = write(file, buf, (ssize_t)n); # ifdef UNIV_DO_FLUSH if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC - && srv_unix_file_flush_method != SRV_UNIX_NOSYNC - && !os_do_not_call_flush_at_each_write) { + && srv_unix_file_flush_method != SRV_UNIX_NOSYNC + && !os_do_not_call_flush_at_each_write) { - /* Always do fsync to reduce the probability that when - the OS crashes, a database page is only partially - physically written to disk. */ + /* Always do fsync to reduce the probability that when + the OS crashes, a database page is only partially + physically written to disk. */ - ut_a(TRUE == os_file_flush(file)); + ut_a(TRUE == os_file_flush(file)); } # endif /* UNIV_DO_FLUSH */ +func_exit: os_mutex_exit(os_file_seek_mutexes[i]); + os_mutex_enter(os_file_count_mutex); + os_n_pending_writes--; + os_mutex_exit(os_file_count_mutex); + return(ret); } #endif @@ -2058,7 +2057,7 @@ os_file_read( offset where to read */ ulint offset_high, /* in: most significant 32 bits of offset */ - ulint n) /* in: number of bytes to read */ + ulint n) /* in: number of bytes to read */ { #ifdef __WIN__ BOOL ret; @@ -2068,13 +2067,13 @@ os_file_read( DWORD high; ibool retry; ulint i; - + ut_a((offset & 0xFFFFFFFFUL) == offset); os_n_file_reads++; os_bytes_read_since_printout += n; -try_again: +try_again: ut_ad(file); ut_ad(buf); ut_ad(n > 0); @@ -2082,9 +2081,13 @@ try_again: low = (DWORD) offset; high = (DWORD) offset_high; + os_mutex_enter(os_file_count_mutex); + os_n_pending_reads++; + os_mutex_exit(os_file_count_mutex); + /* Protect the seek / read operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; - + os_mutex_enter(os_file_seek_mutexes[i]); ret2 = SetFilePointer(file, low, &high, FILE_BEGIN); @@ -2093,20 +2096,24 @@ try_again: os_mutex_exit(os_file_seek_mutexes[i]); + os_mutex_enter(os_file_count_mutex); + os_n_pending_reads--; + os_mutex_exit(os_file_count_mutex); + goto error_handling; - } - - os_n_pending_reads++; - - ret = ReadFile(file, buf, (DWORD) n, &len, NULL); + } - os_n_pending_reads--; + ret = ReadFile(file, buf, (DWORD) n, &len, NULL); os_mutex_exit(os_file_seek_mutexes[i]); - + + os_mutex_enter(os_file_count_mutex); + os_n_pending_reads--; + os_mutex_exit(os_file_count_mutex); + if (ret && len == n) { return(TRUE); - } + } #else ibool retry; ssize_t ret; @@ -2114,12 +2121,8 @@ try_again: os_bytes_read_since_printout += n; try_again: - os_n_pending_reads++; - ret = os_file_pread(file, buf, n, offset, offset_high); - os_n_pending_reads--; - if ((ulint)ret == n) { return(TRUE); @@ -2129,16 +2132,16 @@ try_again: "InnoDB: Error: tried to read %lu bytes at offset %lu %lu.\n" "InnoDB: Was only able to read %ld.\n", (ulong)n, (ulong)offset_high, (ulong)offset, (long)ret); -#endif +#endif #ifdef __WIN__ error_handling: #endif - retry = os_file_handle_error(NULL, "read"); + retry = os_file_handle_error(NULL, "read"); if (retry) { goto try_again; } - + fprintf(stderr, "InnoDB: Fatal error: cannot read from file. OS error number %lu.\n", #ifdef __WIN__ @@ -2169,7 +2172,7 @@ os_file_read_no_error_handling( offset where to read */ ulint offset_high, /* in: most significant 32 bits of offset */ - ulint n) /* in: number of bytes to read */ + ulint n) /* in: number of bytes to read */ { #ifdef __WIN__ BOOL ret; @@ -2179,13 +2182,13 @@ os_file_read_no_error_handling( DWORD high; ibool retry; ulint i; - + ut_a((offset & 0xFFFFFFFFUL) == offset); os_n_file_reads++; os_bytes_read_since_printout += n; -try_again: +try_again: ut_ad(file); ut_ad(buf); ut_ad(n > 0); @@ -2193,9 +2196,13 @@ try_again: low = (DWORD) offset; high = (DWORD) offset_high; + os_mutex_enter(os_file_count_mutex); + os_n_pending_reads++; + os_mutex_exit(os_file_count_mutex); + /* Protect the seek / read operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; - + os_mutex_enter(os_file_seek_mutexes[i]); ret2 = SetFilePointer(file, low, &high, FILE_BEGIN); @@ -2204,20 +2211,24 @@ try_again: os_mutex_exit(os_file_seek_mutexes[i]); + os_mutex_enter(os_file_count_mutex); + os_n_pending_reads--; + os_mutex_exit(os_file_count_mutex); + goto error_handling; - } - - os_n_pending_reads++; - + } + ret = ReadFile(file, buf, (DWORD) n, &len, NULL); - os_n_pending_reads--; - os_mutex_exit(os_file_seek_mutexes[i]); - + + os_mutex_enter(os_file_count_mutex); + os_n_pending_reads--; + os_mutex_exit(os_file_count_mutex); + if (ret && len == n) { return(TRUE); - } + } #else ibool retry; ssize_t ret; @@ -2225,26 +2236,22 @@ try_again: os_bytes_read_since_printout += n; try_again: - os_n_pending_reads++; - ret = os_file_pread(file, buf, n, offset, offset_high); - os_n_pending_reads--; - if ((ulint)ret == n) { return(TRUE); } -#endif +#endif #ifdef __WIN__ error_handling: #endif - retry = os_file_handle_error_no_exit(NULL, "read"); + retry = os_file_handle_error_no_exit(NULL, "read"); if (retry) { goto try_again; } - + return(FALSE); } @@ -2265,7 +2272,7 @@ os_file_read_string( if (size == 0) { return; } - + rewind(file); flen = fread(str, 1, size - 1, file); str[flen] = '\0'; @@ -2287,7 +2294,7 @@ os_file_write( offset where to write */ ulint offset_high, /* in: most significant 32 bits of offset */ - ulint n) /* in: number of bytes to write */ + ulint n) /* in: number of bytes to write */ { #ifdef __WIN__ BOOL ret; @@ -2309,10 +2316,14 @@ os_file_write( retry: low = (DWORD) offset; high = (DWORD) offset_high; - + + os_mutex_enter(os_file_count_mutex); + os_n_pending_writes++; + os_mutex_exit(os_file_count_mutex); + /* Protect the seek / write operation with a mutex */ i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES; - + os_mutex_enter(os_file_seek_mutexes[i]); ret2 = SetFilePointer(file, low, &high, FILE_BEGIN); @@ -2320,7 +2331,11 @@ retry: if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) { os_mutex_exit(os_file_seek_mutexes[i]); - + + os_mutex_enter(os_file_count_mutex); + os_n_pending_writes--; + os_mutex_exit(os_file_count_mutex); + ut_print_timestamp(stderr); fprintf(stderr, @@ -2333,14 +2348,10 @@ retry: (ulong) GetLastError()); return(FALSE); - } + } - os_n_pending_writes++; - ret = WriteFile(file, buf, (DWORD) n, &len, NULL); - os_n_pending_writes--; - /* Always do fsync to reduce the probability that when the OS crashes, a database page is only partially physically written to disk. */ @@ -2352,6 +2363,10 @@ retry: os_mutex_exit(os_file_seek_mutexes[i]); + os_mutex_enter(os_file_count_mutex); + os_n_pending_writes--; + os_mutex_exit(os_file_count_mutex); + if (ret && len == n) { return(TRUE); @@ -2360,18 +2375,18 @@ retry: /* If some background file system backup tool is running, then, at least in Windows 2000, we may get here a specific error. Let us retry the operation 100 times, with 1 second waits. */ - + if (GetLastError() == ERROR_LOCK_VIOLATION && n_retries < 100) { os_thread_sleep(1000000); - + n_retries++; goto retry; - } - + } + if (!os_has_said_disk_full) { - + err = (ulint)GetLastError(); ut_print_timestamp(stderr); @@ -2401,20 +2416,16 @@ retry: return(FALSE); #else ssize_t ret; - - os_n_pending_writes++; - + ret = os_file_pwrite(file, buf, n, offset, offset_high); - os_n_pending_writes--; - if ((ulint)ret == n) { return(TRUE); } if (!os_has_said_disk_full) { - + ut_print_timestamp(stderr); fprintf(stderr, @@ -2438,7 +2449,7 @@ retry: os_has_said_disk_full = TRUE; } - return(FALSE); + return(FALSE); #endif } @@ -2449,14 +2460,14 @@ ibool os_file_status( /*===========*/ /* out: TRUE if call succeeded */ - const char* path, /* in: pathname of the file */ + const char* path, /* in: pathname of the file */ ibool* exists, /* out: TRUE if file exists */ os_file_type_t* type) /* out: type of the file (if it exists) */ { #ifdef __WIN__ int ret; struct _stat statinfo; - + ret = _stat(path, &statinfo); if (ret && (errno == ENOENT || errno == ENOTDIR)) { /* file does not exist */ @@ -2464,27 +2475,27 @@ os_file_status( return(TRUE); } else if (ret) { /* file exists, but stat call failed */ - + os_file_handle_error_no_exit(path, "stat"); - + return(FALSE); } - + if (_S_IFDIR & statinfo.st_mode) { *type = OS_FILE_TYPE_DIR; } else if (_S_IFREG & statinfo.st_mode) { - *type = OS_FILE_TYPE_FILE; + *type = OS_FILE_TYPE_FILE; } else { - *type = OS_FILE_TYPE_UNKNOWN; + *type = OS_FILE_TYPE_UNKNOWN; } *exists = TRUE; - + return(TRUE); #else int ret; struct stat statinfo; - + ret = stat(path, &statinfo); if (ret && (errno == ENOENT || errno == ENOTDIR)) { /* file does not exist */ @@ -2492,24 +2503,24 @@ os_file_status( return(TRUE); } else if (ret) { /* file exists, but stat call failed */ - + os_file_handle_error_no_exit(path, "stat"); - + return(FALSE); } - + if (S_ISDIR(statinfo.st_mode)) { *type = OS_FILE_TYPE_DIR; } else if (S_ISLNK(statinfo.st_mode)) { - *type = OS_FILE_TYPE_LINK; + *type = OS_FILE_TYPE_LINK; } else if (S_ISREG(statinfo.st_mode)) { - *type = OS_FILE_TYPE_FILE; + *type = OS_FILE_TYPE_FILE; } else { - *type = OS_FILE_TYPE_UNKNOWN; + *type = OS_FILE_TYPE_UNKNOWN; } *exists = TRUE; - + return(TRUE); #endif } @@ -2519,15 +2530,15 @@ This function returns information about the specified file */ ibool os_file_get_status( -/*===========*/ +/*===============*/ /* out: TRUE if stat information found */ - const char* path, /* in: pathname of the file */ + const char* path, /* in: pathname of the file */ os_file_stat_t* stat_info) /* information of a file in a directory */ { #ifdef __WIN__ int ret; struct _stat statinfo; - + ret = _stat(path, &statinfo); if (ret && (errno == ENOENT || errno == ENOTDIR)) { /* file does not exist */ @@ -2535,29 +2546,29 @@ os_file_get_status( return(FALSE); } else if (ret) { /* file exists, but stat call failed */ - + os_file_handle_error_no_exit(path, "stat"); - + return(FALSE); } if (_S_IFDIR & statinfo.st_mode) { stat_info->type = OS_FILE_TYPE_DIR; } else if (_S_IFREG & statinfo.st_mode) { - stat_info->type = OS_FILE_TYPE_FILE; + stat_info->type = OS_FILE_TYPE_FILE; } else { - stat_info->type = OS_FILE_TYPE_UNKNOWN; + stat_info->type = OS_FILE_TYPE_UNKNOWN; } stat_info->ctime = statinfo.st_ctime; stat_info->atime = statinfo.st_atime; stat_info->mtime = statinfo.st_mtime; - stat_info->size = statinfo.st_size; - + stat_info->size = statinfo.st_size; + return(TRUE); #else int ret; struct stat statinfo; - + ret = stat(path, &statinfo); if (ret && (errno == ENOENT || errno == ENOTDIR)) { @@ -2566,27 +2577,27 @@ os_file_get_status( return(FALSE); } else if (ret) { /* file exists, but stat call failed */ - + os_file_handle_error_no_exit(path, "stat"); - + return(FALSE); } - + if (S_ISDIR(statinfo.st_mode)) { stat_info->type = OS_FILE_TYPE_DIR; } else if (S_ISLNK(statinfo.st_mode)) { - stat_info->type = OS_FILE_TYPE_LINK; + stat_info->type = OS_FILE_TYPE_LINK; } else if (S_ISREG(statinfo.st_mode)) { - stat_info->type = OS_FILE_TYPE_FILE; + stat_info->type = OS_FILE_TYPE_FILE; } else { - stat_info->type = OS_FILE_TYPE_UNKNOWN; + stat_info->type = OS_FILE_TYPE_UNKNOWN; } stat_info->ctime = statinfo.st_ctime; stat_info->atime = statinfo.st_atime; stat_info->mtime = statinfo.st_mtime; - stat_info->size = statinfo.st_size; - + stat_info->size = statinfo.st_size; + return(TRUE); #endif } @@ -2612,18 +2623,18 @@ yields a complete pathname. The return value is a copy of the directory component of the pathname. The copy is allocated from heap. It is the caller responsibility -to free it after it is no longer needed. +to free it after it is no longer needed. The following list of examples (taken from SUSv2) shows the strings returned by dirname and basename for different paths: - path dirname basename - "/usr/lib" "/usr" "lib" - "/usr/" "/" "usr" - "usr" "." "usr" - "/" "/" "/" - "." "." "." - ".." "." ".." + path dirname basename + "/usr/lib" "/usr" "lib" + "/usr/" "/" "usr" + "usr" "." "usr" + "/" "/" "/" + "." "." "." + ".." "." ".." */ char* @@ -2653,10 +2664,10 @@ os_file_dirname( return(mem_strdupl(path, last_slash - path)); } - + /******************************************************************** Creates all missing subdirectories along the given path. */ - + ibool os_file_create_subdirs_if_needed( /*=============================*/ @@ -2665,12 +2676,12 @@ os_file_create_subdirs_if_needed( const char* path) /* in: path name */ { char* subdir; - ibool success, subdir_exists; + ibool success, subdir_exists; os_file_type_t type; subdir = os_file_dirname(path); if (strlen(subdir) == 1 - && (*subdir == OS_FILE_PATH_SEPARATOR || *subdir == '.')) { + && (*subdir == OS_FILE_PATH_SEPARATOR || *subdir == '.')) { /* subdir is root or cwd, nothing to do */ mem_free(subdir); @@ -2719,32 +2730,32 @@ os_aio_array_create( /* out, own: aio array */ ulint n, /* in: maximum number of pending aio operations allowed; n must be divisible by n_segments */ - ulint n_segments) /* in: number of segments in the aio array */ + ulint n_segments) /* in: number of segments in the aio array */ { os_aio_array_t* array; ulint i; os_aio_slot_t* slot; #ifdef WIN_ASYNC_IO OVERLAPPED* over; -#endif +#endif ut_a(n > 0); ut_a(n_segments > 0); array = ut_malloc(sizeof(os_aio_array_t)); - array->mutex = os_mutex_create(NULL); + array->mutex = os_mutex_create(NULL); array->not_full = os_event_create(NULL); array->is_empty = os_event_create(NULL); os_event_set(array->is_empty); - - array->n_slots = n; + + array->n_slots = n; array->n_segments = n_segments; array->n_reserved = 0; array->slots = ut_malloc(n * sizeof(os_aio_slot_t)); #ifdef __WIN__ array->native_events = ut_malloc(n * sizeof(os_native_event_t)); -#endif +#endif for (i = 0; i < n; i++) { slot = os_aio_array_get_nth_slot(array, i); @@ -2760,7 +2771,7 @@ os_aio_array_create( *((array->native_events) + i) = over->hEvent; #endif } - + return(array); } @@ -2796,13 +2807,13 @@ os_aio_init( os_io_init_simple(); for (i = 0; i < n_segments; i++) { - srv_set_io_thread_op_info(i, "not started yet"); + srv_set_io_thread_op_info(i, "not started yet"); } n_per_seg = n / n_segments; n_write_segs = (n_segments - 2) / 2; n_read_segs = n_segments - 2 - n_write_segs; - + /* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */ os_aio_ibuf_array = os_aio_array_create(n_per_seg, 1); @@ -2817,14 +2828,14 @@ os_aio_init( n_read_segs); for (i = 2; i < 2 + n_read_segs; i++) { ut_a(i < SRV_MAX_N_IO_THREADS); - srv_io_thread_function[i] = "read thread"; + srv_io_thread_function[i] = "read thread"; } os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg, n_write_segs); for (i = 2 + n_read_segs; i < n_segments; i++) { ut_a(i < SRV_MAX_N_IO_THREADS); - srv_io_thread_function[i] = "write thread"; + srv_io_thread_function[i] = "write thread"; } os_aio_sync_array = os_aio_array_create(n_slots_sync, 1); @@ -2846,10 +2857,10 @@ os_aio_init( for this to work, the current thread must be the first created in the database, so that all its children will inherit its signal mask */ - + /* TODO: to work MySQL needs the SIGALARM signal; the following will not work yet! */ - sigemptyset(&sigset); + sigemptyset(&sigset); sigaddset(&sigset, SIGRTMIN + 1 + 0); sigaddset(&sigset, SIGRTMIN + 1 + 1); sigaddset(&sigset, SIGRTMIN + 1 + 2); @@ -2873,7 +2884,7 @@ os_aio_array_wake_win_aio_at_shutdown( for (i = 0; i < array->n_slots; i++) { - os_event_set((array->slots + i)->event); + os_event_set((array->slots + i)->event); } } #endif @@ -2889,7 +2900,7 @@ os_aio_wake_all_threads_at_shutdown(void) ulint i; #ifdef WIN_ASYNC_IO - /* This code wakes up all ai/o threads in Windows native aio */ + /* This code wakes up all ai/o threads in Windows native aio */ os_aio_array_wake_win_aio_at_shutdown(os_aio_read_array); os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array); os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array); @@ -2898,11 +2909,11 @@ os_aio_wake_all_threads_at_shutdown(void) /* This loop wakes up all simulated ai/o threads */ for (i = 0; i < os_aio_n_segments; i++) { - + os_event_set(os_aio_segment_wait_events[i]); - } + } } - + /**************************************************************************** Waits until there are no pending writes in os_aio_write_array. There can be other, synchronous, pending writes. */ @@ -2933,7 +2944,7 @@ os_aio_get_segment_no_from_slot( } else if (array == os_aio_log_array) { segment = 1; - + } else if (array == os_aio_read_array) { seg_len = os_aio_read_array->n_slots / os_aio_read_array->n_segments; @@ -2964,7 +2975,7 @@ os_aio_get_array_and_local_segment( { ulint segment; - ut_a(global_segment < os_aio_n_segments); + ut_a(global_segment < os_aio_n_segments); if (global_segment == 0) { *array = os_aio_ibuf_array; @@ -2973,7 +2984,7 @@ os_aio_get_array_and_local_segment( } else if (global_segment == 1) { *array = os_aio_log_array; segment = 0; - + } else if (global_segment < os_aio_read_array->n_segments + 2) { *array = os_aio_read_array; @@ -2997,9 +3008,9 @@ ulint os_aio_get_array_no( /*================*/ os_aio_array_t* array) /* in: aio array */ -{ +{ if (array == os_aio_ibuf_array) { - + return(0); } else if (array == os_aio_log_array) { @@ -3027,7 +3038,7 @@ os_aio_get_array_from_no( /*=====================*/ /* out: aio array */ ulint n) /* in: array number */ -{ +{ if (n == 0) { return(os_aio_ibuf_array); } else if (n == 1) { @@ -3093,7 +3104,7 @@ loop: os_aio_simulated_wake_handler_threads(); } - + os_event_wait(array->not_full); goto loop; @@ -3116,7 +3127,7 @@ loop: if (array->n_reserved == array->n_slots) { os_event_reset(array->not_full); } - + slot->reserved = TRUE; slot->reservation_time = time(NULL); slot->message1 = message1; @@ -3129,8 +3140,8 @@ loop: slot->offset = offset; slot->offset_high = offset_high; slot->io_already_done = FALSE; - -#ifdef WIN_ASYNC_IO + +#ifdef WIN_ASYNC_IO control = &(slot->control); control->Offset = (DWORD)offset; control->OffsetHigh = (DWORD)offset_high; @@ -3142,7 +3153,7 @@ loop: offset = offset + (offset_high << 32); #else ut_a(offset_high == 0); -#endif +#endif control = &(slot->control); control->aio_fildes = file; control->aio_buf = buf; @@ -3179,7 +3190,7 @@ os_aio_array_free_slot( os_mutex_enter(array->mutex); ut_ad(slot->reserved); - + slot->reserved = FALSE; array->n_reserved--; @@ -3192,7 +3203,7 @@ os_aio_array_free_slot( os_event_set(array->is_empty); } -#ifdef WIN_ASYNC_IO +#ifdef WIN_ASYNC_IO os_event_reset(slot->event); #endif os_mutex_exit(array->mutex); @@ -3228,7 +3239,7 @@ os_aio_simulated_wake_handler_thread( if (slot->reserved) { /* Found an i/o request */ - + break; } } @@ -3253,7 +3264,7 @@ os_aio_simulated_wake_handler_threads(void) /* We do not use simulated aio: do nothing */ return; - } + } os_aio_recommend_sleep_for_read_threads = FALSE; @@ -3281,7 +3292,7 @@ os_aio_simulated_put_read_threads_to_sleep(void) os_aio_get_array_and_local_segment(&array, g); if (array == os_aio_read_array) { - + os_event_reset(os_aio_segment_wait_events[g]); } } @@ -3348,7 +3359,7 @@ os_aio( wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER; mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER); - + if (mode == OS_AIO_SYNC #ifdef WIN_ASYNC_IO && !os_aio_use_native_aio @@ -3395,7 +3406,7 @@ try_again: array = NULL; /* Eliminate compiler warning */ ut_error; } - + slot = os_aio_array_reserve_slot(type, array, message1, message2, file, name, buf, offset, offset_high, n); if (type == OS_FILE_READ) { @@ -3403,7 +3414,7 @@ try_again: #ifdef WIN_ASYNC_IO os_n_file_reads++; os_bytes_read_since_printout += len; - + ret = ReadFile(file, buf, (DWORD)n, &len, &(slot->control)); #elif defined(POSIX_ASYNC_IO) @@ -3441,21 +3452,22 @@ try_again: #ifdef WIN_ASYNC_IO if (os_aio_use_native_aio) { if ((ret && len == n) - || (!ret && GetLastError() == ERROR_IO_PENDING)) { + || (!ret && GetLastError() == ERROR_IO_PENDING)) { /* aio was queued successfully! */ - - if (mode == OS_AIO_SYNC) { - /* We want a synchronous i/o operation on a file - where we also use async i/o: in Windows we must - use the same wait mechanism as for async i/o */ - - retval = os_aio_windows_handle(ULINT_UNDEFINED, + + if (mode == OS_AIO_SYNC) { + /* We want a synchronous i/o operation on a + file where we also use async i/o: in Windows + we must use the same wait mechanism as for + async i/o */ + + retval = os_aio_windows_handle(ULINT_UNDEFINED, slot->pos, - &dummy_mess1, &dummy_mess2, + &dummy_mess1, &dummy_mess2, &dummy_type); - return(retval); - } + return(retval); + } return(TRUE); } @@ -3476,7 +3488,7 @@ try_again: if (retry) { goto try_again; - } + } return(FALSE); } @@ -3503,7 +3515,7 @@ os_aio_windows_handle( sync aio is used, and this parameter is ignored */ ulint pos, /* this parameter is used only in sync aio: - wait for the aio slot at this position */ + wait for the aio slot at this position */ fil_node_t**message1, /* out: the messages passed with the aio request; note that also in the case where the aio operation failed, these output @@ -3527,7 +3539,7 @@ os_aio_windows_handle( } else { segment = os_aio_get_array_and_local_segment(&array, segment); } - + /* NOTE! We only access constant fields in os_aio_array. Therefore we do not have to acquire the protecting mutex yet */ @@ -3569,19 +3581,19 @@ os_aio_windows_handle( # ifdef UNIV_DO_FLUSH if (slot->type == OS_FILE_WRITE && !os_do_not_call_flush_at_each_write) { - ut_a(TRUE == os_file_flush(slot->file)); + ut_a(TRUE == os_file_flush(slot->file)); } # endif /* UNIV_DO_FLUSH */ } else { os_file_handle_error(slot->name, "Windows aio"); - + ret_val = FALSE; - } + } os_mutex_exit(array->mutex); os_aio_array_free_slot(array, slot); - + return(ret_val); } #endif @@ -3608,13 +3620,13 @@ os_aio_posix_handle( os_aio_slot_t* slot; siginfo_t info; sigset_t sigset; - sigset_t proc_sigset; - sigset_t thr_sigset; + sigset_t proc_sigset; + sigset_t thr_sigset; int ret; - int i; - int sig; - - sigemptyset(&sigset); + int i; + int sig; + + sigemptyset(&sigset); sigaddset(&sigset, SIGRTMIN + 1 + array_no); pthread_sigmask(SIG_UNBLOCK, &sigset, NULL); @@ -3635,10 +3647,10 @@ os_aio_posix_handle( if (sig != SIGRTMIN + 1 + array_no) { ut_error; - + return(FALSE); } - + fputs("Handling POSIX aio\n", stderr); array = os_aio_get_array_from_no(array_no); @@ -3662,7 +3674,7 @@ os_aio_posix_handle( os_mutex_exit(array->mutex); os_aio_array_free_slot(array, slot); - + return(TRUE); } #endif @@ -3705,9 +3717,9 @@ os_aio_simulated_handle( ulint n; ulint i; ulint len2; - + segment = os_aio_get_array_and_local_segment(&array, global_segment); - + restart: /* NOTE! We only access constant fields in os_aio_array. Therefore we do not have to acquire the protecting mutex yet */ @@ -3722,14 +3734,14 @@ restart: /* Look through n slots after the segment * n'th slot */ if (array == os_aio_read_array - && os_aio_recommend_sleep_for_read_threads) { + && os_aio_recommend_sleep_for_read_threads) { /* Give other threads chance to add several i/os to the array at once. */ goto recommended_sleep; } - + os_mutex_enter(array->mutex); srv_set_io_thread_op_info(global_segment, @@ -3737,7 +3749,7 @@ restart: /* Check if there is a slot for which the i/o has already been done */ - + for (i = 0; i < n; i++) { slot = os_aio_array_get_nth_slot(array, i + segment * n); @@ -3749,7 +3761,7 @@ restart: } ret = TRUE; - + goto slot_io_done; } } @@ -3767,14 +3779,14 @@ restart: slot = os_aio_array_get_nth_slot(array, i + segment * n); if (slot->reserved) { - age = (ulint)difftime(time(NULL), + age = (ulint)difftime(time(NULL), slot->reservation_time); if ((age >= 2 && age > biggest_age) - || (age >= 2 && age == biggest_age - && slot->offset < lowest_offset)) { + || (age >= 2 && age == biggest_age + && slot->offset < lowest_offset)) { - /* Found an i/o request */ + /* Found an i/o request */ consecutive_ios[0] = slot; n_consecutive = 1; @@ -3786,19 +3798,19 @@ restart: } if (n_consecutive == 0) { - /* There were no old requests. Look for an i/o request at the + /* There were no old requests. Look for an i/o request at the lowest offset in the array (we ignore the high 32 bits of the offset in these heuristics) */ lowest_offset = ULINT_MAX; - + for (i = 0; i < n; i++) { - slot = os_aio_array_get_nth_slot(array, + slot = os_aio_array_get_nth_slot(array, i + segment * n); if (slot->reserved && slot->offset < lowest_offset) { - /* Found an i/o request */ + /* Found an i/o request */ consecutive_ios[0] = slot; n_consecutive = 1; @@ -3819,17 +3831,17 @@ restart: /* Check if there are several consecutive blocks to read or write */ -consecutive_loop: +consecutive_loop: for (i = 0; i < n; i++) { slot2 = os_aio_array_get_nth_slot(array, i + segment * n); if (slot2->reserved && slot2 != slot - && slot2->offset == slot->offset + slot->len - && slot->offset + slot->len > slot->offset /* check that - sum does not wrap over */ - && slot2->offset_high == slot->offset_high - && slot2->type == slot->type - && slot2->file == slot->file) { + && slot2->offset == slot->offset + slot->len + /* check that sum does not wrap over */ + && slot->offset + slot->len > slot->offset + && slot2->offset_high == slot->offset_high + && slot2->type == slot->type + && slot2->file == slot->file) { /* Found a consecutive i/o request */ @@ -3839,7 +3851,7 @@ consecutive_loop: slot = slot2; if (n_consecutive < OS_AIO_MERGE_N_CONSECUTIVE) { - + goto consecutive_loop; } else { break; @@ -3855,7 +3867,7 @@ consecutive_loop: total_len = 0; slot = consecutive_ios[0]; - + for (i = 0; i < n_consecutive; i++) { total_len += consecutive_ios[i]->len; } @@ -3871,7 +3883,7 @@ consecutive_loop: combined_buf = ut_align(combined_buf2, UNIV_PAGE_SIZE); } - + /* We release the array mutex for the time of the i/o: NOTE that this assumes that there is just one i/o-handler thread serving a single segment of slots! */ @@ -3881,7 +3893,7 @@ consecutive_loop: if (slot->type == OS_FILE_WRITE && n_consecutive > 1) { /* Copy the buffers to the combined buffer */ offs = 0; - + for (i = 0; i < n_consecutive; i++) { ut_memcpy(combined_buf + offs, consecutive_ios[i]->buf, @@ -3889,7 +3901,7 @@ consecutive_loop: offs += consecutive_ios[i]->len; } } - + srv_set_io_thread_op_info(global_segment, "doing file i/o"); if (os_aio_print_debug) { @@ -3903,7 +3915,7 @@ consecutive_loop: if (slot->type == OS_FILE_WRITE) { if (array == os_aio_write_array) { if ((total_len % UNIV_PAGE_SIZE != 0) - || (slot->offset % UNIV_PAGE_SIZE != 0)) { + || (slot->offset % UNIV_PAGE_SIZE != 0)) { fprintf(stderr, "InnoDB: Error: trying a displaced write to %s %lu %lu, len %lu\n", slot->name, (ulong) slot->offset_high, @@ -3911,7 +3923,7 @@ consecutive_loop: (ulong) total_len); ut_error; } - + /* Do a 'last millisecond' check that the page end is sensible; reported page checksum errors from Linux seem to wipe over the page end */ @@ -3920,22 +3932,22 @@ consecutive_loop: len2 += UNIV_PAGE_SIZE) { if (mach_read_from_4(combined_buf + len2 + FIL_PAGE_LSN + 4) - != mach_read_from_4(combined_buf + len2 - + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { - ut_print_timestamp(stderr); - fprintf(stderr, + != mach_read_from_4(combined_buf + len2 + + UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: ERROR: The page to be written seems corrupt!\n"); - fprintf(stderr, + fprintf(stderr, "InnoDB: Writing a block of %lu bytes, currently writing at offset %lu\n", (ulong)total_len, (ulong)len2); buf_page_print(combined_buf + len2); - fprintf(stderr, + fprintf(stderr, "InnoDB: ERROR: The page to be written seems corrupt!\n"); } } } - + ret = os_file_write(slot->name, slot->file, combined_buf, slot->offset, slot->offset_high, total_len); } else { @@ -3953,10 +3965,10 @@ consecutive_loop: if (slot->type == OS_FILE_READ && n_consecutive > 1) { /* Copy the combined buffer to individual buffers */ offs = 0; - + for (i = 0; i < n_consecutive; i++) { - ut_memcpy(consecutive_ios[i]->buf, combined_buf + offs, + ut_memcpy(consecutive_ios[i]->buf, combined_buf + offs, consecutive_ios[i]->len); offs += consecutive_ios[i]->len; } @@ -3977,7 +3989,7 @@ consecutive_loop: /* We return the messages for the first slot now, and if there were several slots, the messages will be returned with subsequent calls of this function */ - + slot_io_done: ut_a(slot->reserved); @@ -3990,7 +4002,7 @@ slot_io_done: os_mutex_exit(array->mutex); os_aio_array_free_slot(array, slot); - + return(ret); wait_for_io: @@ -3998,7 +4010,7 @@ wait_for_io: /* We wait here until there again can be i/os in the segment of this thread */ - + os_event_reset(os_aio_segment_wait_events[global_segment]); os_mutex_exit(array->mutex); @@ -4013,7 +4025,7 @@ recommended_sleep: "InnoDB: i/o handler thread for i/o segment %lu wakes up\n", (ulong) global_segment); } - + goto restart; } @@ -4029,17 +4041,17 @@ os_aio_array_validate( os_aio_slot_t* slot; ulint n_reserved = 0; ulint i; - + ut_a(array); os_mutex_enter(array->mutex); ut_a(array->n_slots > 0); ut_a(array->n_segments > 0); - + for (i = 0; i < array->n_slots; i++) { slot = os_aio_array_get_nth_slot(array, i); - + if (slot->reserved) { n_reserved++; ut_a(slot->len > 0); @@ -4092,11 +4104,11 @@ os_aio_print( srv_io_thread_function[i]); #ifndef __WIN__ - if (os_aio_segment_wait_events[i]->is_set) { + if (os_aio_segment_wait_events[i]->is_set) { fprintf(file, " ev set"); } #endif - + fprintf(file, "\n"); } @@ -4105,17 +4117,17 @@ os_aio_print( array = os_aio_read_array; loop: ut_a(array); - + os_mutex_enter(array->mutex); ut_a(array->n_slots > 0); ut_a(array->n_segments > 0); - + n_reserved = 0; for (i = 0; i < array->n_slots; i++) { slot = os_aio_array_get_nth_slot(array, i); - + if (slot->reserved) { n_reserved++; /* fprintf(stderr, "Reserved slot, messages %p %p\n", @@ -4127,12 +4139,12 @@ loop: ut_a(array->n_reserved == n_reserved); fprintf(file, " %lu", (ulong) n_reserved); - + os_mutex_exit(array->mutex); if (array == os_aio_read_array) { fputs(", aio writes:", file); - + array = os_aio_write_array; goto loop; @@ -4173,9 +4185,9 @@ loop: if (os_file_n_pending_preads != 0 || os_file_n_pending_pwrites != 0) { fprintf(file, - "%lu pending preads, %lu pending pwrites\n", - (ulong) os_file_n_pending_preads, - (ulong) os_file_n_pending_pwrites); + "%lu pending preads, %lu pending pwrites\n", + (ulong) os_file_n_pending_preads, + (ulong) os_file_n_pending_pwrites); } if (os_n_file_reads == os_n_file_reads_old) { @@ -4199,7 +4211,7 @@ loop: os_n_file_writes_old = os_n_file_writes; os_n_fsyncs_old = os_n_fsyncs; os_bytes_read_since_printout = 0; - + os_last_printout = current_time; } @@ -4214,7 +4226,7 @@ os_aio_refresh_stats(void) os_n_file_writes_old = os_n_file_writes; os_n_fsyncs_old = os_n_fsyncs; os_bytes_read_since_printout = 0; - + os_last_printout = time(NULL); } @@ -4230,45 +4242,45 @@ os_aio_all_slots_free(void) { os_aio_array_t* array; ulint n_res = 0; - + array = os_aio_read_array; os_mutex_enter(array->mutex); - n_res += array->n_reserved; - + n_res += array->n_reserved; + os_mutex_exit(array->mutex); array = os_aio_write_array; os_mutex_enter(array->mutex); - n_res += array->n_reserved; - + n_res += array->n_reserved; + os_mutex_exit(array->mutex); array = os_aio_ibuf_array; os_mutex_enter(array->mutex); - n_res += array->n_reserved; - + n_res += array->n_reserved; + os_mutex_exit(array->mutex); array = os_aio_log_array; os_mutex_enter(array->mutex); - n_res += array->n_reserved; - + n_res += array->n_reserved; + os_mutex_exit(array->mutex); array = os_aio_sync_array; os_mutex_enter(array->mutex); - n_res += array->n_reserved; - + n_res += array->n_reserved; + os_mutex_exit(array->mutex); if (n_res == 0) { diff --git a/storage/innobase/os/os0proc.c b/storage/innobase/os/os0proc.c index 24bb007e504..fc1b2d0d2dd 100644 --- a/storage/innobase/os/os0proc.c +++ b/storage/innobase/os/os0proc.c @@ -89,59 +89,58 @@ os_awe_enable_lock_pages_in_mem(void) return(TRUE); #elif defined(__WIN2000__) - struct { - DWORD Count; - LUID_AND_ATTRIBUTES Privilege[1]; - } Info; + struct { + DWORD Count; + LUID_AND_ATTRIBUTES Privilege[1]; + } Info; HANDLE hProcess; - HANDLE Token; - BOOL Result; + HANDLE Token; + BOOL Result; hProcess = GetCurrentProcess(); - /* Open the token of the current process */ + /* Open the token of the current process */ - Result = OpenProcessToken(hProcess, - TOKEN_ADJUST_PRIVILEGES, - &Token); - if (Result != TRUE) { - fprintf(stderr, + Result = OpenProcessToken(hProcess, + TOKEN_ADJUST_PRIVILEGES, &Token); + if (Result != TRUE) { + fprintf(stderr, "InnoDB: AWE: Cannot open process token, error %lu\n", (ulint)GetLastError()); - return(FALSE); - } + return(FALSE); + } - Info.Count = 1; + Info.Count = 1; - Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; + Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; - /* Get the local unique identifier (LUID) of the SE_LOCK_MEMORY + /* Get the local unique identifier (LUID) of the SE_LOCK_MEMORY privilege */ - Result = LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, - &(Info.Privilege[0].Luid)); - if (Result != TRUE) { - fprintf(stderr, + Result = LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, + &(Info.Privilege[0].Luid)); + if (Result != TRUE) { + fprintf(stderr, "InnoDB: AWE: Cannot get local privilege value for %s, error %lu.\n", SE_LOCK_MEMORY_NAME, (ulint)GetLastError()); - return(FALSE); - } + return(FALSE); + } - /* Try to adjust the privilege */ + /* Try to adjust the privilege */ - Result = AdjustTokenPrivileges(Token, FALSE, - (PTOKEN_PRIVILEGES)&Info, - 0, NULL, NULL); - /* Check the result */ + Result = AdjustTokenPrivileges(Token, FALSE, + (PTOKEN_PRIVILEGES)&Info, + 0, NULL, NULL); + /* Check the result */ - if (Result != TRUE) { - fprintf(stderr, + if (Result != TRUE) { + fprintf(stderr, "InnoDB: AWE: Cannot adjust process token privileges, error %u.\n", GetLastError()); - return(FALSE); - } else if (GetLastError() != ERROR_SUCCESS) { - fprintf(stderr, + return(FALSE); + } else if (GetLastError() != ERROR_SUCCESS) { + fprintf(stderr, "InnoDB: AWE: Cannot enable SE_LOCK_MEMORY privilege, error %lu.\n" "InnoDB: In Windows XP Home you cannot use AWE. In Windows 2000 and XP\n" "InnoDB: Professional you must go to the Control Panel, to\n" @@ -159,7 +158,7 @@ os_awe_enable_lock_pages_in_mem(void) #ifdef __WIN__ fprintf(stderr, "InnoDB: AWE: Error: to use AWE you must use a ...-nt MySQL executable.\n"); -#endif +#endif return(FALSE); #endif } @@ -193,14 +192,14 @@ os_awe_allocate_physical_mem( #elif defined(__WIN2000__) BOOL bResult; - os_awe_t NumberOfPages; /* Question: why does Windows - use the name ULONG_PTR for - a scalar integer type? Maybe - because we may also refer to - &NumberOfPages? */ - os_awe_t NumberOfPagesInitial; - SYSTEM_INFO sSysInfo; - int PFNArraySize; + os_awe_t NumberOfPages; /* Question: why does Windows + use the name ULONG_PTR for + a scalar integer type? Maybe + because we may also refer to + &NumberOfPages? */ + os_awe_t NumberOfPagesInitial; + SYSTEM_INFO sSysInfo; + int PFNArraySize; if (n_megabytes > 64 * 1024) { @@ -211,9 +210,9 @@ os_awe_allocate_physical_mem( return(FALSE); } - GetSystemInfo(&sSysInfo); /* fill the system information structure */ + GetSystemInfo(&sSysInfo); /* fill the system information structure */ - if ((ulint)OS_AWE_X86_PAGE_SIZE != (ulint)sSysInfo.dwPageSize) { + if ((ulint)OS_AWE_X86_PAGE_SIZE != (ulint)sSysInfo.dwPageSize) { fprintf(stderr, "InnoDB: AWE: Error: this computer has a page size of %lu.\n" "InnoDB: Should be 4096 bytes for InnoDB AWE support to work.\n", @@ -222,36 +221,36 @@ os_awe_allocate_physical_mem( return(FALSE); } - /* Calculate the number of pages of memory to request */ + /* Calculate the number of pages of memory to request */ - NumberOfPages = n_megabytes * ((1024 * 1024) / OS_AWE_X86_PAGE_SIZE); - - /* Calculate the size of page_info for allocated physical pages */ + NumberOfPages = n_megabytes * ((1024 * 1024) / OS_AWE_X86_PAGE_SIZE); - PFNArraySize = NumberOfPages * sizeof(os_awe_t); + /* Calculate the size of page_info for allocated physical pages */ - *page_info = (os_awe_t*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize); + PFNArraySize = NumberOfPages * sizeof(os_awe_t); + + *page_info = (os_awe_t*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize); if (*page_info == NULL) { - fprintf(stderr, + fprintf(stderr, "InnoDB: AWE: Failed to allocate page info array from process heap, error %lu\n", (ulint)GetLastError()); - return(FALSE); - } + return(FALSE); + } ut_total_allocated_memory += PFNArraySize; - /* Enable this process' privilege to lock pages to physical memory */ + /* Enable this process' privilege to lock pages to physical memory */ if (!os_awe_enable_lock_pages_in_mem()) { return(FALSE); } - /* Allocate the physical memory */ + /* Allocate the physical memory */ - NumberOfPagesInitial = NumberOfPages; + NumberOfPagesInitial = NumberOfPages; os_awe_page_info = *page_info; os_awe_n_pages = (ulint)NumberOfPages; @@ -259,19 +258,18 @@ os_awe_allocate_physical_mem( /* Compilation note: if the compiler complains the function is not defined, see the note at the start of this file */ - bResult = AllocateUserPhysicalPages(GetCurrentProcess(), - &NumberOfPages, - *page_info); - if (bResult != TRUE) { - fprintf(stderr, + bResult = AllocateUserPhysicalPages(GetCurrentProcess(), + &NumberOfPages, *page_info); + if (bResult != TRUE) { + fprintf(stderr, "InnoDB: AWE: Cannot allocate physical pages, error %lu.\n", (ulint)GetLastError()); - return(FALSE); - } + return(FALSE); + } - if (NumberOfPagesInitial != NumberOfPages) { - fprintf(stderr, + if (NumberOfPagesInitial != NumberOfPages) { + fprintf(stderr, "InnoDB: AWE: Error: allocated only %lu pages of %lu requested.\n" "InnoDB: Check that you have enough free RAM.\n" "InnoDB: In Windows XP Professional and 2000 Professional\n" @@ -283,18 +281,18 @@ os_awe_allocate_physical_mem( (ulint)NumberOfPages, (ulint)NumberOfPagesInitial); - return(FALSE); - } + return(FALSE); + } fprintf(stderr, "InnoDB: Using Address Windowing Extensions (AWE); allocated %lu MB\n", n_megabytes); - return(TRUE); + return(TRUE); #else UT_NOT_USED(n_megabytes); UT_NOT_USED(page_info); - + return(FALSE); #endif } @@ -324,7 +322,7 @@ os_awe_allocate_virtual_mem_window( } return(os_awe_simulate_window); - + #elif defined(__WIN2000__) byte* ptr; @@ -334,7 +332,7 @@ os_awe_allocate_virtual_mem_window( return(NULL); } - + ptr = VirtualAlloc(NULL, (SIZE_T)size, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE); if (ptr == NULL) { @@ -353,7 +351,7 @@ os_awe_allocate_virtual_mem_window( return(ptr); #else UT_NOT_USED(size); - + return(NULL); #endif } @@ -393,7 +391,7 @@ os_awe_map_physical_mem_to_window( ut_a(ptr < os_awe_simulate_window + os_awe_simulate_window_size); ut_a(page_info >= os_awe_simulate_page_info); ut_a(page_info < os_awe_simulate_page_info + - (os_awe_simulate_mem_size / 4096)); + (os_awe_simulate_mem_size / 4096)); /* First look if some other 'physical pages' are mapped at ptr, and copy them back to where they were if yes */ @@ -401,7 +399,7 @@ os_awe_map_physical_mem_to_window( map = os_awe_simulate_map + ((ulint)(ptr - os_awe_simulate_window)) / 4096; page = ptr; - + for (i = 0; i < n_mem_pages; i++) { if (*map != NULL) { ut_memcpy(*map, page, 4096); @@ -432,13 +430,13 @@ os_awe_map_physical_mem_to_window( } return(TRUE); - + #elif defined(__WIN2000__) BOOL bResult; os_awe_t n_pages; n_pages = (os_awe_t)n_mem_pages; - + if (!(ptr >= os_awe_window)) { fprintf(stderr, "InnoDB: AWE: Error: trying to map to address %lx but AWE window start %lx\n", @@ -487,7 +485,7 @@ os_awe_map_physical_mem_to_window( return(FALSE); #endif -} +} /******************************************************************** Converts the current process id to a number. It is not guaranteed that the @@ -518,7 +516,7 @@ os_mem_alloc_nocache( #ifdef __WIN__ void* ptr; - ptr = VirtualAlloc(NULL, n, MEM_COMMIT, + ptr = VirtualAlloc(NULL, n, MEM_COMMIT, PAGE_READWRITE | PAGE_NOCACHE); ut_a(ptr); @@ -533,60 +531,60 @@ Allocates large pages memory. */ void* os_mem_alloc_large( -/*=================*/ - /* out: allocated memory */ - ulint n, /* in: number of bytes */ - ibool set_to_zero, /* in: TRUE if allocated memory should be set - to zero if UNIV_SET_MEM_TO_ZERO is defined */ - ibool assert_on_error) /* in: if TRUE, we crash mysqld if the memory - cannot be allocated */ +/*===============*/ + /* out: allocated memory */ + ulint n, /* in: number of bytes */ + ibool set_to_zero, /* in: TRUE if allocated memory + should be set to zero if + UNIV_SET_MEM_TO_ZERO is defined */ + ibool assert_on_error)/* in: if TRUE, we crash mysqld if + the memory cannot be allocated */ { #ifdef HAVE_LARGE_PAGES ulint size; int shmid; void *ptr = NULL; struct shmid_ds buf; - + if (!os_use_large_pages || !os_large_page_size) { - goto skip; + goto skip; } #ifdef UNIV_LINUX /* Align block size to os_large_page_size */ size = ((n - 1) & ~(os_large_page_size - 1)) + os_large_page_size; - + shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W); if (shmid < 0) { - fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. " - "errno %d\n", n, errno); + fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate" + " %lu bytes. errno %d\n", n, errno); } else { - ptr = shmat(shmid, NULL, 0); - if (ptr == (void *)-1) { - fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to attach shared memory " - "segment, errno %d\n", errno); - } - /* - Remove the shared memory segment so that it will be automatically freed - after memory is detached or process exits - */ - shmctl(shmid, IPC_RMID, &buf); + ptr = shmat(shmid, NULL, 0); + if (ptr == (void *)-1) { + fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to" + " attach shared memory segment, errno %d\n", errno); + } + + /* Remove the shared memory segment so that it will be + automatically freed after memory is detached or process exits */ + shmctl(shmid, IPC_RMID, &buf); } #endif - + if (ptr) { - if (set_to_zero) { + if (set_to_zero) { #ifdef UNIV_SET_MEM_TO_ZERO - memset(ptr, '\0', size); + memset(ptr, '\0', size); #endif - } + } - return(ptr); + return(ptr); } fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional memory pool\n"); skip: #endif /* HAVE_LARGE_PAGES */ - + return(ut_malloc_low(n, set_to_zero, assert_on_error)); } @@ -595,16 +593,16 @@ Frees large pages memory. */ void os_mem_free_large( -/*=================*/ +/*==============*/ void *ptr) /* in: number of bytes */ { #ifdef HAVE_LARGE_PAGES if (os_use_large_pages && os_large_page_size #ifdef UNIV_LINUX - && !shmdt(ptr) + && !shmdt(ptr) #endif - ) { - return; + ) { + return; } #endif @@ -630,7 +628,9 @@ os_process_set_priority_boost( no_boost = TRUE; } - ut_a(TRUE == 1); +#if TRUE != 1 +# error "TRUE != 1" +#endif /* Does not do anything currently! SetProcessPriorityBoost(GetCurrentProcess(), no_boost); diff --git a/storage/innobase/os/os0sync.c b/storage/innobase/os/os0sync.c index 487e8f40a39..706c10ac613 100644 --- a/storage/innobase/os/os0sync.c +++ b/storage/innobase/os/os0sync.c @@ -20,7 +20,7 @@ Created 9/6/1995 Heikki Tuuri #include "srv0start.h" /* Type definition for an operating system mutex struct */ -struct os_mutex_struct{ +struct os_mutex_struct{ void* handle; /* OS handle to mutex */ ulint count; /* we use this counter to check that the same thread does not @@ -80,24 +80,24 @@ os_sync_free(void) while (event) { - os_event_free(event); + os_event_free(event); - event = UT_LIST_GET_FIRST(os_event_list); + event = UT_LIST_GET_FIRST(os_event_list); } mutex = UT_LIST_GET_FIRST(os_mutex_list); while (mutex) { - if (mutex == os_sync_mutex) { - /* Set the flag to FALSE so that we do not try to - reserve os_sync_mutex any more in remaining freeing - operations in shutdown */ - os_sync_mutex_inited = FALSE; - } + if (mutex == os_sync_mutex) { + /* Set the flag to FALSE so that we do not try to + reserve os_sync_mutex any more in remaining freeing + operations in shutdown */ + os_sync_mutex_inited = FALSE; + } - os_mutex_free(mutex); + os_mutex_free(mutex); - mutex = UT_LIST_GET_FIRST(os_mutex_list); + mutex = UT_LIST_GET_FIRST(os_mutex_list); } } @@ -114,7 +114,7 @@ os_event_create( the event is created without a name */ { #ifdef __WIN__ - os_event_t event; + os_event_t event; event = ut_malloc(sizeof(struct os_event_struct)); @@ -123,7 +123,7 @@ os_event_create( FALSE, /* Initial state nonsignaled */ (LPCTSTR) name); if (!event->handle) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Could not create a Windows event semaphore; Windows error %lu\n", (ulong) GetLastError()); } @@ -146,7 +146,7 @@ os_event_create( event->signal_count = 0; #endif /* __WIN__ */ - /* Put to the list of events */ + /* Put to the list of events */ os_mutex_enter(os_sync_mutex); UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); @@ -170,7 +170,7 @@ os_event_create_auto( const char* name) /* in: the name of the event, if NULL the event is created without a name */ { - os_event_t event; + os_event_t event; event = ut_malloc(sizeof(struct os_event_struct)); @@ -180,12 +180,12 @@ os_event_create_auto( (LPCTSTR) name); if (!event->handle) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Could not create a Windows auto event semaphore; Windows error %lu\n", (ulong) GetLastError()); } - /* Put to the list of events */ + /* Put to the list of events */ os_mutex_enter(os_sync_mutex); UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); @@ -207,7 +207,7 @@ os_event_set( /*=========*/ os_event_t event) /* in: event to set */ { -#ifdef __WIN__ +#ifdef __WIN__ ut_a(event); ut_a(SetEvent(event->handle)); #else @@ -224,7 +224,7 @@ os_event_set( } os_fast_mutex_unlock(&(event->os_mutex)); -#endif +#endif } /************************************************************** @@ -262,7 +262,7 @@ void os_event_free( /*==========*/ os_event_t event) /* in: event to free */ - + { #ifdef __WIN__ ut_a(event); @@ -274,7 +274,7 @@ os_event_free( os_fast_mutex_free(&(event->os_mutex)); ut_a(0 == pthread_cond_destroy(&(event->cond_var))); #endif - /* Remove from the list of events */ + /* Remove from the list of events */ os_mutex_enter(os_sync_mutex); @@ -309,7 +309,7 @@ os_event_wait( ut_a(err == WAIT_OBJECT_0); if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { - os_thread_exit(NULL); + os_thread_exit(NULL); } #else ib_longlong old_signal_count; @@ -317,28 +317,28 @@ os_event_wait( os_fast_mutex_lock(&(event->os_mutex)); old_signal_count = event->signal_count; -loop: - if (event->is_set == TRUE - || event->signal_count != old_signal_count) { - os_fast_mutex_unlock(&(event->os_mutex)); + for (;;) { + if (event->is_set == TRUE + || event->signal_count != old_signal_count) { - if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + os_fast_mutex_unlock(&(event->os_mutex)); - os_thread_exit(NULL); - } - /* Ok, we may return */ + if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { - return; - } + os_thread_exit(NULL); + } + /* Ok, we may return */ - pthread_cond_wait(&(event->cond_var), &(event->os_mutex)); + return; + } - /* Solaris manual said that spurious wakeups may occur: we have to - check if the event really has been signaled after we came here to - wait */ + pthread_cond_wait(&(event->cond_var), &(event->os_mutex)); - goto loop; + /* Solaris manual said that spurious wakeups may occur: we + have to check if the event really has been signaled after + we came here to wait */ + } #endif } @@ -365,7 +365,7 @@ os_event_wait_time( } else { err = WaitForSingleObject(event->handle, INFINITE); } - + if (err == WAIT_OBJECT_0) { return(0); @@ -378,7 +378,7 @@ os_event_wait_time( } #else UT_NOT_USED(time); - + /* In Posix this is just an ordinary, infinite wait */ os_event_wait(event); @@ -416,7 +416,7 @@ os_event_wait_multiple( ut_a(index < WAIT_OBJECT_0 + n); if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { - os_thread_exit(NULL); + os_thread_exit(NULL); } return(index - WAIT_OBJECT_0); @@ -447,11 +447,11 @@ os_mutex_create( os_mutex_t mutex_str; UT_NOT_USED(name); - + mutex = ut_malloc(sizeof(os_fast_mutex_t)); os_fast_mutex_init(mutex); -#endif +#endif mutex_str = ut_malloc(sizeof(os_mutex_str_t)); mutex_str->handle = mutex; @@ -459,7 +459,7 @@ os_mutex_create( if (os_sync_mutex_inited) { /* When creating os_sync_mutex itself we cannot reserve it */ - os_mutex_enter(os_sync_mutex); + os_mutex_enter(os_sync_mutex); } UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str); @@ -519,7 +519,7 @@ os_mutex_exit( ut_a(ReleaseMutex(mutex->handle)); #else os_fast_mutex_unlock(mutex->handle); -#endif +#endif } /************************************************************** @@ -537,7 +537,7 @@ os_mutex_free( } UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex); - + os_mutex_count--; if (os_sync_mutex_inited) { @@ -565,7 +565,7 @@ os_fast_mutex_init( { #ifdef __WIN__ ut_a(fast_mutex); - + InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex); #else #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) @@ -584,7 +584,7 @@ os_fast_mutex_init( os_fast_mutex_count++; if (os_sync_mutex_inited) { - os_mutex_exit(os_sync_mutex); + os_mutex_exit(os_sync_mutex); } } @@ -632,7 +632,7 @@ os_fast_mutex_free( DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); #else int ret; - + ret = pthread_mutex_destroy(fast_mutex); if (ret != 0) { @@ -642,8 +642,7 @@ os_fast_mutex_free( "InnoDB: pthread_mutex_destroy().\n", (ulint)ret); fprintf(stderr, "InnoDB: Byte contents of the pthread mutex at %p:\n", fast_mutex); - ut_print_buf(stderr, (const byte*)fast_mutex, - sizeof(os_fast_mutex_t)); + ut_print_buf(stderr, fast_mutex, sizeof(os_fast_mutex_t)); fprintf(stderr, "\n"); } #endif diff --git a/storage/innobase/os/os0thread.c b/storage/innobase/os/os0thread.c index c0e66ff2b7e..ff0362840c7 100644 --- a/storage/innobase/os/os0thread.c +++ b/storage/innobase/os/os0thread.c @@ -53,8 +53,8 @@ os_thread_pf( os_thread_id_t a) { #ifdef UNIV_HPUX10 - /* In HP-UX-10.20 a pthread_t is a struct of 3 fields: field1, field2, - field3. We do not know if field1 determines the thread uniquely. */ + /* In HP-UX-10.20 a pthread_t is a struct of 3 fields: field1, field2, + field3. We do not know if field1 determines the thread uniquely. */ return((ulint)(a.field1)); #else @@ -115,11 +115,11 @@ os_thread_create( if (srv_set_thread_priorities) { - /* Set created thread priority the same as a normal query - in MYSQL: we try to prevent starvation of threads by - assigning same priority QUERY_PRIOR to all */ + /* Set created thread priority the same as a normal query + in MYSQL: we try to prevent starvation of threads by + assigning same priority QUERY_PRIOR to all */ - ut_a(SetThreadPriority(thread, srv_query_thread_priority)); + ut_a(SetThreadPriority(thread, srv_query_thread_priority)); } *thread_id = win_thread_id; @@ -128,12 +128,12 @@ os_thread_create( #else int ret; os_thread_t pthread; - pthread_attr_t attr; + pthread_attr_t attr; #if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)) - pthread_attr_init(&attr); + pthread_attr_init(&attr); #endif - + #ifdef UNIV_AIX /* We must make sure a thread stack is at least 32 kB, otherwise InnoDB might crash; we do not know if the default stack size on @@ -141,28 +141,19 @@ os_thread_create( the size was 96 kB, though. */ ret = pthread_attr_setstacksize(&attr, - (size_t)(PTHREAD_STACK_MIN + 32 * 1024)); - if (ret) { - fprintf(stderr, - "InnoDB: Error: pthread_attr_setstacksize returned %d\n", ret); + (size_t)(PTHREAD_STACK_MIN + 32 * 1024)); + if (ret) { + fprintf(stderr, + "InnoDB: Error: pthread_attr_setstacksize returned %d\n", ret); exit(1); } #endif #ifdef __NETWARE__ ret = pthread_attr_setstacksize(&attr, (size_t) NW_THD_STACKSIZE); - if (ret) { - fprintf(stderr, - "InnoDB: Error: pthread_attr_setstacksize returned %d\n", ret); - exit(1); - } -#endif -#ifdef __NETWARE__ - ret = pthread_attr_setstacksize(&attr, - (size_t)NW_THD_STACKSIZE); - if (ret) { - fprintf(stderr, - "InnoDB: Error: pthread_attr_setstacksize returned %d\n", ret); + if (ret) { + fprintf(stderr, + "InnoDB: Error: pthread_attr_setstacksize returned %d\n", ret); exit(1); } #endif @@ -175,9 +166,9 @@ os_thread_create( #else ret = pthread_create(&pthread, &attr, start_f, arg); #endif - if (ret) { - fprintf(stderr, - "InnoDB: Error: pthread_create returned %d\n", ret); + if (ret) { + fprintf(stderr, + "InnoDB: Error: pthread_create returned %d\n", ret); exit(1); } @@ -185,8 +176,8 @@ os_thread_create( pthread_attr_destroy(&attr); #endif if (srv_set_thread_priorities) { - - my_pthread_setprio(pthread, srv_query_thread_priority); + + my_pthread_setprio(pthread, srv_query_thread_priority); } *thread_id = pthread; @@ -206,14 +197,14 @@ os_thread_exit( { #ifdef UNIV_DEBUG_THREAD_CREATION fprintf(stderr, "Thread exits, id %lu\n", - os_thread_pf(os_thread_get_curr_id())); + os_thread_pf(os_thread_get_curr_id())); #endif os_mutex_enter(os_sync_mutex); os_thread_count--; os_mutex_exit(os_sync_mutex); #ifdef __WIN__ - ExitThread((DWORD)exit_value); + ExitThread((DWORD)exit_value); #else pthread_exit(exit_value); #endif @@ -222,7 +213,7 @@ os_thread_exit( #ifdef HAVE_PTHREAD_JOIN int os_thread_join( -/*=============*/ +/*===========*/ os_thread_id_t thread_id) /* in: id of the thread to join */ { return pthread_join(thread_id, NULL); @@ -241,7 +232,7 @@ os_thread_get_curr(void) return(pthread_self()); #endif } - + /********************************************************************* Advises the os to give up remainder of the thread's time slice. */ @@ -252,13 +243,13 @@ os_thread_yield(void) #if defined(__WIN__) Sleep(0); #elif (defined(HAVE_SCHED_YIELD) && defined(HAVE_SCHED_H)) - sched_yield(); + sched_yield(); #elif defined(HAVE_PTHREAD_YIELD_ZERO_ARG) pthread_yield(); #elif defined(HAVE_PTHREAD_YIELD_ONE_ARG) pthread_yield(0); #else - os_thread_sleep(0); + os_thread_sleep(0); #endif } @@ -279,7 +270,7 @@ os_thread_sleep( t.tv_sec = tm / 1000000; t.tv_usec = tm % 1000000; - + select(0, NULL, NULL, NULL, &t); #endif } @@ -320,8 +311,8 @@ ulint os_thread_get_priority( /*===================*/ /* out: priority */ - os_thread_t handle __attribute__((unused))) - /* in: OS handle to the thread */ + os_thread_t handle __attribute__((unused))) + /* in: OS handle to the thread */ { #ifdef __WIN__ int os_pri; diff --git a/storage/innobase/page/page0cur.c b/storage/innobase/page/page0cur.c index d0b89e81787..70943ec3c8a 100644 --- a/storage/innobase/page/page0cur.c +++ b/storage/innobase/page/page0cur.c @@ -45,7 +45,7 @@ page_cur_try_search_shortcut( ulint* ilow_matched_bytes, /* in/out: already matched bytes in a field not yet completely matched */ - page_cur_t* cursor) /* out: page cursor */ + page_cur_t* cursor) /* out: page cursor */ { rec_t* rec; rec_t* next_rec; @@ -96,11 +96,11 @@ page_cur_try_search_shortcut( #ifdef UNIV_SEARCH_DEBUG page_cur_search_with_match(page, index, tuple, PAGE_CUR_DBG, - iup_matched_fields, - iup_matched_bytes, - ilow_matched_fields, - ilow_matched_bytes, - &cursor2); + iup_matched_fields, + iup_matched_bytes, + ilow_matched_fields, + ilow_matched_bytes, + &cursor2); ut_a(cursor2.rec == cursor->rec); if (next_rec != page_get_supremum_rec(page)) { @@ -150,38 +150,39 @@ page_cur_rec_field_extends( const ulint* offsets,/* in: array returned by rec_get_offsets() */ ulint n) /* in: compare nth field */ { - dtype_t* type; - dfield_t* dfield; - byte* rec_f; - ulint rec_f_len; + dtype_t* type; + dfield_t* dfield; + byte* rec_f; + ulint rec_f_len; ut_ad(rec_offs_validate(rec, NULL, offsets)); - dfield = dtuple_get_nth_field(tuple, n); + dfield = dtuple_get_nth_field(tuple, n); - type = dfield_get_type(dfield); + type = dfield_get_type(dfield); rec_f = rec_get_nth_field(rec, offsets, n, &rec_f_len); - if (type->mtype == DATA_VARCHAR - || type->mtype == DATA_CHAR - || type->mtype == DATA_FIXBINARY - || type->mtype == DATA_BINARY - || type->mtype == DATA_BLOB - || type->mtype == DATA_VARMYSQL - || type->mtype == DATA_MYSQL) { - - if (dfield_get_len(dfield) != UNIV_SQL_NULL - && rec_f_len != UNIV_SQL_NULL - && rec_f_len >= dfield_get_len(dfield) - && 0 == cmp_data_data_slow(type, dfield_get_data(dfield), - dfield_get_len(dfield), - rec_f, dfield_get_len(dfield))) { - - return(TRUE); + if (type->mtype == DATA_VARCHAR + || type->mtype == DATA_CHAR + || type->mtype == DATA_FIXBINARY + || type->mtype == DATA_BINARY + || type->mtype == DATA_BLOB + || type->mtype == DATA_VARMYSQL + || type->mtype == DATA_MYSQL) { + + if (dfield_get_len(dfield) != UNIV_SQL_NULL + && rec_f_len != UNIV_SQL_NULL + && rec_f_len >= dfield_get_len(dfield) + && 0 == cmp_data_data_slow(type, + dfield_get_data(dfield), + dfield_get_len(dfield), + rec_f, dfield_get_len(dfield))) { + + return(TRUE); } } - return(FALSE); + return(FALSE); } #endif /* PAGE_CUR_LE_OR_EXTENDS */ @@ -208,10 +209,10 @@ page_cur_search_with_match( ulint* ilow_matched_bytes, /* in/out: already matched bytes in a field not yet completely matched */ - page_cur_t* cursor) /* out: page cursor */ + page_cur_t* cursor) /* out: page cursor */ { - ulint up; - ulint low; + ulint up; + ulint low; ulint mid; page_dir_slot_t* slot; rec_t* up_rec; @@ -235,7 +236,7 @@ page_cur_search_with_match( *offsets_ = (sizeof offsets_) / sizeof *offsets_; ut_ad(page && tuple && iup_matched_fields && iup_matched_bytes - && ilow_matched_fields && ilow_matched_bytes && cursor); + && ilow_matched_fields && ilow_matched_bytes && cursor); ut_ad(dtuple_validate(tuple)); ut_ad(dtuple_check_typed(tuple)); #ifdef UNIV_DEBUG @@ -246,38 +247,36 @@ page_cur_search_with_match( if (mode != PAGE_CUR_LE_OR_EXTENDS) # endif /* PAGE_CUR_LE_OR_EXTENDS */ ut_ad((mode == PAGE_CUR_L) || (mode == PAGE_CUR_LE) - || (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)); + || (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)); #endif /* UNIV_DEBUG */ page_check_dir(page); #ifdef PAGE_CUR_ADAPT if ((page_header_get_field(page, PAGE_LEVEL) == 0) - && (mode == PAGE_CUR_LE) - && (page_header_get_field(page, PAGE_N_DIRECTION) > 3) - && (page_header_get_ptr(page, PAGE_LAST_INSERT)) - && (page_header_get_field(page, PAGE_DIRECTION) == PAGE_RIGHT)) { + && (mode == PAGE_CUR_LE) + && (page_header_get_field(page, PAGE_N_DIRECTION) > 3) + && (page_header_get_ptr(page, PAGE_LAST_INSERT)) + && (page_header_get_field(page, PAGE_DIRECTION) == PAGE_RIGHT)) { if (page_cur_try_search_shortcut(page, index, tuple, - iup_matched_fields, - iup_matched_bytes, - ilow_matched_fields, - ilow_matched_bytes, - cursor)) { - return; - } + iup_matched_fields, iup_matched_bytes, + ilow_matched_fields, ilow_matched_bytes, + cursor)) { + return; + } } # ifdef PAGE_CUR_DBG if (mode == PAGE_CUR_DBG) { mode = PAGE_CUR_LE; } # endif -#endif +#endif /* The following flag does not work for non-latin1 char sets because cmp_full_field does not tell how many bytes matched */ #ifdef PAGE_CUR_LE_OR_EXTENDS - ut_a(mode != PAGE_CUR_LE_OR_EXTENDS); + ut_a(mode != PAGE_CUR_LE_OR_EXTENDS); #endif /* PAGE_CUR_LE_OR_EXTENDS */ /* If mode PAGE_CUR_G is specified, we are trying to position the @@ -301,7 +300,7 @@ page_cur_search_with_match( /* Perform binary search until the lower and upper limit directory slots come to the distance 1 of each other */ - while (up - low > 1) { + while (up - low > 1) { mid = (low + up) / 2; slot = page_dir_get_nth_slot(page, mid); mid_rec = page_dir_slot_get_rec(slot); @@ -325,8 +324,8 @@ low_slot_match: } else if (UNIV_LIKELY(cmp /* == -1 */)) { #ifdef PAGE_CUR_LE_OR_EXTENDS if (mode == PAGE_CUR_LE_OR_EXTENDS - && page_cur_rec_field_extends(tuple, mid_rec, - offsets, cur_matched_fields)) { + && page_cur_rec_field_extends(tuple, mid_rec, + offsets, cur_matched_fields)) { goto low_slot_match; } @@ -347,7 +346,7 @@ up_slot_match: goto up_slot_match; } - } + } slot = page_dir_get_nth_slot(page, low); low_rec = page_dir_slot_get_rec(slot); @@ -357,7 +356,7 @@ up_slot_match: /* Perform linear search until the upper and lower records come to distance 1 of each other. */ - while (page_rec_get_next(low_rec) != up_rec) { + while (page_rec_get_next(low_rec) != up_rec) { mid_rec = page_rec_get_next(low_rec); @@ -380,8 +379,8 @@ low_rec_match: } else if (UNIV_LIKELY(cmp /* == -1 */)) { #ifdef PAGE_CUR_LE_OR_EXTENDS if (mode == PAGE_CUR_LE_OR_EXTENDS - && page_cur_rec_field_extends(tuple, mid_rec, - offsets, cur_matched_fields)) { + && page_cur_rec_field_extends(tuple, mid_rec, + offsets, cur_matched_fields)) { goto low_rec_match; } @@ -401,7 +400,7 @@ up_rec_match: goto up_rec_match; } - } + } #ifdef UNIV_SEARCH_DEBUG @@ -426,7 +425,7 @@ up_rec_match: } if (low_rec != page_get_infimum_rec(page)) { - + ut_a(low_matched_fields == dbg_matched_fields); ut_a(low_matched_bytes == dbg_matched_bytes); } @@ -487,9 +486,9 @@ page_cur_open_on_rnd_user_rec( page_cur_position(page_get_infimum_rec(page), cursor); return; - } + } - page_rnd += 87584577; + page_rnd += 87584577; rnd = page_rnd % page_get_n_recs(page); @@ -504,8 +503,8 @@ page_cur_open_on_rnd_user_rec( } page_cur_position(rec, cursor); -} - +} + /*************************************************************** Writes the log record of a record insert on a page. */ static @@ -533,7 +532,8 @@ page_cur_insert_rec_write_log( ut_a(rec_size < UNIV_PAGE_SIZE); ut_ad(buf_frame_align(insert_rec) == buf_frame_align(cursor_rec)); - ut_ad(!page_rec_is_comp(insert_rec) == !index->table->comp); + ut_ad(!page_rec_is_comp(insert_rec) + == !dict_table_is_comp(index->table)); comp = page_rec_is_comp(insert_rec); { @@ -573,7 +573,7 @@ page_cur_insert_rec_write_log( /* Find out the first byte in insert_rec which differs from cursor_rec; skip the bytes in the record info */ - + for (;;) { if (i >= min_rec_size) { @@ -624,15 +624,15 @@ page_cur_insert_rec_write_log( } if ((rec_get_info_and_status_bits(insert_rec, comp) != - rec_get_info_and_status_bits(cursor_rec, comp)) - || (extra_size != cur_extra_size) - || (rec_size != cur_rec_size)) { + rec_get_info_and_status_bits(cursor_rec, comp)) + || (extra_size != cur_extra_size) + || (rec_size != cur_rec_size)) { extra_info_yes = 1; } else { extra_info_yes = 0; } - + /* Write the record end segment length and the extra info storage flag */ log_ptr += mach_write_compressed(log_ptr, 2 * (rec_size - i) @@ -652,7 +652,7 @@ page_cur_insert_rec_write_log( ut_a(i < UNIV_PAGE_SIZE); ut_a(extra_size < UNIV_PAGE_SIZE); } - + /* Write to the log the inserted index record end segment which differs from the cursor record */ @@ -666,7 +666,7 @@ page_cur_insert_rec_write_log( ut_a(rec_size < UNIV_PAGE_SIZE); mlog_catenate_string(mtr, ins_ptr, rec_size); } -} +} /*************************************************************** Parses a log record of a record insert on a page. */ @@ -690,7 +690,7 @@ page_cur_parse_insert_rec( rec_t* cursor_rec; byte buf1[1024]; byte* buf; - byte* ptr2 = ptr; + byte* ptr2 = ptr; ulint info_and_status_bits = 0; /* remove warning */ page_cur_t cursor; mem_heap_t* heap = NULL; @@ -714,7 +714,7 @@ page_cur_parse_insert_rec( return(NULL); } - + ptr += 2; } @@ -733,7 +733,7 @@ page_cur_parse_insert_rec( return(NULL); } - + if (extra_info_yes) { /* Read the info bits */ @@ -741,7 +741,7 @@ page_cur_parse_insert_rec( return(NULL); } - + info_and_status_bits = mach_read_from_1(ptr); ptr++; @@ -768,13 +768,13 @@ page_cur_parse_insert_rec( return(NULL); } - + if (page == NULL) { return(ptr + end_seg_len); } - ut_ad(!!page_is_comp(page) == index->table->comp); + ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); /* Read from the log the inserted index record end segment which differs from the cursor record */ @@ -794,7 +794,7 @@ page_cur_parse_insert_rec( origin_offset = rec_offs_extra_size(offsets); mismatch_index = rec_offs_size(offsets) - end_seg_len; } - + if (mismatch_index + end_seg_len < sizeof buf1) { buf = buf1; } else { @@ -802,25 +802,25 @@ page_cur_parse_insert_rec( } /* Build the inserted record to buf */ - - if (mismatch_index >= UNIV_PAGE_SIZE) { + + if (mismatch_index >= UNIV_PAGE_SIZE) { fprintf(stderr, "Is short %lu, info_and_status_bits %lu, offset %lu, " "o_offset %lu\n" - "mismatch index %lu, end_seg_len %lu\n" - "parsed len %lu\n", - (ulong) is_short, (ulong) info_and_status_bits, - (ulong) offset, - (ulong) origin_offset, - (ulong) mismatch_index, (ulong) end_seg_len, - (ulong) (ptr - ptr2)); + "mismatch index %lu, end_seg_len %lu\n" + "parsed len %lu\n", + (ulong) is_short, (ulong) info_and_status_bits, + (ulong) offset, + (ulong) origin_offset, + (ulong) mismatch_index, (ulong) end_seg_len, + (ulong) (ptr - ptr2)); fputs("Dump of 300 bytes of log:\n", stderr); ut_print_buf(stderr, ptr2, 300); - buf_page_print(page); + buf_page_print(page); - ut_error; + ut_error; } ut_memcpy(buf, rec_get_start(cursor_rec, offsets), mismatch_index); @@ -845,7 +845,7 @@ page_cur_parse_insert_rec( } return(ptr + end_seg_len); -} +} /*************************************************************** Inserts a record next to page cursor. Returns pointer to inserted record if @@ -889,9 +889,9 @@ page_cur_insert_rec_low( page = page_cur_get_page(cursor); comp = page_is_comp(page); - ut_ad(index->table->comp == !!comp); + ut_ad(dict_table_is_comp(index->table) == !!comp); - ut_ad(cursor->rec != page_get_supremum_rec(page)); + ut_ad(cursor->rec != page_get_supremum_rec(page)); /* 1. Get the size of the physical record in the page */ if (tuple != NULL) { @@ -929,7 +929,7 @@ page_cur_insert_rec_low( ut_ad(insert_rec); ut_ad(rec_size == rec_offs_size(offsets)); - + /* 4. Insert the record in the linked list of records */ current_rec = cursor->rec; @@ -944,12 +944,12 @@ page_cur_insert_rec_low( page_header_set_field(page, PAGE_N_RECS, 1 + page_get_n_recs(page)); /* 5. Set the n_owned field in the inserted record to zero, - and set the heap_no field */ - + and set the heap_no field */ + rec_set_n_owned(insert_rec, comp, 0); rec_set_heap_no(insert_rec, comp, heap_no); - /* 6. Update the last insertion info in page header */ + /* 6. Update the last insertion info in page header */ last_insert = page_header_get_ptr(page, PAGE_LAST_INSERT); ut_ad(!last_insert || !comp @@ -957,31 +957,31 @@ page_cur_insert_rec_low( == rec_get_node_ptr_flag(insert_rec)); if (last_insert == NULL) { - page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION); - page_header_set_field(page, PAGE_N_DIRECTION, 0); + page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION); + page_header_set_field(page, PAGE_N_DIRECTION, 0); } else if ((last_insert == current_rec) - && (page_header_get_field(page, PAGE_DIRECTION) != PAGE_LEFT)) { + && (page_header_get_field(page, PAGE_DIRECTION) != PAGE_LEFT)) { - page_header_set_field(page, PAGE_DIRECTION, PAGE_RIGHT); - page_header_set_field(page, PAGE_N_DIRECTION, + page_header_set_field(page, PAGE_DIRECTION, PAGE_RIGHT); + page_header_set_field(page, PAGE_N_DIRECTION, page_header_get_field(page, PAGE_N_DIRECTION) + 1); } else if ((page_rec_get_next(insert_rec) == last_insert) - && (page_header_get_field(page, PAGE_DIRECTION) != PAGE_RIGHT)) { + && (page_header_get_field(page, PAGE_DIRECTION) != PAGE_RIGHT)) { - page_header_set_field(page, PAGE_DIRECTION, PAGE_LEFT); - page_header_set_field(page, PAGE_N_DIRECTION, + page_header_set_field(page, PAGE_DIRECTION, PAGE_LEFT); + page_header_set_field(page, PAGE_N_DIRECTION, page_header_get_field(page, PAGE_N_DIRECTION) + 1); } else { - page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION); - page_header_set_field(page, PAGE_N_DIRECTION, 0); + page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION); + page_header_set_field(page, PAGE_N_DIRECTION, 0); } - + page_header_set_ptr(page, PAGE_LAST_INSERT, insert_rec); - /* 7. It remains to update the owner record. */ - + /* 7. It remains to update the owner record. */ + owner_rec = page_rec_find_owner_rec(insert_rec); n_owned = rec_get_n_owned(owner_rec, comp); rec_set_n_owned(owner_rec, comp, n_owned + 1); @@ -998,7 +998,7 @@ page_cur_insert_rec_low( /* 9. Write log record of the insert */ page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec, index, mtr); - + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -1019,7 +1019,7 @@ page_copy_rec_list_to_created_page_write_log( { byte* log_ptr; - ut_ad(!!page_is_comp(page) == index->table->comp); + ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); log_ptr = mlog_open_and_write_index(mtr, page, index, page_is_comp(page) @@ -1046,7 +1046,7 @@ page_parse_copy_rec_list_to_created_page( { byte* rec_end; ulint log_data_len; - + if (ptr + 4 > end_ptr) { return(NULL); @@ -1073,12 +1073,12 @@ page_parse_copy_rec_list_to_created_page( } ut_a(ptr == rec_end); - + page_header_set_ptr(page, PAGE_LAST_INSERT, NULL); page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION); page_header_set_field(page, PAGE_N_DIRECTION, 0); - return(rec_end); + return(rec_end); } /***************************************************************** @@ -1110,11 +1110,11 @@ page_copy_rec_list_end_to_created_page( ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_; - + ut_ad(page_dir_get_n_heap(new_page) == 2); ut_ad(page != new_page); ut_ad(comp == page_is_comp(new_page)); - + if (rec == page_get_infimum_rec(page)) { rec = page_rec_get_next(rec); @@ -1124,7 +1124,7 @@ page_copy_rec_list_end_to_created_page( return; } - + #ifdef UNIV_DEBUG /* To pass the debug tests we have to set these dummy values in the debug version */ @@ -1141,7 +1141,7 @@ page_copy_rec_list_end_to_created_page( /* Individual inserts are logged in a shorter form */ log_mode = mtr_set_log_mode(mtr, MTR_LOG_SHORT_INSERTS); - + prev_rec = page_get_infimum_rec(new_page); if (comp) { heap_top = new_page + PAGE_NEW_SUPREMUM_END; @@ -1166,7 +1166,7 @@ page_copy_rec_list_end_to_created_page( rec_size = rec_offs_size(offsets); heap_top = heap_top + rec_size; - + ut_ad(heap_top < new_page + UNIV_PAGE_SIZE); count++; @@ -1183,8 +1183,8 @@ page_copy_rec_list_end_to_created_page( count = 0; } - - page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec, + + page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec, index, mtr); prev_rec = insert_rec; rec = page_rec_get_next(rec); @@ -1192,7 +1192,7 @@ page_copy_rec_list_end_to_created_page( if ((slot_index > 0) && (count + 1 + (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2 - <= PAGE_DIR_SLOT_MAX_N_OWNED)) { + <= PAGE_DIR_SLOT_MAX_N_OWNED)) { /* We can merge the two last dir slots. This operation is here to make this function imitate exactly the equivalent task made using page_cur_insert_rec, which we use in database @@ -1201,7 +1201,7 @@ page_copy_rec_list_end_to_created_page( that it imitates exactly. */ count += (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2; - + page_dir_slot_set_n_owned(slot, 0); slot_index--; @@ -1216,7 +1216,7 @@ page_copy_rec_list_end_to_created_page( ut_a(log_data_len < 100 * UNIV_PAGE_SIZE); mach_write_to_4(log_ptr, log_data_len); - + rec_set_next_offs(insert_rec, comp, comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM); @@ -1229,7 +1229,7 @@ page_copy_rec_list_end_to_created_page( page_header_set_ptr(new_page, PAGE_HEAP_TOP, heap_top); page_dir_set_n_heap(new_page, 2 + n_recs); page_header_set_field(new_page, PAGE_N_RECS, n_recs); - + page_header_set_ptr(new_page, PAGE_LAST_INSERT, NULL); page_header_set_field(new_page, PAGE_DIRECTION, PAGE_NO_DIRECTION); page_header_set_field(new_page, PAGE_N_DIRECTION, 0); @@ -1251,7 +1251,7 @@ page_cur_delete_rec_write_log( { byte* log_ptr; - ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); log_ptr = mlog_open_and_write_index(mtr, rec, index, page_rec_is_comp(rec) @@ -1268,7 +1268,7 @@ page_cur_delete_rec_write_log( mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE)); mlog_close(mtr, log_ptr + 2); -} +} /*************************************************************** Parses log record of a record delete on a page. */ @@ -1285,7 +1285,7 @@ page_cur_parse_delete_rec( { ulint offset; page_cur_t cursor; - + if (end_ptr < ptr + 2) { return(NULL); @@ -1314,7 +1314,7 @@ page_cur_parse_delete_rec( } return(ptr); -} +} /*************************************************************** Deletes a record at the page cursor. The cursor is moved to the next @@ -1323,7 +1323,7 @@ record after the deleted one. */ void page_cur_delete_rec( /*================*/ - page_cur_t* cursor, /* in: a page cursor */ + page_cur_t* cursor, /* in: a page cursor */ dict_index_t* index, /* in: record descriptor */ const ulint* offsets,/* in: rec_get_offsets(cursor->rec, index) */ mtr_t* mtr) /* in: mini-transaction handle */ @@ -1337,18 +1337,18 @@ page_cur_delete_rec( ulint cur_slot_no; ulint cur_n_owned; rec_t* rec; - + ut_ad(cursor && mtr); - + page = page_cur_get_page(cursor); current_rec = cursor->rec; ut_ad(rec_offs_validate(current_rec, index, offsets)); - ut_ad(!!page_is_comp(page) == index->table->comp); + ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); /* The record must not be the supremum or infimum record. */ - ut_ad(current_rec != page_get_supremum_rec(page)); - ut_ad(current_rec != page_get_infimum_rec(page)); - + ut_ad(current_rec != page_get_supremum_rec(page)); + ut_ad(current_rec != page_get_infimum_rec(page)); + /* Save to local variables some data associated with current_rec */ cur_slot_no = page_dir_find_owner_slot(current_rec); cur_dir_slot = page_dir_get_nth_slot(page, cur_slot_no); @@ -1366,15 +1366,15 @@ page_cur_delete_rec( frame modify clock */ buf_frame_modify_clock_inc(page); - + /* 2. Find the next and the previous record. Note that the cursor is left at the next record. */ ut_ad(cur_slot_no > 0); prev_slot = page_dir_get_nth_slot(page, cur_slot_no - 1); - + rec = page_dir_slot_get_rec(prev_slot); - + /* rec now points to the record of the previous directory slot. Look for the immediate predecessor of current_rec in a loop. */ @@ -1385,7 +1385,7 @@ page_cur_delete_rec( page_cur_move_to_next(cursor); next_rec = cursor->rec; - + /* 3. Remove the record from the linked list of records */ page_rec_set_next(prev_rec, next_rec); @@ -1396,14 +1396,16 @@ page_cur_delete_rec( record pointer in slot. In the following if-clause we assume that prev_rec is owned by the same slot, i.e., PAGE_DIR_SLOT_MIN_N_OWNED >= 2. */ - - ut_ad(PAGE_DIR_SLOT_MIN_N_OWNED >= 2); + +#if PAGE_DIR_SLOT_MIN_N_OWNED < 2 +# error "PAGE_DIR_SLOT_MIN_N_OWNED < 2" +#endif ut_ad(cur_n_owned > 1); if (current_rec == page_dir_slot_get_rec(cur_dir_slot)) { page_dir_slot_set_rec(cur_dir_slot, prev_rec); } - + /* 5. Update the number of owned records of the slot */ page_dir_slot_set_n_owned(cur_dir_slot, cur_n_owned - 1); @@ -1414,7 +1416,7 @@ page_cur_delete_rec( /* 7. Now we have decremented the number of owned records of the slot. If the number drops below PAGE_DIR_SLOT_MIN_N_OWNED, we balance the slots. */ - + if (cur_n_owned <= PAGE_DIR_SLOT_MIN_N_OWNED) { page_dir_balance_slot(page, cur_slot_no); } diff --git a/storage/innobase/page/page0page.c b/storage/innobase/page/page0page.c index 7e09cdf073e..a7a0dd4b788 100644 --- a/storage/innobase/page/page0page.c +++ b/storage/innobase/page/page0page.c @@ -23,7 +23,7 @@ Created 2/2/1994 Heikki Tuuri /* THE INDEX PAGE ============== - + The index page consists of a page header which contains the page's id and other information. On top of it are the the index records in a heap linked into a one way linear list according to alphabetic order. @@ -33,13 +33,13 @@ to about every sixth record in the list. The pointers are placed in the directory in the alphabetical order of the records pointed to, enabling us to make binary search using the array. Each slot n:o I in the directory points to a record, where a 4-bit field contains a count -of those records which are in the linear list between pointer I and +of those records which are in the linear list between pointer I and the pointer I - 1 in the directory, including the record pointed to by pointer I and not including the record pointed to by I - 1. We say that the record pointed to by slot I, or that slot I, owns these records. The count is always kept in the range 4 to 8, with -the exception that it is 1 for the first slot, and 1--8 for the second slot. - +the exception that it is 1 for the first slot, and 1--8 for the second slot. + An essentially binary search can be performed in the list of index records, like we could do if we had pointer to every record in the page directory. The data structure is, however, more efficient when @@ -200,7 +200,7 @@ page_set_max_trx_id( /* It is not necessary to write this change to the redo log, as during a database recovery we assume that the max trx id of every page is the maximum trx id assigned before the crash. */ - + mach_write_to_8(page + PAGE_HEADER + PAGE_MAX_TRX_ID, trx_id); if (block->is_hashed) { @@ -227,7 +227,7 @@ page_mem_alloc( byte* block; ulint avl_space; ulint garbage; - + ut_ad(page && heap_no); /* If there are records in the free list, look if the first is @@ -269,9 +269,9 @@ page_mem_alloc( } /* Could not find space from the free list, try top of heap */ - + avl_space = page_get_max_insert_size(page, 1); - + if (avl_space >= need) { block = page_header_get_ptr(page, PAGE_HEAP_TOP); @@ -328,7 +328,7 @@ page_parse_create( /************************************************************** The index page creation function. */ -page_t* +page_t* page_create( /*========*/ /* out: pointer to the page */ @@ -339,7 +339,7 @@ page_create( { page_dir_slot_t* slot; mem_heap_t* heap; - dtuple_t* tuple; + dtuple_t* tuple; dfield_t* field; byte* heap_top; rec_t* infimum_rec; @@ -349,25 +349,27 @@ page_create( ulint* offsets; index = comp ? srv_sys->dummy_ind2 : srv_sys->dummy_ind1; - + ut_ad(frame && mtr); - ut_ad(PAGE_BTR_IBUF_FREE_LIST + FLST_BASE_NODE_SIZE - <= PAGE_DATA); - ut_ad(PAGE_BTR_IBUF_FREE_LIST_NODE + FLST_NODE_SIZE - <= PAGE_DATA); +#if PAGE_BTR_IBUF_FREE_LIST + FLST_BASE_NODE_SIZE > PAGE_DATA +# error "PAGE_BTR_IBUF_FREE_LIST + FLST_BASE_NODE_SIZE > PAGE_DATA" +#endif +#if PAGE_BTR_IBUF_FREE_LIST_NODE + FLST_NODE_SIZE > PAGE_DATA +# error "PAGE_BTR_IBUF_FREE_LIST_NODE + FLST_NODE_SIZE > PAGE_DATA" +#endif /* 1. INCREMENT MODIFY CLOCK */ buf_frame_modify_clock_inc(frame); /* 2. WRITE LOG INFORMATION */ page_create_write_log(frame, mtr, comp); - + page = frame; fil_page_set_type(page, FIL_PAGE_INDEX); heap = mem_heap_create(200); - + /* 3. CREATE THE INFIMUM AND SUPREMUM RECORDS */ /* Create first a data tuple for infimum record */ @@ -382,7 +384,7 @@ page_create( record heap */ heap_top = page + PAGE_DATA; - + infimum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple); ut_a(infimum_rec == @@ -448,7 +450,7 @@ page_create( page_dir_slot_set_rec(slot, supremum_rec); /* Set the next pointers in infimum and supremum */ - + rec_set_next_offs(infimum_rec, comp, (ulint)(supremum_rec - page)); rec_set_next_offs(supremum_rec, comp, 0); @@ -483,18 +485,19 @@ page_copy_rec_list_end_no_locks( page_cur_move_to_next(&cur1); } - ut_a((ibool)!!page_is_comp(new_page) == index->table->comp); + ut_a((ibool)!!page_is_comp(new_page) + == dict_table_is_comp(index->table)); ut_a(page_is_comp(new_page) == page_is_comp(page)); ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == (ulint) (page_is_comp(new_page) ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM)); page_cur_set_before_first(new_page, &cur2); - - /* Copy records from the original page to the new page */ + + /* Copy records from the original page to the new page */ sup = page_get_supremum_rec(page); - + for (;;) { rec_t* cur1_rec = page_cur_get_rec(&cur1); if (cur1_rec == sup) { @@ -507,15 +510,16 @@ page_copy_rec_list_end_no_locks( /* Track an assertion failure reported on the mailing list on June 18th, 2003 */ - buf_page_print(new_page); - buf_page_print(page); + buf_page_print(new_page); + buf_page_print(page); ut_print_timestamp(stderr); fprintf(stderr, "InnoDB: rec offset %lu, cur1 offset %lu, cur2 offset %lu\n", - (ulong)(rec - page), - (ulong)(page_cur_get_rec(&cur1) - page), - (ulong)(page_cur_get_rec(&cur2) - new_page)); + (ulong)(rec - page), + (ulong)(page_cur_get_rec(&cur1) - page), + (ulong)(page_cur_get_rec(&cur2) - new_page)); + ut_error; } @@ -557,7 +561,7 @@ page_copy_rec_list_end( page_update_max_trx_id(new_page, page_get_max_trx_id(page)); btr_search_move_or_delete_hash_entries(new_page, page, index); -} +} /***************************************************************** Copies records from page to new_page, up to the given record, @@ -589,12 +593,12 @@ page_copy_rec_list_start( } page_cur_move_to_next(&cur1); - + page_cur_set_after_last(new_page, &cur2); page_cur_move_to_prev(&cur2); old_end = page_cur_get_rec(&cur2); - - /* Copy records from the original page to the new page */ + + /* Copy records from the original page to the new page */ while (page_cur_get_rec(&cur1) != rec) { rec_t* ins_rec; @@ -610,7 +614,7 @@ page_copy_rec_list_start( } /* Update the lock table, MAX_TRX_ID, and possible hash index */ - + lock_move_rec_list_start(new_page, page, rec, old_end); page_update_max_trx_id(new_page, page_get_max_trx_id(page)); @@ -666,19 +670,19 @@ page_parse_delete_rec_list( mtr_t* mtr) /* in: mtr or NULL */ { ulint offset; - + ut_ad(type == MLOG_LIST_END_DELETE || type == MLOG_LIST_START_DELETE || type == MLOG_COMP_LIST_END_DELETE || type == MLOG_COMP_LIST_START_DELETE); - + /* Read the record offset as a 2-byte ulint */ if (end_ptr < ptr + 2) { return(NULL); } - + offset = mach_read_from_2(ptr); ptr += 2; @@ -687,7 +691,7 @@ page_parse_delete_rec_list( return(ptr); } - ut_ad(!!page_is_comp(page) == index->table->comp); + ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); if (type == MLOG_LIST_END_DELETE || type == MLOG_COMP_LIST_END_DELETE) { @@ -738,9 +742,9 @@ page_delete_rec_list_end( frame modify clock */ buf_frame_modify_clock_inc(page); - + sup = page_get_supremum_rec(page); - + comp = page_is_comp(page); if (page_rec_is_infimum_low(rec - page)) { rec = page_rec_get_next(rec); @@ -753,7 +757,7 @@ page_delete_rec_list_end( return; } - + prev_rec = page_rec_get_prev(rec); last_rec = page_rec_get_prev(sup); @@ -792,10 +796,10 @@ page_delete_rec_list_end( /* Update the page directory; there is no need to balance the number of the records owned by the supremum record, as it is allowed to be less than PAGE_DIR_SLOT_MIN_N_OWNED */ - + rec2 = rec; count = 0; - + while (rec_get_n_owned(rec2, comp) == 0) { count++; @@ -805,15 +809,15 @@ page_delete_rec_list_end( ut_ad(rec_get_n_owned(rec2, comp) - count > 0); n_owned = rec_get_n_owned(rec2, comp) - count; - + slot_index = page_dir_find_owner_slot(rec2); slot = page_dir_get_nth_slot(page, slot_index); - + page_dir_slot_set_rec(slot, sup); page_dir_slot_set_n_owned(slot, n_owned); page_dir_set_n_slots(page, slot_index + 1); - + /* Remove the record chain segment from the record chain */ page_rec_set_next(prev_rec, page_get_supremum_rec(page)); @@ -829,7 +833,7 @@ page_delete_rec_list_end( page_header_set_field(page, PAGE_N_RECS, (ulint)(page_get_n_recs(page) - n_recs)); -} +} /***************************************************************** Deletes records from page, up to the given record, NOT including @@ -851,7 +855,7 @@ page_delete_rec_list_start( byte type; *offsets_ = (sizeof offsets_) / sizeof *offsets_; - ut_ad(!!page_is_comp(page) == index->table->comp); + ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); if (page_is_comp(page)) { type = MLOG_COMP_LIST_START_DELETE; @@ -869,7 +873,7 @@ page_delete_rec_list_start( } page_cur_move_to_next(&cur1); - + /* Individual deletes are not logged */ log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); @@ -887,7 +891,7 @@ page_delete_rec_list_start( /* Restore log mode */ mtr_set_log_mode(mtr, log_mode); -} +} /***************************************************************** Moves record list end to another page. Moved records include @@ -909,7 +913,7 @@ page_move_rec_list_end( old_data_size = page_get_data_size(new_page); old_n_recs = page_get_n_recs(new_page); - + page_copy_rec_list_end(new_page, page, split_rec, index, mtr); new_data_size = page_get_data_size(new_page); @@ -953,7 +957,7 @@ page_rec_write_index_page_no( { byte* data; ulint len; - + data = rec_get_nth_field_old(rec, i, &len); ut_ad(len == 4); @@ -971,7 +975,7 @@ page_dir_delete_slots( /*==================*/ page_t* page, /* in: the index page */ ulint start, /* in: first slot to be deleted */ - ulint n) /* in: number of slots to delete (currently + ulint n) /* in: number of slots to delete (currently only n == 1 allowed) */ { page_dir_slot_t* slot; @@ -980,7 +984,7 @@ page_dir_delete_slots( ulint n_slots; rec_t* rec; - ut_ad(n == 1); + ut_ad(n == 1); ut_ad(start > 0); ut_ad(start + n < page_dir_get_n_slots(page)); @@ -1023,7 +1027,7 @@ page_dir_add_slots( /*===============*/ page_t* page, /* in: the index page */ ulint start, /* in: the slot above which the new slots are added */ - ulint n) /* in: number of slots to add (currently only n == 1 + ulint n) /* in: number of slots to add (currently only n == 1 allowed) */ { page_dir_slot_t* slot; @@ -1032,7 +1036,7 @@ page_dir_add_slots( rec_t* rec; ut_ad(n == 1); - + n_slots = page_dir_get_n_slots(page); ut_ad(start < n_slots - 1); @@ -1060,7 +1064,7 @@ page_dir_split_slot( /*================*/ page_t* page, /* in: the index page in question */ ulint slot_no) /* in: the directory slot */ -{ +{ rec_t* rec; page_dir_slot_t* new_slot; page_dir_slot_t* prev_slot; @@ -1072,13 +1076,13 @@ page_dir_split_slot( ut_ad(slot_no > 0); slot = page_dir_get_nth_slot(page, slot_no); - + n_owned = page_dir_slot_get_n_owned(slot); ut_ad(n_owned == PAGE_DIR_SLOT_MAX_N_OWNED + 1); - /* 1. We loop to find a record approximately in the middle of the + /* 1. We loop to find a record approximately in the middle of the records owned by the slot. */ - + prev_slot = page_dir_get_nth_slot(page, slot_no - 1); rec = page_dir_slot_get_rec(prev_slot); @@ -1100,11 +1104,11 @@ page_dir_split_slot( slot = page_dir_get_nth_slot(page, slot_no + 1); /* 3. We store the appropriate values to the new slot. */ - + page_dir_slot_set_rec(new_slot, rec); page_dir_slot_set_n_owned(new_slot, n_owned / 2); - - /* 4. Finally, we update the number of records field of the + + /* 4. Finally, we update the number of records field of the original slot */ page_dir_slot_set_n_owned(slot, n_owned - (n_owned / 2)); @@ -1119,7 +1123,7 @@ void page_dir_balance_slot( /*==================*/ page_t* page, /* in: index page */ - ulint slot_no) /* in: the directory slot */ + ulint slot_no) /* in: the directory slot */ { page_dir_slot_t* slot; page_dir_slot_t* up_slot; @@ -1132,7 +1136,7 @@ page_dir_balance_slot( ut_ad(slot_no > 0); slot = page_dir_get_nth_slot(page, slot_no); - + /* The last directory slot cannot be balanced with the upper neighbor, as there is none. */ @@ -1140,35 +1144,35 @@ page_dir_balance_slot( return; } - + up_slot = page_dir_get_nth_slot(page, slot_no + 1); - + n_owned = page_dir_slot_get_n_owned(slot); up_n_owned = page_dir_slot_get_n_owned(up_slot); - + ut_ad(n_owned == PAGE_DIR_SLOT_MIN_N_OWNED - 1); /* If the upper slot has the minimum value of n_owned, we will merge - the two slots, therefore we assert: */ + the two slots, therefore we assert: */ ut_ad(2 * PAGE_DIR_SLOT_MIN_N_OWNED - 1 <= PAGE_DIR_SLOT_MAX_N_OWNED); - + if (up_n_owned > PAGE_DIR_SLOT_MIN_N_OWNED) { /* In this case we can just transfer one record owned by the upper slot to the property of the lower slot */ old_rec = page_dir_slot_get_rec(slot); new_rec = page_rec_get_next(old_rec); - + rec_set_n_owned(old_rec, page_is_comp(page), 0); rec_set_n_owned(new_rec, page_is_comp(page), n_owned + 1); - + page_dir_slot_set_rec(slot, new_rec); - + page_dir_slot_set_n_owned(up_slot, up_n_owned -1); } else { /* In this case we may merge the two slots */ page_dir_delete_slots(page, slot_no, 1); - } + } } /**************************************************************** @@ -1218,7 +1222,7 @@ page_get_middle_rec( return(rec); } - + /******************************************************************* Returns the number of records before the given record in chain. The number includes infimum and supremum records. */ @@ -1246,7 +1250,7 @@ page_rec_get_n_recs_before( rec = page_rec_get_next(rec); n--; } - + for (i = 0; ; i++) { slot = page_dir_get_nth_slot(page, i); slot_rec = page_dir_slot_get_rec(slot); @@ -1269,7 +1273,7 @@ page_rec_get_n_recs_before( /**************************************************************** Prints record contents including the data relevant only in the index page context. */ - + void page_rec_print( /*===========*/ @@ -1281,7 +1285,7 @@ page_rec_print( ut_a(!comp == !rec_offs_comp(offsets)); rec_print_new(stderr, rec, offsets); fprintf(stderr, - " n_owned: %lu; heap_no: %lu; next rec: %lu\n", + " n_owned: %lu; heap_no: %lu; next rec: %lu\n", (ulong) rec_get_n_owned(rec, comp), (ulong) rec_get_heap_no(rec, comp), (ulong) rec_get_next_offs(rec, comp)); @@ -1305,7 +1309,7 @@ page_dir_print( page_dir_slot_t* slot; n = page_dir_get_n_slots(page); - + fprintf(stderr, "--------------------------------\n" "PAGE DIRECTORY\n" "Page address %p\n" @@ -1316,18 +1320,18 @@ page_dir_print( if ((i == pr_n) && (i < n - pr_n)) { fputs(" ... \n", stderr); } - if ((i < pr_n) || (i >= n - pr_n)) { + if ((i < pr_n) || (i >= n - pr_n)) { fprintf(stderr, - "Contents of slot: %lu: n_owned: %lu, rec offs: %lu\n", + "Contents of slot: %lu: n_owned: %lu, rec offs: %lu\n", (ulong) i, (ulong) page_dir_slot_get_n_owned(slot), (ulong)(page_dir_slot_get_rec(slot) - page)); - } + } } fprintf(stderr, "Total of %lu records\n" "--------------------------------\n", (ulong) (2 + page_get_n_recs(page))); -} - +} + /******************************************************************* This is used to print the contents of the page record list for debugging purposes. */ @@ -1347,7 +1351,7 @@ page_print_list( ulint* offsets = offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_; - ut_a((ibool)!!page_is_comp(page) == index->table->comp); + ut_a((ibool)!!page_is_comp(page) == dict_table_is_comp(index->table)); fprintf(stderr, "--------------------------------\n" @@ -1365,27 +1369,27 @@ page_print_list( if (count == pr_n) { break; - } + } if (page_cur_is_after_last(&cur)) { break; - } + } page_cur_move_to_next(&cur); - count++; + count++; } - + if (n_recs > 2 * pr_n) { fputs(" ... \n", stderr); } - + while (!page_cur_is_after_last(&cur)) { page_cur_move_to_next(&cur); - if (count + pr_n >= n_recs) { + if (count + pr_n >= n_recs) { offsets = rec_get_offsets(cur.rec, index, offsets, ULINT_UNDEFINED, &heap); page_rec_print(cur.rec, offsets); } - count++; + count++; } fprintf(stderr, @@ -1396,7 +1400,7 @@ page_print_list( if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } -} +} /******************************************************************* Prints the info in a page header. */ @@ -1431,7 +1435,7 @@ debugging purposes. */ void page_print( -/*======*/ +/*=======*/ page_t* page, /* in: index page */ dict_index_t* index, /* in: dictionary index of the page */ ulint dn, /* in: print dn first and last entries @@ -1442,7 +1446,7 @@ page_print( page_header_print(page); page_dir_print(page, dn); page_print_list(page, index, rn); -} +} /******************************************************************* The following is used to validate a record on a page. This function @@ -1485,7 +1489,7 @@ page_rec_validate( (ulong) page_dir_get_n_heap(page)); return(FALSE); } - + return(TRUE); } @@ -1504,22 +1508,22 @@ page_check_dir( n_slots = page_dir_get_n_slots(page); if (page_dir_slot_get_rec(page_dir_get_nth_slot(page, 0)) - != page_get_infimum_rec(page)) { + != page_get_infimum_rec(page)) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Page directory corruption: supremum not pointed to\n"); buf_page_print(page); - } + } if (page_dir_slot_get_rec(page_dir_get_nth_slot(page, n_slots - 1)) - != page_get_supremum_rec(page)) { + != page_get_supremum_rec(page)) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Page directory corruption: supremum not pointed to\n"); buf_page_print(page); - } + } } - + /******************************************************************* This function checks the consistency of an index page when we do not know the index. This is also resilient so that this should never crash @@ -1531,7 +1535,7 @@ page_simple_validate( /* out: TRUE if ok */ page_t* page) /* in: index page */ { - page_cur_t cur; + page_cur_t cur; page_dir_slot_t* slot; ulint slot_no; ulint n_slots; @@ -1555,16 +1559,16 @@ page_simple_validate( } rec_heap_top = page_header_get_ptr(page, PAGE_HEAP_TOP); - + if (rec_heap_top > page_dir_get_nth_slot(page, n_slots - 1)) { fprintf(stderr, "InnoDB: Record heap and dir overlap on a page, heap top %lu, dir %lu\n", - (ulong)(page_header_get_ptr(page, PAGE_HEAP_TOP) - page), - (ulong)(page_dir_get_nth_slot(page, n_slots - 1) - page)); + (ulong)(page_header_get_ptr(page, PAGE_HEAP_TOP) - page), + (ulong)(page_dir_get_nth_slot(page, n_slots - 1) - page)); - goto func_exit; - } + goto func_exit; + } /* Validate the record list in a loop checking also that it is consistent with the page record directory. */ @@ -1578,7 +1582,7 @@ page_simple_validate( for (;;) { rec = (&cur)->rec; - + if (rec > rec_heap_top) { fprintf(stderr, "InnoDB: Record %lu is above rec heap top %lu\n", @@ -1607,7 +1611,7 @@ page_simple_validate( goto func_exit; } - + own_count = 0; if (!page_cur_is_after_last(&cur)) { @@ -1631,7 +1635,7 @@ page_simple_validate( goto func_exit; } - count++; + count++; if (count > UNIV_PAGE_SIZE) { fprintf(stderr, @@ -1639,22 +1643,22 @@ page_simple_validate( (ulong) count); goto func_exit; } - + page_cur_move_to_next(&cur); own_count++; } - + if (rec_get_n_owned(rec, comp) == 0) { fprintf(stderr, "InnoDB: n owned is zero in a supremum rec\n"); goto func_exit; } - + if (slot_no != n_slots - 1) { fprintf(stderr, "InnoDB: n slots wrong %lu, %lu\n", (ulong) slot_no, (ulong) (n_slots - 1)); goto func_exit; - } + } if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) { fprintf(stderr, "InnoDB: n recs wrong %lu %lu\n", @@ -1686,17 +1690,17 @@ page_simple_validate( } count++; - + if (count > UNIV_PAGE_SIZE) { fprintf(stderr, "InnoDB: Page free list appears to be circular %lu\n", - (ulong) count); + (ulong) count); goto func_exit; } rec = page_rec_get_next(rec); } - + if (page_dir_get_n_heap(page) != count + 1) { fprintf(stderr, "InnoDB: N heap is wrong %lu, %lu\n", @@ -1706,10 +1710,10 @@ page_simple_validate( goto func_exit; } - ret = TRUE; + ret = TRUE; func_exit: - return(ret); + return(ret); } /******************************************************************* @@ -1725,7 +1729,7 @@ page_validate( { page_dir_slot_t* slot; mem_heap_t* heap; - page_cur_t cur; + page_cur_t cur; byte* buf; ulint count; ulint own_count; @@ -1741,7 +1745,7 @@ page_validate( ulint* offsets = NULL; ulint* old_offsets = NULL; - if ((ibool)!!comp != index->table->comp) { + if ((ibool)!!comp != dict_table_is_comp(index->table)) { fputs("InnoDB: 'compact format' flag mismatch\n", stderr); goto func_exit2; } @@ -1750,7 +1754,7 @@ page_validate( } heap = mem_heap_create(UNIV_PAGE_SIZE + 200); - + /* The following buffer is used to check that the records in the page record heap do not overlap */ @@ -1772,8 +1776,8 @@ page_validate( page_header_get_ptr(page, PAGE_HEAP_TOP), page_dir_get_nth_slot(page, n_slots - 1)); - goto func_exit; - } + goto func_exit; + } /* Validate the record list in a loop checking also that it is consistent with the directory. */ @@ -1801,7 +1805,7 @@ page_validate( if (!page_rec_validate(rec, offsets)) { goto func_exit; } - + /* Check that the records are in the ascending order */ if ((count >= 2) && (!page_cur_is_after_last(&cur))) { if (!(1 == cmp_rec_rec(rec, old_rec, @@ -1815,7 +1819,7 @@ page_validate( fputs("\nInnoDB: record ", stderr); rec_print_new(stderr, rec, offsets); putc('\n', stderr); - + goto func_exit; } } @@ -1824,9 +1828,9 @@ page_validate( data_size += rec_offs_size(offsets); } - + offs = rec_get_start(rec, offsets) - page; - + for (i = 0; i < rec_offs_size(offsets); i++) { if (!buf[offs + i] == 0) { /* No other record may overlap this */ @@ -1835,10 +1839,10 @@ page_validate( stderr); goto func_exit; } - + buf[offs + i] = 1; } - + if (rec_get_n_owned(rec, comp) != 0) { /* This is a record pointed to by a dir slot */ if (rec_get_n_owned(rec, comp) != own_count) { @@ -1855,9 +1859,9 @@ page_validate( stderr); goto func_exit; } - + page_dir_slot_check(slot); - + own_count = 0; if (!page_cur_is_after_last(&cur)) { slot_no++; @@ -1877,7 +1881,7 @@ page_validate( goto func_exit; } - count++; + count++; page_cur_move_to_next(&cur); own_count++; old_rec = rec; @@ -1888,17 +1892,17 @@ page_validate( offsets = offs; } } - + if (rec_get_n_owned(rec, comp) == 0) { fputs("InnoDB: n owned is zero\n", stderr); goto func_exit; } - + if (slot_no != n_slots - 1) { fprintf(stderr, "InnoDB: n slots wrong %lu %lu\n", (ulong) slot_no, (ulong) (n_slots - 1)); goto func_exit; - } + } if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) { fprintf(stderr, "InnoDB: n recs wrong %lu %lu\n", @@ -1924,10 +1928,10 @@ page_validate( goto func_exit; } - - count++; + + count++; offs = rec_get_start(rec, offsets) - page; - + for (i = 0; i < rec_offs_size(offsets); i++) { if (buf[offs + i] != 0) { @@ -1935,13 +1939,13 @@ page_validate( "InnoDB: Record overlaps another in free list\n", stderr); goto func_exit; } - + buf[offs + i] = 1; } - + rec = page_rec_get_next(rec); } - + if (page_dir_get_n_heap(page) != count + 1) { fprintf(stderr, "InnoDB: N heap is wrong %lu %lu\n", (ulong) page_dir_get_n_heap(page), @@ -1949,7 +1953,7 @@ page_validate( goto func_exit; } - ret = TRUE; + ret = TRUE; func_exit: mem_heap_free(heap); @@ -1962,8 +1966,8 @@ func_exit: putc('\n', stderr); buf_page_print(page); } - - return(ret); + + return(ret); } /******************************************************************* @@ -1989,7 +1993,7 @@ page_find_rec_with_heap_no( if (page_cur_is_after_last(&cur)) { return(NULL); - } + } page_cur_move_to_next(&cur); } diff --git a/storage/innobase/pars/lexyy.c b/storage/innobase/pars/lexyy.c index 1145ca295e7..d64ecbbfcbc 100644 --- a/storage/innobase/pars/lexyy.c +++ b/storage/innobase/pars/lexyy.c @@ -1,34 +1,87 @@ -/* A lexical scanner generated by flex */ -/* Scanner skeleton version: - * $Header: /home/heikki/cvsroot/ib/pars/lexyy.c,v 1.2 2003/10/30 20:27:19 heikki Exp $ - */ +#line 3 "lex.yy.c" -/* This include MUST be first to keep things portable ! */ #include "univ.i" +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 31 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ #include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ +/* flex integer type definitions */ -/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ -#ifdef c_plusplus -#ifndef __cplusplus -#define __cplusplus +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) #endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) #endif +#endif /* ! FLEXINT_H */ #ifdef __cplusplus -#include <stdlib.h> - -/* Use prototypes in function declarations. */ -#define YY_USE_PROTOS - /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST @@ -36,34 +89,17 @@ #if __STDC__ -#define YY_USE_PROTOS #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ -#ifdef __TURBOC__ - #pragma warn -rch - #pragma warn -use -#include <io.h> -#include <stdlib.h> -#define YY_USE_CONST -#define YY_USE_PROTOS -#endif - #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif - -#ifdef YY_USE_PROTOS -#define YY_PROTO(proto) proto -#else -#define YY_PROTO(proto) () -#endif - /* Returned upon end-of-file. */ #define YY_NULL 0 @@ -78,71 +114,71 @@ * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ -#define BEGIN yy_start = 1 + 2 * +#define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ -#define YY_START ((yy_start - 1) / 2) +#define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart( yyin ) +#define YY_NEW_FILE yyrestart(yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ +#ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 +#endif +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif extern int yyleng; + extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 -/* The funky do-while in the following #define is used to turn the definition - * int a single C statement (which needs a semi-colon terminator). This - * avoids problems with code like: - * - * if ( condition_holds ) - * yyless( 5 ); - * else - * do_something_else(); - * - * Prior to using the do-while the compiler would get upset at the - * "else" because it interpreted the "if" statement as being all - * done when it reached the ';' after the yyless() call. - */ - -/* Return all but the first 'n' matched characters back to the input stream. */ - + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ - *yy_cp = yy_hold_char; \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ - yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) -#define unput(c) yyunput( c, yytext_ptr ) +#define unput(c) yyunput( c, (yytext_ptr) ) /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ -typedef unsigned int yy_size_t; +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef unsigned int yy_size_t; +#endif +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; @@ -179,12 +215,16 @@ struct yy_buffer_state */ int yy_at_bol; + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; + #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process @@ -198,23 +238,33 @@ struct yy_buffer_state * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ -static YY_BUFFER_STATE yy_current_buffer = 0; +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". + * + * Returns the top of the stack, or NULL. */ -#define YY_CURRENT_BUFFER yy_current_buffer +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; - static int yy_n_chars; /* number of characters read into yy_ch_buf */ - - int yyleng; /* Points to current character in buffer. */ @@ -227,113 +277,139 @@ static int yy_start = 0; /* start state number */ */ static int yy_did_buffer_switch_on_eof; -void yyrestart YY_PROTO(( FILE *input_file )); +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); -void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); -void yy_load_buffer_state YY_PROTO(( void )); -YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); -void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); -void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); -void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); -#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); -YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); -YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); -YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) -static void *yy_flex_alloc YY_PROTO(( yy_size_t )); -static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); -static void yy_flex_free YY_PROTO(( void * )); +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_is_interactive = is_interactive; \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_at_bol = at_bol; \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } -#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) +/* Begin user sect3 */ -#define yywrap() 1 +#define yywrap(n) 1 #define YY_SKIP_YYWRAP + typedef unsigned char YY_CHAR; + FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + extern char *yytext; #define yytext_ptr yytext -static yy_state_type yy_get_previous_state YY_PROTO(( void )); -static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); -static int yy_get_next_buffer YY_PROTO(( void )); -static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ - yytext_ptr = yy_bp; \ - yyleng = (int) (yy_cp - yy_bp); \ - yy_hold_char = *yy_cp; \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ - yy_c_buf_p = yy_cp; + (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 107 -#define YY_END_OF_BUFFER 108 -static yyconst short int yy_accept[367] = +#define YY_NUM_RULES 109 +#define YY_END_OF_BUFFER 110 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[370] = { 0, - 0, 0, 102, 102, 0, 0, 108, 106, 105, 105, - 97, 3, 86, 92, 95, 93, 90, 94, 106, 96, - 1, 106, 91, 89, 87, 88, 100, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 98, 99, 102, 103, 4, - 5, 105, 81, 101, 2, 1, 82, 83, 85, 84, - 80, 80, 80, 80, 80, 38, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 21, 12, 18, 80, 80, 80, 80, 48, 55, 80, - 9, 80, 80, 80, 80, 80, 80, 80, 80, 80, - - 80, 80, 80, 80, 80, 80, 80, 80, 102, 103, - 103, 104, 4, 5, 2, 8, 39, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 20, 80, 80, 34, 80, 80, - 80, 14, 80, 80, 10, 80, 80, 80, 13, 80, - 80, 80, 80, 80, 74, 80, 80, 80, 45, 7, - 80, 29, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 17, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 40, 80, 80, - 23, 80, 80, 80, 32, 80, 80, 80, 80, 42, - - 80, 25, 80, 6, 58, 80, 80, 80, 36, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 22, 80, - 80, 80, 80, 80, 80, 80, 80, 79, 80, 19, - 80, 60, 80, 80, 80, 80, 30, 80, 80, 80, - 80, 80, 80, 80, 24, 59, 16, 51, 80, 69, - 80, 80, 80, 37, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 50, 80, 80, 80, 80, 80, - 80, 33, 26, 73, 80, 80, 77, 68, 80, 49, - 80, 57, 80, 46, 80, 80, 41, 80, 70, 80, - 72, 80, 80, 27, 80, 80, 80, 28, 66, 80, - - 80, 80, 80, 52, 44, 43, 80, 80, 80, 47, - 56, 80, 80, 15, 80, 80, 67, 75, 80, 80, - 71, 80, 62, 80, 80, 80, 80, 31, 80, 61, - 80, 78, 80, 80, 80, 80, 53, 80, 80, 11, - 80, 64, 63, 80, 35, 80, 76, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 65, 80, 80, - 80, 80, 80, 80, 54, 0 + 0, 0, 104, 104, 0, 0, 110, 108, 107, 107, + 99, 3, 88, 94, 97, 95, 92, 96, 108, 98, + 1, 108, 93, 91, 89, 90, 102, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 100, 101, 104, 105, 4, + 5, 107, 83, 103, 2, 1, 84, 85, 87, 86, + 82, 82, 82, 82, 82, 82, 40, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 23, 12, 20, 82, 82, 82, 82, 50, 57, + 82, 9, 82, 82, 82, 82, 82, 82, 82, 82, + + 82, 82, 82, 82, 82, 82, 82, 82, 82, 104, + 105, 105, 106, 4, 5, 2, 8, 41, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 22, 82, 82, 36, + 82, 82, 82, 16, 82, 82, 10, 82, 82, 82, + 13, 82, 82, 82, 82, 82, 76, 82, 82, 82, + 47, 7, 82, 31, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 15, 19, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 42, 82, 82, 25, 82, 82, 82, 34, 82, 82, + + 82, 82, 44, 82, 27, 82, 6, 60, 82, 82, + 82, 38, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 24, 82, 82, 82, 82, 82, 82, 82, 82, + 81, 82, 21, 82, 62, 82, 82, 82, 82, 32, + 82, 82, 82, 82, 82, 82, 82, 26, 61, 18, + 53, 82, 71, 82, 82, 82, 39, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 52, 82, 82, + 82, 82, 82, 82, 35, 28, 75, 14, 82, 79, + 70, 82, 51, 82, 59, 82, 48, 82, 82, 43, + 82, 72, 82, 74, 82, 82, 29, 82, 82, 82, + + 30, 68, 82, 82, 82, 82, 54, 46, 45, 82, + 82, 82, 49, 58, 82, 82, 17, 82, 82, 69, + 77, 82, 82, 73, 82, 64, 82, 82, 82, 82, + 33, 82, 63, 82, 80, 82, 82, 82, 82, 55, + 82, 82, 11, 82, 66, 65, 82, 37, 82, 78, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 67, 82, 82, 82, 82, 82, 82, 56, 0 } ; -static yyconst int yy_ec[256] = +static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -365,7 +441,7 @@ static yyconst int yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst int yy_meta[49] = +static yyconst flex_int32_t yy_meta[49] = { 0, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, @@ -374,150 +450,150 @@ static yyconst int yy_meta[49] = 4, 4, 4, 4, 4, 4, 1, 1 } ; -static yyconst short int yy_base[373] = +static yyconst flex_int16_t yy_base[376] = { 0, - 0, 0, 387, 386, 388, 387, 391, 396, 47, 49, - 396, 396, 396, 396, 396, 396, 396, 396, 378, 381, - 41, 370, 396, 38, 396, 369, 396, 20, 33, 32, - 36, 34, 44, 0, 46, 49, 40, 57, 348, 52, - 63, 68, 56, 364, 66, 396, 396, 0, 89, 0, - 379, 103, 396, 396, 369, 95, 396, 396, 396, 396, - 0, 358, 76, 354, 346, 0, 358, 75, 78, 353, - 339, 90, 337, 350, 335, 349, 332, 336, 332, 334, - 0, 93, 0, 334, 332, 326, 333, 0, 0, 339, - 339, 322, 85, 100, 337, 91, 86, 328, 102, 320, - - 336, 332, 310, 326, 330, 321, 102, 314, 0, 117, - 129, 396, 0, 346, 336, 0, 0, 324, 319, 326, - 308, 306, 305, 310, 105, 308, 320, 100, 308, 314, - 315, 297, 297, 116, 0, 312, 313, 0, 300, 307, - 118, 121, 304, 294, 303, 296, 293, 301, 0, 291, - 301, 299, 290, 280, 274, 287, 272, 292, 0, 0, - 277, 0, 291, 282, 279, 125, 275, 290, 269, 271, - 276, 276, 268, 271, 266, 0, 278, 262, 272, 279, - 270, 258, 257, 271, 260, 273, 253, 0, 263, 245, - 0, 264, 261, 248, 0, 243, 248, 247, 257, 0, - - 243, 0, 247, 0, 0, 243, 240, 254, 0, 239, - 239, 237, 253, 238, 250, 232, 250, 245, 0, 240, - 240, 226, 225, 225, 239, 238, 237, 0, 221, 0, - 215, 0, 234, 218, 217, 217, 0, 230, 220, 215, - 214, 226, 216, 215, 0, 0, 0, 0, 208, 0, - 222, 218, 204, 0, 218, 219, 202, 207, 200, 218, - 200, 197, 198, 195, 0, 200, 212, 199, 206, 205, - 190, 0, 0, 0, 182, 189, 0, 0, 186, 0, - 185, 0, 199, 0, 200, 187, 0, 183, 0, 186, - 0, 178, 180, 0, 179, 193, 186, 0, 0, 189, - - 192, 174, 189, 0, 0, 0, 170, 184, 183, 0, - 0, 167, 166, 0, 181, 166, 0, 0, 172, 168, - 0, 163, 0, 175, 164, 174, 163, 0, 150, 0, - 170, 0, 154, 148, 154, 145, 0, 150, 163, 0, - 162, 0, 0, 153, 0, 157, 0, 144, 144, 150, - 136, 159, 151, 152, 136, 119, 109, 0, 121, 128, - 119, 116, 112, 104, 0, 396, 159, 163, 59, 167, - 171, 175 + 0, 0, 390, 389, 391, 390, 394, 399, 47, 49, + 399, 399, 399, 399, 399, 399, 399, 399, 381, 384, + 41, 373, 399, 38, 399, 372, 399, 20, 33, 32, + 46, 29, 44, 0, 46, 49, 42, 60, 351, 65, + 66, 67, 32, 367, 69, 399, 399, 0, 79, 0, + 382, 103, 399, 399, 372, 96, 399, 399, 399, 399, + 0, 361, 70, 357, 349, 347, 0, 360, 77, 80, + 355, 341, 92, 339, 352, 337, 351, 334, 338, 334, + 336, 0, 93, 0, 336, 334, 328, 335, 0, 0, + 341, 341, 324, 87, 98, 339, 93, 88, 330, 104, + + 322, 338, 334, 312, 328, 332, 323, 98, 316, 0, + 122, 131, 399, 0, 348, 338, 0, 0, 326, 321, + 328, 326, 309, 307, 306, 311, 106, 309, 321, 102, + 309, 315, 316, 298, 298, 117, 0, 313, 314, 0, + 301, 308, 118, 122, 305, 295, 304, 297, 294, 302, + 0, 292, 302, 300, 291, 281, 275, 288, 273, 293, + 0, 0, 278, 0, 292, 283, 280, 126, 276, 291, + 270, 272, 277, 277, 269, 272, 267, 0, 0, 279, + 263, 273, 280, 271, 259, 258, 272, 261, 274, 254, + 0, 264, 246, 0, 265, 262, 249, 0, 244, 249, + + 248, 258, 0, 244, 0, 248, 0, 0, 244, 241, + 255, 0, 240, 240, 238, 254, 239, 251, 233, 251, + 246, 0, 241, 241, 227, 226, 226, 240, 239, 238, + 0, 222, 0, 216, 0, 235, 219, 218, 218, 0, + 231, 221, 216, 215, 227, 217, 216, 0, 0, 0, + 0, 209, 0, 223, 219, 205, 0, 219, 220, 203, + 208, 201, 219, 201, 198, 199, 196, 0, 201, 213, + 200, 207, 206, 191, 0, 0, 0, 183, 190, 0, + 0, 187, 0, 186, 0, 200, 0, 201, 188, 0, + 184, 0, 187, 0, 179, 181, 0, 180, 194, 187, + + 0, 0, 190, 193, 175, 190, 0, 0, 0, 171, + 185, 184, 0, 0, 168, 167, 0, 182, 167, 0, + 0, 173, 169, 0, 164, 0, 176, 165, 175, 164, + 0, 151, 0, 171, 0, 155, 149, 155, 146, 0, + 151, 164, 0, 163, 0, 0, 154, 0, 158, 0, + 145, 145, 151, 137, 160, 152, 153, 137, 121, 110, + 0, 122, 129, 120, 117, 113, 105, 0, 399, 160, + 164, 85, 168, 172, 176 } ; -static yyconst short int yy_def[373] = +static yyconst flex_int16_t yy_def[376] = { 0, - 366, 1, 367, 367, 368, 368, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 366, 366, 370, 371, 372, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - - 369, 369, 369, 369, 369, 369, 369, 369, 370, 371, - 371, 366, 372, 366, 366, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 1, 370, 370, 371, 371, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 369, 369, 373, 374, 375, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 0, 366, 366, 366, 366, - 366, 366 + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + + 372, 372, 372, 372, 372, 372, 372, 372, 372, 373, + 374, 374, 369, 375, 369, 369, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 0, 369, + 369, 369, 369, 369, 369 } ; -static yyconst short int yy_nxt[445] = +static yyconst flex_int16_t yy_nxt[448] = { 0, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 34, 35, 34, 34, 36, 34, 37, 38, 39, 34, 40, 41, 42, 43, 44, 45, 34, 34, 34, 46, 47, 52, 52, - 52, 52, 55, 62, 56, 58, 59, 64, 63, 67, - 72, 65, 61, 68, 73, 75, 69, 76, 77, 70, - 74, 81, 71, 84, 86, 78, 94, 66, 79, 82, - 87, 80, 88, 85, 83, 95, 96, 97, 101, 104, - 89, 105, 90, 107, 91, 102, 111, 92, 117, 98, - - 108, 112, 103, 99, 52, 52, 55, 100, 56, 122, - 124, 125, 129, 150, 118, 123, 140, 158, 126, 151, - 152, 130, 156, 161, 366, 159, 170, 180, 131, 366, - 171, 141, 142, 157, 162, 153, 111, 184, 185, 154, - 191, 112, 197, 181, 192, 199, 220, 221, 365, 364, - 363, 362, 361, 360, 359, 200, 358, 198, 222, 48, - 48, 48, 48, 50, 50, 50, 50, 109, 109, 357, - 109, 110, 110, 110, 110, 113, 356, 113, 113, 355, - 354, 353, 352, 351, 350, 349, 348, 347, 346, 345, - 344, 343, 342, 341, 340, 339, 338, 337, 336, 335, - - 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, - 324, 323, 322, 321, 320, 319, 318, 317, 316, 315, - 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, - 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, - 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, - 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, - 274, 273, 272, 271, 270, 269, 268, 267, 266, 265, - 264, 263, 262, 261, 260, 259, 258, 257, 256, 255, - 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, - 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, - - 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, - 224, 223, 219, 218, 217, 216, 215, 214, 213, 212, - 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, - 201, 196, 195, 194, 193, 190, 189, 188, 187, 186, - 183, 182, 179, 178, 177, 176, 175, 174, 173, 115, - 114, 172, 169, 168, 167, 166, 165, 164, 163, 160, - 155, 149, 148, 147, 146, 145, 144, 143, 139, 138, - 137, 136, 135, 134, 133, 132, 128, 127, 121, 120, - 119, 116, 115, 114, 106, 93, 60, 57, 54, 53, - 366, 51, 51, 49, 49, 7, 366, 366, 366, 366, - - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366 + 52, 52, 55, 62, 56, 58, 59, 64, 63, 68, + 76, 65, 77, 69, 66, 105, 70, 106, 78, 71, + 73, 82, 72, 85, 74, 79, 87, 67, 80, 83, + 75, 81, 88, 86, 84, 89, 112, 102, 61, 95, + 98, 113, 118, 90, 103, 91, 108, 92, 96, 97, + + 93, 104, 99, 109, 52, 52, 100, 55, 119, 56, + 101, 124, 126, 127, 131, 152, 142, 125, 154, 160, + 128, 153, 172, 132, 158, 163, 173, 161, 183, 369, + 133, 143, 144, 155, 369, 159, 164, 156, 112, 187, + 188, 194, 200, 113, 184, 195, 202, 223, 224, 368, + 367, 366, 365, 364, 363, 362, 203, 201, 361, 225, + 48, 48, 48, 48, 50, 50, 50, 50, 110, 110, + 360, 110, 111, 111, 111, 111, 114, 359, 114, 114, + 358, 357, 356, 355, 354, 353, 352, 351, 350, 349, + 348, 347, 346, 345, 344, 343, 342, 341, 340, 339, + + 338, 337, 336, 335, 334, 333, 332, 331, 330, 329, + 328, 327, 326, 325, 324, 323, 322, 321, 320, 319, + 318, 317, 316, 315, 314, 313, 312, 311, 310, 309, + 308, 307, 306, 305, 304, 303, 302, 301, 300, 299, + 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, + 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, + 278, 277, 276, 275, 274, 273, 272, 271, 270, 269, + 268, 267, 266, 265, 264, 263, 262, 261, 260, 259, + 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, + 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, + + 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, + 228, 227, 226, 222, 221, 220, 219, 218, 217, 216, + 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, + 205, 204, 199, 198, 197, 196, 193, 192, 191, 190, + 189, 186, 185, 182, 181, 180, 179, 178, 177, 176, + 175, 116, 115, 174, 171, 170, 169, 168, 167, 166, + 165, 162, 157, 151, 150, 149, 148, 147, 146, 145, + 141, 140, 139, 138, 137, 136, 135, 134, 130, 129, + 123, 122, 121, 120, 117, 116, 115, 107, 94, 60, + 57, 54, 53, 369, 51, 51, 49, 49, 7, 369, + + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369 } ; -static yyconst short int yy_chk[445] = +static yyconst flex_int16_t yy_chk[448] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -525,54 +601,57 @@ static yyconst short int yy_chk[445] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 10, 10, 21, 28, 21, 24, 24, 29, 28, 30, - 31, 29, 369, 30, 31, 32, 30, 32, 33, 30, - 31, 35, 30, 36, 37, 33, 40, 29, 33, 35, - 37, 33, 38, 36, 35, 40, 40, 41, 42, 43, - 38, 43, 38, 45, 38, 42, 49, 38, 63, 41, - - 45, 49, 42, 41, 52, 52, 56, 41, 56, 68, - 69, 69, 72, 93, 63, 68, 82, 97, 69, 93, - 94, 72, 96, 99, 110, 97, 107, 125, 72, 110, - 107, 82, 82, 96, 99, 94, 111, 128, 128, 94, - 134, 111, 141, 125, 134, 142, 166, 166, 364, 363, - 362, 361, 360, 359, 357, 142, 356, 141, 166, 367, - 367, 367, 367, 368, 368, 368, 368, 370, 370, 355, - 370, 371, 371, 371, 371, 372, 354, 372, 372, 353, - 352, 351, 350, 349, 348, 346, 344, 341, 339, 338, - 336, 335, 334, 333, 331, 329, 327, 326, 325, 324, - - 322, 320, 319, 316, 315, 313, 312, 309, 308, 307, - 303, 302, 301, 300, 297, 296, 295, 293, 292, 290, - 288, 286, 285, 283, 281, 279, 276, 275, 271, 270, - 269, 268, 267, 266, 264, 263, 262, 261, 260, 259, - 258, 257, 256, 255, 253, 252, 251, 249, 244, 243, - 242, 241, 240, 239, 238, 236, 235, 234, 233, 231, - 229, 227, 226, 225, 224, 223, 222, 221, 220, 218, - 217, 216, 215, 214, 213, 212, 211, 210, 208, 207, - 206, 203, 201, 199, 198, 197, 196, 194, 193, 192, - 190, 189, 187, 186, 185, 184, 183, 182, 181, 180, - - 179, 178, 177, 175, 174, 173, 172, 171, 170, 169, - 168, 167, 165, 164, 163, 161, 158, 157, 156, 155, - 154, 153, 152, 151, 150, 148, 147, 146, 145, 144, - 143, 140, 139, 137, 136, 133, 132, 131, 130, 129, - 127, 126, 124, 123, 122, 121, 120, 119, 118, 115, - 114, 108, 106, 105, 104, 103, 102, 101, 100, 98, - 95, 92, 91, 90, 87, 86, 85, 84, 80, 79, - 78, 77, 76, 75, 74, 73, 71, 70, 67, 65, - 64, 62, 55, 51, 44, 39, 26, 22, 20, 19, - 7, 6, 5, 4, 3, 366, 366, 366, 366, 366, - - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366 + 32, 29, 32, 30, 29, 43, 30, 43, 33, 30, + 31, 35, 30, 36, 31, 33, 37, 29, 33, 35, + 31, 33, 37, 36, 35, 38, 49, 42, 372, 40, + 41, 49, 63, 38, 42, 38, 45, 38, 40, 40, + + 38, 42, 41, 45, 52, 52, 41, 56, 63, 56, + 41, 69, 70, 70, 73, 94, 83, 69, 95, 98, + 70, 94, 108, 73, 97, 100, 108, 98, 127, 111, + 73, 83, 83, 95, 111, 97, 100, 95, 112, 130, + 130, 136, 143, 112, 127, 136, 144, 168, 168, 367, + 366, 365, 364, 363, 362, 360, 144, 143, 359, 168, + 370, 370, 370, 370, 371, 371, 371, 371, 373, 373, + 358, 373, 374, 374, 374, 374, 375, 357, 375, 375, + 356, 355, 354, 353, 352, 351, 349, 347, 344, 342, + 341, 339, 338, 337, 336, 334, 332, 330, 329, 328, + + 327, 325, 323, 322, 319, 318, 316, 315, 312, 311, + 310, 306, 305, 304, 303, 300, 299, 298, 296, 295, + 293, 291, 289, 288, 286, 284, 282, 279, 278, 274, + 273, 272, 271, 270, 269, 267, 266, 265, 264, 263, + 262, 261, 260, 259, 258, 256, 255, 254, 252, 247, + 246, 245, 244, 243, 242, 241, 239, 238, 237, 236, + 234, 232, 230, 229, 228, 227, 226, 225, 224, 223, + 221, 220, 219, 218, 217, 216, 215, 214, 213, 211, + 210, 209, 206, 204, 202, 201, 200, 199, 197, 196, + 195, 193, 192, 190, 189, 188, 187, 186, 185, 184, + + 183, 182, 181, 180, 177, 176, 175, 174, 173, 172, + 171, 170, 169, 167, 166, 165, 163, 160, 159, 158, + 157, 156, 155, 154, 153, 152, 150, 149, 148, 147, + 146, 145, 142, 141, 139, 138, 135, 134, 133, 132, + 131, 129, 128, 126, 125, 124, 123, 122, 121, 120, + 119, 116, 115, 109, 107, 106, 105, 104, 103, 102, + 101, 99, 96, 93, 92, 91, 88, 87, 86, 85, + 81, 80, 79, 78, 77, 76, 75, 74, 72, 71, + 68, 66, 65, 64, 62, 55, 51, 44, 39, 26, + 22, 20, 19, 7, 6, 5, 4, 3, 369, 369, + + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; +extern int yy_flex_debug; +int yy_flex_debug = 0; + /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ @@ -582,7 +661,6 @@ static char *yy_last_accepting_cpos; #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "pars0lex.l" -#define INITIAL 0 /****************************************************** SQL parser lexical analyzer: input file for the GNU Flex lexer generator @@ -622,13 +700,9 @@ How to make the InnoDB parser and lexer C files: These instructions seem to work at least with bison-1.28 and flex-2.5.4 on Linux. *******************************************************/ -#define YY_NEVER_INTERACTIVE 1 #define YY_NO_INPUT 1 -#define YY_NO_UNPUT 1 -#define YY_NO_SCAN_BUFFER 1 -#define YY_NO_SCAN_BYTES 1 -#define YY_NO_SCAN_STRING 1 -#line 52 "pars0lex.l" +#define YY_NO_UNISTD_H 1 +#line 56 "pars0lex.l" #define YYSTYPE que_node_t* #include "univ.i" @@ -673,11 +747,25 @@ string_append( stringbuf_len += len; } -#define comment 1 + +#line 751 "lex.yy.c" + +#define INITIAL 0 +#define comment 1 #define quoted 2 -#line 676 "lex.yy.c" +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif /* Macros after this point can all be overridden by user definitions in * section 1. @@ -685,65 +773,28 @@ string_append( #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus -extern "C" int yywrap YY_PROTO(( void )); +extern "C" int yywrap (void ); #else -extern int yywrap YY_PROTO(( void )); +extern int yywrap (void ); #endif #endif -#ifndef YY_NO_UNPUT -static void yyunput YY_PROTO(( int c, char *buf_ptr )); -#endif - #ifndef yytext_ptr -static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen YY_PROTO(( yyconst char * )); +static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT -#ifdef __cplusplus -static int yyinput YY_PROTO(( void )); -#else -static int input YY_PROTO(( void )); -#endif -#endif - -#if YY_STACK_USED -static int yy_start_stack_ptr = 0; -static int yy_start_stack_depth = 0; -static int *yy_start_stack = 0; -#ifndef YY_NO_PUSH_STATE -static void yy_push_state YY_PROTO(( int new_state )); -#endif -#ifndef YY_NO_POP_STATE -static void yy_pop_state YY_PROTO(( void )); -#endif -#ifndef YY_NO_TOP_STATE -static int yy_top_state YY_PROTO(( void )); -#endif +#ifdef __cplusplus +static int yyinput (void ); #else -#define YY_NO_PUSH_STATE 1 -#define YY_NO_POP_STATE 1 -#define YY_NO_TOP_STATE 1 +static int input (void ); #endif -#ifdef YY_MALLOC_DECL -YY_MALLOC_DECL -#else -#if __STDC__ -#ifndef __cplusplus -#include <stdlib.h> -#endif -#else -/* Just try to get by without declaring the routines. This will fail - * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) - * or sizeof(void*) != sizeof(int). - */ -#endif #endif /* Amount of stuff to slurp up with each read. */ @@ -752,7 +803,6 @@ YY_MALLOC_DECL #endif /* Copy whatever the last rule matched to the standard output. */ - #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). @@ -765,9 +815,10 @@ YY_MALLOC_DECL */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ - if ( yy_current_buffer->yy_is_interactive ) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ - int c = '*', n; \ + int c = '*'; \ + size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -777,9 +828,22 @@ YY_MALLOC_DECL YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ - else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ - && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - @@ -800,12 +864,18 @@ YY_MALLOC_DECL #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif +/* end tables serialization structures and prototypes */ + /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL -#define YY_DECL int yylex YY_PROTO(( void )) -#endif +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. @@ -822,27 +892,29 @@ YY_MALLOC_DECL #define YY_RULE_SETUP \ YY_USER_ACTION +/** The main scanner function which does all the work. + */ YY_DECL - { +{ register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; - -#line 102 "pars0lex.l" + +#line 106 "pars0lex.l" -#line 830 "lex.yy.c" +#line 905 "lex.yy.c" - if ( yy_init ) + if ( (yy_init) ) { - yy_init = 0; + (yy_init) = 0; #ifdef YY_USER_INIT YY_USER_INIT; #endif - if ( ! yy_start ) - yy_start = 1; /* first start state */ + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; @@ -850,73 +922,69 @@ YY_DECL if ( ! yyout ) yyout = stdout; - if ( ! yy_current_buffer ) - yy_current_buffer = - yy_create_buffer( yyin, YY_BUF_SIZE ); + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } - yy_load_buffer_state(); + yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { - yy_cp = yy_c_buf_p; + yy_cp = (yy_c_buf_p); /* Support of yytext. */ - *yy_cp = yy_hold_char; + *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; - yy_current_state = yy_start; + yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 367 ) + if ( yy_current_state >= 370 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 396 ); + while ( yy_current_state != 369 ); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); yy_find_action: yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; - yy_act = yy_accept[yy_current_state]; - } YY_DO_BEFORE_ACTION; - do_action: /* This label is used only to access EOF actions. */ - switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = yy_hold_char; - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP -#line 104 "pars0lex.l" +#line 108 "pars0lex.l" { yylval = sym_tab_add_int_lit(pars_sym_tab_global, atoi(yytext)); @@ -925,7 +993,7 @@ YY_RULE_SETUP YY_BREAK case 2: YY_RULE_SETUP -#line 110 "pars0lex.l" +#line 114 "pars0lex.l" { ut_error; /* not implemented */ @@ -934,7 +1002,7 @@ YY_RULE_SETUP YY_BREAK case 3: YY_RULE_SETUP -#line 116 "pars0lex.l" +#line 120 "pars0lex.l" { /* Quoted character string literals are handled in an explicit start state 'quoted'. This state is entered and the buffer for @@ -946,8 +1014,9 @@ In the state 'quoted', only two actions are possible (defined below). */ } YY_BREAK case 4: +/* rule 4 can match eol */ YY_RULE_SETUP -#line 125 "pars0lex.l" +#line 129 "pars0lex.l" { /* Got a sequence of characters other than "'": append to string buffer */ @@ -956,7 +1025,7 @@ YY_RULE_SETUP YY_BREAK case 5: YY_RULE_SETUP -#line 130 "pars0lex.l" +#line 134 "pars0lex.l" { /* Got a sequence of "'" characters: append half of them to string buffer, @@ -983,7 +1052,7 @@ YY_RULE_SETUP YY_BREAK case 6: YY_RULE_SETUP -#line 154 "pars0lex.l" +#line 158 "pars0lex.l" { yylval = sym_tab_add_null_lit(pars_sym_tab_global); @@ -992,7 +1061,7 @@ YY_RULE_SETUP YY_BREAK case 7: YY_RULE_SETUP -#line 160 "pars0lex.l" +#line 164 "pars0lex.l" { /* Implicit cursor name */ yylval = sym_tab_add_str_lit(pars_sym_tab_global, @@ -1002,572 +1071,570 @@ YY_RULE_SETUP YY_BREAK case 8: YY_RULE_SETUP -#line 167 "pars0lex.l" +#line 171 "pars0lex.l" { return(PARS_AND_TOKEN); } YY_BREAK case 9: YY_RULE_SETUP -#line 171 "pars0lex.l" +#line 175 "pars0lex.l" { return(PARS_OR_TOKEN); } YY_BREAK case 10: YY_RULE_SETUP -#line 175 "pars0lex.l" +#line 179 "pars0lex.l" { return(PARS_NOT_TOKEN); } YY_BREAK case 11: YY_RULE_SETUP -#line 179 "pars0lex.l" +#line 183 "pars0lex.l" { return(PARS_PROCEDURE_TOKEN); } YY_BREAK case 12: YY_RULE_SETUP -#line 183 "pars0lex.l" +#line 187 "pars0lex.l" { return(PARS_IN_TOKEN); } YY_BREAK case 13: YY_RULE_SETUP -#line 187 "pars0lex.l" +#line 191 "pars0lex.l" { return(PARS_OUT_TOKEN); } YY_BREAK case 14: YY_RULE_SETUP -#line 191 "pars0lex.l" +#line 195 "pars0lex.l" { - return(PARS_INT_TOKEN); + return(PARS_BINARY_TOKEN); } YY_BREAK case 15: YY_RULE_SETUP -#line 195 "pars0lex.l" +#line 199 "pars0lex.l" { - return(PARS_INT_TOKEN); + return(PARS_BLOB_TOKEN); } YY_BREAK case 16: YY_RULE_SETUP -#line 199 "pars0lex.l" +#line 203 "pars0lex.l" { - return(PARS_FLOAT_TOKEN); + return(PARS_INT_TOKEN); } YY_BREAK case 17: YY_RULE_SETUP -#line 203 "pars0lex.l" +#line 207 "pars0lex.l" { - return(PARS_CHAR_TOKEN); + return(PARS_INT_TOKEN); } YY_BREAK case 18: YY_RULE_SETUP -#line 207 "pars0lex.l" +#line 211 "pars0lex.l" { - return(PARS_IS_TOKEN); + return(PARS_FLOAT_TOKEN); } YY_BREAK case 19: YY_RULE_SETUP -#line 211 "pars0lex.l" +#line 215 "pars0lex.l" { - return(PARS_BEGIN_TOKEN); + return(PARS_CHAR_TOKEN); } YY_BREAK case 20: YY_RULE_SETUP -#line 215 "pars0lex.l" +#line 219 "pars0lex.l" { - return(PARS_END_TOKEN); + return(PARS_IS_TOKEN); } YY_BREAK case 21: YY_RULE_SETUP -#line 219 "pars0lex.l" +#line 223 "pars0lex.l" { - return(PARS_IF_TOKEN); + return(PARS_BEGIN_TOKEN); } YY_BREAK case 22: YY_RULE_SETUP -#line 223 "pars0lex.l" +#line 227 "pars0lex.l" { - return(PARS_THEN_TOKEN); + return(PARS_END_TOKEN); } YY_BREAK case 23: YY_RULE_SETUP -#line 227 "pars0lex.l" +#line 231 "pars0lex.l" { - return(PARS_ELSE_TOKEN); + return(PARS_IF_TOKEN); } YY_BREAK case 24: YY_RULE_SETUP -#line 231 "pars0lex.l" +#line 235 "pars0lex.l" { - return(PARS_ELSIF_TOKEN); + return(PARS_THEN_TOKEN); } YY_BREAK case 25: YY_RULE_SETUP -#line 235 "pars0lex.l" +#line 239 "pars0lex.l" { - return(PARS_LOOP_TOKEN); + return(PARS_ELSE_TOKEN); } YY_BREAK case 26: YY_RULE_SETUP -#line 239 "pars0lex.l" +#line 243 "pars0lex.l" { - return(PARS_WHILE_TOKEN); + return(PARS_ELSIF_TOKEN); } YY_BREAK case 27: YY_RULE_SETUP -#line 243 "pars0lex.l" +#line 247 "pars0lex.l" { - return(PARS_RETURN_TOKEN); + return(PARS_LOOP_TOKEN); } YY_BREAK case 28: YY_RULE_SETUP -#line 247 "pars0lex.l" +#line 251 "pars0lex.l" { - return(PARS_SELECT_TOKEN); + return(PARS_WHILE_TOKEN); } YY_BREAK case 29: YY_RULE_SETUP -#line 251 "pars0lex.l" +#line 255 "pars0lex.l" { - return(PARS_SUM_TOKEN); + return(PARS_RETURN_TOKEN); } YY_BREAK case 30: YY_RULE_SETUP -#line 255 "pars0lex.l" +#line 259 "pars0lex.l" { - return(PARS_COUNT_TOKEN); + return(PARS_SELECT_TOKEN); } YY_BREAK case 31: YY_RULE_SETUP -#line 259 "pars0lex.l" +#line 263 "pars0lex.l" { - return(PARS_DISTINCT_TOKEN); + return(PARS_SUM_TOKEN); } YY_BREAK case 32: YY_RULE_SETUP -#line 263 "pars0lex.l" +#line 267 "pars0lex.l" { - return(PARS_FROM_TOKEN); + return(PARS_COUNT_TOKEN); } YY_BREAK case 33: YY_RULE_SETUP -#line 267 "pars0lex.l" +#line 271 "pars0lex.l" { - return(PARS_WHERE_TOKEN); + return(PARS_DISTINCT_TOKEN); } YY_BREAK case 34: YY_RULE_SETUP -#line 271 "pars0lex.l" +#line 275 "pars0lex.l" { - return(PARS_FOR_TOKEN); + return(PARS_FROM_TOKEN); } YY_BREAK case 35: YY_RULE_SETUP -#line 275 "pars0lex.l" +#line 279 "pars0lex.l" { - return(PARS_CONSISTENT_TOKEN); + return(PARS_WHERE_TOKEN); } YY_BREAK case 36: YY_RULE_SETUP -#line 279 "pars0lex.l" +#line 283 "pars0lex.l" { - return(PARS_READ_TOKEN); + return(PARS_FOR_TOKEN); } YY_BREAK case 37: YY_RULE_SETUP -#line 283 "pars0lex.l" +#line 287 "pars0lex.l" { - return(PARS_ORDER_TOKEN); + return(PARS_CONSISTENT_TOKEN); } YY_BREAK case 38: YY_RULE_SETUP -#line 287 "pars0lex.l" +#line 291 "pars0lex.l" { - return(PARS_BY_TOKEN); + return(PARS_READ_TOKEN); } YY_BREAK case 39: YY_RULE_SETUP -#line 291 "pars0lex.l" +#line 295 "pars0lex.l" { - return(PARS_ASC_TOKEN); + return(PARS_ORDER_TOKEN); } YY_BREAK case 40: YY_RULE_SETUP -#line 295 "pars0lex.l" +#line 299 "pars0lex.l" { - return(PARS_DESC_TOKEN); + return(PARS_BY_TOKEN); } YY_BREAK case 41: YY_RULE_SETUP -#line 299 "pars0lex.l" +#line 303 "pars0lex.l" { - return(PARS_INSERT_TOKEN); + return(PARS_ASC_TOKEN); } YY_BREAK case 42: YY_RULE_SETUP -#line 303 "pars0lex.l" +#line 307 "pars0lex.l" { - return(PARS_INTO_TOKEN); + return(PARS_DESC_TOKEN); } YY_BREAK case 43: YY_RULE_SETUP -#line 307 "pars0lex.l" +#line 311 "pars0lex.l" { - return(PARS_VALUES_TOKEN); + return(PARS_INSERT_TOKEN); } YY_BREAK case 44: YY_RULE_SETUP -#line 311 "pars0lex.l" +#line 315 "pars0lex.l" { - return(PARS_UPDATE_TOKEN); + return(PARS_INTO_TOKEN); } YY_BREAK case 45: YY_RULE_SETUP -#line 315 "pars0lex.l" +#line 319 "pars0lex.l" { - return(PARS_SET_TOKEN); + return(PARS_VALUES_TOKEN); } YY_BREAK case 46: YY_RULE_SETUP -#line 319 "pars0lex.l" +#line 323 "pars0lex.l" { - return(PARS_DELETE_TOKEN); + return(PARS_UPDATE_TOKEN); } YY_BREAK case 47: YY_RULE_SETUP -#line 323 "pars0lex.l" +#line 327 "pars0lex.l" { - return(PARS_CURRENT_TOKEN); + return(PARS_SET_TOKEN); } YY_BREAK case 48: YY_RULE_SETUP -#line 327 "pars0lex.l" +#line 331 "pars0lex.l" { - return(PARS_OF_TOKEN); + return(PARS_DELETE_TOKEN); } YY_BREAK case 49: YY_RULE_SETUP -#line 331 "pars0lex.l" +#line 335 "pars0lex.l" { - return(PARS_CREATE_TOKEN); + return(PARS_CURRENT_TOKEN); } YY_BREAK case 50: YY_RULE_SETUP -#line 335 "pars0lex.l" +#line 339 "pars0lex.l" { - return(PARS_TABLE_TOKEN); + return(PARS_OF_TOKEN); } YY_BREAK case 51: YY_RULE_SETUP -#line 339 "pars0lex.l" +#line 343 "pars0lex.l" { - return(PARS_INDEX_TOKEN); + return(PARS_CREATE_TOKEN); } YY_BREAK case 52: YY_RULE_SETUP -#line 343 "pars0lex.l" +#line 347 "pars0lex.l" { - return(PARS_UNIQUE_TOKEN); + return(PARS_TABLE_TOKEN); } YY_BREAK case 53: YY_RULE_SETUP -#line 347 "pars0lex.l" +#line 351 "pars0lex.l" { - return(PARS_CLUSTERED_TOKEN); + return(PARS_INDEX_TOKEN); } YY_BREAK case 54: YY_RULE_SETUP -#line 351 "pars0lex.l" +#line 355 "pars0lex.l" { - return(PARS_DOES_NOT_FIT_IN_MEM_TOKEN); + return(PARS_UNIQUE_TOKEN); } YY_BREAK case 55: YY_RULE_SETUP -#line 355 "pars0lex.l" +#line 359 "pars0lex.l" { - return(PARS_ON_TOKEN); + return(PARS_CLUSTERED_TOKEN); } YY_BREAK case 56: YY_RULE_SETUP -#line 359 "pars0lex.l" +#line 363 "pars0lex.l" { - return(PARS_DECLARE_TOKEN); + return(PARS_DOES_NOT_FIT_IN_MEM_TOKEN); } YY_BREAK case 57: YY_RULE_SETUP -#line 363 "pars0lex.l" +#line 367 "pars0lex.l" { - return(PARS_CURSOR_TOKEN); + return(PARS_ON_TOKEN); } YY_BREAK case 58: YY_RULE_SETUP -#line 367 "pars0lex.l" +#line 371 "pars0lex.l" { - return(PARS_OPEN_TOKEN); + return(PARS_DECLARE_TOKEN); } YY_BREAK case 59: YY_RULE_SETUP -#line 371 "pars0lex.l" +#line 375 "pars0lex.l" { - return(PARS_FETCH_TOKEN); + return(PARS_CURSOR_TOKEN); } YY_BREAK case 60: YY_RULE_SETUP -#line 375 "pars0lex.l" +#line 379 "pars0lex.l" { - return(PARS_CLOSE_TOKEN); + return(PARS_OPEN_TOKEN); } YY_BREAK case 61: YY_RULE_SETUP -#line 379 "pars0lex.l" +#line 383 "pars0lex.l" { - return(PARS_NOTFOUND_TOKEN); + return(PARS_FETCH_TOKEN); } YY_BREAK case 62: YY_RULE_SETUP -#line 383 "pars0lex.l" +#line 387 "pars0lex.l" { - return(PARS_TO_CHAR_TOKEN); + return(PARS_CLOSE_TOKEN); } YY_BREAK case 63: YY_RULE_SETUP -#line 387 "pars0lex.l" +#line 391 "pars0lex.l" { - return(PARS_TO_NUMBER_TOKEN); + return(PARS_NOTFOUND_TOKEN); } YY_BREAK case 64: YY_RULE_SETUP -#line 391 "pars0lex.l" +#line 395 "pars0lex.l" { - return(PARS_TO_BINARY_TOKEN); + return(PARS_TO_CHAR_TOKEN); } YY_BREAK case 65: YY_RULE_SETUP -#line 395 "pars0lex.l" +#line 399 "pars0lex.l" { - return(PARS_BINARY_TO_NUMBER_TOKEN); + return(PARS_TO_NUMBER_TOKEN); } YY_BREAK case 66: YY_RULE_SETUP -#line 399 "pars0lex.l" +#line 403 "pars0lex.l" { - return(PARS_SUBSTR_TOKEN); + return(PARS_TO_BINARY_TOKEN); } YY_BREAK case 67: YY_RULE_SETUP -#line 403 "pars0lex.l" +#line 407 "pars0lex.l" { - return(PARS_REPLSTR_TOKEN); + return(PARS_BINARY_TO_NUMBER_TOKEN); } YY_BREAK case 68: YY_RULE_SETUP -#line 407 "pars0lex.l" +#line 411 "pars0lex.l" { - return(PARS_CONCAT_TOKEN); + return(PARS_SUBSTR_TOKEN); } YY_BREAK case 69: YY_RULE_SETUP -#line 411 "pars0lex.l" +#line 415 "pars0lex.l" { - return(PARS_INSTR_TOKEN); + return(PARS_REPLSTR_TOKEN); } YY_BREAK case 70: YY_RULE_SETUP -#line 415 "pars0lex.l" +#line 419 "pars0lex.l" { - return(PARS_LENGTH_TOKEN); + return(PARS_CONCAT_TOKEN); } YY_BREAK case 71: YY_RULE_SETUP -#line 419 "pars0lex.l" +#line 423 "pars0lex.l" { - return(PARS_SYSDATE_TOKEN); + return(PARS_INSTR_TOKEN); } YY_BREAK case 72: YY_RULE_SETUP -#line 423 "pars0lex.l" +#line 427 "pars0lex.l" { - return(PARS_PRINTF_TOKEN); + return(PARS_LENGTH_TOKEN); } YY_BREAK case 73: YY_RULE_SETUP -#line 427 "pars0lex.l" +#line 431 "pars0lex.l" { - return(PARS_ASSERT_TOKEN); + return(PARS_SYSDATE_TOKEN); } YY_BREAK case 74: YY_RULE_SETUP -#line 431 "pars0lex.l" +#line 435 "pars0lex.l" { - return(PARS_RND_TOKEN); + return(PARS_PRINTF_TOKEN); } YY_BREAK case 75: YY_RULE_SETUP -#line 435 "pars0lex.l" +#line 439 "pars0lex.l" { - return(PARS_RND_STR_TOKEN); + return(PARS_ASSERT_TOKEN); } YY_BREAK case 76: YY_RULE_SETUP -#line 439 "pars0lex.l" +#line 443 "pars0lex.l" { - return(PARS_ROW_PRINTF_TOKEN); + return(PARS_RND_TOKEN); } YY_BREAK case 77: YY_RULE_SETUP -#line 443 "pars0lex.l" +#line 447 "pars0lex.l" { - return(PARS_COMMIT_TOKEN); + return(PARS_RND_STR_TOKEN); } YY_BREAK case 78: YY_RULE_SETUP -#line 447 "pars0lex.l" +#line 451 "pars0lex.l" { - return(PARS_ROLLBACK_TOKEN); + return(PARS_ROW_PRINTF_TOKEN); } YY_BREAK case 79: YY_RULE_SETUP -#line 451 "pars0lex.l" +#line 455 "pars0lex.l" { - return(PARS_WORK_TOKEN); + return(PARS_COMMIT_TOKEN); } YY_BREAK case 80: YY_RULE_SETUP -#line 455 "pars0lex.l" +#line 459 "pars0lex.l" { - yylval = sym_tab_add_id(pars_sym_tab_global, - (byte*)yytext, - ut_strlen(yytext)); - return(PARS_ID_TOKEN); + return(PARS_ROLLBACK_TOKEN); } YY_BREAK case 81: YY_RULE_SETUP -#line 462 "pars0lex.l" +#line 463 "pars0lex.l" { - return(PARS_DDOT_TOKEN); + return(PARS_WORK_TOKEN); } YY_BREAK case 82: YY_RULE_SETUP -#line 466 "pars0lex.l" +#line 467 "pars0lex.l" { - return(PARS_ASSIGN_TOKEN); + yylval = sym_tab_add_id(pars_sym_tab_global, + (byte*)yytext, + ut_strlen(yytext)); + return(PARS_ID_TOKEN); } YY_BREAK case 83: YY_RULE_SETUP -#line 470 "pars0lex.l" +#line 474 "pars0lex.l" { - return(PARS_LE_TOKEN); + return(PARS_DDOT_TOKEN); } YY_BREAK case 84: YY_RULE_SETUP -#line 474 "pars0lex.l" +#line 478 "pars0lex.l" { - return(PARS_GE_TOKEN); + return(PARS_ASSIGN_TOKEN); } YY_BREAK case 85: YY_RULE_SETUP -#line 478 "pars0lex.l" +#line 482 "pars0lex.l" { - return(PARS_NE_TOKEN); + return(PARS_LE_TOKEN); } YY_BREAK case 86: YY_RULE_SETUP -#line 482 "pars0lex.l" +#line 486 "pars0lex.l" { - - return((int)(*yytext)); + return(PARS_GE_TOKEN); } YY_BREAK case 87: YY_RULE_SETUP -#line 487 "pars0lex.l" +#line 490 "pars0lex.l" { - - return((int)(*yytext)); + return(PARS_NE_TOKEN); } YY_BREAK case 88: YY_RULE_SETUP -#line 492 "pars0lex.l" +#line 494 "pars0lex.l" { return((int)(*yytext)); @@ -1575,7 +1642,7 @@ YY_RULE_SETUP YY_BREAK case 89: YY_RULE_SETUP -#line 497 "pars0lex.l" +#line 499 "pars0lex.l" { return((int)(*yytext)); @@ -1583,7 +1650,7 @@ YY_RULE_SETUP YY_BREAK case 90: YY_RULE_SETUP -#line 502 "pars0lex.l" +#line 504 "pars0lex.l" { return((int)(*yytext)); @@ -1591,7 +1658,7 @@ YY_RULE_SETUP YY_BREAK case 91: YY_RULE_SETUP -#line 507 "pars0lex.l" +#line 509 "pars0lex.l" { return((int)(*yytext)); @@ -1599,7 +1666,7 @@ YY_RULE_SETUP YY_BREAK case 92: YY_RULE_SETUP -#line 512 "pars0lex.l" +#line 514 "pars0lex.l" { return((int)(*yytext)); @@ -1607,7 +1674,7 @@ YY_RULE_SETUP YY_BREAK case 93: YY_RULE_SETUP -#line 517 "pars0lex.l" +#line 519 "pars0lex.l" { return((int)(*yytext)); @@ -1615,7 +1682,7 @@ YY_RULE_SETUP YY_BREAK case 94: YY_RULE_SETUP -#line 522 "pars0lex.l" +#line 524 "pars0lex.l" { return((int)(*yytext)); @@ -1623,7 +1690,7 @@ YY_RULE_SETUP YY_BREAK case 95: YY_RULE_SETUP -#line 527 "pars0lex.l" +#line 529 "pars0lex.l" { return((int)(*yytext)); @@ -1631,7 +1698,7 @@ YY_RULE_SETUP YY_BREAK case 96: YY_RULE_SETUP -#line 532 "pars0lex.l" +#line 534 "pars0lex.l" { return((int)(*yytext)); @@ -1639,7 +1706,7 @@ YY_RULE_SETUP YY_BREAK case 97: YY_RULE_SETUP -#line 537 "pars0lex.l" +#line 539 "pars0lex.l" { return((int)(*yytext)); @@ -1647,7 +1714,7 @@ YY_RULE_SETUP YY_BREAK case 98: YY_RULE_SETUP -#line 542 "pars0lex.l" +#line 544 "pars0lex.l" { return((int)(*yytext)); @@ -1655,7 +1722,7 @@ YY_RULE_SETUP YY_BREAK case 99: YY_RULE_SETUP -#line 547 "pars0lex.l" +#line 549 "pars0lex.l" { return((int)(*yytext)); @@ -1663,7 +1730,7 @@ YY_RULE_SETUP YY_BREAK case 100: YY_RULE_SETUP -#line 552 "pars0lex.l" +#line 554 "pars0lex.l" { return((int)(*yytext)); @@ -1671,32 +1738,51 @@ YY_RULE_SETUP YY_BREAK case 101: YY_RULE_SETUP -#line 557 "pars0lex.l" -BEGIN(comment); /* eat up comment */ +#line 559 "pars0lex.l" +{ + + return((int)(*yytext)); +} YY_BREAK case 102: YY_RULE_SETUP -#line 559 "pars0lex.l" +#line 564 "pars0lex.l" +{ + return((int)(*yytext)); +} YY_BREAK case 103: YY_RULE_SETUP -#line 560 "pars0lex.l" - +#line 569 "pars0lex.l" +BEGIN(comment); /* eat up comment */ YY_BREAK case 104: +/* rule 104 can match eol */ YY_RULE_SETUP -#line 561 "pars0lex.l" -BEGIN(INITIAL); +#line 571 "pars0lex.l" + YY_BREAK case 105: +/* rule 105 can match eol */ YY_RULE_SETUP -#line 563 "pars0lex.l" -/* eat up whitespace */ +#line 572 "pars0lex.l" + YY_BREAK case 106: YY_RULE_SETUP -#line 566 "pars0lex.l" +#line 573 "pars0lex.l" +BEGIN(INITIAL); + YY_BREAK +case 107: +/* rule 107 can match eol */ +YY_RULE_SETUP +#line 575 "pars0lex.l" +/* eat up whitespace */ + YY_BREAK +case 108: +YY_RULE_SETUP +#line 578 "pars0lex.l" { fprintf(stderr,"Unrecognized character: %02x\n", *yytext); @@ -1706,12 +1792,12 @@ YY_RULE_SETUP return(0); } YY_BREAK -case 107: +case 109: YY_RULE_SETUP -#line 575 "pars0lex.l" +#line 587 "pars0lex.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK -#line 1710 "lex.yy.c" +#line 1799 "lex.yy.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(comment): case YY_STATE_EOF(quoted): @@ -1720,26 +1806,26 @@ case YY_STATE_EOF(quoted): case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = yy_hold_char; + *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure - * consistency between yy_current_buffer and our + * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ - yy_n_chars = yy_current_buffer->yy_n_chars; - yy_current_buffer->yy_input_file = yyin; - yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position @@ -1749,13 +1835,13 @@ case YY_STATE_EOF(quoted): * end-of-buffer state). Contrast this with the test * in input(). */ - if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; - yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; - yy_current_state = yy_get_previous_state(); + yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have @@ -1768,30 +1854,31 @@ case YY_STATE_EOF(quoted): yy_next_state = yy_try_NUL_trans( yy_current_state ); - yy_bp = yytext_ptr + YY_MORE_ADJ; + yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ - yy_cp = ++yy_c_buf_p; + yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { - yy_cp = yy_c_buf_p; + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); goto yy_find_action; } } - else switch ( yy_get_next_buffer() ) + else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { - yy_did_buffer_switch_on_eof = 0; + (yy_did_buffer_switch_on_eof) = 0; - if ( yywrap() ) + if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up @@ -1802,7 +1889,7 @@ case YY_STATE_EOF(quoted): * YY_NULL, it'll still work - another * YY_NULL will get returned. */ - yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; @@ -1810,30 +1897,30 @@ case YY_STATE_EOF(quoted): else { - if ( ! yy_did_buffer_switch_on_eof ) + if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = - yytext_ptr + yy_amount_of_matched_text; + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; - yy_current_state = yy_get_previous_state(); + yy_current_state = yy_get_previous_state( ); - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: - yy_c_buf_p = - &yy_current_buffer->yy_ch_buf[yy_n_chars]; + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; - yy_current_state = yy_get_previous_state(); + yy_current_state = yy_get_previous_state( ); - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; @@ -1844,8 +1931,7 @@ case YY_STATE_EOF(quoted): "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ - } /* end of yylex */ - +} /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * @@ -1854,21 +1940,20 @@ case YY_STATE_EOF(quoted): * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ - -static int yy_get_next_buffer() - { - register char *dest = yy_current_buffer->yy_ch_buf; - register char *source = yytext_ptr; +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; - if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); - if ( yy_current_buffer->yy_fill_buffer == 0 ) + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ - if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. @@ -1888,34 +1973,30 @@ static int yy_get_next_buffer() /* Try to read more data. */ /* First move last chars to start of buffer. */ - number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ - yy_current_buffer->yy_n_chars = yy_n_chars = 0; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { - int num_to_read = - yy_current_buffer->yy_buf_size - number_to_move - 1; + size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ -#ifdef YY_USES_REJECT - YY_FATAL_ERROR( -"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); -#else /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = yy_current_buffer; + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = - (int) (yy_c_buf_p - b->yy_ch_buf); + (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { @@ -1928,8 +2009,7 @@ static int yy_get_next_buffer() b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ - yy_flex_realloc( (void *) b->yy_ch_buf, - b->yy_buf_size + 2 ); + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ @@ -1939,35 +2019,35 @@ static int yy_get_next_buffer() YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); - yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; - num_to_read = yy_current_buffer->yy_buf_size - + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; -#endif + } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ - YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), - yy_n_chars, num_to_read ); + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); - yy_current_buffer->yy_n_chars = yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } - if ( yy_n_chars == 0 ) + if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; - yyrestart( yyin ); + yyrestart(yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; - yy_current_buffer->yy_buffer_status = + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } @@ -1975,152 +2055,100 @@ static int yy_get_next_buffer() else ret_val = EOB_ACT_CONTINUE_SCAN; - yy_n_chars += number_to_move; - yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; - yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; - yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; - } - +} /* yy_get_previous_state - get the state just before the EOB char was reached */ -static yy_state_type yy_get_previous_state() - { + static yy_state_type yy_get_previous_state (void) +{ register yy_state_type yy_current_state; register char *yy_cp; + + yy_current_state = (yy_start); - yy_current_state = yy_start; - - for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 367 ) + if ( yy_current_state >= 370 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; - } - +} /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ - -#ifdef YY_USE_PROTOS -static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) -#else -static yy_state_type yy_try_NUL_trans( yy_current_state ) -yy_state_type yy_current_state; -#endif - { + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ register int yy_is_jam; - register char *yy_cp = yy_c_buf_p; + register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 367 ) + if ( yy_current_state >= 370 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 366); + yy_is_jam = (yy_current_state == 369); return yy_is_jam ? 0 : yy_current_state; - } - - -#ifndef YY_NO_UNPUT -#ifdef YY_USE_PROTOS -static void yyunput( int c, register char *yy_bp ) -#else -static void yyunput( c, yy_bp ) -int c; -register char *yy_bp; -#endif - { - register char *yy_cp = yy_c_buf_p; - - /* undo effects of setting up yytext */ - *yy_cp = yy_hold_char; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - register int number_to_move = yy_n_chars + 2; - register char *dest = &yy_current_buffer->yy_ch_buf[ - yy_current_buffer->yy_buf_size + 2]; - register char *source = - &yy_current_buffer->yy_ch_buf[number_to_move]; - - while ( source > yy_current_buffer->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - yy_current_buffer->yy_n_chars = - yy_n_chars = yy_current_buffer->yy_buf_size; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - - yytext_ptr = yy_bp; - yy_hold_char = *yy_cp; - yy_c_buf_p = yy_cp; - } -#endif /* ifndef YY_NO_UNPUT */ - +} +#ifndef YY_NO_INPUT #ifdef __cplusplus -static int yyinput() + static int yyinput (void) #else -static int input() + static int input (void) #endif - { - int c; - *yy_c_buf_p = yy_hold_char; +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); - if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ - if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ - *yy_c_buf_p = '\0'; + *(yy_c_buf_p) = '\0'; else { /* need more input */ - int offset = (int) (yy_c_buf_p - yytext_ptr); - ++yy_c_buf_p; + int offset = (int)(yy_c_buf_p - yytext_ptr); + ++(yy_c_buf_p); - switch ( yy_get_next_buffer() ) + switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() @@ -2134,16 +2162,16 @@ static int input() */ /* Reset buffer status. */ - yyrestart( yyin ); + yyrestart(yyin ); - /* fall through */ + /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { - if ( yywrap() ) + if ( yywrap( ) ) return EOF; - if ( ! yy_did_buffer_switch_on_eof ) + if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); @@ -2153,90 +2181,92 @@ static int input() } case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = yytext_ptr + offset; + (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } - c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ - *yy_c_buf_p = '\0'; /* preserve yytext */ - yy_hold_char = *++yy_c_buf_p; - + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); return c; - } - - -#ifdef YY_USE_PROTOS -void yyrestart( FILE *input_file ) -#else -void yyrestart( input_file ) -FILE *input_file; -#endif - { - if ( ! yy_current_buffer ) - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); +} +#endif /* ifndef YY_NO_INPUT */ - yy_init_buffer( yy_current_buffer, input_file ); - yy_load_buffer_state(); +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); } + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} -#ifdef YY_USE_PROTOS -void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) -#else -void yy_switch_to_buffer( new_buffer ) -YY_BUFFER_STATE new_buffer; -#endif - { - if ( yy_current_buffer == new_buffer ) +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) return; - if ( yy_current_buffer ) + if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ - *yy_c_buf_p = yy_hold_char; - yy_current_buffer->yy_buf_pos = yy_c_buf_p; - yy_current_buffer->yy_n_chars = yy_n_chars; + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } - yy_current_buffer = new_buffer; - yy_load_buffer_state(); + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ - yy_did_buffer_switch_on_eof = 1; - } - - -#ifdef YY_USE_PROTOS -void yy_load_buffer_state( void ) -#else -void yy_load_buffer_state() -#endif - { - yy_n_chars = yy_current_buffer->yy_n_chars; - yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; - yyin = yy_current_buffer->yy_input_file; - yy_hold_char = *yy_c_buf_p; - } + (yy_did_buffer_switch_on_eof) = 1; +} +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) -#else -YY_BUFFER_STATE yy_create_buffer( file, size ) -FILE *file; -int size; -#endif - { +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); @@ -2245,80 +2275,71 @@ int size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; - yy_init_buffer( b, file ); + yy_init_buffer(b,file ); return b; - } - +} -#ifdef YY_USE_PROTOS -void yy_delete_buffer( YY_BUFFER_STATE b ) -#else -void yy_delete_buffer( b ) -YY_BUFFER_STATE b; -#endif - { +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) return; - if ( b == yy_current_buffer ) - yy_current_buffer = (YY_BUFFER_STATE) 0; + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) - yy_flex_free( (void *) b->yy_ch_buf ); - - yy_flex_free( (void *) b ); - } - - -#ifndef YY_ALWAYS_INTERACTIVE -#ifndef YY_NEVER_INTERACTIVE -extern int isatty YY_PROTO(( int )); -#endif -#endif + yyfree((void *) b->yy_ch_buf ); -#ifdef YY_USE_PROTOS -void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) -#else -void yy_init_buffer( b, file ) -YY_BUFFER_STATE b; -FILE *file; -#endif + yyfree((void *) b ); +} +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) - { - yy_flush_buffer( b ); +{ + int oerrno = errno; + + yy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; -#if YY_ALWAYS_INTERACTIVE - b->yy_is_interactive = 1; -#else -#if YY_NEVER_INTERACTIVE - b->yy_is_interactive = 0; -#else - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; -#endif -#endif - } + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + b->yy_is_interactive = 0; + + errno = oerrno; +} -#ifdef YY_USE_PROTOS -void yy_flush_buffer( YY_BUFFER_STATE b ) -#else -void yy_flush_buffer( b ) -YY_BUFFER_STATE b; -#endif - - { - if ( ! b ) +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) return; b->yy_n_chars = 0; @@ -2335,243 +2356,260 @@ YY_BUFFER_STATE b; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; - if ( b == yy_current_buffer ) - yy_load_buffer_state(); - } - + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} -#ifndef YY_NO_SCAN_BUFFER -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) -#else -YY_BUFFER_STATE yy_scan_buffer( base, size ) -char *base; -yy_size_t size; -#endif - { - YY_BUFFER_STATE b; +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; + yyensure_buffer_stack(); - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } - yy_switch_to_buffer( b ); + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; - return b; - } -#endif + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; -#ifndef YY_NO_SCAN_STRING -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) -#else -YY_BUFFER_STATE yy_scan_string( yy_str ) -yyconst char *yy_str; -#endif - { - int len; - for ( len = 0; yy_str[len]; ++len ) - ; + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); - return yy_scan_bytes( yy_str, len ); + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; } -#endif - - -#ifndef YY_NO_SCAN_BYTES -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) -#else -YY_BUFFER_STATE yy_scan_bytes( bytes, len ) -yyconst char *bytes; -int len; -#endif - { - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = len + 2; - buf = (char *) yy_flex_alloc( n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); +} - for ( i = 0; i < len; ++i ) - buf[i] = bytes[i]; +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } - buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - b = yy_scan_buffer( buf, n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); - return b; + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; } -#endif - +} -#ifndef YY_NO_PUSH_STATE -#ifdef YY_USE_PROTOS -static void yy_push_state( int new_state ) -#else -static void yy_push_state( new_state ) -int new_state; +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 #endif - { - if ( yy_start_stack_ptr >= yy_start_stack_depth ) - { - yy_size_t new_size; - yy_start_stack_depth += YY_START_STACK_INCR; - new_size = yy_start_stack_depth * sizeof( int ); +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} - if ( ! yy_start_stack ) - yy_start_stack = (int *) yy_flex_alloc( new_size ); +/* Redefine yyless() so it works in section 3 code. */ - else - yy_start_stack = (int *) yy_flex_realloc( - (void *) yy_start_stack, new_size ); +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) - if ( ! yy_start_stack ) - YY_FATAL_ERROR( - "out of memory expanding start-condition stack" ); - } +/* Accessor methods (get/set functions) to struct members. */ - yy_start_stack[yy_start_stack_ptr++] = YY_START; +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} - BEGIN(new_state); - } -#endif +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} -#ifndef YY_NO_POP_STATE -static void yy_pop_state() - { - if ( --yy_start_stack_ptr < 0 ) - YY_FATAL_ERROR( "start-condition stack underflow" ); +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} - BEGIN(yy_start_stack[yy_start_stack_ptr]); - } -#endif +/** Get the current token. + * + */ +char *yyget_text (void) +{ + return yytext; +} -#ifndef YY_NO_TOP_STATE -static int yy_top_state() - { - return yy_start_stack[yy_start_stack_ptr - 1]; - } -#endif +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} -#ifdef YY_USE_PROTOS -static void yy_fatal_error( yyconst char msg[] ) -#else -static void yy_fatal_error( msg ) -char msg[]; -#endif - { - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); - } +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} +int yyget_debug (void) +{ + return yy_flex_debug; +} +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} -/* Redefine yyless() so it works in section 3 code. */ +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - yytext[yyleng] = yy_hold_char; \ - yy_c_buf_p = yytext + n; \ - yy_hold_char = *yy_c_buf_p; \ - *yy_c_buf_p = '\0'; \ - yyleng = n; \ - } \ - while ( 0 ) + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + return 0; +} -/* Internal utility routines. */ +/* + * Internal utility routines. + */ #ifndef yytext_ptr -#ifdef YY_USE_PROTOS -static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) -#else -static void yy_flex_strncpy( s1, s2, n ) -char *s1; -yyconst char *s2; -int n; -#endif - { +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ register int i; - for ( i = 0; i < n; ++i ) + for ( i = 0; i < n; ++i ) s1[i] = s2[i]; - } +} #endif #ifdef YY_NEED_STRLEN -#ifdef YY_USE_PROTOS -static int yy_flex_strlen( yyconst char *s ) -#else -static int yy_flex_strlen( s ) -yyconst char *s; -#endif - { +static int yy_flex_strlen (yyconst char * s ) +{ register int n; - for ( n = 0; s[n]; ++n ) + for ( n = 0; s[n]; ++n ) ; return n; - } +} #endif - -#ifdef YY_USE_PROTOS -static void *yy_flex_alloc( yy_size_t size ) -#else -static void *yy_flex_alloc( size ) -yy_size_t size; -#endif - { +void *yyalloc (yy_size_t size ) +{ return (void *) malloc( size ); - } +} -#ifdef YY_USE_PROTOS -static void *yy_flex_realloc( void *ptr, yy_size_t size ) -#else -static void *yy_flex_realloc( ptr, size ) -void *ptr; -yy_size_t size; -#endif - { +void *yyrealloc (void * ptr, yy_size_t size ) +{ /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter @@ -2580,24 +2618,28 @@ yy_size_t size; * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); - } +} -#ifdef YY_USE_PROTOS -static void yy_flex_free( void *ptr ) -#else -static void yy_flex_free( ptr ) -void *ptr; -#endif - { - free( ptr ); - } +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} -#if YY_MAIN -int main() - { - yylex(); - return 0; - } +#define YYTABLES_NAME "yytables" + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef yytext_ptr +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL #endif -#line 575 "pars0lex.l" +#line 587 "pars0lex.l" + + diff --git a/storage/innobase/pars/make_bison.sh b/storage/innobase/pars/make_bison.sh new file mode 100755 index 00000000000..43b0322494c --- /dev/null +++ b/storage/innobase/pars/make_bison.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# regenerate parser from bison input files as documented at the top of +# pars0lex.l. + +set -eu + +bison -d pars0grm.y +mv pars0grm.tab.c pars0grm.c +mv pars0grm.tab.h pars0grm.h +cp pars0grm.h ../include diff --git a/storage/innobase/pars/pars0grm.c b/storage/innobase/pars/pars0grm.c index 05b75398084..3800cdda88e 100644 --- a/storage/innobase/pars/pars0grm.c +++ b/storage/innobase/pars/pars0grm.c @@ -1,94 +1,237 @@ +/* A Bison parser, made by GNU Bison 1.875d. */ -/* A Bison parser, made from pars0grm.y - by GNU Bison version 1.28 */ - -#define YYBISON 1 /* Identify Bison output. */ - -#define PARS_INT_LIT 257 -#define PARS_FLOAT_LIT 258 -#define PARS_STR_LIT 259 -#define PARS_NULL_LIT 260 -#define PARS_ID_TOKEN 261 -#define PARS_AND_TOKEN 262 -#define PARS_OR_TOKEN 263 -#define PARS_NOT_TOKEN 264 -#define PARS_GE_TOKEN 265 -#define PARS_LE_TOKEN 266 -#define PARS_NE_TOKEN 267 -#define PARS_PROCEDURE_TOKEN 268 -#define PARS_IN_TOKEN 269 -#define PARS_OUT_TOKEN 270 -#define PARS_INT_TOKEN 271 -#define PARS_INTEGER_TOKEN 272 -#define PARS_FLOAT_TOKEN 273 -#define PARS_CHAR_TOKEN 274 -#define PARS_IS_TOKEN 275 -#define PARS_BEGIN_TOKEN 276 -#define PARS_END_TOKEN 277 -#define PARS_IF_TOKEN 278 -#define PARS_THEN_TOKEN 279 -#define PARS_ELSE_TOKEN 280 -#define PARS_ELSIF_TOKEN 281 -#define PARS_LOOP_TOKEN 282 -#define PARS_WHILE_TOKEN 283 -#define PARS_RETURN_TOKEN 284 -#define PARS_SELECT_TOKEN 285 -#define PARS_SUM_TOKEN 286 -#define PARS_COUNT_TOKEN 287 -#define PARS_DISTINCT_TOKEN 288 -#define PARS_FROM_TOKEN 289 -#define PARS_WHERE_TOKEN 290 -#define PARS_FOR_TOKEN 291 -#define PARS_DDOT_TOKEN 292 -#define PARS_CONSISTENT_TOKEN 293 -#define PARS_READ_TOKEN 294 -#define PARS_ORDER_TOKEN 295 -#define PARS_BY_TOKEN 296 -#define PARS_ASC_TOKEN 297 -#define PARS_DESC_TOKEN 298 -#define PARS_INSERT_TOKEN 299 -#define PARS_INTO_TOKEN 300 -#define PARS_VALUES_TOKEN 301 -#define PARS_UPDATE_TOKEN 302 -#define PARS_SET_TOKEN 303 -#define PARS_DELETE_TOKEN 304 -#define PARS_CURRENT_TOKEN 305 -#define PARS_OF_TOKEN 306 -#define PARS_CREATE_TOKEN 307 -#define PARS_TABLE_TOKEN 308 -#define PARS_INDEX_TOKEN 309 -#define PARS_UNIQUE_TOKEN 310 -#define PARS_CLUSTERED_TOKEN 311 -#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 312 -#define PARS_ON_TOKEN 313 -#define PARS_ASSIGN_TOKEN 314 -#define PARS_DECLARE_TOKEN 315 -#define PARS_CURSOR_TOKEN 316 -#define PARS_SQL_TOKEN 317 -#define PARS_OPEN_TOKEN 318 -#define PARS_FETCH_TOKEN 319 -#define PARS_CLOSE_TOKEN 320 -#define PARS_NOTFOUND_TOKEN 321 -#define PARS_TO_CHAR_TOKEN 322 -#define PARS_TO_NUMBER_TOKEN 323 -#define PARS_TO_BINARY_TOKEN 324 -#define PARS_BINARY_TO_NUMBER_TOKEN 325 -#define PARS_SUBSTR_TOKEN 326 -#define PARS_REPLSTR_TOKEN 327 -#define PARS_CONCAT_TOKEN 328 -#define PARS_INSTR_TOKEN 329 -#define PARS_LENGTH_TOKEN 330 -#define PARS_SYSDATE_TOKEN 331 -#define PARS_PRINTF_TOKEN 332 -#define PARS_ASSERT_TOKEN 333 -#define PARS_RND_TOKEN 334 -#define PARS_RND_STR_TOKEN 335 -#define PARS_ROW_PRINTF_TOKEN 336 -#define PARS_COMMIT_TOKEN 337 -#define PARS_ROLLBACK_TOKEN 338 -#define PARS_WORK_TOKEN 339 -#define NEG 340 +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + PARS_INT_LIT = 258, + PARS_FLOAT_LIT = 259, + PARS_STR_LIT = 260, + PARS_NULL_LIT = 261, + PARS_ID_TOKEN = 262, + PARS_AND_TOKEN = 263, + PARS_OR_TOKEN = 264, + PARS_NOT_TOKEN = 265, + PARS_GE_TOKEN = 266, + PARS_LE_TOKEN = 267, + PARS_NE_TOKEN = 268, + PARS_PROCEDURE_TOKEN = 269, + PARS_IN_TOKEN = 270, + PARS_OUT_TOKEN = 271, + PARS_BINARY_TOKEN = 272, + PARS_BLOB_TOKEN = 273, + PARS_INT_TOKEN = 274, + PARS_INTEGER_TOKEN = 275, + PARS_FLOAT_TOKEN = 276, + PARS_CHAR_TOKEN = 277, + PARS_IS_TOKEN = 278, + PARS_BEGIN_TOKEN = 279, + PARS_END_TOKEN = 280, + PARS_IF_TOKEN = 281, + PARS_THEN_TOKEN = 282, + PARS_ELSE_TOKEN = 283, + PARS_ELSIF_TOKEN = 284, + PARS_LOOP_TOKEN = 285, + PARS_WHILE_TOKEN = 286, + PARS_RETURN_TOKEN = 287, + PARS_SELECT_TOKEN = 288, + PARS_SUM_TOKEN = 289, + PARS_COUNT_TOKEN = 290, + PARS_DISTINCT_TOKEN = 291, + PARS_FROM_TOKEN = 292, + PARS_WHERE_TOKEN = 293, + PARS_FOR_TOKEN = 294, + PARS_DDOT_TOKEN = 295, + PARS_CONSISTENT_TOKEN = 296, + PARS_READ_TOKEN = 297, + PARS_ORDER_TOKEN = 298, + PARS_BY_TOKEN = 299, + PARS_ASC_TOKEN = 300, + PARS_DESC_TOKEN = 301, + PARS_INSERT_TOKEN = 302, + PARS_INTO_TOKEN = 303, + PARS_VALUES_TOKEN = 304, + PARS_UPDATE_TOKEN = 305, + PARS_SET_TOKEN = 306, + PARS_DELETE_TOKEN = 307, + PARS_CURRENT_TOKEN = 308, + PARS_OF_TOKEN = 309, + PARS_CREATE_TOKEN = 310, + PARS_TABLE_TOKEN = 311, + PARS_INDEX_TOKEN = 312, + PARS_UNIQUE_TOKEN = 313, + PARS_CLUSTERED_TOKEN = 314, + PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 315, + PARS_ON_TOKEN = 316, + PARS_ASSIGN_TOKEN = 317, + PARS_DECLARE_TOKEN = 318, + PARS_CURSOR_TOKEN = 319, + PARS_SQL_TOKEN = 320, + PARS_OPEN_TOKEN = 321, + PARS_FETCH_TOKEN = 322, + PARS_CLOSE_TOKEN = 323, + PARS_NOTFOUND_TOKEN = 324, + PARS_TO_CHAR_TOKEN = 325, + PARS_TO_NUMBER_TOKEN = 326, + PARS_TO_BINARY_TOKEN = 327, + PARS_BINARY_TO_NUMBER_TOKEN = 328, + PARS_SUBSTR_TOKEN = 329, + PARS_REPLSTR_TOKEN = 330, + PARS_CONCAT_TOKEN = 331, + PARS_INSTR_TOKEN = 332, + PARS_LENGTH_TOKEN = 333, + PARS_SYSDATE_TOKEN = 334, + PARS_PRINTF_TOKEN = 335, + PARS_ASSERT_TOKEN = 336, + PARS_RND_TOKEN = 337, + PARS_RND_STR_TOKEN = 338, + PARS_ROW_PRINTF_TOKEN = 339, + PARS_COMMIT_TOKEN = 340, + PARS_ROLLBACK_TOKEN = 341, + PARS_WORK_TOKEN = 342, + NEG = 343 + }; +#endif +#define PARS_INT_LIT 258 +#define PARS_FLOAT_LIT 259 +#define PARS_STR_LIT 260 +#define PARS_NULL_LIT 261 +#define PARS_ID_TOKEN 262 +#define PARS_AND_TOKEN 263 +#define PARS_OR_TOKEN 264 +#define PARS_NOT_TOKEN 265 +#define PARS_GE_TOKEN 266 +#define PARS_LE_TOKEN 267 +#define PARS_NE_TOKEN 268 +#define PARS_PROCEDURE_TOKEN 269 +#define PARS_IN_TOKEN 270 +#define PARS_OUT_TOKEN 271 +#define PARS_BINARY_TOKEN 272 +#define PARS_BLOB_TOKEN 273 +#define PARS_INT_TOKEN 274 +#define PARS_INTEGER_TOKEN 275 +#define PARS_FLOAT_TOKEN 276 +#define PARS_CHAR_TOKEN 277 +#define PARS_IS_TOKEN 278 +#define PARS_BEGIN_TOKEN 279 +#define PARS_END_TOKEN 280 +#define PARS_IF_TOKEN 281 +#define PARS_THEN_TOKEN 282 +#define PARS_ELSE_TOKEN 283 +#define PARS_ELSIF_TOKEN 284 +#define PARS_LOOP_TOKEN 285 +#define PARS_WHILE_TOKEN 286 +#define PARS_RETURN_TOKEN 287 +#define PARS_SELECT_TOKEN 288 +#define PARS_SUM_TOKEN 289 +#define PARS_COUNT_TOKEN 290 +#define PARS_DISTINCT_TOKEN 291 +#define PARS_FROM_TOKEN 292 +#define PARS_WHERE_TOKEN 293 +#define PARS_FOR_TOKEN 294 +#define PARS_DDOT_TOKEN 295 +#define PARS_CONSISTENT_TOKEN 296 +#define PARS_READ_TOKEN 297 +#define PARS_ORDER_TOKEN 298 +#define PARS_BY_TOKEN 299 +#define PARS_ASC_TOKEN 300 +#define PARS_DESC_TOKEN 301 +#define PARS_INSERT_TOKEN 302 +#define PARS_INTO_TOKEN 303 +#define PARS_VALUES_TOKEN 304 +#define PARS_UPDATE_TOKEN 305 +#define PARS_SET_TOKEN 306 +#define PARS_DELETE_TOKEN 307 +#define PARS_CURRENT_TOKEN 308 +#define PARS_OF_TOKEN 309 +#define PARS_CREATE_TOKEN 310 +#define PARS_TABLE_TOKEN 311 +#define PARS_INDEX_TOKEN 312 +#define PARS_UNIQUE_TOKEN 313 +#define PARS_CLUSTERED_TOKEN 314 +#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 315 +#define PARS_ON_TOKEN 316 +#define PARS_ASSIGN_TOKEN 317 +#define PARS_DECLARE_TOKEN 318 +#define PARS_CURSOR_TOKEN 319 +#define PARS_SQL_TOKEN 320 +#define PARS_OPEN_TOKEN 321 +#define PARS_FETCH_TOKEN 322 +#define PARS_CLOSE_TOKEN 323 +#define PARS_NOTFOUND_TOKEN 324 +#define PARS_TO_CHAR_TOKEN 325 +#define PARS_TO_NUMBER_TOKEN 326 +#define PARS_TO_BINARY_TOKEN 327 +#define PARS_BINARY_TO_NUMBER_TOKEN 328 +#define PARS_SUBSTR_TOKEN 329 +#define PARS_REPLSTR_TOKEN 330 +#define PARS_CONCAT_TOKEN 331 +#define PARS_INSTR_TOKEN 332 +#define PARS_LENGTH_TOKEN 333 +#define PARS_SYSDATE_TOKEN 334 +#define PARS_PRINTF_TOKEN 335 +#define PARS_ASSERT_TOKEN 336 +#define PARS_RND_TOKEN 337 +#define PARS_RND_STR_TOKEN 338 +#define PARS_ROW_PRINTF_TOKEN 339 +#define PARS_COMMIT_TOKEN 340 +#define PARS_ROLLBACK_TOKEN 341 +#define PARS_WORK_TOKEN 342 +#define NEG 343 + + + + +/* Copy the first part of user declarations. */ #line 13 "pars0grm.y" /* The value of the semantic attribute is a pointer to a query tree node @@ -108,767 +251,1136 @@ que_node_t */ int yylex(void); -#ifndef YYSTYPE -#define YYSTYPE int + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 #endif -#include <stdio.h> -#ifndef __cplusplus -#ifndef __STDC__ -#define const +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 #endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +typedef int YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 #endif -#define YYFINAL 311 -#define YYFLAG -32768 -#define YYNTBASE 102 - -#define YYTRANSLATE(x) ((unsigned)(x) <= 340 ? yytranslate[x] : 163) - -static const char yytranslate[] = { 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 94, 2, 2, 96, - 97, 91, 90, 99, 89, 2, 92, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 95, 87, - 86, 88, 98, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 100, 2, 101, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 93 -}; +/* Copy the second part of user declarations. */ -#if YYDEBUG != 0 -static const short yyprhs[] = { 0, - 0, 3, 5, 8, 11, 14, 17, 20, 23, 26, - 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, - 59, 62, 65, 67, 70, 72, 77, 79, 81, 83, - 85, 87, 91, 95, 99, 103, 106, 110, 114, 118, - 122, 126, 130, 134, 138, 142, 145, 149, 153, 155, - 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, - 176, 178, 182, 189, 194, 196, 198, 200, 202, 206, - 207, 209, 213, 214, 216, 220, 222, 227, 233, 238, - 239, 241, 245, 247, 251, 253, 254, 257, 258, 261, - 262, 265, 266, 268, 270, 271, 276, 285, 289, 295, - 298, 302, 304, 308, 313, 318, 321, 324, 328, 331, - 334, 337, 341, 346, 348, 351, 352, 355, 357, 365, - 372, 383, 385, 388, 391, 396, 399, 401, 405, 406, - 408, 416, 418, 422, 423, 425, 426, 428, 439, 442, - 445, 447, 449, 453, 457, 458, 460, 464, 468, 469, - 471, 474, 481, 482, 484, 487 -}; -static const short yyrhs[] = { 162, - 95, 0, 107, 0, 108, 95, 0, 139, 95, 0, - 140, 95, 0, 138, 95, 0, 141, 95, 0, 134, - 95, 0, 121, 95, 0, 123, 95, 0, 133, 95, - 0, 131, 95, 0, 132, 95, 0, 128, 95, 0, - 129, 95, 0, 142, 95, 0, 144, 95, 0, 143, - 95, 0, 153, 95, 0, 154, 95, 0, 148, 95, - 0, 152, 95, 0, 102, 0, 103, 102, 0, 7, - 0, 105, 96, 112, 97, 0, 3, 0, 4, 0, - 5, 0, 6, 0, 63, 0, 104, 90, 104, 0, - 104, 89, 104, 0, 104, 91, 104, 0, 104, 92, - 104, 0, 89, 104, 0, 96, 104, 97, 0, 104, - 86, 104, 0, 104, 87, 104, 0, 104, 88, 104, - 0, 104, 11, 104, 0, 104, 12, 104, 0, 104, - 13, 104, 0, 104, 8, 104, 0, 104, 9, 104, - 0, 10, 104, 0, 7, 94, 67, 0, 63, 94, - 67, 0, 68, 0, 69, 0, 70, 0, 71, 0, - 72, 0, 74, 0, 75, 0, 76, 0, 77, 0, - 80, 0, 81, 0, 0, 98, 0, 106, 99, 98, - 0, 100, 7, 96, 106, 97, 101, 0, 109, 96, - 112, 97, 0, 73, 0, 78, 0, 79, 0, 7, - 0, 110, 99, 7, 0, 0, 7, 0, 111, 99, - 7, 0, 0, 104, 0, 112, 99, 104, 0, 104, - 0, 33, 96, 91, 97, 0, 33, 96, 34, 7, - 97, 0, 32, 96, 104, 97, 0, 0, 113, 0, - 114, 99, 113, 0, 91, 0, 114, 46, 111, 0, - 114, 0, 0, 36, 104, 0, 0, 37, 48, 0, - 0, 39, 40, 0, 0, 43, 0, 44, 0, 0, - 41, 42, 7, 119, 0, 31, 115, 35, 110, 116, - 117, 118, 120, 0, 45, 46, 7, 0, 122, 47, - 96, 112, 97, 0, 122, 121, 0, 7, 86, 104, - 0, 124, 0, 125, 99, 124, 0, 36, 51, 52, - 7, 0, 48, 7, 49, 125, 0, 127, 116, 0, - 127, 126, 0, 50, 35, 7, 0, 130, 116, 0, - 130, 126, 0, 82, 121, 0, 7, 60, 104, 0, - 27, 104, 25, 103, 0, 135, 0, 136, 135, 0, - 0, 26, 103, 0, 136, 0, 24, 104, 25, 103, - 137, 23, 24, 0, 29, 104, 28, 103, 23, 28, - 0, 37, 7, 15, 104, 38, 104, 28, 103, 23, - 28, 0, 30, 0, 64, 7, 0, 66, 7, 0, - 65, 7, 46, 111, 0, 7, 155, 0, 145, 0, - 146, 99, 145, 0, 0, 58, 0, 53, 54, 7, - 96, 146, 97, 147, 0, 7, 0, 149, 99, 7, - 0, 0, 56, 0, 0, 57, 0, 53, 150, 151, - 55, 7, 59, 7, 96, 149, 97, 0, 83, 85, - 0, 84, 85, 0, 17, 0, 20, 0, 7, 15, - 155, 0, 7, 16, 155, 0, 0, 156, 0, 157, - 99, 156, 0, 7, 155, 95, 0, 0, 158, 0, - 159, 158, 0, 61, 62, 7, 21, 121, 95, 0, - 0, 160, 0, 161, 160, 0, 14, 7, 96, 157, - 97, 21, 159, 161, 22, 103, 23, 0 -}; +/* Line 214 of yacc.c. */ +#line 283 "pars0grm.tab.c" -#endif +#if ! defined (yyoverflow) || YYERROR_VERBOSE -#if YYDEBUG != 0 -static const short yyrline[] = { 0, - 129, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 154, 156, 160, 162, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 186, 190, 192, - 193, 194, 196, 197, 198, 199, 200, 201, 202, 205, - 207, 208, 211, 216, 221, 223, 224, 227, 229, 233, - 235, 236, 240, 242, 243, 246, 248, 253, 259, 265, - 267, 268, 272, 275, 277, 280, 282, 285, 287, 291, - 293, 297, 299, 300, 303, 305, 309, 319, 324, 327, - 331, 335, 337, 341, 347, 354, 359, 364, 370, 375, - 380, 385, 390, 396, 398, 402, 404, 406, 409, 416, - 422, 430, 434, 440, 446, 451, 455, 457, 461, 463, - 468, 474, 476, 480, 482, 485, 487, 490, 498, 503, - 508, 510, 513, 517, 522, 524, 525, 529, 534, 536, - 537, 540, 546, 548, 549, 552 -}; -#endif +# ifndef YYFREE +# define YYFREE free +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# endif +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# endif +# else +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short int yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined (__GNUC__) && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) -#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) - -static const char * const yytname[] = { "$","error","$undefined.","PARS_INT_LIT", -"PARS_FLOAT_LIT","PARS_STR_LIT","PARS_NULL_LIT","PARS_ID_TOKEN","PARS_AND_TOKEN", -"PARS_OR_TOKEN","PARS_NOT_TOKEN","PARS_GE_TOKEN","PARS_LE_TOKEN","PARS_NE_TOKEN", -"PARS_PROCEDURE_TOKEN","PARS_IN_TOKEN","PARS_OUT_TOKEN","PARS_INT_TOKEN","PARS_INTEGER_TOKEN", -"PARS_FLOAT_TOKEN","PARS_CHAR_TOKEN","PARS_IS_TOKEN","PARS_BEGIN_TOKEN","PARS_END_TOKEN", -"PARS_IF_TOKEN","PARS_THEN_TOKEN","PARS_ELSE_TOKEN","PARS_ELSIF_TOKEN","PARS_LOOP_TOKEN", -"PARS_WHILE_TOKEN","PARS_RETURN_TOKEN","PARS_SELECT_TOKEN","PARS_SUM_TOKEN", -"PARS_COUNT_TOKEN","PARS_DISTINCT_TOKEN","PARS_FROM_TOKEN","PARS_WHERE_TOKEN", -"PARS_FOR_TOKEN","PARS_DDOT_TOKEN","PARS_CONSISTENT_TOKEN","PARS_READ_TOKEN", -"PARS_ORDER_TOKEN","PARS_BY_TOKEN","PARS_ASC_TOKEN","PARS_DESC_TOKEN","PARS_INSERT_TOKEN", -"PARS_INTO_TOKEN","PARS_VALUES_TOKEN","PARS_UPDATE_TOKEN","PARS_SET_TOKEN","PARS_DELETE_TOKEN", -"PARS_CURRENT_TOKEN","PARS_OF_TOKEN","PARS_CREATE_TOKEN","PARS_TABLE_TOKEN", -"PARS_INDEX_TOKEN","PARS_UNIQUE_TOKEN","PARS_CLUSTERED_TOKEN","PARS_DOES_NOT_FIT_IN_MEM_TOKEN", -"PARS_ON_TOKEN","PARS_ASSIGN_TOKEN","PARS_DECLARE_TOKEN","PARS_CURSOR_TOKEN", -"PARS_SQL_TOKEN","PARS_OPEN_TOKEN","PARS_FETCH_TOKEN","PARS_CLOSE_TOKEN","PARS_NOTFOUND_TOKEN", -"PARS_TO_CHAR_TOKEN","PARS_TO_NUMBER_TOKEN","PARS_TO_BINARY_TOKEN","PARS_BINARY_TO_NUMBER_TOKEN", -"PARS_SUBSTR_TOKEN","PARS_REPLSTR_TOKEN","PARS_CONCAT_TOKEN","PARS_INSTR_TOKEN", -"PARS_LENGTH_TOKEN","PARS_SYSDATE_TOKEN","PARS_PRINTF_TOKEN","PARS_ASSERT_TOKEN", -"PARS_RND_TOKEN","PARS_RND_STR_TOKEN","PARS_ROW_PRINTF_TOKEN","PARS_COMMIT_TOKEN", -"PARS_ROLLBACK_TOKEN","PARS_WORK_TOKEN","'='","'<'","'>'","'-'","'+'","'*'", -"'/'","NEG","'%'","';'","'('","')'","'?'","','","'{'","'}'","statement","statement_list", -"exp","function_name","question_mark_list","stored_procedure_call","predefined_procedure_call", -"predefined_procedure_name","table_list","variable_list","exp_list","select_item", -"select_item_list","select_list","search_condition","for_update_clause","consistent_read_clause", -"order_direction","order_by_clause","select_statement","insert_statement_start", -"insert_statement","column_assignment","column_assignment_list","cursor_positioned", -"update_statement_start","update_statement_searched","update_statement_positioned", -"delete_statement_start","delete_statement_searched","delete_statement_positioned", -"row_printf_statement","assignment_statement","elsif_element","elsif_list","else_part", -"if_statement","while_statement","for_statement","return_statement","open_cursor_statement", -"close_cursor_statement","fetch_statement","column_def","column_def_list","not_fit_in_memory", -"create_table","column_list","unique_def","clustered_def","create_index","commit_statement", -"rollback_statement","type_name","parameter_declaration","parameter_declaration_list", -"variable_declaration","variable_declaration_list","cursor_declaration","declaration_list", -"procedure_definition", NULL -}; #endif -static const short yyr1[] = { 0, - 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 103, 103, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, - 105, 105, 105, 105, 105, 105, 105, 105, 105, 106, - 106, 106, 107, 108, 109, 109, 109, 110, 110, 111, - 111, 111, 112, 112, 112, 113, 113, 113, 113, 114, - 114, 114, 115, 115, 115, 116, 116, 117, 117, 118, - 118, 119, 119, 119, 120, 120, 121, 122, 123, 123, - 124, 125, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 136, 137, 137, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 146, 147, 147, - 148, 149, 149, 150, 150, 151, 151, 152, 153, 154, - 155, 155, 156, 156, 157, 157, 157, 158, 159, 159, - 159, 160, 161, 161, 161, 162 +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short int yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 95 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 734 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 104 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 64 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 164 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 321 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 343 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 96, 2, 2, + 98, 99, 93, 92, 101, 91, 2, 94, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 97, + 89, 88, 90, 100, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 102, 2, 103, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 95 }; -static const short yyr2[] = { 0, - 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 1, 2, 1, 4, 1, 1, 1, 1, - 1, 3, 3, 3, 3, 2, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 2, 3, 3, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 3, 6, 4, 1, 1, 1, 1, 3, 0, - 1, 3, 0, 1, 3, 1, 4, 5, 4, 0, - 1, 3, 1, 3, 1, 0, 2, 0, 2, 0, - 2, 0, 1, 1, 0, 4, 8, 3, 5, 2, - 3, 1, 3, 4, 4, 2, 2, 3, 2, 2, - 2, 3, 4, 1, 2, 0, 2, 1, 7, 6, - 10, 1, 2, 2, 4, 2, 1, 3, 0, 1, - 7, 1, 3, 0, 1, 0, 1, 10, 2, 2, - 1, 1, 3, 3, 0, 1, 3, 3, 0, 1, - 2, 6, 0, 1, 2, 11 +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned short int yyprhs[] = +{ + 0, 0, 3, 6, 8, 11, 14, 17, 20, 23, + 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, + 56, 59, 62, 65, 68, 70, 73, 75, 80, 82, + 84, 86, 88, 90, 94, 98, 102, 106, 109, 113, + 117, 121, 125, 129, 133, 137, 141, 145, 148, 152, + 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, + 176, 178, 179, 181, 185, 192, 197, 199, 201, 203, + 205, 209, 210, 212, 216, 217, 219, 223, 225, 230, + 236, 241, 242, 244, 248, 250, 254, 256, 257, 260, + 261, 264, 265, 268, 269, 271, 273, 274, 279, 288, + 292, 298, 301, 305, 307, 311, 316, 321, 324, 327, + 331, 334, 337, 340, 344, 349, 351, 354, 355, 358, + 360, 368, 375, 386, 388, 391, 394, 399, 404, 406, + 410, 411, 415, 416, 419, 420, 422, 430, 432, 436, + 437, 439, 440, 442, 453, 456, 459, 461, 463, 465, + 467, 469, 473, 477, 478, 480, 484, 488, 489, 491, + 494, 501, 502, 504, 507 }; -static const short yydefact[] = { 0, - 0, 0, 0, 0, 122, 80, 0, 0, 0, 0, - 134, 0, 0, 0, 65, 66, 67, 0, 0, 0, - 0, 2, 0, 0, 0, 0, 0, 86, 0, 0, - 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, - 28, 29, 30, 25, 0, 31, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 0, 0, 0, - 0, 0, 0, 0, 83, 76, 81, 85, 0, 0, - 0, 0, 0, 0, 135, 136, 123, 0, 124, 111, - 139, 140, 0, 3, 73, 9, 0, 100, 10, 0, - 106, 107, 14, 15, 109, 110, 12, 13, 11, 8, - 6, 4, 5, 7, 16, 18, 17, 21, 22, 19, - 20, 1, 112, 145, 0, 46, 0, 36, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 73, 0, 0, 0, 70, 0, 0, 0, - 98, 0, 108, 0, 137, 0, 70, 60, 74, 0, - 73, 0, 87, 0, 146, 0, 47, 48, 37, 44, - 45, 41, 42, 43, 23, 116, 38, 39, 40, 33, - 32, 34, 35, 0, 0, 0, 0, 0, 71, 84, - 82, 68, 86, 0, 0, 102, 105, 0, 0, 125, - 61, 0, 64, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 24, 114, 118, 0, 26, 0, 79, 0, - 77, 0, 0, 0, 88, 0, 0, 0, 0, 127, - 0, 0, 0, 0, 75, 99, 104, 141, 142, 143, - 144, 149, 147, 117, 0, 115, 0, 120, 78, 72, - 69, 0, 90, 0, 101, 103, 126, 129, 0, 0, - 63, 62, 0, 150, 153, 0, 119, 89, 0, 95, - 0, 130, 131, 128, 0, 0, 0, 151, 154, 0, - 113, 91, 0, 97, 0, 0, 148, 0, 0, 155, - 0, 0, 132, 0, 0, 0, 92, 121, 138, 0, - 0, 156, 93, 94, 96, 133, 0, 152, 0, 0, - 0 +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const short int yyrhs[] = +{ + 105, 0, -1, 167, 97, -1, 110, -1, 111, 97, + -1, 142, 97, -1, 143, 97, -1, 141, 97, -1, + 144, 97, -1, 137, 97, -1, 124, 97, -1, 126, + 97, -1, 136, 97, -1, 134, 97, -1, 135, 97, + -1, 131, 97, -1, 132, 97, -1, 145, 97, -1, + 147, 97, -1, 146, 97, -1, 158, 97, -1, 159, + 97, -1, 153, 97, -1, 157, 97, -1, 105, -1, + 106, 105, -1, 7, -1, 108, 98, 115, 99, -1, + 3, -1, 4, -1, 5, -1, 6, -1, 65, -1, + 107, 92, 107, -1, 107, 91, 107, -1, 107, 93, + 107, -1, 107, 94, 107, -1, 91, 107, -1, 98, + 107, 99, -1, 107, 88, 107, -1, 107, 89, 107, + -1, 107, 90, 107, -1, 107, 11, 107, -1, 107, + 12, 107, -1, 107, 13, 107, -1, 107, 8, 107, + -1, 107, 9, 107, -1, 10, 107, -1, 7, 96, + 69, -1, 65, 96, 69, -1, 70, -1, 71, -1, + 72, -1, 73, -1, 74, -1, 76, -1, 77, -1, + 78, -1, 79, -1, 82, -1, 83, -1, -1, 100, + -1, 109, 101, 100, -1, 102, 7, 98, 109, 99, + 103, -1, 112, 98, 115, 99, -1, 75, -1, 80, + -1, 81, -1, 7, -1, 113, 101, 7, -1, -1, + 7, -1, 114, 101, 7, -1, -1, 107, -1, 115, + 101, 107, -1, 107, -1, 35, 98, 93, 99, -1, + 35, 98, 36, 7, 99, -1, 34, 98, 107, 99, + -1, -1, 116, -1, 117, 101, 116, -1, 93, -1, + 117, 48, 114, -1, 117, -1, -1, 38, 107, -1, + -1, 39, 50, -1, -1, 41, 42, -1, -1, 45, + -1, 46, -1, -1, 43, 44, 7, 122, -1, 33, + 118, 37, 113, 119, 120, 121, 123, -1, 47, 48, + 7, -1, 125, 49, 98, 115, 99, -1, 125, 124, + -1, 7, 88, 107, -1, 127, -1, 128, 101, 127, + -1, 38, 53, 54, 7, -1, 50, 7, 51, 128, + -1, 130, 119, -1, 130, 129, -1, 52, 37, 7, + -1, 133, 119, -1, 133, 129, -1, 84, 124, -1, + 7, 62, 107, -1, 29, 107, 27, 106, -1, 138, + -1, 139, 138, -1, -1, 28, 106, -1, 139, -1, + 26, 107, 27, 106, 140, 25, 26, -1, 31, 107, + 30, 106, 25, 30, -1, 39, 7, 15, 107, 40, + 107, 30, 106, 25, 30, -1, 32, -1, 66, 7, + -1, 68, 7, -1, 67, 7, 48, 114, -1, 7, + 160, 150, 151, -1, 148, -1, 149, 101, 148, -1, + -1, 98, 3, 99, -1, -1, 10, 6, -1, -1, + 60, -1, 55, 56, 7, 98, 149, 99, 152, -1, + 7, -1, 154, 101, 7, -1, -1, 58, -1, -1, + 59, -1, 55, 155, 156, 57, 7, 61, 7, 98, + 154, 99, -1, 85, 87, -1, 86, 87, -1, 19, + -1, 20, -1, 22, -1, 17, -1, 18, -1, 7, + 15, 160, -1, 7, 16, 160, -1, -1, 161, -1, + 162, 101, 161, -1, 7, 160, 97, -1, -1, 163, + -1, 164, 163, -1, 63, 64, 7, 23, 124, 97, + -1, -1, 165, -1, 166, 165, -1, 14, 7, 98, + 162, 99, 23, 164, 166, 24, 106, 25, -1 }; -static const short yydefgoto[] = { 175, - 176, 159, 71, 202, 22, 23, 24, 193, 190, 160, - 77, 78, 79, 101, 253, 270, 305, 284, 25, 26, - 27, 196, 197, 102, 28, 29, 30, 31, 32, 33, - 34, 35, 214, 215, 216, 36, 37, 38, 39, 40, - 41, 42, 230, 231, 273, 43, 294, 86, 156, 44, - 45, 46, 240, 165, 166, 264, 265, 279, 280, 47 +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short int yyrline[] = +{ + 0, 131, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, 152, 156, 157, 162, 163, 165, 166, + 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 187, + 192, 193, 194, 195, 197, 198, 199, 200, 201, 202, + 203, 206, 208, 209, 213, 218, 223, 224, 225, 229, + 230, 235, 236, 237, 242, 243, 244, 248, 249, 254, + 260, 267, 268, 269, 274, 276, 278, 282, 283, 287, + 288, 293, 294, 299, 300, 301, 305, 306, 311, 321, + 326, 328, 333, 337, 338, 343, 349, 356, 361, 366, + 372, 377, 382, 387, 392, 398, 399, 404, 405, 407, + 411, 418, 424, 432, 436, 442, 448, 453, 458, 459, + 464, 465, 470, 471, 477, 478, 484, 490, 491, 496, + 497, 501, 502, 506, 514, 519, 524, 525, 526, 527, + 528, 532, 535, 541, 542, 543, 548, 552, 554, 555, + 559, 564, 566, 567, 571 }; +#endif -static const short yypact[] = { 443, - -36, 39, 479, 479,-32768, 7, 45, 10, 54, 28, - -28, 57, 59, 66,-32768,-32768,-32768, 49, 12, 15, - 88,-32768, 16, 6, 21, 3, 22, 84, 26, 27, - 84, 29, 30, 31, 33, 47, 48, 51, 53, 56, - 58, 60, 62, 64, 65, 67, 68, 479, 71,-32768, --32768,-32768,-32768, 70, 479, 75,-32768,-32768,-32768,-32768, --32768,-32768,-32768,-32768,-32768,-32768,-32768, 479, 479, 293, - 74, 502, 76, 77,-32768, 356,-32768, -25, 117, 108, - 147, 107, 154, 164,-32768, 122,-32768, 128,-32768,-32768, --32768,-32768, 87,-32768, 479,-32768, 90,-32768,-32768, 38, --32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, --32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, --32768,-32768, 356, 177, 120, 550, 131, 176, 234, 479, - 479, 479, 479, 479, 443, 479, 479, 479, 479, 479, - 479, 479, 479, 443, 479, -26, 188, 187, 193, 479, --32768, 195,-32768, 109,-32768, 152, 188, 110, 356, -70, - 479, 157, 356, 20,-32768, -67,-32768,-32768,-32768, 550, - 550, 2, 2, 356,-32768, 151, 2, 2, 2, -6, - -6, 176, 176, -66, 263, 490, 199, 113,-32768, 114, --32768,-32768, -30, 520, 126,-32768, 115, 211, 214, 114, --32768, -48,-32768, 479, -44, 216, 5, 5, 206, 177, - 443, 479,-32768,-32768, 201, 208,-32768, 204,-32768, 139, --32768, 230, 479, 231, 202, 479, 479, 195, 5,-32768, - -40, 181, 140, 150, 356,-32768,-32768,-32768,-32768,-32768, --32768, 242,-32768, 443, 527,-32768, 228,-32768,-32768,-32768, --32768, 205, 215, 558, 356,-32768,-32768, 207, 211, 253, --32768,-32768, 5,-32768, 11, 443,-32768,-32768, 226, 232, - 443,-32768,-32768,-32768, 173, 179, 209,-32768,-32768, -3, - 443,-32768, 233,-32768, 325, 265,-32768, 271, 443,-32768, - 272, 252,-32768, -37, 261, 387, 61,-32768,-32768, 281, - 49,-32768,-32768,-32768,-32768,-32768, 194,-32768, 290, 291, --32768 +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "PARS_INT_LIT", "PARS_FLOAT_LIT", + "PARS_STR_LIT", "PARS_NULL_LIT", "PARS_ID_TOKEN", "PARS_AND_TOKEN", + "PARS_OR_TOKEN", "PARS_NOT_TOKEN", "PARS_GE_TOKEN", "PARS_LE_TOKEN", + "PARS_NE_TOKEN", "PARS_PROCEDURE_TOKEN", "PARS_IN_TOKEN", + "PARS_OUT_TOKEN", "PARS_BINARY_TOKEN", "PARS_BLOB_TOKEN", + "PARS_INT_TOKEN", "PARS_INTEGER_TOKEN", "PARS_FLOAT_TOKEN", + "PARS_CHAR_TOKEN", "PARS_IS_TOKEN", "PARS_BEGIN_TOKEN", "PARS_END_TOKEN", + "PARS_IF_TOKEN", "PARS_THEN_TOKEN", "PARS_ELSE_TOKEN", + "PARS_ELSIF_TOKEN", "PARS_LOOP_TOKEN", "PARS_WHILE_TOKEN", + "PARS_RETURN_TOKEN", "PARS_SELECT_TOKEN", "PARS_SUM_TOKEN", + "PARS_COUNT_TOKEN", "PARS_DISTINCT_TOKEN", "PARS_FROM_TOKEN", + "PARS_WHERE_TOKEN", "PARS_FOR_TOKEN", "PARS_DDOT_TOKEN", + "PARS_CONSISTENT_TOKEN", "PARS_READ_TOKEN", "PARS_ORDER_TOKEN", + "PARS_BY_TOKEN", "PARS_ASC_TOKEN", "PARS_DESC_TOKEN", + "PARS_INSERT_TOKEN", "PARS_INTO_TOKEN", "PARS_VALUES_TOKEN", + "PARS_UPDATE_TOKEN", "PARS_SET_TOKEN", "PARS_DELETE_TOKEN", + "PARS_CURRENT_TOKEN", "PARS_OF_TOKEN", "PARS_CREATE_TOKEN", + "PARS_TABLE_TOKEN", "PARS_INDEX_TOKEN", "PARS_UNIQUE_TOKEN", + "PARS_CLUSTERED_TOKEN", "PARS_DOES_NOT_FIT_IN_MEM_TOKEN", + "PARS_ON_TOKEN", "PARS_ASSIGN_TOKEN", "PARS_DECLARE_TOKEN", + "PARS_CURSOR_TOKEN", "PARS_SQL_TOKEN", "PARS_OPEN_TOKEN", + "PARS_FETCH_TOKEN", "PARS_CLOSE_TOKEN", "PARS_NOTFOUND_TOKEN", + "PARS_TO_CHAR_TOKEN", "PARS_TO_NUMBER_TOKEN", "PARS_TO_BINARY_TOKEN", + "PARS_BINARY_TO_NUMBER_TOKEN", "PARS_SUBSTR_TOKEN", "PARS_REPLSTR_TOKEN", + "PARS_CONCAT_TOKEN", "PARS_INSTR_TOKEN", "PARS_LENGTH_TOKEN", + "PARS_SYSDATE_TOKEN", "PARS_PRINTF_TOKEN", "PARS_ASSERT_TOKEN", + "PARS_RND_TOKEN", "PARS_RND_STR_TOKEN", "PARS_ROW_PRINTF_TOKEN", + "PARS_COMMIT_TOKEN", "PARS_ROLLBACK_TOKEN", "PARS_WORK_TOKEN", "'='", + "'<'", "'>'", "'-'", "'+'", "'*'", "'/'", "NEG", "'%'", "';'", "'('", + "')'", "'?'", "','", "'{'", "'}'", "$accept", "statement", + "statement_list", "exp", "function_name", "question_mark_list", + "stored_procedure_call", "predefined_procedure_call", + "predefined_procedure_name", "table_list", "variable_list", "exp_list", + "select_item", "select_item_list", "select_list", "search_condition", + "for_update_clause", "consistent_read_clause", "order_direction", + "order_by_clause", "select_statement", "insert_statement_start", + "insert_statement", "column_assignment", "column_assignment_list", + "cursor_positioned", "update_statement_start", + "update_statement_searched", "update_statement_positioned", + "delete_statement_start", "delete_statement_searched", + "delete_statement_positioned", "row_printf_statement", + "assignment_statement", "elsif_element", "elsif_list", "else_part", + "if_statement", "while_statement", "for_statement", "return_statement", + "open_cursor_statement", "close_cursor_statement", "fetch_statement", + "column_def", "column_def_list", "opt_column_len", "opt_not_null", + "not_fit_in_memory", "create_table", "column_list", "unique_def", + "clustered_def", "create_index", "commit_statement", + "rollback_statement", "type_name", "parameter_declaration", + "parameter_declaration_list", "variable_declaration", + "variable_declaration_list", "cursor_declaration", "declaration_list", + "procedure_definition", 0 }; +#endif -static const short yypgoto[] = { 0, - -121, -1,-32768,-32768,-32768,-32768,-32768,-32768, 138, -123, - 149,-32768,-32768, -27,-32768,-32768,-32768,-32768, -17,-32768, --32768, 79,-32768, 267,-32768,-32768,-32768,-32768,-32768,-32768, --32768,-32768, 94,-32768,-32768,-32768,-32768,-32768,-32768,-32768, --32768,-32768, 40,-32768,-32768,-32768,-32768,-32768,-32768,-32768, --32768,-32768, -192, 93,-32768, 50,-32768, 32,-32768,-32768 +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short int yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 341, 342, 61, 60, + 62, 45, 43, 42, 47, 343, 37, 59, 40, 41, + 63, 44, 123, 125 }; +# endif +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 104, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 106, 106, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 109, 109, 109, 110, 111, 112, 112, 112, 113, + 113, 114, 114, 114, 115, 115, 115, 116, 116, 116, + 116, 117, 117, 117, 118, 118, 118, 119, 119, 120, + 120, 121, 121, 122, 122, 122, 123, 123, 124, 125, + 126, 126, 127, 128, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 139, 140, 140, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 149, + 150, 150, 151, 151, 152, 152, 153, 154, 154, 155, + 155, 156, 156, 157, 158, 159, 160, 160, 160, 160, + 160, 161, 161, 162, 162, 162, 163, 164, 164, 164, + 165, 166, 166, 166, 167 +}; -#define YYLAST 650 - - -static const short yytable[] = { 309, - 90, 70, 72, 105, 76, 223, 134, 187, 98, 50, - 51, 52, 53, 54, 134, 241, 55, 263, 289, 184, - 147, 238, 185, 48, 239, 84, 203, 85, 204, 209, - 217, 210, 204, 6, 207, 208, 257, 205, 73, 74, - 50, 51, 52, 53, 54, 49, 123, 55, 233, 97, - 234, 80, 236, 126, 204, 81, 258, 277, 259, 299, - 82, 300, 83, 87, 188, 88, 128, 129, 224, 56, - 276, 277, 89, 148, 57, 58, 59, 60, 61, 6, - 62, 63, 64, 65, 141, 142, 66, 67, 162, 244, - 139, 140, 141, 142, 93, 68, 91, 75, 163, 92, - 56, 95, 69, 303, 304, 57, 58, 59, 60, 61, - 94, 62, 63, 64, 65, 96, 99, 66, 67, 100, - 103, 104, 150, 107, 108, 109, 68, 110, 170, 171, - 172, 173, 174, 69, 177, 178, 179, 180, 181, 182, - 183, 111, 112, 186, 281, 113, 76, 114, 194, 285, - 115, 149, 116, 151, 117, 152, 118, 1, 119, 120, - 153, 121, 122, 125, 2, 225, 124, 296, 127, 143, - 154, 145, 146, 157, 3, 213, 211, 212, 155, 4, - 5, 6, 158, 164, 213, 161, 167, 7, 134, 50, - 51, 52, 53, 54, 189, 8, 55, 168, 9, 192, - 10, 195, 235, 11, 198, 220, 199, 201, 206, 221, - 245, 227, 222, 228, 12, 13, 14, 229, 73, 74, - 232, 163, 237, 15, 254, 255, 242, 212, 16, 17, - 247, 248, 18, 19, 20, 249, 250, 251, 252, 260, - 261, 130, 131, 213, 132, 133, 134, 262, 263, 56, - 21, 267, 268, 269, 57, 58, 59, 60, 61, 275, - 62, 63, 64, 65, 272, 282, 66, 67, 286, 1, - 288, 293, 283, 287, 291, 68, 2, 295, 297, 298, - 213, 301, 69, 307, 213, 218, 3, 306, 308, 310, - 311, 4, 5, 6, 200, 213, 191, 106, 274, 7, - 130, 131, 243, 132, 133, 134, 256, 8, 246, 0, - 9, 290, 10, 0, 278, 11, 0, 135, 0, 136, - 137, 138, 139, 140, 141, 142, 12, 13, 14, 0, - 169, 1, 0, 0, 0, 15, 0, 0, 2, 0, - 16, 17, 0, 0, 18, 19, 20, 292, 3, 0, - 0, 0, 0, 4, 5, 6, 0, 0, 0, 0, - 0, 7, 21, 130, 131, 0, 132, 133, 134, 8, - 0, 0, 9, 0, 10, 0, 0, 11, 136, 137, - 138, 139, 140, 141, 142, 0, 0, 0, 12, 13, - 14, 0, 0, 1, 0, 0, 0, 15, 0, 0, - 2, 0, 16, 17, 0, 0, 18, 19, 20, 302, - 3, 0, 0, 0, 0, 4, 5, 6, 0, 0, - 0, 0, 0, 7, 21, 0, 0, 0, 0, 0, - 0, 8, 0, 0, 9, 0, 10, 0, 0, 11, - 0, 136, 137, 138, 139, 140, 141, 142, 0, 1, - 12, 13, 14, 0, 0, 0, 2, 0, 0, 15, - 0, 0, 0, 0, 16, 17, 3, 0, 18, 19, - 20, 4, 5, 6, 0, 0, 0, 0, 0, 7, - 0, 50, 51, 52, 53, 54, 21, 8, 55, 0, - 9, 0, 10, 0, 0, 11, 0, 130, 131, 0, - 132, 133, 134, 0, 0, 0, 12, 13, 14, 130, - 131, 0, 132, 133, 134, 15, 0, 0, 0, 0, - 16, 17, 0, 0, 18, 19, 20, 130, 131, 144, - 132, 133, 134, 0, 130, 131, 0, 132, 133, 134, - 0, 56, 21, 0, 0, 0, 57, 58, 59, 60, - 61, 266, 62, 63, 64, 65, 0, 226, 66, 67, - 132, 133, 134, 0, 0, 130, 131, 68, 132, 133, - 134, 0, 0, 0, 69, 136, 137, 138, 139, 140, - 141, 142, 0, 0, 0, 271, 219, 136, 137, 138, - 139, 140, 141, 142, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 136, 137, 138, 139, 140, - 141, 142, 136, 137, 138, 139, 140, 141, 142, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 136, 137, 138, 139, 140, - 141, 142, 0, 136, 137, 138, 139, 140, 141, 142 +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 2, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 1, 2, 1, 4, 1, 1, + 1, 1, 1, 3, 3, 3, 3, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 3, 6, 4, 1, 1, 1, 1, + 3, 0, 1, 3, 0, 1, 3, 1, 4, 5, + 4, 0, 1, 3, 1, 3, 1, 0, 2, 0, + 2, 0, 2, 0, 1, 1, 0, 4, 8, 3, + 5, 2, 3, 1, 3, 4, 4, 2, 2, 3, + 2, 2, 2, 3, 4, 1, 2, 0, 2, 1, + 7, 6, 10, 1, 2, 2, 4, 4, 1, 3, + 0, 3, 0, 2, 0, 1, 7, 1, 3, 0, + 1, 0, 1, 10, 2, 2, 1, 1, 1, 1, + 1, 3, 3, 0, 1, 3, 3, 0, 1, 2, + 6, 0, 1, 2, 11 }; -static const short yycheck[] = { 0, - 18, 3, 4, 31, 6, 36, 13, 34, 26, 3, - 4, 5, 6, 7, 13, 208, 10, 7, 22, 143, - 46, 17, 144, 60, 20, 54, 97, 56, 99, 97, - 97, 99, 99, 31, 15, 16, 229, 161, 32, 33, - 3, 4, 5, 6, 7, 7, 48, 10, 97, 47, - 99, 7, 97, 55, 99, 46, 97, 61, 99, 97, - 7, 99, 35, 7, 91, 7, 68, 69, 99, 63, - 263, 61, 7, 99, 68, 69, 70, 71, 72, 31, - 74, 75, 76, 77, 91, 92, 80, 81, 51, 211, - 89, 90, 91, 92, 7, 89, 85, 91, 100, 85, - 63, 96, 96, 43, 44, 68, 69, 70, 71, 72, - 95, 74, 75, 76, 77, 95, 95, 80, 81, 36, - 95, 95, 15, 95, 95, 95, 89, 95, 130, 131, - 132, 133, 134, 96, 136, 137, 138, 139, 140, 141, - 142, 95, 95, 145, 266, 95, 148, 95, 150, 271, - 95, 35, 95, 7, 95, 49, 95, 7, 95, 95, - 7, 95, 95, 94, 14, 193, 96, 289, 94, 96, - 7, 96, 96, 46, 24, 176, 26, 27, 57, 29, - 30, 31, 96, 7, 185, 96, 67, 37, 13, 3, - 4, 5, 6, 7, 7, 45, 10, 67, 48, 7, - 50, 7, 204, 53, 96, 7, 55, 98, 52, 97, - 212, 86, 99, 99, 64, 65, 66, 7, 32, 33, - 7, 223, 7, 73, 226, 227, 21, 27, 78, 79, - 23, 28, 82, 83, 84, 97, 7, 7, 37, 59, - 101, 8, 9, 244, 11, 12, 13, 98, 7, 63, - 100, 24, 48, 39, 68, 69, 70, 71, 72, 7, - 74, 75, 76, 77, 58, 40, 80, 81, 96, 7, - 62, 7, 41, 95, 42, 89, 14, 7, 7, 28, - 281, 21, 96, 301, 285, 23, 24, 7, 95, 0, - 0, 29, 30, 31, 157, 296, 148, 31, 259, 37, - 8, 9, 210, 11, 12, 13, 228, 45, 215, -1, - 48, 280, 50, -1, 265, 53, -1, 25, -1, 86, - 87, 88, 89, 90, 91, 92, 64, 65, 66, -1, - 97, 7, -1, -1, -1, 73, -1, -1, 14, -1, - 78, 79, -1, -1, 82, 83, 84, 23, 24, -1, - -1, -1, -1, 29, 30, 31, -1, -1, -1, -1, - -1, 37, 100, 8, 9, -1, 11, 12, 13, 45, - -1, -1, 48, -1, 50, -1, -1, 53, 86, 87, - 88, 89, 90, 91, 92, -1, -1, -1, 64, 65, - 66, -1, -1, 7, -1, -1, -1, 73, -1, -1, - 14, -1, 78, 79, -1, -1, 82, 83, 84, 23, - 24, -1, -1, -1, -1, 29, 30, 31, -1, -1, - -1, -1, -1, 37, 100, -1, -1, -1, -1, -1, - -1, 45, -1, -1, 48, -1, 50, -1, -1, 53, - -1, 86, 87, 88, 89, 90, 91, 92, -1, 7, - 64, 65, 66, -1, -1, -1, 14, -1, -1, 73, - -1, -1, -1, -1, 78, 79, 24, -1, 82, 83, - 84, 29, 30, 31, -1, -1, -1, -1, -1, 37, - -1, 3, 4, 5, 6, 7, 100, 45, 10, -1, - 48, -1, 50, -1, -1, 53, -1, 8, 9, -1, - 11, 12, 13, -1, -1, -1, 64, 65, 66, 8, - 9, -1, 11, 12, 13, 73, -1, -1, -1, -1, - 78, 79, -1, -1, 82, 83, 84, 8, 9, 28, - 11, 12, 13, -1, 8, 9, -1, 11, 12, 13, - -1, 63, 100, -1, -1, -1, 68, 69, 70, 71, - 72, 25, 74, 75, 76, 77, -1, 38, 80, 81, - 11, 12, 13, -1, -1, 8, 9, 89, 11, 12, - 13, -1, -1, -1, 96, 86, 87, 88, 89, 90, - 91, 92, -1, -1, -1, 28, 97, 86, 87, 88, - 89, 90, 91, 92, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 86, 87, 88, 89, 90, - 91, 92, 86, 87, 88, 89, 90, 91, 92, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 86, 87, 88, 89, 90, - 91, 92, -1, 86, 87, 88, 89, 90, 91, 92 +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 0, 0, 0, 0, 0, 123, 81, 0, 0, 0, + 0, 139, 0, 0, 0, 66, 67, 68, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 87, + 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 28, 29, 30, 31, 26, 0, 32, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 0, + 0, 0, 0, 0, 0, 0, 84, 77, 82, 86, + 0, 0, 0, 0, 0, 0, 140, 141, 124, 0, + 125, 112, 144, 145, 0, 1, 4, 74, 10, 0, + 101, 11, 0, 107, 108, 15, 16, 110, 111, 13, + 14, 12, 9, 7, 5, 6, 8, 17, 19, 18, + 22, 23, 20, 21, 2, 113, 153, 0, 47, 0, + 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 74, 0, 0, 0, 71, + 0, 0, 0, 99, 0, 109, 0, 142, 0, 71, + 61, 75, 0, 74, 0, 88, 0, 154, 0, 48, + 49, 38, 45, 46, 42, 43, 44, 24, 117, 39, + 40, 41, 34, 33, 35, 36, 0, 0, 0, 0, + 0, 72, 85, 83, 69, 87, 0, 0, 103, 106, + 0, 0, 126, 62, 0, 65, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 25, 115, 119, 0, 27, + 0, 80, 0, 78, 0, 0, 0, 89, 0, 0, + 0, 0, 128, 0, 0, 0, 0, 76, 100, 105, + 149, 150, 146, 147, 148, 151, 152, 157, 155, 118, + 0, 116, 0, 121, 79, 73, 70, 0, 91, 0, + 102, 104, 130, 134, 0, 0, 64, 63, 0, 158, + 161, 0, 120, 90, 0, 96, 0, 0, 132, 135, + 136, 129, 0, 0, 0, 159, 162, 0, 114, 92, + 0, 98, 0, 0, 0, 127, 0, 156, 0, 0, + 163, 0, 0, 131, 133, 137, 0, 0, 0, 93, + 122, 143, 0, 0, 164, 94, 95, 97, 138, 0, + 160 }; -/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/usr/share/bison.simple" -/* This file comes from bison-1.28. */ -/* Skeleton output parser for bison, - Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. +/* YYDEFGOTO[NTERM-NUM]. */ +static const short int yydefgoto[] = +{ + -1, 177, 178, 161, 72, 204, 23, 24, 25, 195, + 192, 162, 78, 79, 80, 103, 258, 275, 317, 291, + 26, 27, 28, 198, 199, 104, 29, 30, 31, 32, + 33, 34, 35, 36, 216, 217, 218, 37, 38, 39, + 40, 41, 42, 43, 232, 233, 278, 295, 280, 44, + 306, 87, 158, 45, 46, 47, 245, 167, 168, 269, + 270, 286, 287, 48 +}; - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -205 +static const short int yypact[] = +{ + 454, -48, 30, 521, 521, -205, 12, 42, -18, 46, + -4, -33, 67, 69, 71, -205, -205, -205, 47, -8, + -6, 85, 93, -205, 1, -2, 2, -20, 3, 59, + 5, 7, 59, 24, 27, 28, 31, 32, 33, 39, + 50, 51, 55, 56, 57, 58, 60, 62, 63, 521, + 22, -205, -205, -205, -205, 48, 521, 65, -205, -205, + -205, -205, -205, -205, -205, -205, -205, -205, -205, 521, + 521, 252, 64, 576, 66, 68, -205, 640, -205, -40, + 86, 111, 120, 105, 156, 161, -205, 110, -205, 122, + -205, -205, -205, -205, 73, -205, -205, 521, -205, 74, + -205, -205, 492, -205, -205, -205, -205, -205, -205, -205, + -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, + -205, -205, -205, -205, -205, 640, 167, 106, 309, 107, + 168, 23, 521, 521, 521, 521, 521, 454, 521, 521, + 521, 521, 521, 521, 521, 521, 454, 521, -27, 178, + 204, 179, 521, -205, 181, -205, 91, -205, 134, 178, + 92, 640, -75, 521, 139, 640, 29, -205, -59, -205, + -205, -205, 309, 309, 15, 15, 640, -205, 151, 15, + 15, 15, 25, 25, 168, 168, -58, 284, 535, 187, + 96, -205, 95, -205, -205, -31, 568, 109, -205, 98, + 193, 195, 95, -205, -49, -205, 521, -45, 197, 40, + 40, 189, 167, 454, 521, -205, -205, 186, 191, -205, + 190, -205, 123, -205, 214, 521, 216, 194, 521, 521, + 181, 40, -205, -36, 164, 126, 130, 640, -205, -205, + -205, -205, -205, -205, -205, -205, -205, 227, -205, 454, + 605, -205, 215, -205, -205, -205, -205, 192, 199, 633, + 640, -205, 145, 184, 193, 238, -205, -205, 40, -205, + 4, 454, -205, -205, 205, 203, 454, 245, 240, -205, + -205, -205, 153, 155, 198, -205, -205, -12, 454, -205, + 210, -205, 341, 157, 249, -205, 250, -205, 251, 454, + -205, 259, 229, -205, -205, -205, -26, 244, 398, 26, + -205, -205, 261, 47, -205, -205, -205, -205, -205, 173, + -205 +}; - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +/* YYPGOTO[NTERM-NUM]. */ +static const short int yypgoto[] = +{ + -205, 0, -126, -1, -205, -205, -205, -205, -205, -205, + 112, -124, 135, -205, -205, -28, -205, -205, -205, -205, + -17, -205, -205, 43, -205, 257, -205, -205, -205, -205, + -205, -205, -205, -205, 76, -205, -205, -205, -205, -205, + -205, -205, -205, -205, 8, -205, -205, -205, -205, -205, + -205, -205, -205, -205, -205, -205, -204, 72, -205, 20, + -205, 10, -205, -205 +}; - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const unsigned short int yytable[] = +{ + 22, 91, 71, 73, 107, 77, 246, 225, 149, 189, + 100, 268, 299, 6, 49, 51, 52, 53, 54, 55, + 187, 186, 56, 85, 205, 86, 206, 262, 136, 99, + 82, 132, 133, 84, 134, 135, 136, 50, 136, 207, + 211, 219, 212, 206, 209, 210, 74, 75, 125, 81, + 235, 284, 236, 83, 238, 128, 206, 240, 241, 242, + 243, 150, 244, 263, 283, 264, 190, 284, 130, 131, + 226, 315, 316, 311, 88, 312, 89, 57, 90, 92, + 6, 93, 58, 59, 60, 61, 62, 249, 63, 64, + 65, 66, 94, 95, 67, 68, 97, 102, 96, 98, + 101, 165, 105, 69, 106, 76, 141, 142, 143, 144, + 70, 138, 139, 140, 141, 142, 143, 144, 143, 144, + 126, 109, 171, 151, 110, 111, 152, 153, 112, 113, + 114, 172, 173, 174, 175, 176, 115, 179, 180, 181, + 182, 183, 184, 185, 127, 288, 188, 116, 117, 77, + 292, 196, 118, 119, 120, 121, 154, 122, 1, 123, + 124, 129, 145, 155, 147, 2, 148, 227, 156, 157, + 159, 160, 163, 308, 166, 169, 170, 3, 215, 213, + 214, 136, 4, 5, 6, 191, 194, 215, 197, 200, + 7, 201, 203, 208, 222, 223, 224, 229, 8, 230, + 231, 9, 234, 10, 239, 237, 11, 51, 52, 53, + 54, 55, 247, 250, 56, 214, 252, 12, 13, 14, + 253, 255, 254, 256, 165, 265, 15, 259, 260, 266, + 267, 16, 17, 257, 268, 18, 19, 20, 74, 75, + 274, 272, 273, 277, 279, 282, 290, 289, 293, 215, + 294, 296, 297, 21, 301, 304, 303, 305, 307, 310, + 132, 133, 298, 134, 135, 136, 309, 313, 318, 57, + 320, 202, 281, 261, 58, 59, 60, 61, 62, 137, + 63, 64, 65, 66, 248, 193, 67, 68, 215, 108, + 285, 1, 215, 251, 0, 69, 319, 300, 2, 0, + 0, 0, 70, 0, 0, 0, 0, 0, 215, 220, + 3, 0, 0, 0, 0, 4, 5, 6, 0, 0, + 134, 135, 136, 7, 0, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 9, 0, 10, 0, 0, 11, + 138, 139, 140, 141, 142, 143, 144, 0, 1, 0, + 12, 13, 14, 0, 0, 2, 0, 0, 0, 15, + 0, 0, 0, 0, 16, 17, 302, 3, 18, 19, + 20, 0, 4, 5, 6, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 21, 0, 8, 0, + 0, 9, 0, 10, 0, 0, 11, 138, 139, 140, + 141, 142, 143, 144, 0, 1, 0, 12, 13, 14, + 0, 0, 2, 0, 0, 0, 15, 0, 0, 0, + 0, 16, 17, 314, 3, 18, 19, 20, 0, 4, + 5, 6, 0, 0, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 21, 0, 8, 0, 0, 9, 0, + 10, 0, 0, 11, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 12, 13, 14, 0, 2, 0, + 0, 0, 0, 15, 0, 0, 0, 0, 16, 17, + 3, 0, 18, 19, 20, 4, 5, 6, 0, 0, + 0, 0, 0, 7, 0, 51, 52, 53, 54, 55, + 21, 8, 56, 0, 9, 0, 10, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 13, 14, 0, 51, 52, 53, 54, 55, 15, + 0, 56, 0, 0, 16, 17, 0, 0, 18, 19, + 20, 0, 0, 132, 133, 164, 134, 135, 136, 0, + 0, 0, 0, 0, 0, 0, 21, 57, 0, 0, + 0, 0, 58, 59, 60, 61, 62, 0, 63, 64, + 65, 66, 0, 0, 67, 68, 132, 133, 0, 134, + 135, 136, 0, 69, 132, 133, 57, 134, 135, 136, + 70, 58, 59, 60, 61, 62, 0, 63, 64, 65, + 66, 0, 0, 67, 68, 0, 146, 0, 228, 0, + 0, 0, 69, 132, 133, 0, 134, 135, 136, 70, + 0, 0, 0, 138, 139, 140, 141, 142, 143, 144, + 0, 0, 271, 0, 221, 0, 0, 0, 0, 0, + 0, 132, 133, 0, 134, 135, 136, 0, 132, 133, + 0, 134, 135, 136, 0, 0, 138, 139, 140, 141, + 142, 143, 144, 276, 138, 139, 140, 141, 142, 143, + 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 138, 139, 140, 141, 142, 143, 144, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 138, 139, 140, 141, 142, 143, 144, 138, 139, + 140, 141, 142, 143, 144 +}; -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ +static const short int yycheck[] = +{ + 0, 18, 3, 4, 32, 6, 210, 38, 48, 36, + 27, 7, 24, 33, 62, 3, 4, 5, 6, 7, + 146, 145, 10, 56, 99, 58, 101, 231, 13, 49, + 48, 8, 9, 37, 11, 12, 13, 7, 13, 163, + 99, 99, 101, 101, 15, 16, 34, 35, 49, 7, + 99, 63, 101, 7, 99, 56, 101, 17, 18, 19, + 20, 101, 22, 99, 268, 101, 93, 63, 69, 70, + 101, 45, 46, 99, 7, 101, 7, 65, 7, 87, + 33, 87, 70, 71, 72, 73, 74, 213, 76, 77, + 78, 79, 7, 0, 82, 83, 98, 38, 97, 97, + 97, 102, 97, 91, 97, 93, 91, 92, 93, 94, + 98, 88, 89, 90, 91, 92, 93, 94, 93, 94, + 98, 97, 99, 37, 97, 97, 15, 7, 97, 97, + 97, 132, 133, 134, 135, 136, 97, 138, 139, 140, + 141, 142, 143, 144, 96, 271, 147, 97, 97, 150, + 276, 152, 97, 97, 97, 97, 51, 97, 7, 97, + 97, 96, 98, 7, 98, 14, 98, 195, 7, 59, + 48, 98, 98, 299, 7, 69, 69, 26, 178, 28, + 29, 13, 31, 32, 33, 7, 7, 187, 7, 98, + 39, 57, 100, 54, 7, 99, 101, 88, 47, 101, + 7, 50, 7, 52, 7, 206, 55, 3, 4, 5, + 6, 7, 23, 214, 10, 29, 25, 66, 67, 68, + 30, 7, 99, 7, 225, 61, 75, 228, 229, 103, + 100, 80, 81, 39, 7, 84, 85, 86, 34, 35, + 41, 26, 50, 98, 60, 7, 43, 42, 3, 249, + 10, 98, 97, 102, 44, 6, 99, 7, 7, 30, + 8, 9, 64, 11, 12, 13, 7, 23, 7, 65, + 97, 159, 264, 230, 70, 71, 72, 73, 74, 27, + 76, 77, 78, 79, 212, 150, 82, 83, 288, 32, + 270, 7, 292, 217, -1, 91, 313, 287, 14, -1, + -1, -1, 98, -1, -1, -1, -1, -1, 308, 25, + 26, -1, -1, -1, -1, 31, 32, 33, -1, -1, + 11, 12, 13, 39, -1, -1, -1, -1, -1, -1, + -1, 47, -1, -1, 50, -1, 52, -1, -1, 55, + 88, 89, 90, 91, 92, 93, 94, -1, 7, -1, + 66, 67, 68, -1, -1, 14, -1, -1, -1, 75, + -1, -1, -1, -1, 80, 81, 25, 26, 84, 85, + 86, -1, 31, 32, 33, -1, -1, -1, -1, -1, + 39, -1, -1, -1, -1, -1, 102, -1, 47, -1, + -1, 50, -1, 52, -1, -1, 55, 88, 89, 90, + 91, 92, 93, 94, -1, 7, -1, 66, 67, 68, + -1, -1, 14, -1, -1, -1, 75, -1, -1, -1, + -1, 80, 81, 25, 26, 84, 85, 86, -1, 31, + 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, + -1, -1, -1, 102, -1, 47, -1, -1, 50, -1, + 52, -1, -1, 55, -1, -1, -1, -1, -1, -1, + -1, 7, -1, -1, 66, 67, 68, -1, 14, -1, + -1, -1, -1, 75, -1, -1, -1, -1, 80, 81, + 26, -1, 84, 85, 86, 31, 32, 33, -1, -1, + -1, -1, -1, 39, -1, 3, 4, 5, 6, 7, + 102, 47, 10, -1, 50, -1, 52, -1, -1, 55, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 66, 67, 68, -1, 3, 4, 5, 6, 7, 75, + -1, 10, -1, -1, 80, 81, -1, -1, 84, 85, + 86, -1, -1, 8, 9, 53, 11, 12, 13, -1, + -1, -1, -1, -1, -1, -1, 102, 65, -1, -1, + -1, -1, 70, 71, 72, 73, 74, -1, 76, 77, + 78, 79, -1, -1, 82, 83, 8, 9, -1, 11, + 12, 13, -1, 91, 8, 9, 65, 11, 12, 13, + 98, 70, 71, 72, 73, 74, -1, 76, 77, 78, + 79, -1, -1, 82, 83, -1, 30, -1, 40, -1, + -1, -1, 91, 8, 9, -1, 11, 12, 13, 98, + -1, -1, -1, 88, 89, 90, 91, 92, 93, 94, + -1, -1, 27, -1, 99, -1, -1, -1, -1, -1, + -1, 8, 9, -1, 11, 12, 13, -1, 8, 9, + -1, 11, 12, 13, -1, -1, 88, 89, 90, 91, + 92, 93, 94, 30, 88, 89, 90, 91, 92, 93, + 94, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 88, 89, 90, 91, 92, 93, 94, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 88, 89, 90, 91, 92, 93, 94, 88, 89, + 90, 91, 92, 93, 94 +}; -/* This is the parser code that is written into each bison parser - when the %semantic_parser declaration is not specified in the grammar. - It was written by Richard Stallman by simplifying the hairy parser - used when %semantic_parser is specified. */ +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 7, 14, 26, 31, 32, 33, 39, 47, 50, + 52, 55, 66, 67, 68, 75, 80, 81, 84, 85, + 86, 102, 105, 110, 111, 112, 124, 125, 126, 130, + 131, 132, 133, 134, 135, 136, 137, 141, 142, 143, + 144, 145, 146, 147, 153, 157, 158, 159, 167, 62, + 7, 3, 4, 5, 6, 7, 10, 65, 70, 71, + 72, 73, 74, 76, 77, 78, 79, 82, 83, 91, + 98, 107, 108, 107, 34, 35, 93, 107, 116, 117, + 118, 7, 48, 7, 37, 56, 58, 155, 7, 7, + 7, 124, 87, 87, 7, 0, 97, 98, 97, 49, + 124, 97, 38, 119, 129, 97, 97, 119, 129, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 107, 98, 96, 107, 96, + 107, 107, 8, 9, 11, 12, 13, 27, 88, 89, + 90, 91, 92, 93, 94, 98, 30, 98, 98, 48, + 101, 37, 15, 7, 51, 7, 7, 59, 156, 48, + 98, 107, 115, 98, 53, 107, 7, 161, 162, 69, + 69, 99, 107, 107, 107, 107, 107, 105, 106, 107, + 107, 107, 107, 107, 107, 107, 115, 106, 107, 36, + 93, 7, 114, 116, 7, 113, 107, 7, 127, 128, + 98, 57, 114, 100, 109, 99, 101, 115, 54, 15, + 16, 99, 101, 28, 29, 105, 138, 139, 140, 99, + 25, 99, 7, 99, 101, 38, 101, 119, 40, 88, + 101, 7, 148, 149, 7, 99, 101, 107, 99, 7, + 17, 18, 19, 20, 22, 160, 160, 23, 161, 106, + 107, 138, 25, 30, 99, 7, 7, 39, 120, 107, + 107, 127, 160, 99, 101, 61, 103, 100, 7, 163, + 164, 27, 26, 50, 41, 121, 30, 98, 150, 60, + 152, 148, 7, 160, 63, 163, 165, 166, 106, 42, + 43, 123, 106, 3, 10, 151, 98, 97, 64, 24, + 165, 44, 25, 99, 6, 7, 154, 7, 106, 7, + 30, 99, 101, 23, 25, 45, 46, 122, 7, 124, + 97 +}; -#ifndef YYPARSE_RETURN_TYPE -#define YYPARSE_RETURN_TYPE int +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ #endif - - -#ifndef YYSTACK_USE_ALLOCA -#ifdef alloca -#define YYSTACK_USE_ALLOCA -#else /* alloca not defined */ -#ifdef __GNUC__ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#else /* not GNU C. */ -#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) -#define YYSTACK_USE_ALLOCA -#include <alloca.h> -#else /* not sparc */ -/* We think this test detects Watcom and Microsoft C. */ -/* This used to test MSDOS, but that is a bad idea - since that symbol is in the user namespace. */ -#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) -#if 0 /* No need for malloc.h, which pollutes the namespace; - instead, just don't use alloca. */ -#include <malloc.h> +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t #endif -#else /* not MSDOS, or __TURBOC__ */ -#if defined(_AIX) -/* I don't know what this was needed for, but it pollutes the namespace. - So I turned it off. rms, 2 May 1997. */ -/* #include <malloc.h> */ - #pragma alloca -#define YYSTACK_USE_ALLOCA -#else /* not MSDOS, or __TURBOC__, or _AIX */ -#if 0 -#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, - and on HPUX 10. Eventually we can turn this on. */ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#endif /* __hpux */ +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif #endif -#endif /* not _AIX */ -#endif /* not MSDOS, or __TURBOC__ */ -#endif /* not sparc */ -#endif /* not GNU C */ -#endif /* alloca not defined */ -#endif /* YYSTACK_USE_ALLOCA not defined */ - -#ifdef YYSTACK_USE_ALLOCA -#define YYSTACK_ALLOC alloca -#else -#define YYSTACK_ALLOC malloc +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int #endif -/* Note: there must be only one dollar sign in this file. - It is replaced by the list of actions, each action - as one case of the switch. */ - #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) -#define YYEMPTY -2 +#define YYEMPTY (-2) #define YYEOF 0 + #define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrlab1 -/* Like YYERROR except do call yyerror. - This remains here temporarily to ease the - transition to the new meaning of YYERROR, for GCC. +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ + #define YYFAIL goto yyerrlab + #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(token, value) \ + +#define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ - { yychar = (token), yylval = (value); \ - yychar1 = YYTRANSLATE (yychar); \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ - { yyerror ("syntax error: cannot back up"); YYERROR; } \ + { \ + yyerror ("syntax error: cannot back up");\ + YYERROR; \ + } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 -#ifndef YYPURE -#define YYLEX yylex() -#endif +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ -#ifdef YYPURE -#ifdef YYLSP_NEEDED -#ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) -#else -#define YYLEX yylex(&yylval, &yylloc) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + ((Current).first_line = (Rhs)[1].first_line, \ + (Current).first_column = (Rhs)[1].first_column, \ + (Current).last_line = (Rhs)[N].last_line, \ + (Current).last_column = (Rhs)[N].last_column) #endif -#else /* not YYLSP_NEEDED */ + +/* YYLEX -- calling `yylex' with the right arguments. */ + #ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, YYLEX_PARAM) +# define YYLEX yylex (YYLEX_PARAM) #else -#define YYLEX yylex(&yylval) +# define YYLEX yylex () #endif -#endif /* not YYLSP_NEEDED */ -#endif - -/* If nonreentrant, generate the variables here */ -#ifndef YYPURE +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) + +# define YYDSYMPRINTF(Title, Token, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Token, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) -int yychar; /* the lookahead symbol */ -YYSTYPE yylval; /* the semantic value of the */ - /* lookahead symbol */ +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ -#ifdef YYLSP_NEEDED -YYLTYPE yylloc; /* location data for the lookahead */ - /* symbol */ +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short int *bottom, short int *top) +#else +static void +yy_stack_print (bottom, top) + short int *bottom; + short int *top; #endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} -int yynerrs; /* number of parse errors so far */ -#endif /* not YYPURE */ +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) -#if YYDEBUG != 0 -int yydebug; /* nonzero means print parse trace */ -/* Since this is uninitialized, it does not stop multiple parsers - from coexisting. */ -#endif -/* YYINITDEPTH indicates the initial size of the parser's stacks */ +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH -#define YYINITDEPTH 200 +# define YYINITDEPTH 200 #endif -/* YYMAXDEPTH is the maximum size the stacks can grow to - (effective only if the built-in stack extension method is used). */ +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ -#if YYMAXDEPTH == 0 -#undef YYMAXDEPTH +#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0 +# undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH -#define YYMAXDEPTH 10000 +# define YYMAXDEPTH 10000 #endif + -/* Define __yy_memcpy. Note that the size argument - should be passed with type unsigned int, because that is what the non-GCC - definitions require. With GCC, __builtin_memcpy takes an arg - of type size_t, but it can handle unsigned int. */ - -#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ -#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) -#else /* not GNU C or C++ */ -#ifndef __cplusplus - -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ -static void -__yy_memcpy (to, from, count) - char *to; - char *from; - unsigned int count; + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif { - register char *f = from; - register char *t = to; - register int i = count; + register char *yyd = yydest; + register const char *yys = yysrc; - while (i-- > 0) - *t++ = *f++; + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; } +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ -#else /* __cplusplus */ + -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) static void -__yy_memcpy (char *to, char *from, unsigned int count) +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; +#endif { - register char *t = to; - register char *f = from; - register int i = count; + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + } + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - while (i-- > 0) - *t++ = *f++; + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); } +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yytype, yyvaluep) + int yytype; + YYSTYPE *yyvaluep; #endif -#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + switch (yytype) + { + + default: + break; + } +} -#line 222 "/usr/share/bison.simple" -/* The user can define YYPARSE_PARAM as the name of an argument to be passed - into yyparse. The argument should have type void *. - It should actually point to an object. - Grammar actions can access the variable by casting it - to the proper pointer type. */ +/* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM -#ifdef __cplusplus -#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM -#define YYPARSE_PARAM_DECL -#else /* not __cplusplus */ -#define YYPARSE_PARAM_ARG YYPARSE_PARAM -#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; -#endif /* not __cplusplus */ -#else /* not YYPARSE_PARAM */ -#define YYPARSE_PARAM_ARG -#define YYPARSE_PARAM_DECL -#endif /* not YYPARSE_PARAM */ - -/* Prevent warning if -Wstrict-prototypes. */ -#ifdef __GNUC__ +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + #ifdef YYPARSE_PARAM -YYPARSE_RETURN_TYPE -yyparse (void *); +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) #else -YYPARSE_RETURN_TYPE -yyparse (void); +int +yyparse () + #endif #endif - -YYPARSE_RETURN_TYPE -yyparse(YYPARSE_PARAM_ARG) - YYPARSE_PARAM_DECL { + register int yystate; register int yyn; - register short *yyssp; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short int yyssa[YYINITDEPTH]; + short int *yyss = yyssa; + register short int *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; register YYSTYPE *yyvsp; - int yyerrstatus; /* number of tokens to shift before error messages enabled */ - int yychar1 = 0; /* lookahead token as an internal (translated) token number */ - short yyssa[YYINITDEPTH]; /* the state stack */ - YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ - short *yyss = yyssa; /* refer to the stacks thru separate pointers */ - YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ -#ifdef YYLSP_NEEDED - YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp; - -#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) -#else #define YYPOPSTACK (yyvsp--, yyssp--) -#endif - int yystacksize = YYINITDEPTH; -#ifndef YYSTACK_USE_ALLOCA - int yyfree_stacks = 0; -#endif + YYSIZE_T yystacksize = YYINITDEPTH; -#ifdef YYPURE - int yychar; - YYSTYPE yylval; - int yynerrs; -#ifdef YYLSP_NEEDED - YYLTYPE yylloc; -#endif -#endif + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; - YYSTYPE yyval; /* the variable used to return */ - /* semantic values from the action */ - /* routines */ + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ int yylen; -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Starting parse\n"); -#endif + YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; @@ -880,112 +1392,97 @@ yyparse(YYPARSE_PARAM_ARG) so that they stay on the same level as the state stack. The wasted elements are never initialized. */ - yyssp = yyss - 1; + yyssp = yyss; yyvsp = yyvs; -#ifdef YYLSP_NEEDED - yylsp = yyls; -#endif -/* Push a new state, which is found in yystate . */ -/* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. */ -yynewstate: - *++yyssp = yystate; + goto yysetstate; - if (yyssp >= yyss + yystacksize - 1) - { - /* Give user a chance to reallocate the stack */ - /* Use copies of these so that the &'s don't force the real ones into memory. */ - YYSTYPE *yyvs1 = yyvs; - short *yyss1 = yyss; -#ifdef YYLSP_NEEDED - YYLTYPE *yyls1 = yyls; -#endif +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { /* Get the current used size of the three stacks, in elements. */ - int size = yyssp - yyss + 1; + YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow - /* Each stack pointer address is followed by the size of - the data in use in that stack, in bytes. */ -#ifdef YYLSP_NEEDED - /* This used to be a conditional around just the two extra args, - but that might be undefined if yyoverflow is a macro. */ - yyoverflow("parser stack overflow", - &yyss1, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yyls1, size * sizeof (*yylsp), - &yystacksize); -#else - yyoverflow("parser stack overflow", - &yyss1, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yystacksize); -#endif - - yyss = yyss1; yyvs = yyvs1; -#ifdef YYLSP_NEEDED - yyls = yyls1; -#endif + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short int *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } #else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else /* Extend the stack our own way. */ - if (yystacksize >= YYMAXDEPTH) - { - yyerror("parser stack overflow"); -#ifndef YYSTACK_USE_ALLOCA - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } -#endif - return 2; - } + if (YYMAXDEPTH <= yystacksize) + goto yyoverflowlab; yystacksize *= 2; - if (yystacksize > YYMAXDEPTH) + if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; -#ifndef YYSTACK_USE_ALLOCA - yyfree_stacks = 1; -#endif - yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); - __yy_memcpy ((char *)yyss, (char *)yyss1, - size * (unsigned int) sizeof (*yyssp)); - yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); - __yy_memcpy ((char *)yyvs, (char *)yyvs1, - size * (unsigned int) sizeof (*yyvsp)); -#ifdef YYLSP_NEEDED - yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); - __yy_memcpy ((char *)yyls, (char *)yyls1, - size * (unsigned int) sizeof (*yylsp)); -#endif + + { + short int *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif #endif /* no yyoverflow */ - yyssp = yyss + size - 1; - yyvsp = yyvs + size - 1; -#ifdef YYLSP_NEEDED - yylsp = yyls + size - 1; -#endif + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Stack size increased to %d\n", yystacksize); -#endif - if (yyssp >= yyss + yystacksize - 1) + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) YYABORT; } -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Entering state %d\n", yystate); -#endif + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; - yybackup: + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ @@ -994,876 +1491,1005 @@ yynewstate: /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYFLAG) + if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ - /* yychar is either YYEMPTY or YYEOF - or a valid token in external form. */ - + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Reading a token: "); -#endif + YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } - /* Convert token to internal form (in yychar1) for indexing tables with */ - - if (yychar <= 0) /* This means end of input. */ + if (yychar <= YYEOF) { - yychar1 = 0; - yychar = YYEOF; /* Don't call YYLEX any more */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Now at end of input.\n"); -#endif + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); } else { - yychar1 = YYTRANSLATE(yychar); - -#if YYDEBUG != 0 - if (yydebug) - { - fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); - /* Give the individual parser a way to print the precise meaning - of a token, for further debugging info. */ -#ifdef YYPRINT - YYPRINT (stderr, yychar, yylval); -#endif - fprintf (stderr, ")\n"); - } -#endif + yytoken = YYTRANSLATE (yychar); + YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); } - yyn += yychar1; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; - yyn = yytable[yyn]; - - /* yyn is what to do for this token type in this state. - Negative => reduce, -yyn is rule number. - Positive => shift, yyn is new state. - New state is final state => don't bother to shift, - just return success. - 0, or most negative number => error. */ - - if (yyn < 0) + if (yyn <= 0) { - if (yyn == YYFLAG) + if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } - else if (yyn == 0) - goto yyerrlab; if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); -#endif + YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif - /* count tokens shifted since error; after three, turn off error status. */ - if (yyerrstatus) yyerrstatus--; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; yystate = yyn; goto yynewstate; -/* Do the default action for the current state. */ -yydefault: +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; + goto yyreduce; + -/* Do a reduction. yyn is the number of a rule to reduce with. */ +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ yyreduce: + /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; - if (yylen > 0) - yyval = yyvsp[1-yylen]; /* implement default value of the action */ -#if YYDEBUG != 0 - if (yydebug) - { - int i; - - fprintf (stderr, "Reducing via rule %d (line %d), ", - yyn, yyrline[yyn]); + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. - /* Print the symbols being reduced, and their result. */ - for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) - fprintf (stderr, "%s ", yytname[yyrhs[i]]); - fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); - } -#endif + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; - switch (yyn) { - -case 23: -#line 155 "pars0grm.y" -{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ; - break;} -case 24: -#line 157 "pars0grm.y" -{ yyval = que_node_list_add_last(yyvsp[-1], yyvsp[0]); ; - break;} -case 25: -#line 161 "pars0grm.y" -{ yyval = yyvsp[0];; - break;} -case 26: -#line 163 "pars0grm.y" -{ yyval = pars_func(yyvsp[-3], yyvsp[-1]); ; - break;} -case 27: + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 24: +#line 156 "pars0grm.y" + { yyval = que_node_list_add_last(NULL, yyvsp[0]); ;} + break; + + case 25: +#line 158 "pars0grm.y" + { yyval = que_node_list_add_last(yyvsp[-1], yyvsp[0]); ;} + break; + + case 26: +#line 162 "pars0grm.y" + { yyval = yyvsp[0];;} + break; + + case 27: #line 164 "pars0grm.y" -{ yyval = yyvsp[0];; - break;} -case 28: + { yyval = pars_func(yyvsp[-3], yyvsp[-1]); ;} + break; + + case 28: #line 165 "pars0grm.y" -{ yyval = yyvsp[0];; - break;} -case 29: + { yyval = yyvsp[0];;} + break; + + case 29: #line 166 "pars0grm.y" -{ yyval = yyvsp[0];; - break;} -case 30: + { yyval = yyvsp[0];;} + break; + + case 30: #line 167 "pars0grm.y" -{ yyval = yyvsp[0];; - break;} -case 31: + { yyval = yyvsp[0];;} + break; + + case 31: #line 168 "pars0grm.y" -{ yyval = yyvsp[0];; - break;} -case 32: + { yyval = yyvsp[0];;} + break; + + case 32: #line 169 "pars0grm.y" -{ yyval = pars_op('+', yyvsp[-2], yyvsp[0]); ; - break;} -case 33: + { yyval = yyvsp[0];;} + break; + + case 33: #line 170 "pars0grm.y" -{ yyval = pars_op('-', yyvsp[-2], yyvsp[0]); ; - break;} -case 34: + { yyval = pars_op('+', yyvsp[-2], yyvsp[0]); ;} + break; + + case 34: #line 171 "pars0grm.y" -{ yyval = pars_op('*', yyvsp[-2], yyvsp[0]); ; - break;} -case 35: + { yyval = pars_op('-', yyvsp[-2], yyvsp[0]); ;} + break; + + case 35: #line 172 "pars0grm.y" -{ yyval = pars_op('/', yyvsp[-2], yyvsp[0]); ; - break;} -case 36: + { yyval = pars_op('*', yyvsp[-2], yyvsp[0]); ;} + break; + + case 36: #line 173 "pars0grm.y" -{ yyval = pars_op('-', yyvsp[0], NULL); ; - break;} -case 37: + { yyval = pars_op('/', yyvsp[-2], yyvsp[0]); ;} + break; + + case 37: #line 174 "pars0grm.y" -{ yyval = yyvsp[-1]; ; - break;} -case 38: + { yyval = pars_op('-', yyvsp[0], NULL); ;} + break; + + case 38: #line 175 "pars0grm.y" -{ yyval = pars_op('=', yyvsp[-2], yyvsp[0]); ; - break;} -case 39: + { yyval = yyvsp[-1]; ;} + break; + + case 39: #line 176 "pars0grm.y" -{ yyval = pars_op('<', yyvsp[-2], yyvsp[0]); ; - break;} -case 40: + { yyval = pars_op('=', yyvsp[-2], yyvsp[0]); ;} + break; + + case 40: #line 177 "pars0grm.y" -{ yyval = pars_op('>', yyvsp[-2], yyvsp[0]); ; - break;} -case 41: + { yyval = pars_op('<', yyvsp[-2], yyvsp[0]); ;} + break; + + case 41: #line 178 "pars0grm.y" -{ yyval = pars_op(PARS_GE_TOKEN, yyvsp[-2], yyvsp[0]); ; - break;} -case 42: + { yyval = pars_op('>', yyvsp[-2], yyvsp[0]); ;} + break; + + case 42: #line 179 "pars0grm.y" -{ yyval = pars_op(PARS_LE_TOKEN, yyvsp[-2], yyvsp[0]); ; - break;} -case 43: + { yyval = pars_op(PARS_GE_TOKEN, yyvsp[-2], yyvsp[0]); ;} + break; + + case 43: #line 180 "pars0grm.y" -{ yyval = pars_op(PARS_NE_TOKEN, yyvsp[-2], yyvsp[0]); ; - break;} -case 44: + { yyval = pars_op(PARS_LE_TOKEN, yyvsp[-2], yyvsp[0]); ;} + break; + + case 44: #line 181 "pars0grm.y" -{ yyval = pars_op(PARS_AND_TOKEN, yyvsp[-2], yyvsp[0]); ; - break;} -case 45: + { yyval = pars_op(PARS_NE_TOKEN, yyvsp[-2], yyvsp[0]); ;} + break; + + case 45: #line 182 "pars0grm.y" -{ yyval = pars_op(PARS_OR_TOKEN, yyvsp[-2], yyvsp[0]); ; - break;} -case 46: + { yyval = pars_op(PARS_AND_TOKEN, yyvsp[-2], yyvsp[0]); ;} + break; + + case 46: #line 183 "pars0grm.y" -{ yyval = pars_op(PARS_NOT_TOKEN, yyvsp[0], NULL); ; - break;} -case 47: -#line 185 "pars0grm.y" -{ yyval = pars_op(PARS_NOTFOUND_TOKEN, yyvsp[-2], NULL); ; - break;} -case 48: -#line 187 "pars0grm.y" -{ yyval = pars_op(PARS_NOTFOUND_TOKEN, yyvsp[-2], NULL); ; - break;} -case 49: -#line 191 "pars0grm.y" -{ yyval = &pars_to_char_token; ; - break;} -case 50: + { yyval = pars_op(PARS_OR_TOKEN, yyvsp[-2], yyvsp[0]); ;} + break; + + case 47: +#line 184 "pars0grm.y" + { yyval = pars_op(PARS_NOT_TOKEN, yyvsp[0], NULL); ;} + break; + + case 48: +#line 186 "pars0grm.y" + { yyval = pars_op(PARS_NOTFOUND_TOKEN, yyvsp[-2], NULL); ;} + break; + + case 49: +#line 188 "pars0grm.y" + { yyval = pars_op(PARS_NOTFOUND_TOKEN, yyvsp[-2], NULL); ;} + break; + + case 50: #line 192 "pars0grm.y" -{ yyval = &pars_to_number_token; ; - break;} -case 51: + { yyval = &pars_to_char_token; ;} + break; + + case 51: #line 193 "pars0grm.y" -{ yyval = &pars_to_binary_token; ; - break;} -case 52: -#line 195 "pars0grm.y" -{ yyval = &pars_binary_to_number_token; ; - break;} -case 53: + { yyval = &pars_to_number_token; ;} + break; + + case 52: +#line 194 "pars0grm.y" + { yyval = &pars_to_binary_token; ;} + break; + + case 53: #line 196 "pars0grm.y" -{ yyval = &pars_substr_token; ; - break;} -case 54: + { yyval = &pars_binary_to_number_token; ;} + break; + + case 54: #line 197 "pars0grm.y" -{ yyval = &pars_concat_token; ; - break;} -case 55: + { yyval = &pars_substr_token; ;} + break; + + case 55: #line 198 "pars0grm.y" -{ yyval = &pars_instr_token; ; - break;} -case 56: + { yyval = &pars_concat_token; ;} + break; + + case 56: #line 199 "pars0grm.y" -{ yyval = &pars_length_token; ; - break;} -case 57: + { yyval = &pars_instr_token; ;} + break; + + case 57: #line 200 "pars0grm.y" -{ yyval = &pars_sysdate_token; ; - break;} -case 58: + { yyval = &pars_length_token; ;} + break; + + case 58: #line 201 "pars0grm.y" -{ yyval = &pars_rnd_token; ; - break;} -case 59: + { yyval = &pars_sysdate_token; ;} + break; + + case 59: #line 202 "pars0grm.y" -{ yyval = &pars_rnd_str_token; ; - break;} -case 63: -#line 213 "pars0grm.y" -{ yyval = pars_stored_procedure_call(yyvsp[-4]); ; - break;} -case 64: -#line 218 "pars0grm.y" -{ yyval = pars_procedure_call(yyvsp[-3], yyvsp[-1]); ; - break;} -case 65: -#line 222 "pars0grm.y" -{ yyval = &pars_replstr_token; ; - break;} -case 66: + { yyval = &pars_rnd_token; ;} + break; + + case 60: +#line 203 "pars0grm.y" + { yyval = &pars_rnd_str_token; ;} + break; + + case 64: +#line 214 "pars0grm.y" + { yyval = pars_stored_procedure_call(yyvsp[-4]); ;} + break; + + case 65: +#line 219 "pars0grm.y" + { yyval = pars_procedure_call(yyvsp[-3], yyvsp[-1]); ;} + break; + + case 66: #line 223 "pars0grm.y" -{ yyval = &pars_printf_token; ; - break;} -case 67: + { yyval = &pars_replstr_token; ;} + break; + + case 67: #line 224 "pars0grm.y" -{ yyval = &pars_assert_token; ; - break;} -case 68: -#line 228 "pars0grm.y" -{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ; - break;} -case 69: -#line 230 "pars0grm.y" -{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ; - break;} -case 70: -#line 234 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 71: + { yyval = &pars_printf_token; ;} + break; + + case 68: +#line 225 "pars0grm.y" + { yyval = &pars_assert_token; ;} + break; + + case 69: +#line 229 "pars0grm.y" + { yyval = que_node_list_add_last(NULL, yyvsp[0]); ;} + break; + + case 70: +#line 231 "pars0grm.y" + { yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;} + break; + + case 71: #line 235 "pars0grm.y" -{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ; - break;} -case 72: -#line 237 "pars0grm.y" -{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ; - break;} -case 73: -#line 241 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 74: + { yyval = NULL; ;} + break; + + case 72: +#line 236 "pars0grm.y" + { yyval = que_node_list_add_last(NULL, yyvsp[0]); ;} + break; + + case 73: +#line 238 "pars0grm.y" + { yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;} + break; + + case 74: #line 242 "pars0grm.y" -{ yyval = que_node_list_add_last(NULL, yyvsp[0]);; - break;} -case 75: + { yyval = NULL; ;} + break; + + case 75: #line 243 "pars0grm.y" -{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ; - break;} -case 76: -#line 247 "pars0grm.y" -{ yyval = yyvsp[0]; ; - break;} -case 77: -#line 249 "pars0grm.y" -{ yyval = pars_func(&pars_count_token, + { yyval = que_node_list_add_last(NULL, yyvsp[0]);;} + break; + + case 76: +#line 244 "pars0grm.y" + { yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;} + break; + + case 77: +#line 248 "pars0grm.y" + { yyval = yyvsp[0]; ;} + break; + + case 78: +#line 250 "pars0grm.y" + { yyval = pars_func(&pars_count_token, que_node_list_add_last(NULL, sym_tab_add_int_lit( - pars_sym_tab_global, 1))); ; - break;} -case 78: -#line 254 "pars0grm.y" -{ yyval = pars_func(&pars_count_token, + pars_sym_tab_global, 1))); ;} + break; + + case 79: +#line 255 "pars0grm.y" + { yyval = pars_func(&pars_count_token, que_node_list_add_last(NULL, pars_func(&pars_distinct_token, que_node_list_add_last( - NULL, yyvsp[-1])))); ; - break;} -case 79: -#line 260 "pars0grm.y" -{ yyval = pars_func(&pars_sum_token, + NULL, yyvsp[-1])))); ;} + break; + + case 80: +#line 261 "pars0grm.y" + { yyval = pars_func(&pars_sum_token, que_node_list_add_last(NULL, - yyvsp[-1])); ; - break;} -case 80: -#line 266 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 81: + yyvsp[-1])); ;} + break; + + case 81: #line 267 "pars0grm.y" -{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ; - break;} -case 82: -#line 269 "pars0grm.y" -{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ; - break;} -case 83: -#line 273 "pars0grm.y" -{ yyval = pars_select_list(&pars_star_denoter, - NULL); ; - break;} -case 84: -#line 276 "pars0grm.y" -{ yyval = pars_select_list(yyvsp[-2], yyvsp[0]); ; - break;} -case 85: + { yyval = NULL; ;} + break; + + case 82: +#line 268 "pars0grm.y" + { yyval = que_node_list_add_last(NULL, yyvsp[0]); ;} + break; + + case 83: +#line 270 "pars0grm.y" + { yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;} + break; + + case 84: +#line 274 "pars0grm.y" + { yyval = pars_select_list(&pars_star_denoter, + NULL); ;} + break; + + case 85: #line 277 "pars0grm.y" -{ yyval = pars_select_list(yyvsp[0], NULL); ; - break;} -case 86: -#line 281 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 87: + { yyval = pars_select_list(yyvsp[-2], yyvsp[0]); ;} + break; + + case 86: +#line 278 "pars0grm.y" + { yyval = pars_select_list(yyvsp[0], NULL); ;} + break; + + case 87: #line 282 "pars0grm.y" -{ yyval = yyvsp[0]; ; - break;} -case 88: -#line 286 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 89: -#line 288 "pars0grm.y" -{ yyval = &pars_update_token; ; - break;} -case 90: -#line 292 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 91: -#line 294 "pars0grm.y" -{ yyval = &pars_consistent_token; ; - break;} -case 92: -#line 298 "pars0grm.y" -{ yyval = &pars_asc_token; ; - break;} -case 93: + { yyval = NULL; ;} + break; + + case 88: +#line 283 "pars0grm.y" + { yyval = yyvsp[0]; ;} + break; + + case 89: +#line 287 "pars0grm.y" + { yyval = NULL; ;} + break; + + case 90: +#line 289 "pars0grm.y" + { yyval = &pars_update_token; ;} + break; + + case 91: +#line 293 "pars0grm.y" + { yyval = NULL; ;} + break; + + case 92: +#line 295 "pars0grm.y" + { yyval = &pars_consistent_token; ;} + break; + + case 93: #line 299 "pars0grm.y" -{ yyval = &pars_asc_token; ; - break;} -case 94: + { yyval = &pars_asc_token; ;} + break; + + case 94: #line 300 "pars0grm.y" -{ yyval = &pars_desc_token; ; - break;} -case 95: -#line 304 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 96: -#line 306 "pars0grm.y" -{ yyval = pars_order_by(yyvsp[-1], yyvsp[0]); ; - break;} -case 97: -#line 315 "pars0grm.y" -{ yyval = pars_select_statement(yyvsp[-6], yyvsp[-4], yyvsp[-3], - yyvsp[-2], yyvsp[-1], yyvsp[0]); ; - break;} -case 98: -#line 321 "pars0grm.y" -{ yyval = yyvsp[0]; ; - break;} -case 99: -#line 326 "pars0grm.y" -{ yyval = pars_insert_statement(yyvsp[-4], yyvsp[-1], NULL); ; - break;} -case 100: -#line 328 "pars0grm.y" -{ yyval = pars_insert_statement(yyvsp[-1], NULL, yyvsp[0]); ; - break;} -case 101: -#line 332 "pars0grm.y" -{ yyval = pars_column_assignment(yyvsp[-2], yyvsp[0]); ; - break;} -case 102: -#line 336 "pars0grm.y" -{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ; - break;} -case 103: -#line 338 "pars0grm.y" -{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ; - break;} -case 104: -#line 344 "pars0grm.y" -{ yyval = yyvsp[0]; ; - break;} -case 105: -#line 350 "pars0grm.y" -{ yyval = pars_update_statement_start(FALSE, - yyvsp[-2], yyvsp[0]); ; - break;} -case 106: -#line 356 "pars0grm.y" -{ yyval = pars_update_statement(yyvsp[-1], NULL, yyvsp[0]); ; - break;} -case 107: -#line 361 "pars0grm.y" -{ yyval = pars_update_statement(yyvsp[-1], yyvsp[0], NULL); ; - break;} -case 108: -#line 366 "pars0grm.y" -{ yyval = pars_update_statement_start(TRUE, - yyvsp[0], NULL); ; - break;} -case 109: -#line 372 "pars0grm.y" -{ yyval = pars_update_statement(yyvsp[-1], NULL, yyvsp[0]); ; - break;} -case 110: -#line 377 "pars0grm.y" -{ yyval = pars_update_statement(yyvsp[-1], yyvsp[0], NULL); ; - break;} -case 111: -#line 382 "pars0grm.y" -{ yyval = pars_row_printf_statement(yyvsp[0]); ; - break;} -case 112: -#line 387 "pars0grm.y" -{ yyval = pars_assignment_statement(yyvsp[-2], yyvsp[0]); ; - break;} -case 113: -#line 393 "pars0grm.y" -{ yyval = pars_elsif_element(yyvsp[-2], yyvsp[0]); ; - break;} -case 114: -#line 397 "pars0grm.y" -{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ; - break;} -case 115: -#line 399 "pars0grm.y" -{ yyval = que_node_list_add_last(yyvsp[-1], yyvsp[0]); ; - break;} -case 116: -#line 403 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 117: -#line 405 "pars0grm.y" -{ yyval = yyvsp[0]; ; - break;} -case 118: + { yyval = &pars_asc_token; ;} + break; + + case 95: +#line 301 "pars0grm.y" + { yyval = &pars_desc_token; ;} + break; + + case 96: +#line 305 "pars0grm.y" + { yyval = NULL; ;} + break; + + case 97: +#line 307 "pars0grm.y" + { yyval = pars_order_by(yyvsp[-1], yyvsp[0]); ;} + break; + + case 98: +#line 316 "pars0grm.y" + { yyval = pars_select_statement(yyvsp[-6], yyvsp[-4], yyvsp[-3], + yyvsp[-2], yyvsp[-1], yyvsp[0]); ;} + break; + + case 99: +#line 322 "pars0grm.y" + { yyval = yyvsp[0]; ;} + break; + + case 100: +#line 327 "pars0grm.y" + { yyval = pars_insert_statement(yyvsp[-4], yyvsp[-1], NULL); ;} + break; + + case 101: +#line 329 "pars0grm.y" + { yyval = pars_insert_statement(yyvsp[-1], NULL, yyvsp[0]); ;} + break; + + case 102: +#line 333 "pars0grm.y" + { yyval = pars_column_assignment(yyvsp[-2], yyvsp[0]); ;} + break; + + case 103: +#line 337 "pars0grm.y" + { yyval = que_node_list_add_last(NULL, yyvsp[0]); ;} + break; + + case 104: +#line 339 "pars0grm.y" + { yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;} + break; + + case 105: +#line 345 "pars0grm.y" + { yyval = yyvsp[0]; ;} + break; + + case 106: +#line 351 "pars0grm.y" + { yyval = pars_update_statement_start(FALSE, + yyvsp[-2], yyvsp[0]); ;} + break; + + case 107: +#line 357 "pars0grm.y" + { yyval = pars_update_statement(yyvsp[-1], NULL, yyvsp[0]); ;} + break; + + case 108: +#line 362 "pars0grm.y" + { yyval = pars_update_statement(yyvsp[-1], yyvsp[0], NULL); ;} + break; + + case 109: +#line 367 "pars0grm.y" + { yyval = pars_update_statement_start(TRUE, + yyvsp[0], NULL); ;} + break; + + case 110: +#line 373 "pars0grm.y" + { yyval = pars_update_statement(yyvsp[-1], NULL, yyvsp[0]); ;} + break; + + case 111: +#line 378 "pars0grm.y" + { yyval = pars_update_statement(yyvsp[-1], yyvsp[0], NULL); ;} + break; + + case 112: +#line 383 "pars0grm.y" + { yyval = pars_row_printf_statement(yyvsp[0]); ;} + break; + + case 113: +#line 388 "pars0grm.y" + { yyval = pars_assignment_statement(yyvsp[-2], yyvsp[0]); ;} + break; + + case 114: +#line 394 "pars0grm.y" + { yyval = pars_elsif_element(yyvsp[-2], yyvsp[0]); ;} + break; + + case 115: +#line 398 "pars0grm.y" + { yyval = que_node_list_add_last(NULL, yyvsp[0]); ;} + break; + + case 116: +#line 400 "pars0grm.y" + { yyval = que_node_list_add_last(yyvsp[-1], yyvsp[0]); ;} + break; + + case 117: +#line 404 "pars0grm.y" + { yyval = NULL; ;} + break; + + case 118: #line 406 "pars0grm.y" -{ yyval = yyvsp[0]; ; - break;} -case 119: -#line 413 "pars0grm.y" -{ yyval = pars_if_statement(yyvsp[-5], yyvsp[-3], yyvsp[-2]); ; - break;} -case 120: -#line 419 "pars0grm.y" -{ yyval = pars_while_statement(yyvsp[-4], yyvsp[-2]); ; - break;} -case 121: -#line 427 "pars0grm.y" -{ yyval = pars_for_statement(yyvsp[-8], yyvsp[-6], yyvsp[-4], yyvsp[-2]); ; - break;} -case 122: -#line 431 "pars0grm.y" -{ yyval = pars_return_statement(); ; - break;} -case 123: -#line 436 "pars0grm.y" -{ yyval = pars_open_statement( - ROW_SEL_OPEN_CURSOR, yyvsp[0]); ; - break;} -case 124: -#line 442 "pars0grm.y" -{ yyval = pars_open_statement( - ROW_SEL_CLOSE_CURSOR, yyvsp[0]); ; - break;} -case 125: -#line 448 "pars0grm.y" -{ yyval = pars_fetch_statement(yyvsp[-2], yyvsp[0]); ; - break;} -case 126: -#line 452 "pars0grm.y" -{ yyval = pars_column_def(yyvsp[-1], yyvsp[0]); ; - break;} -case 127: -#line 456 "pars0grm.y" -{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ; - break;} -case 128: + { yyval = yyvsp[0]; ;} + break; + + case 119: +#line 407 "pars0grm.y" + { yyval = yyvsp[0]; ;} + break; + + case 120: +#line 414 "pars0grm.y" + { yyval = pars_if_statement(yyvsp[-5], yyvsp[-3], yyvsp[-2]); ;} + break; + + case 121: +#line 420 "pars0grm.y" + { yyval = pars_while_statement(yyvsp[-4], yyvsp[-2]); ;} + break; + + case 122: +#line 428 "pars0grm.y" + { yyval = pars_for_statement(yyvsp[-8], yyvsp[-6], yyvsp[-4], yyvsp[-2]); ;} + break; + + case 123: +#line 432 "pars0grm.y" + { yyval = pars_return_statement(); ;} + break; + + case 124: +#line 437 "pars0grm.y" + { yyval = pars_open_statement( + ROW_SEL_OPEN_CURSOR, yyvsp[0]); ;} + break; + + case 125: +#line 443 "pars0grm.y" + { yyval = pars_open_statement( + ROW_SEL_CLOSE_CURSOR, yyvsp[0]); ;} + break; + + case 126: +#line 449 "pars0grm.y" + { yyval = pars_fetch_statement(yyvsp[-2], yyvsp[0]); ;} + break; + + case 127: +#line 454 "pars0grm.y" + { yyval = pars_column_def(yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); ;} + break; + + case 128: #line 458 "pars0grm.y" -{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ; - break;} -case 129: -#line 462 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 130: + { yyval = que_node_list_add_last(NULL, yyvsp[0]); ;} + break; + + case 129: +#line 460 "pars0grm.y" + { yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;} + break; + + case 130: #line 464 "pars0grm.y" -{ yyval = &pars_int_token; - /* pass any non-NULL pointer */ ; - break;} -case 131: -#line 471 "pars0grm.y" -{ yyval = pars_create_table(yyvsp[-4], yyvsp[-2], yyvsp[0]); ; - break;} -case 132: -#line 475 "pars0grm.y" -{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ; - break;} -case 133: + { yyval = NULL; ;} + break; + + case 131: +#line 466 "pars0grm.y" + { yyval = yyvsp[-1]; ;} + break; + + case 132: +#line 470 "pars0grm.y" + { yyval = NULL; ;} + break; + + case 133: +#line 472 "pars0grm.y" + { yyval = &pars_int_token; + /* pass any non-NULL pointer */ ;} + break; + + case 134: #line 477 "pars0grm.y" -{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ; - break;} -case 134: -#line 481 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 135: -#line 482 "pars0grm.y" -{ yyval = &pars_unique_token; ; - break;} -case 136: + { yyval = NULL; ;} + break; + + case 135: +#line 479 "pars0grm.y" + { yyval = &pars_int_token; + /* pass any non-NULL pointer */ ;} + break; + + case 136: #line 486 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 137: -#line 487 "pars0grm.y" -{ yyval = &pars_clustered_token; ; - break;} -case 138: -#line 495 "pars0grm.y" -{ yyval = pars_create_index(yyvsp[-8], yyvsp[-7], yyvsp[-5], yyvsp[-3], yyvsp[-1]); ; - break;} -case 139: -#line 500 "pars0grm.y" -{ yyval = pars_commit_statement(); ; - break;} -case 140: -#line 505 "pars0grm.y" -{ yyval = pars_rollback_statement(); ; - break;} -case 141: -#line 509 "pars0grm.y" -{ yyval = &pars_int_token; ; - break;} -case 142: + { yyval = pars_create_table(yyvsp[-4], yyvsp[-2], yyvsp[0]); ;} + break; + + case 137: +#line 490 "pars0grm.y" + { yyval = que_node_list_add_last(NULL, yyvsp[0]); ;} + break; + + case 138: +#line 492 "pars0grm.y" + { yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;} + break; + + case 139: +#line 496 "pars0grm.y" + { yyval = NULL; ;} + break; + + case 140: +#line 497 "pars0grm.y" + { yyval = &pars_unique_token; ;} + break; + + case 141: +#line 501 "pars0grm.y" + { yyval = NULL; ;} + break; + + case 142: +#line 502 "pars0grm.y" + { yyval = &pars_clustered_token; ;} + break; + + case 143: #line 510 "pars0grm.y" -{ yyval = &pars_char_token; ; - break;} -case 143: + { yyval = pars_create_index(yyvsp[-8], yyvsp[-7], yyvsp[-5], yyvsp[-3], yyvsp[-1]); ;} + break; + + case 144: #line 515 "pars0grm.y" -{ yyval = pars_parameter_declaration(yyvsp[-2], - PARS_INPUT, yyvsp[0]); ; - break;} -case 144: -#line 518 "pars0grm.y" -{ yyval = pars_parameter_declaration(yyvsp[-2], - PARS_OUTPUT, yyvsp[0]); ; - break;} -case 145: -#line 523 "pars0grm.y" -{ yyval = NULL; ; - break;} -case 146: + { yyval = pars_commit_statement(); ;} + break; + + case 145: +#line 520 "pars0grm.y" + { yyval = pars_rollback_statement(); ;} + break; + + case 146: #line 524 "pars0grm.y" -{ yyval = que_node_list_add_last(NULL, yyvsp[0]); ; - break;} -case 147: + { yyval = &pars_int_token; ;} + break; + + case 147: +#line 525 "pars0grm.y" + { yyval = &pars_int_token; ;} + break; + + case 148: #line 526 "pars0grm.y" -{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ; - break;} -case 148: -#line 531 "pars0grm.y" -{ yyval = pars_variable_declaration(yyvsp[-2], yyvsp[-1]); ; - break;} -case 152: -#line 543 "pars0grm.y" -{ yyval = pars_cursor_declaration(yyvsp[-3], yyvsp[-1]); ; - break;} -case 156: -#line 559 "pars0grm.y" -{ yyval = pars_procedure_definition(yyvsp[-9], yyvsp[-7], - yyvsp[-1]); ; - break;} -} - /* the action file gets copied in in place of this dollarsign */ -#line 554 "/usr/share/bison.simple" + { yyval = &pars_char_token; ;} + break; + + case 149: +#line 527 "pars0grm.y" + { yyval = &pars_binary_token; ;} + break; + + case 150: +#line 528 "pars0grm.y" + { yyval = &pars_blob_token; ;} + break; + + case 151: +#line 533 "pars0grm.y" + { yyval = pars_parameter_declaration(yyvsp[-2], + PARS_INPUT, yyvsp[0]); ;} + break; + + case 152: +#line 536 "pars0grm.y" + { yyval = pars_parameter_declaration(yyvsp[-2], + PARS_OUTPUT, yyvsp[0]); ;} + break; + + case 153: +#line 541 "pars0grm.y" + { yyval = NULL; ;} + break; + + case 154: +#line 542 "pars0grm.y" + { yyval = que_node_list_add_last(NULL, yyvsp[0]); ;} + break; + + case 155: +#line 544 "pars0grm.y" + { yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); ;} + break; + + case 156: +#line 549 "pars0grm.y" + { yyval = pars_variable_declaration(yyvsp[-2], yyvsp[-1]); ;} + break; + + case 160: +#line 561 "pars0grm.y" + { yyval = pars_cursor_declaration(yyvsp[-3], yyvsp[-1]); ;} + break; + + case 164: +#line 577 "pars0grm.y" + { yyval = pars_procedure_definition(yyvsp[-9], yyvsp[-7], + yyvsp[-1]); ;} + break; + + + } + +/* Line 1010 of yacc.c. */ +#line 2269 "pars0grm.tab.c" yyvsp -= yylen; yyssp -= yylen; -#ifdef YYLSP_NEEDED - yylsp -= yylen; -#endif -#if YYDEBUG != 0 - if (yydebug) - { - short *ssp1 = yyss - 1; - fprintf (stderr, "state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif + + YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; -#ifdef YYLSP_NEEDED - yylsp++; - if (yylen == 0) - { - yylsp->first_line = yylloc.first_line; - yylsp->first_column = yylloc.first_column; - yylsp->last_line = (yylsp-1)->last_line; - yylsp->last_column = (yylsp-1)->last_column; - yylsp->text = 0; - } - else - { - yylsp->last_line = (yylsp+yylen-1)->last_line; - yylsp->last_column = (yylsp+yylen-1)->last_column; - } -#endif - /* Now "shift" the result of the reduction. - Determine what state that goes to, - based on the state we popped back to - and the rule number reduced by. */ + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ yyn = yyr1[yyn]; - yystate = yypgoto[yyn - YYNTBASE] + *yyssp; - if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else - yystate = yydefgoto[yyn - YYNTBASE]; + yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; -yyerrlab: /* here on detecting error */ - if (! yyerrstatus) - /* If not already recovering from an error, report this error. */ +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) { ++yynerrs; - -#ifdef YYERROR_VERBOSE +#if YYERROR_VERBOSE yyn = yypact[yystate]; - if (yyn > YYFLAG && yyn < YYLAST) + if (YYPACT_NINF < yyn && yyn < YYLAST) { - int size = 0; - char *msg; - int x, count; - - count = 0; - /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) - size += strlen(yytname[x]) + 15, count++; - msg = (char *) malloc(size + 15); - if (msg != 0) + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + const char* yyprefix; + char *yymsg; + int yyx; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 0; + + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); + yycount += 1; + if (yycount == 5) + { + yysize = 0; + break; + } + } + yysize += (sizeof ("syntax error, unexpected ") + + yystrlen (yytname[yytype])); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) { - strcpy(msg, "parse error"); + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); - if (count < 5) + if (yycount < 5) { - count = 0; - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { - strcat(msg, count == 0 ? ", expecting `" : " or `"); - strcat(msg, yytname[x]); - strcat(msg, "'"); - count++; + yyp = yystpcpy (yyp, yyprefix); + yyp = yystpcpy (yyp, yytname[yyx]); + yyprefix = " or "; } } - yyerror(msg); - free(msg); + yyerror (yymsg); + YYSTACK_FREE (yymsg); } else - yyerror ("parse error; also virtual memory exceeded"); + yyerror ("syntax error; also virtual memory exhausted"); } else #endif /* YYERROR_VERBOSE */ - yyerror("parse error"); + yyerror ("syntax error"); } - goto yyerrlab1; -yyerrlab1: /* here on error raised explicitly by an action */ + if (yyerrstatus == 3) { - /* if just tried and failed to reuse lookahead token after an error, discard it. */ - - /* return failure if at end of input */ - if (yychar == YYEOF) - YYABORT; - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); -#endif + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* If at end of input, pop the error token, + then the rest of the stack, then return failure. */ + if (yychar == YYEOF) + for (;;) + { + YYPOPSTACK; + if (yyssp == yyss) + YYABORT; + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[*yyssp], yyvsp); + } + } + else + { + YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); + yydestruct (yytoken, &yylval); + yychar = YYEMPTY; - yychar = YYEMPTY; + } } - /* Else will try to reuse lookahead token - after shifting the error token. */ - - yyerrstatus = 3; /* Each real token shifted decrements this */ + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; - goto yyerrhandle; -yyerrdefault: /* current state does not do anything special for the error token. */ +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: -#if 0 - /* This is wrong; only states that explicitly want error tokens - should shift them. */ - yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ - if (yyn) goto yydefault; +#ifdef __GNUC__ + /* Pacify GCC when the user code never invokes YYERROR and the label + yyerrorlab therefore never appears in user code. */ + if (0) + goto yyerrorlab; #endif -yyerrpop: /* pop the current state because it cannot handle the error token */ - - if (yyssp == yyss) YYABORT; - yyvsp--; - yystate = *--yyssp; -#ifdef YYLSP_NEEDED - yylsp--; -#endif + yyvsp -= yylen; + yyssp -= yylen; + yystate = *yyssp; + goto yyerrlab1; -#if YYDEBUG != 0 - if (yydebug) - { - short *ssp1 = yyss - 1; - fprintf (stderr, "Error: state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif -yyerrhandle: +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ - yyn = yypact[yystate]; - if (yyn == YYFLAG) - goto yyerrdefault; + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } - yyn += YYTERROR; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) - goto yyerrdefault; + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; - yyn = yytable[yyn]; - if (yyn < 0) - { - if (yyn == YYFLAG) - goto yyerrpop; - yyn = -yyn; - goto yyreduce; + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[yystate], yyvsp); + YYPOPSTACK; + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); } - else if (yyn == 0) - goto yyerrpop; if (yyn == YYFINAL) YYACCEPT; -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting error token, "); -#endif + YYDPRINTF ((stderr, "Shifting error token, ")); *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif + yystate = yyn; goto yynewstate; - yyacceptlab: - /* YYACCEPT comes here. */ -#ifndef YYSTACK_USE_ALLOCA - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ #endif - return 0; - yyabortlab: - /* YYABORT comes here. */ -#ifndef YYSTACK_USE_ALLOCA - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); #endif - } -#endif - return 1; + return yyresult; } -#line 563 "pars0grm.y" + + +#line 581 "pars0grm.y" + diff --git a/storage/innobase/pars/pars0grm.h b/storage/innobase/pars/pars0grm.h index b2790949057..e35fcf47692 100644 --- a/storage/innobase/pars/pars0grm.h +++ b/storage/innobase/pars/pars0grm.h @@ -1,90 +1,220 @@ -#ifndef YYSTYPE -#define YYSTYPE int +/* A Bison parser, made by GNU Bison 1.875d. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + PARS_INT_LIT = 258, + PARS_FLOAT_LIT = 259, + PARS_STR_LIT = 260, + PARS_NULL_LIT = 261, + PARS_ID_TOKEN = 262, + PARS_AND_TOKEN = 263, + PARS_OR_TOKEN = 264, + PARS_NOT_TOKEN = 265, + PARS_GE_TOKEN = 266, + PARS_LE_TOKEN = 267, + PARS_NE_TOKEN = 268, + PARS_PROCEDURE_TOKEN = 269, + PARS_IN_TOKEN = 270, + PARS_OUT_TOKEN = 271, + PARS_BINARY_TOKEN = 272, + PARS_BLOB_TOKEN = 273, + PARS_INT_TOKEN = 274, + PARS_INTEGER_TOKEN = 275, + PARS_FLOAT_TOKEN = 276, + PARS_CHAR_TOKEN = 277, + PARS_IS_TOKEN = 278, + PARS_BEGIN_TOKEN = 279, + PARS_END_TOKEN = 280, + PARS_IF_TOKEN = 281, + PARS_THEN_TOKEN = 282, + PARS_ELSE_TOKEN = 283, + PARS_ELSIF_TOKEN = 284, + PARS_LOOP_TOKEN = 285, + PARS_WHILE_TOKEN = 286, + PARS_RETURN_TOKEN = 287, + PARS_SELECT_TOKEN = 288, + PARS_SUM_TOKEN = 289, + PARS_COUNT_TOKEN = 290, + PARS_DISTINCT_TOKEN = 291, + PARS_FROM_TOKEN = 292, + PARS_WHERE_TOKEN = 293, + PARS_FOR_TOKEN = 294, + PARS_DDOT_TOKEN = 295, + PARS_CONSISTENT_TOKEN = 296, + PARS_READ_TOKEN = 297, + PARS_ORDER_TOKEN = 298, + PARS_BY_TOKEN = 299, + PARS_ASC_TOKEN = 300, + PARS_DESC_TOKEN = 301, + PARS_INSERT_TOKEN = 302, + PARS_INTO_TOKEN = 303, + PARS_VALUES_TOKEN = 304, + PARS_UPDATE_TOKEN = 305, + PARS_SET_TOKEN = 306, + PARS_DELETE_TOKEN = 307, + PARS_CURRENT_TOKEN = 308, + PARS_OF_TOKEN = 309, + PARS_CREATE_TOKEN = 310, + PARS_TABLE_TOKEN = 311, + PARS_INDEX_TOKEN = 312, + PARS_UNIQUE_TOKEN = 313, + PARS_CLUSTERED_TOKEN = 314, + PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 315, + PARS_ON_TOKEN = 316, + PARS_ASSIGN_TOKEN = 317, + PARS_DECLARE_TOKEN = 318, + PARS_CURSOR_TOKEN = 319, + PARS_SQL_TOKEN = 320, + PARS_OPEN_TOKEN = 321, + PARS_FETCH_TOKEN = 322, + PARS_CLOSE_TOKEN = 323, + PARS_NOTFOUND_TOKEN = 324, + PARS_TO_CHAR_TOKEN = 325, + PARS_TO_NUMBER_TOKEN = 326, + PARS_TO_BINARY_TOKEN = 327, + PARS_BINARY_TO_NUMBER_TOKEN = 328, + PARS_SUBSTR_TOKEN = 329, + PARS_REPLSTR_TOKEN = 330, + PARS_CONCAT_TOKEN = 331, + PARS_INSTR_TOKEN = 332, + PARS_LENGTH_TOKEN = 333, + PARS_SYSDATE_TOKEN = 334, + PARS_PRINTF_TOKEN = 335, + PARS_ASSERT_TOKEN = 336, + PARS_RND_TOKEN = 337, + PARS_RND_STR_TOKEN = 338, + PARS_ROW_PRINTF_TOKEN = 339, + PARS_COMMIT_TOKEN = 340, + PARS_ROLLBACK_TOKEN = 341, + PARS_WORK_TOKEN = 342, + NEG = 343 + }; #endif -#define PARS_INT_LIT 257 -#define PARS_FLOAT_LIT 258 -#define PARS_STR_LIT 259 -#define PARS_NULL_LIT 260 -#define PARS_ID_TOKEN 261 -#define PARS_AND_TOKEN 262 -#define PARS_OR_TOKEN 263 -#define PARS_NOT_TOKEN 264 -#define PARS_GE_TOKEN 265 -#define PARS_LE_TOKEN 266 -#define PARS_NE_TOKEN 267 -#define PARS_PROCEDURE_TOKEN 268 -#define PARS_IN_TOKEN 269 -#define PARS_OUT_TOKEN 270 -#define PARS_INT_TOKEN 271 -#define PARS_INTEGER_TOKEN 272 -#define PARS_FLOAT_TOKEN 273 -#define PARS_CHAR_TOKEN 274 -#define PARS_IS_TOKEN 275 -#define PARS_BEGIN_TOKEN 276 -#define PARS_END_TOKEN 277 -#define PARS_IF_TOKEN 278 -#define PARS_THEN_TOKEN 279 -#define PARS_ELSE_TOKEN 280 -#define PARS_ELSIF_TOKEN 281 -#define PARS_LOOP_TOKEN 282 -#define PARS_WHILE_TOKEN 283 -#define PARS_RETURN_TOKEN 284 -#define PARS_SELECT_TOKEN 285 -#define PARS_SUM_TOKEN 286 -#define PARS_COUNT_TOKEN 287 -#define PARS_DISTINCT_TOKEN 288 -#define PARS_FROM_TOKEN 289 -#define PARS_WHERE_TOKEN 290 -#define PARS_FOR_TOKEN 291 -#define PARS_DDOT_TOKEN 292 -#define PARS_CONSISTENT_TOKEN 293 -#define PARS_READ_TOKEN 294 -#define PARS_ORDER_TOKEN 295 -#define PARS_BY_TOKEN 296 -#define PARS_ASC_TOKEN 297 -#define PARS_DESC_TOKEN 298 -#define PARS_INSERT_TOKEN 299 -#define PARS_INTO_TOKEN 300 -#define PARS_VALUES_TOKEN 301 -#define PARS_UPDATE_TOKEN 302 -#define PARS_SET_TOKEN 303 -#define PARS_DELETE_TOKEN 304 -#define PARS_CURRENT_TOKEN 305 -#define PARS_OF_TOKEN 306 -#define PARS_CREATE_TOKEN 307 -#define PARS_TABLE_TOKEN 308 -#define PARS_INDEX_TOKEN 309 -#define PARS_UNIQUE_TOKEN 310 -#define PARS_CLUSTERED_TOKEN 311 -#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 312 -#define PARS_ON_TOKEN 313 -#define PARS_ASSIGN_TOKEN 314 -#define PARS_DECLARE_TOKEN 315 -#define PARS_CURSOR_TOKEN 316 -#define PARS_SQL_TOKEN 317 -#define PARS_OPEN_TOKEN 318 -#define PARS_FETCH_TOKEN 319 -#define PARS_CLOSE_TOKEN 320 -#define PARS_NOTFOUND_TOKEN 321 -#define PARS_TO_CHAR_TOKEN 322 -#define PARS_TO_NUMBER_TOKEN 323 -#define PARS_TO_BINARY_TOKEN 324 -#define PARS_BINARY_TO_NUMBER_TOKEN 325 -#define PARS_SUBSTR_TOKEN 326 -#define PARS_REPLSTR_TOKEN 327 -#define PARS_CONCAT_TOKEN 328 -#define PARS_INSTR_TOKEN 329 -#define PARS_LENGTH_TOKEN 330 -#define PARS_SYSDATE_TOKEN 331 -#define PARS_PRINTF_TOKEN 332 -#define PARS_ASSERT_TOKEN 333 -#define PARS_RND_TOKEN 334 -#define PARS_RND_STR_TOKEN 335 -#define PARS_ROW_PRINTF_TOKEN 336 -#define PARS_COMMIT_TOKEN 337 -#define PARS_ROLLBACK_TOKEN 338 -#define PARS_WORK_TOKEN 339 -#define NEG 340 +#define PARS_INT_LIT 258 +#define PARS_FLOAT_LIT 259 +#define PARS_STR_LIT 260 +#define PARS_NULL_LIT 261 +#define PARS_ID_TOKEN 262 +#define PARS_AND_TOKEN 263 +#define PARS_OR_TOKEN 264 +#define PARS_NOT_TOKEN 265 +#define PARS_GE_TOKEN 266 +#define PARS_LE_TOKEN 267 +#define PARS_NE_TOKEN 268 +#define PARS_PROCEDURE_TOKEN 269 +#define PARS_IN_TOKEN 270 +#define PARS_OUT_TOKEN 271 +#define PARS_BINARY_TOKEN 272 +#define PARS_BLOB_TOKEN 273 +#define PARS_INT_TOKEN 274 +#define PARS_INTEGER_TOKEN 275 +#define PARS_FLOAT_TOKEN 276 +#define PARS_CHAR_TOKEN 277 +#define PARS_IS_TOKEN 278 +#define PARS_BEGIN_TOKEN 279 +#define PARS_END_TOKEN 280 +#define PARS_IF_TOKEN 281 +#define PARS_THEN_TOKEN 282 +#define PARS_ELSE_TOKEN 283 +#define PARS_ELSIF_TOKEN 284 +#define PARS_LOOP_TOKEN 285 +#define PARS_WHILE_TOKEN 286 +#define PARS_RETURN_TOKEN 287 +#define PARS_SELECT_TOKEN 288 +#define PARS_SUM_TOKEN 289 +#define PARS_COUNT_TOKEN 290 +#define PARS_DISTINCT_TOKEN 291 +#define PARS_FROM_TOKEN 292 +#define PARS_WHERE_TOKEN 293 +#define PARS_FOR_TOKEN 294 +#define PARS_DDOT_TOKEN 295 +#define PARS_CONSISTENT_TOKEN 296 +#define PARS_READ_TOKEN 297 +#define PARS_ORDER_TOKEN 298 +#define PARS_BY_TOKEN 299 +#define PARS_ASC_TOKEN 300 +#define PARS_DESC_TOKEN 301 +#define PARS_INSERT_TOKEN 302 +#define PARS_INTO_TOKEN 303 +#define PARS_VALUES_TOKEN 304 +#define PARS_UPDATE_TOKEN 305 +#define PARS_SET_TOKEN 306 +#define PARS_DELETE_TOKEN 307 +#define PARS_CURRENT_TOKEN 308 +#define PARS_OF_TOKEN 309 +#define PARS_CREATE_TOKEN 310 +#define PARS_TABLE_TOKEN 311 +#define PARS_INDEX_TOKEN 312 +#define PARS_UNIQUE_TOKEN 313 +#define PARS_CLUSTERED_TOKEN 314 +#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 315 +#define PARS_ON_TOKEN 316 +#define PARS_ASSIGN_TOKEN 317 +#define PARS_DECLARE_TOKEN 318 +#define PARS_CURSOR_TOKEN 319 +#define PARS_SQL_TOKEN 320 +#define PARS_OPEN_TOKEN 321 +#define PARS_FETCH_TOKEN 322 +#define PARS_CLOSE_TOKEN 323 +#define PARS_NOTFOUND_TOKEN 324 +#define PARS_TO_CHAR_TOKEN 325 +#define PARS_TO_NUMBER_TOKEN 326 +#define PARS_TO_BINARY_TOKEN 327 +#define PARS_BINARY_TO_NUMBER_TOKEN 328 +#define PARS_SUBSTR_TOKEN 329 +#define PARS_REPLSTR_TOKEN 330 +#define PARS_CONCAT_TOKEN 331 +#define PARS_INSTR_TOKEN 332 +#define PARS_LENGTH_TOKEN 333 +#define PARS_SYSDATE_TOKEN 334 +#define PARS_PRINTF_TOKEN 335 +#define PARS_ASSERT_TOKEN 336 +#define PARS_RND_TOKEN 337 +#define PARS_RND_STR_TOKEN 338 +#define PARS_ROW_PRINTF_TOKEN 339 +#define PARS_COMMIT_TOKEN 340 +#define PARS_ROLLBACK_TOKEN 341 +#define PARS_WORK_TOKEN 342 +#define NEG 343 + + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +typedef int YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + extern YYSTYPE yylval; + + + diff --git a/storage/innobase/pars/pars0grm.y b/storage/innobase/pars/pars0grm.y index a142d04301e..435025d7386 100644 --- a/storage/innobase/pars/pars0grm.y +++ b/storage/innobase/pars/pars0grm.y @@ -44,6 +44,8 @@ yylex(void); %token PARS_PROCEDURE_TOKEN %token PARS_IN_TOKEN %token PARS_OUT_TOKEN +%token PARS_BINARY_TOKEN +%token PARS_BLOB_TOKEN %token PARS_INT_TOKEN %token PARS_INTEGER_TOKEN %token PARS_FLOAT_TOKEN @@ -448,7 +450,8 @@ fetch_statement: ; column_def: - PARS_ID_TOKEN type_name { $$ = pars_column_def($1, $2); } + PARS_ID_TOKEN type_name opt_column_len opt_not_null + { $$ = pars_column_def($1, $2, $3, $4); } ; column_def_list: @@ -457,6 +460,19 @@ column_def_list: { $$ = que_node_list_add_last($1, $3); } ; +opt_column_len: + /* Nothing */ { $$ = NULL; } + | '(' PARS_INT_LIT ')' + { $$ = $2; } +; + +opt_not_null: + /* Nothing */ { $$ = NULL; } + | PARS_NOT_TOKEN PARS_NULL_LIT + { $$ = &pars_int_token; + /* pass any non-NULL pointer */ } +; + not_fit_in_memory: /* Nothing */ { $$ = NULL; } | PARS_DOES_NOT_FIT_IN_MEM_TOKEN @@ -506,7 +522,10 @@ rollback_statement: type_name: PARS_INT_TOKEN { $$ = &pars_int_token; } + | PARS_INTEGER_TOKEN { $$ = &pars_int_token; } | PARS_CHAR_TOKEN { $$ = &pars_char_token; } + | PARS_BINARY_TOKEN { $$ = &pars_binary_token; } + | PARS_BLOB_TOKEN { $$ = &pars_blob_token; } ; parameter_declaration: diff --git a/storage/innobase/pars/pars0lex.l b/storage/innobase/pars/pars0lex.l index e481634f77e..4224536d49e 100644 --- a/storage/innobase/pars/pars0lex.l +++ b/storage/innobase/pars/pars0lex.l @@ -26,12 +26,10 @@ How to make the InnoDB parser and lexer C files: 5. Rename lex.yy.c to lexyy.c. -6. Remove the #include of unistd.h from about line 2500 of lexyy.c - -7. Add '#include "univ.i"' before #include <stdio.h> in lexyy.c +6. Add '#include "univ.i"' before #include <stdio.h> in lexyy.c (Needed for AIX) -8. Add a type cast to int to the assignment below the comment +7. Add a type cast to int to the assignment below the comment 'need more input.' (Removes a warning on Win64) These instructions seem to work at least with bison-1.28 and flex-2.5.4 on @@ -50,6 +48,7 @@ Linux. %option noyy_scan_buffer %option noyy_scan_bytes %option noyy_scan_string +%option nounistd %{ #define YYSTYPE que_node_t* @@ -191,6 +190,14 @@ In the state 'quoted', only two actions are possible (defined below). */ return(PARS_OUT_TOKEN); } +"BINARY" { + return(PARS_BINARY_TOKEN); +} + +"BLOB" { + return(PARS_BLOB_TOKEN); +} + "INT" { return(PARS_INT_TOKEN); } diff --git a/storage/innobase/pars/pars0opt.c b/storage/innobase/pars/pars0opt.c index 88022e2efe1..bb41b5da074 100644 --- a/storage/innobase/pars/pars0opt.c +++ b/storage/innobase/pars/pars0opt.c @@ -106,7 +106,7 @@ opt_check_exp_determined_before( } for (i = 0; i < nth_table; i++) { - + table = sel_node_get_nth_plan(sel_node, i)->table; if (sym_node->table == table) { @@ -115,7 +115,7 @@ opt_check_exp_determined_before( } } - return(FALSE); + return(FALSE); } /*********************************************************************** @@ -148,10 +148,10 @@ opt_look_for_col_in_comparison_before( ut_ad(search_cond); ut_a((search_cond->func == '<') - || (search_cond->func == '>') - || (search_cond->func == '=') - || (search_cond->func == PARS_GE_TOKEN) - || (search_cond->func == PARS_LE_TOKEN)); + || (search_cond->func == '>') + || (search_cond->func == '=') + || (search_cond->func == PARS_GE_TOKEN) + || (search_cond->func == PARS_LE_TOKEN)); table = sel_node_get_nth_plan(sel_node, nth_table)->table; @@ -161,7 +161,7 @@ opt_look_for_col_in_comparison_before( } else if ((cmp_type == OPT_COMPARISON) && (search_cond->func != '<') - && (search_cond->func != '>') + && (search_cond->func != '>') && (search_cond->func != PARS_GE_TOKEN) && (search_cond->func != PARS_LE_TOKEN)) { @@ -176,14 +176,14 @@ opt_look_for_col_in_comparison_before( if ((sym_node->token_type == SYM_COLUMN) && (sym_node->table == table) && (sym_node->col_no == col_no)) { - + /* sym_node contains the desired column id */ /* Check if the expression on the right side of the operator is already determined */ exp = que_node_get_next(arg); - + if (opt_check_exp_determined_before(exp, sel_node, nth_table)) { *op = search_cond->func; @@ -191,10 +191,10 @@ opt_look_for_col_in_comparison_before( return(exp); } } - } + } - exp = search_cond->args; - arg = que_node_get_next(arg); + exp = search_cond->args; + arg = que_node_get_next(arg); if (que_node_get_type(arg) == QUE_NODE_SYMBOL) { sym_node = arg; @@ -202,7 +202,7 @@ opt_look_for_col_in_comparison_before( if ((sym_node->token_type == SYM_COLUMN) && (sym_node->table == table) && (sym_node->col_no == col_no)) { - + if (opt_check_exp_determined_before(exp, sel_node, nth_table)) { *op = opt_invert_cmp_op(search_cond->func); @@ -210,8 +210,8 @@ opt_look_for_col_in_comparison_before( return(exp); } } - } - + } + return(NULL); } @@ -243,12 +243,12 @@ opt_look_for_col_in_cond_before( if (search_cond == NULL) { return(NULL); - } + } ut_a(que_node_get_type(search_cond) == QUE_NODE_FUNC); ut_a(search_cond->func != PARS_OR_TOKEN); - ut_a(search_cond->func != PARS_NOT_TOKEN); - + ut_a(search_cond->func != PARS_NOT_TOKEN); + if (search_cond->func == PARS_AND_TOKEN) { new_cond = search_cond->args; @@ -260,7 +260,7 @@ opt_look_for_col_in_cond_before( } new_cond = que_node_get_next(new_cond); - + exp = opt_look_for_col_in_cond_before(cmp_type, col_no, new_cond, sel_node, nth_table, op); return(exp); @@ -276,7 +276,7 @@ opt_look_for_col_in_cond_before( /* If we will fetch in an ascending order, we cannot utilize an upper limit for a column value; in a descending order, respectively, a lower limit */ - + if (sel_node->asc && ((*op == '<') || (*op == PARS_LE_TOKEN))) { return(NULL); @@ -323,11 +323,11 @@ opt_calc_index_goodness( page addresses as the last field, we must not put more fields in the search tuple than dict_index_get_n_unique_in_tree(index); see the note in btr_cur_search_to_nth_level. */ - + n_fields = dict_index_get_n_unique_in_tree(index); mix_id_col_no = dict_table_get_sys_col_no(index->table, DATA_MIX_ID); - + for (j = 0; j < n_fields; j++) { col_no = dict_index_get_nth_col_no(index, j); @@ -337,11 +337,11 @@ opt_calc_index_goodness( sel_node, nth_table, &op); if (col_no == mix_id_col_no) { ut_ad(exp == NULL); - + index_plan[j] = NULL; *last_op = '='; goodness += 4; - } else if (exp) { + } else if (exp) { /* The value for this column is exactly known already at this stage of the join */ @@ -358,10 +358,10 @@ opt_calc_index_goodness( index_plan[j] = exp; *last_op = op; goodness += 2; - } - + } + break; - } + } } if (goodness >= 4 * dict_index_get_n_unique(index)) { @@ -412,7 +412,7 @@ opt_op_to_search_mode( return(PAGE_CUR_GE); } else { return(PAGE_CUR_LE); - } + } } else if (op == '<') { ut_a(!asc); return(PAGE_CUR_L); @@ -490,8 +490,8 @@ opt_check_order_by( column defined in the order-by clause, and for all the other tables we should get only at most a single row, otherwise we cannot presently calculate the order-by, as we have no sort utility */ - - for (i = 0; i < sel_node->n_tables; i++) { + + for (i = 0; i < sel_node->n_tables; i++) { plan = sel_node_get_nth_plan(sel_node, i); @@ -502,10 +502,10 @@ opt_check_order_by( ut_a(plan->table == order_table); ut_a((dict_index_get_n_unique(plan->index) - <= plan->n_exact_match) - || (dict_index_get_nth_col_no(plan->index, - plan->n_exact_match) - == order_col_no)); + <= plan->n_exact_match) + || (dict_index_get_nth_col_no(plan->index, + plan->n_exact_match) + == order_col_no)); } } } @@ -547,7 +547,7 @@ opt_search_plan_for_table( index = dict_table_get_first_index(table); best_index = index; /* Eliminate compiler warning */ best_goodness = 0; - + /* should be do ... until ? comment by Jani */ while (index) { goodness = opt_calc_index_goodness(index, sel_node, i, @@ -564,7 +564,7 @@ opt_search_plan_for_table( } index = dict_table_get_next_index(index); - } + } plan->index = best_index; @@ -577,24 +577,24 @@ opt_search_plan_for_table( plan->tuple = dtuple_create(pars_sym_tab_global->heap, n_fields); dict_index_copy_types(plan->tuple, plan->index, n_fields); - + plan->tuple_exps = mem_heap_alloc(pars_sym_tab_global->heap, n_fields * sizeof(void*)); ut_memcpy(plan->tuple_exps, best_index_plan, - n_fields * sizeof(void*)); + n_fields * sizeof(void*)); if (best_last_op == '=') { plan->n_exact_match = n_fields; } else { plan->n_exact_match = n_fields - 1; } - + plan->mode = opt_op_to_search_mode(sel_node->asc, best_last_op); } if ((best_index->type & DICT_CLUSTERED) - && (plan->n_exact_match >= dict_index_get_n_unique(best_index))) { + && (plan->n_exact_match >= dict_index_get_n_unique(best_index))) { plan->unique_search = TRUE; } else { @@ -602,25 +602,25 @@ opt_search_plan_for_table( } if ((table->type != DICT_TABLE_ORDINARY) - && (best_index->type & DICT_CLUSTERED)) { + && (best_index->type & DICT_CLUSTERED)) { - plan->mixed_index = TRUE; + plan->mixed_index = TRUE; - mix_id_pos = table->mix_len; + mix_id_pos = table->mix_len; - if (mix_id_pos < n_fields) { - /* We have to add the mix id as a (string) literal + if (mix_id_pos < n_fields) { + /* We have to add the mix id as a (string) literal expression to the tuple_exps */ plan->tuple_exps[mix_id_pos] = sym_tab_add_str_lit(pars_sym_tab_global, table->mix_id_buf, table->mix_id_len); - } + } } else { plan->mixed_index = FALSE; } - + plan->old_vers_heap = NULL; btr_pcur_init(&(plan->pcur)); @@ -690,9 +690,9 @@ opt_classify_comparison( the testing is necessary when the cursor is reversed. */ if ((n_fields > plan->n_exact_match) - && opt_is_arg(plan->tuple_exps[n_fields - 1], cond)) { + && opt_is_arg(plan->tuple_exps[n_fields - 1], cond)) { - return(OPT_SCROLL_COND); + return(OPT_SCROLL_COND); } /* If the condition is a non-exact match condition on the first field @@ -701,12 +701,12 @@ opt_classify_comparison( access the table, it is classified as OPT_END_COND */ if ((dict_index_get_n_fields(plan->index) > plan->n_exact_match) - && opt_look_for_col_in_comparison_before( - OPT_COMPARISON, - dict_index_get_nth_col_no(plan->index, - plan->n_exact_match), - cond, sel_node, i, &op)) { - + && opt_look_for_col_in_comparison_before( + OPT_COMPARISON, + dict_index_get_nth_col_no(plan->index, + plan->n_exact_match), + cond, sel_node, i, &op)) { + if (sel_node->asc && ((op == '<') || (op == PARS_LE_TOKEN))) { return(OPT_END_COND); @@ -749,7 +749,7 @@ opt_find_test_conds( opt_find_test_conds(sel_node, i, new_cond); new_cond = que_node_get_next(new_cond); - + opt_find_test_conds(sel_node, i, new_cond); return; @@ -808,7 +808,7 @@ opt_normalize_cmp_conds( cond = UT_LIST_GET_NEXT(cond_list, cond); } -} +} /*********************************************************************** Finds out the search condition conjuncts we can, and need, to test as the ith @@ -827,7 +827,7 @@ opt_determine_and_normalize_test_conds( UT_LIST_INIT(plan->end_conds); UT_LIST_INIT(plan->other_conds); - + /* Recursively go through the conjuncts and classify them */ opt_find_test_conds(sel_node, i, sel_node->search_cond); @@ -868,7 +868,7 @@ opt_find_all_cols( return; } - + if (que_node_get_type(exp) == QUE_NODE_FUNC) { func_node = exp; @@ -929,12 +929,12 @@ opt_find_all_cols( sym_node->copy_val = copy_val; /* Fill in the field_no fields in sym_node */ - + sym_node->field_nos[SYM_CLUST_FIELD_NO] = dict_index_get_nth_col_pos( dict_table_get_first_index(index->table), sym_node->col_no); - if (!(index->type & DICT_CLUSTERED)) { + if (!(index->type & DICT_CLUSTERED)) { ut_a(plan); @@ -944,7 +944,7 @@ opt_find_all_cols( plan->must_get_clust = TRUE; } - + sym_node->field_nos[SYM_SEC_FIELD_NO] = col_pos; } } @@ -969,16 +969,16 @@ opt_find_copy_cols( return; } - + ut_ad(que_node_get_type(search_cond) == QUE_NODE_FUNC); if (search_cond->func == PARS_AND_TOKEN) { new_cond = search_cond->args; opt_find_copy_cols(sel_node, i, new_cond); - + new_cond = que_node_get_next(new_cond); - + opt_find_copy_cols(sel_node, i, new_cond); return; @@ -991,7 +991,7 @@ opt_find_copy_cols( fetch from the ith table */ plan = sel_node_get_nth_plan(sel_node, i); - + opt_find_all_cols(TRUE, plan->index, &(plan->columns), plan, search_cond); } @@ -1036,7 +1036,7 @@ opt_classify_cols( /* All remaining columns in the search condition are temporary columns: therefore FALSE */ - + opt_find_all_cols(FALSE, plan->index, &(plan->columns), plan, sel_node->search_cond); } @@ -1064,10 +1064,10 @@ opt_clust_access( plan = sel_node_get_nth_plan(sel_node, n); index = plan->index; - + /* The final value of the following field depends on the environment of the select statement: */ - + plan->no_prefetch = FALSE; if (index->type & DICT_CLUSTERED) { @@ -1088,9 +1088,9 @@ opt_clust_access( plan->clust_ref = dtuple_create(heap, n_fields); dict_index_copy_types(plan->clust_ref, clust_index, n_fields); - + plan->clust_map = mem_heap_alloc(heap, n_fields * sizeof(ulint)); - + for (i = 0; i < n_fields; i++) { pos = dict_index_get_nth_field_pos(index, clust_index, i); @@ -1100,8 +1100,8 @@ opt_clust_access( tables, and they should not contain column prefix indexes. */ if (dict_index_get_nth_field(index, pos)->prefix_len != 0 - || dict_index_get_nth_field(clust_index, i) - ->prefix_len != 0) { + || dict_index_get_nth_field(clust_index, i) + ->prefix_len != 0) { fprintf(stderr, "InnoDB: Error in pars0opt.c: table %s has prefix_len != 0\n", index->table_name); @@ -1111,15 +1111,15 @@ opt_clust_access( ut_ad((pos != ULINT_UNDEFINED) || ((table->type == DICT_TABLE_CLUSTER_MEMBER) - && (i == table->mix_len))); + && (i == table->mix_len))); } if (table->type == DICT_TABLE_CLUSTER_MEMBER) { - + /* Preset the mix id field to the mix id constant */ - + dfield = dtuple_get_nth_field(plan->clust_ref, table->mix_len); - + dfield_set_data(dfield, mem_heap_alloc(heap, table->mix_id_len), table->mix_id_len); @@ -1142,7 +1142,7 @@ opt_search_plan( dict_table_t* table; order_node_t* order_by; ulint i; - + sel_node->plans = mem_heap_alloc(pars_sym_tab_global->heap, sel_node->n_tables * sizeof(plan_t)); @@ -1159,18 +1159,18 @@ opt_search_plan( sel_node->asc = order_by->asc; } - + for (i = 0; i < sel_node->n_tables; i++) { table = table_node->table; /* Choose index through which to access the table */ - + opt_search_plan_for_table(sel_node, i, table); /* Determine the search condition conjuncts we can test at this table; normalize the end conditions */ - + opt_determine_and_normalize_test_conds(sel_node, i); table_node = que_node_get_next(table_node); @@ -1192,10 +1192,10 @@ opt_search_plan( table_node = que_node_get_next(table_node); } - + /* Check that the plan obeys a possible order-by clause: if not, an assertion error occurs */ - + opt_check_order_by(sel_node); #ifdef UNIV_SQL_DEBUG @@ -1244,8 +1244,8 @@ opt_print_query_plan( fputs("Table ", stderr); dict_index_name_print(stderr, NULL, plan->index); fprintf(stderr,"; exact m. %lu, match %lu, end conds %lu\n", - (unsigned long) plan->n_exact_match, - (unsigned long) n_fields, + (unsigned long) plan->n_exact_match, + (unsigned long) n_fields, (unsigned long) UT_LIST_GET_LEN(plan->end_conds)); } } diff --git a/storage/innobase/pars/pars0pars.c b/storage/innobase/pars/pars0pars.c index c62184abd85..1b7a3a653a9 100644 --- a/storage/innobase/pars/pars0pars.c +++ b/storage/innobase/pars/pars0pars.c @@ -62,6 +62,8 @@ pars_res_word_t pars_rnd_str_token = {PARS_RND_STR_TOKEN}; pars_res_word_t pars_count_token = {PARS_COUNT_TOKEN}; pars_res_word_t pars_sum_token = {PARS_SUM_TOKEN}; pars_res_word_t pars_distinct_token = {PARS_DISTINCT_TOKEN}; +pars_res_word_t pars_binary_token = {PARS_BINARY_TOKEN}; +pars_res_word_t pars_blob_token = {PARS_BLOB_TOKEN}; pars_res_word_t pars_int_token = {PARS_INT_TOKEN}; pars_res_word_t pars_char_token = {PARS_CHAR_TOKEN}; pars_res_word_t pars_float_token = {PARS_FLOAT_TOKEN}; @@ -128,7 +130,7 @@ pars_func_get_class( return(PARS_FUNC_OTHER); } } - + /************************************************************************* Parses an operator or predefined function expression. */ static @@ -146,7 +148,7 @@ pars_func_low( node->common.type = QUE_NODE_FUNC; dfield_set_data(&(node->common.val), NULL, 0); node->common.val_buf_size = 0; - + node->func = func; node->class = pars_func_get_class(func); @@ -165,7 +167,7 @@ func_node_t* pars_func( /*======*/ /* out, own: function node in a query tree */ - que_node_t* res_word,/* in: function name reserved word */ + que_node_t* res_word,/* in: function name reserved word */ que_node_t* arg) /* in: first argument in the argument list */ { return(pars_func_low(((pars_res_word_t*)res_word)->code, arg)); @@ -207,7 +209,7 @@ pars_order_by( node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(order_node_t)); node->common.type = QUE_NODE_ORDER; - + node->column = column; if (asc == &pars_asc_token) { @@ -233,15 +235,15 @@ pars_resolve_func_data_type( ulint func; ut_a(que_node_get_type(node) == QUE_NODE_FUNC); - + arg = node->args; func = node->func; if ((func == PARS_SUM_TOKEN) - || (func == '+') || (func == '-') || (func == '*') + || (func == '+') || (func == '-') || (func == '*') || (func == '/') || (func == '+')) { - + /* Inherit the data type from the first argument (which must not be the SQL null literal whose type is DATA_ERROR) */ @@ -253,7 +255,7 @@ pars_resolve_func_data_type( } else if (func == PARS_COUNT_TOKEN) { ut_a(arg); dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0); - + } else if (func == PARS_TO_CHAR_TOKEN) { ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT); dtype_set(que_node_get_data_type(node), DATA_VARCHAR, @@ -360,7 +362,7 @@ pars_resolve_exp_variables_and_types( return; } - + ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL); sym_node = exp_node; @@ -369,7 +371,7 @@ pars_resolve_exp_variables_and_types( return; } - + /* Not resolved yet: look in the symbol table for a variable or a cursor with the same name */ @@ -386,7 +388,7 @@ pars_resolve_exp_variables_and_types( /* Found a variable or a cursor declared with the same name */ - + break; } @@ -397,12 +399,12 @@ pars_resolve_exp_variables_and_types( fprintf(stderr, "PARSER ERROR: Unresolved identifier %s\n", sym_node->name); } - + ut_a(node); sym_node->resolved = TRUE; sym_node->token_type = SYM_IMPLICIT_VAR; - sym_node->alias = node; + sym_node->alias = node; sym_node->indirection = node; if (select_node) { @@ -466,7 +468,7 @@ pars_resolve_exp_columns( return; } - + ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL); sym_node = exp_node; @@ -475,7 +477,7 @@ pars_resolve_exp_columns( return; } - + /* Not resolved yet: look in the table list for a column with the same name */ @@ -490,17 +492,18 @@ pars_resolve_exp_columns( col = dict_table_get_nth_col(table, i); if ((sym_node->name_len == ut_strlen(col->name)) - && (0 == ut_memcmp(sym_node->name, col->name, - sym_node->name_len))) { - /* Found */ + && (0 == ut_memcmp(sym_node->name, col->name, + sym_node->name_len))) { + /* Found */ sym_node->resolved = TRUE; sym_node->token_type = SYM_COLUMN; sym_node->table = table; sym_node->col_no = i; sym_node->prefetch_buf = NULL; - + dfield_set_type(&(sym_node->common.val), dict_col_get_type(col)); + return; } } @@ -543,7 +546,7 @@ pars_retrieve_table_def( sym_node->token_type = SYM_TABLE; table_name = (const char*) sym_node->name; - + sym_node->table = dict_table_get_low(table_name); ut_a(sym_node->table); @@ -559,7 +562,7 @@ pars_retrieve_table_list_defs( sym_node_t* sym_node) /* in: first table node in list */ { ulint count = 0; - + if (sym_node == NULL) { return(count); @@ -592,7 +595,7 @@ pars_select_all_columns( ulint i; select_node->select_list = NULL; - + table_node = select_node->table_list; while (table_node) { @@ -630,7 +633,7 @@ pars_select_list( sel_node_t* node; node = sel_node_create(pars_sym_tab_global->heap); - + node->select_list = select_list; node->into_list = into_list; @@ -659,7 +662,7 @@ pars_check_aggregate( while (exp_node) { n_nodes++; - + if (que_node_get_type(exp_node) == QUE_NODE_FUNC) { func_node = exp_node; @@ -709,7 +712,7 @@ pars_select_statement( /* SELECT * FROM ... */ pars_select_all_columns(select_node); } - + if (select_node->into_list) { ut_a(que_node_list_get_len(select_node->into_list) == que_node_list_get_len(select_node->select_list)); @@ -750,7 +753,7 @@ pars_select_statement( if (order_by) { pars_resolve_exp_columns(table_list, order_by->column); } - + /* The final value of the following fields depend on the environment where the select statement appears: */ @@ -780,7 +783,7 @@ pars_cursor_declaration( select_node->state = SEL_NODE_CLOSED; select_node->explicit_cursor = sym_node; - return(sym_node); + return(sym_node); } /************************************************************************* @@ -794,10 +797,10 @@ pars_update_statement_start( ibool is_delete, /* in: TRUE if delete */ sym_node_t* table_sym, /* in: table name node */ col_assign_node_t* col_assign_list)/* in: column assignment list, NULL - if delete */ + if delete */ { upd_node_t* node; - + node = upd_node_create(pars_sym_tab_global->heap); node->is_delete = is_delete; @@ -807,7 +810,7 @@ pars_update_statement_start( return(node); } - + /************************************************************************* Parses a column assignment in an update. */ @@ -852,7 +855,7 @@ pars_process_assign_list( table_sym = node->table_sym; col_assign_list = node->col_assign_list; clust_index = dict_table_get_first_index(node->table); - + assign_node = col_assign_list; n_assigns = 0; @@ -863,7 +866,7 @@ pars_process_assign_list( /* ut_a(dtype_get_mtype(dfield_get_type( que_node_get_val(assign_node->col))) - == dtype_get_mtype(dfield_get_type( + == dtype_get_mtype(dfield_get_type( que_node_get_val(assign_node->val)))); */ /* Add to the update node all the columns found in assignment @@ -897,8 +900,8 @@ pars_process_assign_list( dict_index_get_nth_type(clust_index, upd_field->field_no))) { changes_field_size = 0; - } - + } + assign_node = que_node_get_next(assign_node); } @@ -910,10 +913,10 @@ pars_process_assign_list( node->update)) { changes_ord_field = 0; } - + node->cmpl_info = changes_ord_field | changes_field_size; } - + /************************************************************************* Parses an update or delete statement. */ @@ -932,14 +935,14 @@ pars_update_statement( plan_t* plan; table_sym = node->table_sym; - + pars_retrieve_table_def(table_sym); node->table = table_sym->table; UT_LIST_INIT(node->columns); - + /* Make the single table node into a list of table nodes of length 1 */ - + que_node_list_add_last(NULL, table_sym); if (cursor_sym) { @@ -956,7 +959,7 @@ pars_update_statement( node->searched_update = TRUE; sel_node->common.parent = node; } - + node->select = sel_node; ut_a(!node->is_delete || (node->col_assign_list == NULL)); @@ -982,9 +985,9 @@ pars_update_statement( ut_a(sel_node->is_aggregate == FALSE); sel_node->can_get_updated = TRUE; - + node->state = UPD_NODE_UPDATE_CLUSTERED; - + plan = sel_node_get_nth_plan(sel_node, 0); plan->no_prefetch = TRUE; @@ -1023,7 +1026,7 @@ pars_insert_statement( /* out, own: update node in a query tree */ sym_node_t* table_sym, /* in: table name node */ - que_node_t* values_list, /* in: value expression list or NULL */ + que_node_t* values_list, /* in: value expression list or NULL */ sel_node_t* select) /* in: select condition or NULL */ { ins_node_t* node; @@ -1059,7 +1062,7 @@ pars_insert_statement( ut_a(que_node_list_get_len(select->select_list) == dict_table_get_n_user_cols(table_sym->table)); } - + node->values_list = values_list; if (node->values_list) { @@ -1078,17 +1081,61 @@ static void pars_set_dfield_type( /*=================*/ - dfield_t* dfield, /* in: dfield */ - pars_res_word_t* type) /* in: pointer to a type token */ + dfield_t* dfield, /* in: dfield */ + pars_res_word_t* type, /* in: pointer to a type + token */ + ulint len, /* in: length, or 0 */ + ibool is_not_null) /* in: if TRUE, column is + NOT NULL. */ { + ulint flags = 0; + + if (is_not_null) { + flags |= DATA_NOT_NULL; + } + if (type == &pars_int_token) { + if (len != 0) { + ut_error; + } - dtype_set(dfield_get_type(dfield), DATA_INT, 0, 4, 0); + dtype_set(dfield_get_type(dfield), DATA_INT, flags, 4, 0); } else if (type == &pars_char_token) { + if (len != 0) { + ut_error; + } dtype_set(dfield_get_type(dfield), DATA_VARCHAR, - DATA_ENGLISH, 0, 0); + DATA_ENGLISH | flags, 0, 0); + } else if (type == &pars_binary_token) { + if (len == 0) { + ut_error; + } + + dtype_set(dfield_get_type(dfield), DATA_FIXBINARY, + DATA_BINARY_TYPE | flags, len, 0); + } else if (type == &pars_blob_token) { + if (len != 0) { + ut_error; + } + + dtype_set(dfield_get_type(dfield), DATA_BLOB, + DATA_BINARY_TYPE | flags, 0, 0); + } else if (type == &pars_binary_token) { + if (len == 0) { + ut_error; + } + + dtype_set(dfield_get_type(dfield), DATA_FIXBINARY, + DATA_BINARY_TYPE, len, 0); + } else if (type == &pars_blob_token) { + if (len != 0) { + ut_error; + } + + dtype_set(dfield_get_type(dfield), DATA_BLOB, + DATA_BINARY_TYPE, 0, 0); } else { ut_error; } @@ -1111,8 +1158,8 @@ pars_variable_declaration( node->param_type = PARS_NOT_PARAM; - pars_set_dfield_type(que_node_get_val(node), type); - + pars_set_dfield_type(que_node_get_val(node), type, 0, FALSE); + return(node); } @@ -1129,7 +1176,7 @@ pars_parameter_declaration( ulint param_type, /* in: PARS_INPUT or PARS_OUTPUT */ pars_res_word_t* type) /* in: pointer to a type token */ -{ +{ ut_a((param_type == PARS_INPUT) || (param_type == PARS_OUTPUT)); pars_variable_declaration(node, type); @@ -1158,7 +1205,7 @@ pars_set_parent_in_list( common = que_node_get_next(common); } -} +} /************************************************************************* Parses an elsif element. */ @@ -1179,7 +1226,7 @@ pars_elsif_element( node->cond = cond; pars_resolve_exp_variables_and_types(NULL, cond); - + node->stat_list = stat_list; return(node); @@ -1207,7 +1254,7 @@ pars_if_statement( node->cond = cond; pars_resolve_exp_variables_and_types(NULL, cond); - + node->stat_list = stat_list; if (else_part && (que_node_get_type(else_part) == QUE_NODE_ELSIF)) { @@ -1232,7 +1279,7 @@ pars_if_statement( } pars_set_parent_in_list(stat_list, node); - + return(node); } @@ -1259,7 +1306,7 @@ pars_while_statement( node->stat_list = stat_list; pars_set_parent_in_list(stat_list, node); - + return(node); } @@ -1295,7 +1342,7 @@ pars_for_statement( node->stat_list = stat_list; pars_set_parent_in_list(stat_list, node); - + return(node); } @@ -1337,9 +1384,9 @@ pars_assignment_statement( pars_resolve_exp_variables_and_types(NULL, var); pars_resolve_exp_variables_and_types(NULL, val); - + ut_a(dtype_get_mtype(dfield_get_type(que_node_get_val(var))) - == dtype_get_mtype(dfield_get_type(que_node_get_val(val)))); + == dtype_get_mtype(dfield_get_type(que_node_get_val(val)))); return(node); } @@ -1359,7 +1406,7 @@ pars_procedure_call( node = pars_func(res_word, args); pars_resolve_exp_list_variables_and_types(NULL, args); - + return(node); } @@ -1378,8 +1425,8 @@ pars_fetch_statement( node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(fetch_node_t)); - node->common.type = QUE_NODE_FETCH; - + node->common.type = QUE_NODE_FETCH; + pars_resolve_exp_variables_and_types(NULL, cursor); pars_resolve_exp_list_variables_and_types(NULL, into_list); @@ -1413,7 +1460,7 @@ pars_open_statement( node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(open_node_t)); - node->common.type = QUE_NODE_OPEN; + node->common.type = QUE_NODE_OPEN; pars_resolve_exp_variables_and_types(NULL, cursor); @@ -1437,11 +1484,11 @@ pars_row_printf_statement( sel_node_t* sel_node) /* in: select node */ { row_printf_node_t* node; - + node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(row_printf_node_t)); node->common.type = QUE_NODE_ROW_PRINTF; - + node->sel_node = sel_node; sel_node->common.parent = node; @@ -1475,12 +1522,26 @@ Parses a column definition at a table creation. */ sym_node_t* pars_column_def( /*============*/ - /* out: column sym table node */ - sym_node_t* sym_node, /* in: column node in the symbol - table */ - pars_res_word_t* type) /* in: data type */ + /* out: column sym table + node */ + sym_node_t* sym_node, /* in: column node in the + symbol table */ + pars_res_word_t* type, /* in: data type */ + sym_node_t* len, /* in: length of column, or + NULL */ + void* is_not_null) /* in: if not NULL, column + is of type NOT NULL. */ { - pars_set_dfield_type(que_node_get_val(sym_node), type); + ulint len2; + + if (len) { + len2 = eval_node_get_int_val(len); + } else { + len2 = 0; + } + + pars_set_dfield_type(que_node_get_val(sym_node), type, len2, + is_not_null != NULL); return(sym_node); } @@ -1517,7 +1578,7 @@ pars_create_table( /* As the InnoDB SQL parser is for internal use only, for creating some system tables, this function will only create tables in the old (not compact) record format. */ - table = dict_mem_table_create(table_sym->name, 0, n_cols, FALSE); + table = dict_mem_table_create(table_sym->name, 0, n_cols, 0); if (not_fit_in_memory != NULL) { table->does_not_fit_in_memory = TRUE; @@ -1527,7 +1588,7 @@ pars_create_table( while (column) { dtype = dfield_get_type(que_node_get_val(column)); - + dict_mem_table_add_col(table, column->name, dtype->mtype, dtype->prtype, dtype->len, dtype->prec); @@ -1536,12 +1597,12 @@ pars_create_table( column = que_node_get_next(column); } - + node = tab_create_graph_create(table, pars_sym_tab_global->heap); table_sym->resolved = TRUE; table_sym->token_type = SYM_TABLE; - + return(node); } @@ -1577,20 +1638,20 @@ pars_create_index( if (clustered_def) { ind_type = ind_type | DICT_CLUSTERED; } - + index = dict_mem_index_create(table_sym->name, index_sym->name, 0, ind_type, n_fields); column = column_list; while (column) { - dict_mem_index_add_field(index, column->name, 0, 0); + dict_mem_index_add_field(index, column->name, 0); column->resolved = TRUE; column->token_type = SYM_COLUMN; column = que_node_get_next(column); } - + node = ind_create_graph_create(index, pars_sym_tab_global->heap); table_sym->resolved = TRUE; @@ -1633,7 +1694,7 @@ pars_procedure_definition( sym_node->token_type = SYM_PROCEDURE_NAME; sym_node->resolved = TRUE; - + node->proc_id = sym_node; node->param_list = param_list; node->stat_list = stat_list; @@ -1644,7 +1705,7 @@ pars_procedure_definition( thr->child = node; - pars_sym_tab_global->query_graph = fork; + pars_sym_tab_global->query_graph = fork; return(fork); } @@ -1678,13 +1739,13 @@ pars_get_lex_chars( in the buffer */ { int len; - + len = pars_sym_tab_global->string_len - pars_sym_tab_global->next_char_pos; if (len == 0) { #ifdef YYDEBUG /* fputs("SQL string ends\n", stderr); */ -#endif +#endif *result = 0; return; @@ -1696,7 +1757,7 @@ pars_get_lex_chars( #ifdef UNIV_SQL_DEBUG if (pars_print_lexed) { - + if (len >= 5) { len = 5; } @@ -1706,7 +1767,7 @@ pars_get_lex_chars( 1, len, stderr); } #endif /* UNIV_SQL_DEBUG */ - + ut_memcpy(buf, pars_sym_tab_global->sql_string + pars_sym_tab_global->next_char_pos, len); *result = len; @@ -1756,7 +1817,7 @@ pars_sql( pars_sym_tab_global->sql_string = mem_heap_strdup(heap, str); pars_sym_tab_global->string_len = strlen(str); pars_sym_tab_global->next_char_pos = 0; - + yyparse(); sym_node = UT_LIST_GET_FIRST(pars_sym_tab_global->sym_list); @@ -1792,7 +1853,7 @@ pars_complete_graph_for_exec( { que_fork_t* fork; que_thr_t* thr; - + fork = que_fork_create(NULL, NULL, QUE_FORK_MYSQL_INTERFACE, heap); fork->trx = trx; @@ -1803,6 +1864,6 @@ pars_complete_graph_for_exec( que_node_set_parent(node, thr); trx->graph = NULL; - + return(thr); } diff --git a/storage/innobase/pars/pars0sym.c b/storage/innobase/pars/pars0sym.c index 8ade5579e47..d8025998f9a 100644 --- a/storage/innobase/pars/pars0sym.c +++ b/storage/innobase/pars/pars0sym.c @@ -66,7 +66,7 @@ sym_tab_free_private( if (sym->cursor_def) { que_graph_free_recursive(sym->cursor_def); } - + sym = UT_LIST_GET_NEXT(sym_list, sym); } @@ -91,23 +91,23 @@ sym_tab_add_int_lit( { sym_node_t* node; byte* data; - + node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t)); node->common.type = QUE_NODE_SYMBOL; - + node->resolved = TRUE; node->token_type = SYM_LIT; node->indirection = NULL; - + dtype_set(&(node->common.val.type), DATA_INT, 0, 4, 0); data = mem_heap_alloc(sym_tab->heap, 4); mach_write_to_4(data, val); dfield_set_data(&(node->common.val), data, 4); - + node->common.val_buf_size = 0; node->prefetch_buf = NULL; node->cursor_def = NULL; @@ -115,7 +115,7 @@ sym_tab_add_int_lit( UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); node->sym_table = sym_tab; - + return(node); } @@ -133,7 +133,7 @@ sym_tab_add_str_lit( { sym_node_t* node; byte* data; - + node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t)); node->common.type = QUE_NODE_SYMBOL; @@ -142,7 +142,7 @@ sym_tab_add_str_lit( node->token_type = SYM_LIT; node->indirection = NULL; - + dtype_set(&(node->common.val.type), DATA_VARCHAR, DATA_ENGLISH, 0, 0); if (len) { @@ -157,7 +157,7 @@ sym_tab_add_str_lit( node->common.val_buf_size = 0; node->prefetch_buf = NULL; node->cursor_def = NULL; - + UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); node->sym_table = sym_tab; @@ -175,16 +175,16 @@ sym_tab_add_null_lit( sym_tab_t* sym_tab) /* in: symbol table */ { sym_node_t* node; - + node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t)); node->common.type = QUE_NODE_SYMBOL; - + node->resolved = TRUE; node->token_type = SYM_LIT; node->indirection = NULL; - + node->common.val.type.mtype = DATA_ERROR; dfield_set_data(&(node->common.val), NULL, UNIV_SQL_NULL); @@ -192,7 +192,7 @@ sym_tab_add_null_lit( node->common.val_buf_size = 0; node->prefetch_buf = NULL; node->cursor_def = NULL; - + UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); node->sym_table = sym_tab; @@ -212,11 +212,11 @@ sym_tab_add_id( ulint len) /* in: identifier length */ { sym_node_t* node; - + node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t)); node->common.type = QUE_NODE_SYMBOL; - + node->resolved = FALSE; node->indirection = NULL; @@ -230,7 +230,7 @@ sym_tab_add_id( node->common.val_buf_size = 0; node->prefetch_buf = NULL; node->cursor_def = NULL; - + node->sym_table = sym_tab; return(node); diff --git a/storage/innobase/que/que0que.c b/storage/innobase/que/que0que.c index a0a6adf9b83..e048b94cdc5 100644 --- a/storage/innobase/que/que0que.c +++ b/storage/innobase/que/que0que.c @@ -7,7 +7,7 @@ Created 5/27/1996 Heikki Tuuri *******************************************************/ #include "que0que.h" - + #ifdef UNIV_NONINL #include "que0que.ic" #endif @@ -106,7 +106,7 @@ que_fork_create( que_fork_t* fork; ut_ad(heap); - + fork = mem_heap_alloc(heap, sizeof(que_fork_t)); fork->common.type = QUE_NODE_FORK; @@ -119,7 +119,7 @@ que_fork_create( } else { fork->graph = fork; } - + fork->common.parent = parent; fork->fork_type = fork_type; @@ -128,9 +128,9 @@ que_fork_create( UT_LIST_INIT(fork->thrs); fork->sym_tab = NULL; - + fork->heap = heap; - + return(fork); } @@ -145,9 +145,9 @@ que_thr_create( mem_heap_t* heap) /* in: memory heap where created */ { que_thr_t* thr; - + ut_ad(parent && heap); - + thr = mem_heap_alloc(heap, sizeof(que_thr_t)); thr->common.type = QUE_NODE_THR; @@ -159,7 +159,7 @@ que_thr_create( thr->state = QUE_THR_COMMAND_WAIT; - thr->is_active = FALSE; + thr->is_active = FALSE; thr->run_node = NULL; thr->resource = 0; @@ -197,20 +197,20 @@ que_thr_end_wait( #endif /* UNIV_SYNC_DEBUG */ ut_ad(thr); ut_ad((thr->state == QUE_THR_LOCK_WAIT) - || (thr->state == QUE_THR_PROCEDURE_WAIT) - || (thr->state == QUE_THR_SIG_REPLY_WAIT)); + || (thr->state == QUE_THR_PROCEDURE_WAIT) + || (thr->state == QUE_THR_SIG_REPLY_WAIT)); ut_ad(thr->run_node); thr->prev_node = thr->run_node; was_active = thr->is_active; - + que_thr_move_to_run_state(thr); if (was_active) { return; - } + } if (next_thr && *next_thr == NULL) { *next_thr = thr; @@ -218,7 +218,7 @@ que_thr_end_wait( ut_a(0); srv_que_task_enqueue_low(thr); } -} +} /************************************************************************** Same as que_thr_end_wait, but no parameter next_thr available. */ @@ -239,11 +239,11 @@ que_thr_end_wait_no_next_thr( #endif /* UNIV_SYNC_DEBUG */ ut_ad(thr); ut_ad((thr->state == QUE_THR_LOCK_WAIT) - || (thr->state == QUE_THR_PROCEDURE_WAIT) - || (thr->state == QUE_THR_SIG_REPLY_WAIT)); + || (thr->state == QUE_THR_PROCEDURE_WAIT) + || (thr->state == QUE_THR_SIG_REPLY_WAIT)); was_active = thr->is_active; - + que_thr_move_to_run_state(thr); if (was_active) { @@ -253,7 +253,7 @@ que_thr_end_wait_no_next_thr( /* In MySQL we let the OS thread (not just the query thread) to wait for the lock to be released: */ - + srv_release_mysql_thread_if_suspended(thr); /* srv_que_task_enqueue_low(thr); */ @@ -286,12 +286,12 @@ que_fork_start_command( QUE_THR_RUNNING state, or NULL; the query thread should be executed by que_run_threads by the caller */ - que_fork_t* fork) /* in: a query fork */ + que_fork_t* fork) /* in: a query fork */ { que_thr_t* thr; fork->state = QUE_FORK_ACTIVE; - + fork->last_sel_node = NULL; /* Choose the query thread to run: usually there is just one thread, @@ -300,7 +300,7 @@ que_fork_start_command( /*--------------------------------------------------------------- First we try to find a query thread in the QUE_THR_COMMAND_WAIT state */ - + thr = UT_LIST_GET_FIRST(fork->thrs); while (thr != NULL) { @@ -315,7 +315,7 @@ que_fork_start_command( } ut_ad(thr->state != QUE_THR_LOCK_WAIT); - + thr = UT_LIST_GET_NEXT(thrs, thr); } @@ -340,7 +340,7 @@ que_fork_start_command( /*----------------------------------------------------------------- Then we try to find a query thread in the QUE_THR_COMPLETED state */ - + thr = UT_LIST_GET_FIRST(fork->thrs); while (thr != NULL) { @@ -384,16 +384,16 @@ que_fork_error_handle( ut_ad(!thr->is_active); ut_ad(thr->state != QUE_THR_SIG_REPLY_WAIT); ut_ad(thr->state != QUE_THR_LOCK_WAIT); - + thr->run_node = thr; thr->prev_node = thr->child; thr->state = QUE_THR_COMPLETED; - + thr = UT_LIST_GET_NEXT(thrs, thr); } thr = UT_LIST_GET_FIRST(fork->thrs); - + que_thr_move_to_run_state(thr); ut_a(0); @@ -459,7 +459,7 @@ que_graph_free_recursive( upd_node_t* upd; tab_node_t* cre_tab; ind_node_t* cre_ind; - + if (node == NULL) { return; @@ -487,7 +487,7 @@ que_graph_free_recursive( fprintf(stderr, "que_thr struct appears corrupt; magic n %lu\n", (unsigned long) thr->magic_n); - mem_analyze_corruption((byte*)thr); + mem_analyze_corruption(thr); ut_error; } @@ -524,16 +524,16 @@ que_graph_free_recursive( upd = node; if (upd->in_mysql_interface) { - + btr_pcur_free_for_mysql(upd->pcur); } - que_graph_free_recursive(upd->cascade_node); + que_graph_free_recursive(upd->cascade_node); if (upd->cascade_heap) { mem_heap_free(upd->cascade_heap); } - + que_graph_free_recursive(upd->select); mem_heap_free(upd->heap); @@ -541,7 +541,7 @@ que_graph_free_recursive( break; case QUE_NODE_CREATE_TABLE: cre_tab = node; - + que_graph_free_recursive(cre_tab->tab_def); que_graph_free_recursive(cre_tab->col_def); que_graph_free_recursive(cre_tab->commit_node); @@ -551,7 +551,7 @@ que_graph_free_recursive( break; case QUE_NODE_CREATE_INDEX: cre_ind = node; - + que_graph_free_recursive(cre_ind->ind_def); que_graph_free_recursive(cre_ind->field_def); que_graph_free_recursive(cre_ind->commit_node); @@ -599,7 +599,7 @@ que_graph_free_recursive( fprintf(stderr, "que_node struct appears corrupt; type %lu\n", (unsigned long) que_node_get_type(node)); - mem_analyze_corruption((byte*)node); + mem_analyze_corruption(node); ut_error; } } @@ -622,7 +622,7 @@ que_graph_free( /* The following call frees dynamic memory allocated for variables etc. during execution. Frees also explicit cursor definitions. */ - + sym_tab_free_private(graph->sym_tab); } @@ -649,7 +649,7 @@ que_graph_try_free( #endif /* UNIV_SYNC_DEBUG */ sess = (graph->trx)->sess; - + if ((graph->state == QUE_FORK_BEING_FREED) && (graph->n_active_thrs == 0)) { @@ -680,7 +680,7 @@ que_thr_handle_error( function will take care of freeing of the string! */ ulint err_len __attribute__((unused))) - /* in: error string length */ + /* in: error string length */ { /* Does nothing */ } @@ -697,29 +697,29 @@ que_thr_node_step( be the thread node itself */ { ut_ad(thr->run_node == thr); - + if (thr->prev_node == thr->common.parent) { /* If control to the node came from above, it is just passed on */ thr->run_node = thr->child; - + return(thr); } mutex_enter(&kernel_mutex); if (que_thr_peek_stop(thr)) { - + mutex_exit(&kernel_mutex); return(thr); } /* Thread execution completed */ - + thr->state = QUE_THR_COMPLETED; - + mutex_exit(&kernel_mutex); return(NULL); @@ -754,7 +754,7 @@ que_thr_move_to_run_state( ut_ad((thr->graph)->n_active_thrs == 1); ut_ad(trx->n_active_thrs == 1); } - + thr->state = QUE_THR_RUNNING; } @@ -776,14 +776,14 @@ que_thr_dec_refer_count( if the value which is passed in is a pointer to a NULL pointer, then the calling function can start running - a new query thread */ + a new query thread */ { que_fork_t* fork; trx_t* trx; sess_t* sess; ulint fork_type; ibool stopped; - + fork = thr->common.parent; trx = thr->graph->trx; sess = trx->sess; @@ -815,7 +815,7 @@ que_thr_dec_refer_count( return; } - } + } ut_ad(fork->n_active_thrs == 1); ut_ad(trx->n_active_thrs == 1); @@ -831,7 +831,7 @@ que_thr_dec_refer_count( return; } - + fork_type = fork->fork_type; /* Check if all query threads in the same fork are completed */ @@ -841,12 +841,12 @@ que_thr_dec_refer_count( if (fork_type == QUE_FORK_ROLLBACK) { /* This is really the undo graph used in rollback, no roll_node in this graph */ - + ut_ad(UT_LIST_GET_LEN(trx->signals) > 0); ut_ad(trx->handling_signals == TRUE); - + trx_finish_rollback_off_kernel(fork, trx, next_thr); - + } else if (fork_type == QUE_FORK_PURGE) { /* Do nothing */ @@ -863,7 +863,7 @@ que_thr_dec_refer_count( if (UT_LIST_GET_LEN(trx->signals) > 0 && trx->n_active_thrs == 0) { - /* If the trx is signaled and its query thread count drops to + /* If the trx is signaled and its query thread count drops to zero, then we start processing a signal; from it we may get a new query thread to run */ @@ -896,7 +896,7 @@ que_thr_stop( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - + graph = thr->graph; trx = graph->trx; @@ -922,7 +922,7 @@ que_thr_stop( ut_ad(graph->state == QUE_FORK_ACTIVE); ret = FALSE; - } + } return(ret); } @@ -941,13 +941,13 @@ que_thr_stop_for_mysql( trx_t* trx; trx = thr_get_trx(thr); - + mutex_enter(&kernel_mutex); if (thr->state == QUE_THR_RUNNING) { if (trx->error_state != DB_SUCCESS - && trx->error_state != DB_LOCK_WAIT) { + && trx->error_state != DB_LOCK_WAIT) { /* Error handling built for the MySQL interface */ thr->state = QUE_THR_COMPLETED; @@ -961,7 +961,7 @@ que_thr_stop_for_mysql( return; } } - + ut_ad(thr->is_active == TRUE); ut_ad(trx->n_active_thrs == 1); ut_ad(thr->graph->n_active_thrs == 1); @@ -990,7 +990,7 @@ que_thr_move_to_run_state_for_mysql( "que_thr struct appears corrupt; magic n %lu\n", (unsigned long) thr->magic_n); - mem_analyze_corruption((byte*)thr); + mem_analyze_corruption(thr); ut_error; } @@ -1003,7 +1003,7 @@ que_thr_move_to_run_state_for_mysql( thr->is_active = TRUE; } - + thr->state = QUE_THR_RUNNING; } @@ -1021,13 +1021,13 @@ que_thr_stop_for_mysql_no_error( ut_ad(thr->is_active == TRUE); ut_ad(trx->n_active_thrs == 1); ut_ad(thr->graph->n_active_thrs == 1); - + if (thr->magic_n != QUE_THR_MAGIC_N) { fprintf(stderr, "que_thr struct appears corrupt; magic n %lu\n", (unsigned long) thr->magic_n); - mem_analyze_corruption((byte*)thr); + mem_analyze_corruption(thr); ut_error; } @@ -1108,23 +1108,23 @@ que_thr_step( /*=========*/ /* out: query thread to run next: it may differ from the input parameter if, e.g., a - subprocedure call is made */ + subprocedure call is made */ que_thr_t* thr) /* in: query thread */ { que_node_t* node; que_thr_t* old_thr; trx_t* trx; ulint type; - + ut_ad(thr->state == QUE_THR_RUNNING); thr->resource++; - + type = que_node_get_type(thr->run_node); node = thr->run_node; old_thr = thr; - + #ifdef UNIV_DEBUG if (que_trace_on) { fputs("To execute: ", stderr); @@ -1150,13 +1150,13 @@ que_thr_step( /* We can access trx->undo_no without reserving trx->undo_mutex, because there cannot be active query threads doing updating or inserting at the moment! */ - + if (thr->prev_node == que_node_get_parent(node)) { trx = thr_get_trx(thr); trx->last_sql_stat_start.least_undo_no = trx->undo_no; } - + proc_step(thr); } else if (type == QUE_NODE_WHILE) { while_step(thr); @@ -1220,9 +1220,9 @@ que_run_threads( que_thr_t* thr) /* in: query thread which is run initially */ { que_thr_t* next_thr; - ulint cumul_resource; + ulint cumul_resource; ulint loop_count; - + ut_ad(thr->state == QUE_THR_RUNNING); #ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&kernel_mutex)); @@ -1232,7 +1232,7 @@ que_run_threads( query thread) has spent in this function */ loop_count = QUE_MAX_LOOPS_WITHOUT_CHECK; - cumul_resource = 0; + cumul_resource = 0; loop: /* Check that there is enough space in the log to accommodate possible log entries by this query step; if the operation can touch @@ -1240,7 +1240,7 @@ loop: step! */ log_free_check(); - + /* Perform the actual query step: note that the query thread may change if, e.g., a subprocedure call is made */ @@ -1254,7 +1254,7 @@ loop: /* if (srv_test_extra_mutexes) { mutex_enter(&kernel_mutex); mutex_exit(&kernel_mutex); - } + } */ loop_count++; diff --git a/storage/innobase/read/read0read.c b/storage/innobase/read/read0read.c index 06349c1fd39..1d6809ae5b7 100644 --- a/storage/innobase/read/read0read.c +++ b/storage/innobase/read/read0read.c @@ -15,6 +15,111 @@ Created 2/16/1997 Heikki Tuuri #include "srv0srv.h" #include "trx0sys.h" +/* +------------------------------------------------------------------------------- +FACT A: Cursor read view on a secondary index sees only committed versions +------- +of the records in the secondary index or those versions of rows created +by transaction which created a cursor before cursor was created even +if transaction which created the cursor has changed that clustered index page. + +PROOF: We must show that read goes always to the clustered index record +to see that record is visible in the cursor read view. Consider e.g. +following table and SQL-clauses: + +create table t1(a int not null, b int, primary key(a), index(b)); +insert into t1 values (1,1),(2,2); +commit; + +Now consider that we have a cursor for a query + +select b from t1 where b >= 1; + +This query will use secondary key on the table t1. Now after the first fetch +on this cursor if we do a update: + +update t1 set b = 5 where b = 2; + +Now second fetch of the cursor should not see record (2,5) instead it should +see record (2,2). + +We also should show that if we have delete t1 where b = 5; we still +can see record (2,2). + +When we access a secondary key record maximum transaction id is fetched +from this record and this trx_id is compared to up_limit_id in the view. +If trx_id in the record is greater or equal than up_limit_id in the view +cluster record is accessed. Because trx_id of the creating +transaction is stored when this view was created to the list of +trx_ids not seen by this read view previous version of the +record is requested to be built. This is build using clustered record. +If the secondary key record is delete marked it's corresponding +clustered record can be already be purged only if records +trx_id < low_limit_no. Purge can't remove any record deleted by a +transaction which was active when cursor was created. But, we still +may have a deleted secondary key record but no clustered record. But, +this is not a problem because this case is handled in +row_sel_get_clust_rec() function which is called +whenever we note that this read view does not see trx_id in the +record. Thus, we see correct version. Q. E. D. + +------------------------------------------------------------------------------- +FACT B: Cursor read view on a clustered index sees only committed versions +------- +of the records in the clustered index or those versions of rows created +by transaction which created a cursor before cursor was created even +if transaction which created the cursor has changed that clustered index page. + +PROOF: Consider e.g.following table and SQL-clauses: + +create table t1(a int not null, b int, primary key(a)); +insert into t1 values (1),(2); +commit; + +Now consider that we have a cursor for a query + +select a from t1 where a >= 1; + +This query will use clustered key on the table t1. Now after the first fetch +on this cursor if we do a update: + +update t1 set a = 5 where a = 2; + +Now second fetch of the cursor should not see record (5) instead it should +see record (2). + +We also should show that if we have execute delete t1 where a = 5; after +the cursor is opened we still can see record (2). + +When accessing clustered record we always check if this read view sees +trx_id stored to clustered record. By default we don't see any changes +if record trx_id >= low_limit_id i.e. change was made transaction +which started after transaction which created the cursor. If row +was changed by the future transaction a previous version of the +clustered record is created. Thus we see only committed version in +this case. We see all changes made by committed transactions i.e. +record trx_id < up_limit_id. In this case we don't need to do anything, +we already see correct version of the record. We don't see any changes +made by active transaction except creating transaction. We have stored +trx_id of creating transaction to list of trx_ids when this view was +created. Thus we can easily see if this record was changed by the +creating transaction. Because we already have clustered record we can +access roll_ptr. Using this roll_ptr we can fetch undo record. +We can now check that undo_no of the undo record is less than undo_no of the +trancaction which created a view when cursor was created. We see this +clustered record only in case when record undo_no is less than undo_no +in the view. If this is not true we build based on undo_rec previous +version of the record. This record is found because purge can't remove +records accessed by active transaction. Thus we see correct version. Q. E. D. +------------------------------------------------------------------------------- +FACT C: Purge does not remove any delete marked row that is visible +------- +to cursor view. + +TODO: proof this + +*/ + /************************************************************************* Creates a read view object. */ UNIV_INLINE @@ -44,9 +149,11 @@ with ..._close. This is used in purge. */ read_view_t* read_view_oldest_copy_or_open_new( /*==============================*/ - /* out, own: read view struct */ - trx_t* cr_trx, /* in: creating transaction, or NULL */ - mem_heap_t* heap) /* in: memory heap from which allocated */ + /* out, own: read view struct */ + dulint cr_trx_id, /* in: trx_id of creating + transaction, or (0, 0) used in purge*/ + mem_heap_t* heap) /* in: memory heap from which + allocated */ { read_view_t* old_view; read_view_t* view_copy; @@ -62,32 +169,33 @@ read_view_oldest_copy_or_open_new( if (old_view == NULL) { - return(read_view_open_now(cr_trx, heap)); + return(read_view_open_now(cr_trx_id, heap)); } n = old_view->n_trx_ids; - if (old_view->creator) { + if (ut_dulint_cmp(old_view->creator_trx_id, + ut_dulint_create(0,0)) != 0) { n++; } else { needs_insert = FALSE; } view_copy = read_view_create_low(n, heap); - + /* Insert the id of the creator in the right place of the descending array of ids, if needs_insert is TRUE: */ i = 0; while (i < n) { if (needs_insert - && (i >= old_view->n_trx_ids - || ut_dulint_cmp(old_view->creator->id, + && (i >= old_view->n_trx_ids + || ut_dulint_cmp(old_view->creator_trx_id, read_view_get_nth_trx_id(old_view, i)) > 0)) { read_view_set_nth_trx_id(view_copy, i, - old_view->creator->id); + old_view->creator_trx_id); needs_insert = FALSE; insert_done = 1; } else { @@ -99,9 +207,9 @@ read_view_oldest_copy_or_open_new( i++; } - view_copy->creator = cr_trx; - - view_copy->low_limit_no = old_view->low_limit_no; + view_copy->creator_trx_id = cr_trx_id; + + 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; @@ -126,9 +234,12 @@ point in time are seen in the view. */ read_view_t* read_view_open_now( /*===============*/ - /* out, own: read view struct */ - trx_t* cr_trx, /* in: creating transaction, or NULL */ - mem_heap_t* heap) /* in: memory heap from which allocated */ + /* out, own: read view struct */ + dulint cr_trx_id, /* in: trx_id of creating + transaction, or (0, 0) used in + purge */ + mem_heap_t* heap) /* in: memory heap from which + allocated */ { read_view_t* view; trx_t* trx; @@ -138,11 +249,13 @@ read_view_open_now( #endif /* UNIV_SYNC_DEBUG */ view = read_view_create_low(UT_LIST_GET_LEN(trx_sys->trx_list), heap); - view->creator = cr_trx; + view->creator_trx_id = cr_trx_id; + view->type = VIEW_NORMAL; + view->undo_no = ut_dulint_create(0, 0); /* No future transactions should be visible in the view */ - view->low_limit_no = trx_sys->max_trx_id; + view->low_limit_no = trx_sys->max_trx_id; view->low_limit_id = view->low_limit_no; view->can_be_too_old = FALSE; @@ -153,8 +266,9 @@ read_view_open_now( /* No active transaction should be visible, except cr_trx */ while (trx) { - if (trx != cr_trx && (trx->conc_state == TRX_ACTIVE || - trx->conc_state == TRX_PREPARED)) { + if (ut_dulint_cmp(trx->id, cr_trx_id) != 0 + && (trx->conc_state == TRX_ACTIVE + || trx->conc_state == TRX_PREPARED)) { read_view_set_nth_trx_id(view, n, trx->id); @@ -169,13 +283,13 @@ read_view_open_now( if (ut_dulint_cmp(view->low_limit_no, trx->no) > 0) { view->low_limit_no = trx->no; - } + } } trx = UT_LIST_GET_NEXT(trx_list, trx); } - view->n_trx_ids = n; + view->n_trx_ids = n; if (n > 0) { /* The last active transaction has the smallest id: */ @@ -184,8 +298,9 @@ read_view_open_now( view->up_limit_id = view->low_limit_id; } + UT_LIST_ADD_FIRST(view_list, trx_sys->view_list, view); - + return(view); } @@ -201,7 +316,7 @@ read_view_close( ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ UT_LIST_REMOVE(view_list, trx_sys->view_list, view); -} +} /************************************************************************* Closes a consistent read view for MySQL. This function is called at an SQL @@ -225,7 +340,7 @@ read_view_close_for_mysql( mutex_exit(&kernel_mutex); } - + /************************************************************************* Prints a read view to stderr. */ @@ -236,14 +351,23 @@ read_view_print( { ulint n_ids; ulint i; - + + if (view->type == VIEW_HIGH_GRANULARITY) { + fprintf(stderr, + "High-granularity read view undo_n:o %lu %lu\n", + (ulong) ut_dulint_get_high(view->undo_no), + (ulong) ut_dulint_get_low(view->undo_no)); + } else { + fprintf(stderr, "Normal read view\n"); + } + fprintf(stderr, "Read view low limit trx n:o %lu %lu\n", (ulong) ut_dulint_get_high(view->low_limit_no), (ulong) ut_dulint_get_low(view->low_limit_no)); fprintf(stderr, "Read view up limit trx id %lu %lu\n", (ulong) ut_dulint_get_high(view->up_limit_id), - (ulong) ut_dulint_get_low(view->up_limit_id)); + (ulong) ut_dulint_get_low(view->up_limit_id)); fprintf(stderr, "Read view low limit trx id %lu %lu\n", (ulong) ut_dulint_get_high(view->low_limit_id), @@ -261,9 +385,10 @@ read_view_print( } /************************************************************************* -Create a consistent cursor view for mysql to be used in cursors. In this -consistent read view modifications done by the creating transaction or future -transactions are not visible. */ +Create a high-granularity consistent cursor view for mysql to be used +in cursors. In this consistent read view modifications done by the +creating transaction after the cursor is created or future transactions +are not visible. */ cursor_view_t* read_cursor_view_create_for_mysql( @@ -278,7 +403,7 @@ read_cursor_view_create_for_mysql( ut_a(cr_trx); - /* Use larger heap than in trx_create when creating a read_view + /* Use larger heap than in trx_create when creating a read_view because cursors are quite long. */ heap = mem_heap_create(512); @@ -286,23 +411,25 @@ read_cursor_view_create_for_mysql( curview = (cursor_view_t*) mem_heap_alloc(heap, sizeof(cursor_view_t)); curview->heap = heap; - /* Drop cursor tables from consideration when evaluating the need of - auto-commit */ + /* Drop cursor tables from consideration when evaluating the need of + auto-commit */ curview->n_mysql_tables_in_use = cr_trx->n_mysql_tables_in_use; cr_trx->n_mysql_tables_in_use = 0; mutex_enter(&kernel_mutex); curview->read_view = read_view_create_low( - UT_LIST_GET_LEN(trx_sys->trx_list), + UT_LIST_GET_LEN(trx_sys->trx_list), curview->heap); view = curview->read_view; - view->creator = cr_trx; + view->creator_trx_id = cr_trx->id; + view->type = VIEW_HIGH_GRANULARITY; + view->undo_no = cr_trx->undo_no; /* No future transactions should be visible in the view */ - view->low_limit_no = trx_sys->max_trx_id; + view->low_limit_no = trx_sys->max_trx_id; view->low_limit_id = view->low_limit_no; view->can_be_too_old = FALSE; @@ -310,13 +437,12 @@ read_cursor_view_create_for_mysql( n = 0; trx = UT_LIST_GET_FIRST(trx_sys->trx_list); - /* No active transaction should be visible, except cr_trx. - This is quick fix for a bug 12456 and needs to be fixed when - semi-consistent high-granularity read view is implemented. */ + /* No active transaction should be visible */ while (trx) { - if (trx != cr_trx && (trx->conc_state == TRX_ACTIVE || - trx->conc_state == TRX_PREPARED)) { + + if (trx->conc_state == TRX_ACTIVE + || trx->conc_state == TRX_PREPARED) { read_view_set_nth_trx_id(view, n, trx->id); @@ -331,13 +457,13 @@ read_cursor_view_create_for_mysql( if (ut_dulint_cmp(view->low_limit_no, trx->no) > 0) { view->low_limit_no = trx->no; - } + } } trx = UT_LIST_GET_NEXT(trx_list, trx); } - view->n_trx_ids = n; + view->n_trx_ids = n; if (n > 0) { /* The last active transaction has the smallest id: */ @@ -347,7 +473,7 @@ read_cursor_view_create_for_mysql( } UT_LIST_ADD_FIRST(view_list, trx_sys->view_list, view); - + mutex_exit(&kernel_mutex); return(curview); @@ -364,11 +490,11 @@ read_cursor_view_close_for_mysql( cursor_view_t* curview)/* in: cursor view to be closed */ { ut_a(curview); - ut_a(curview->read_view); + ut_a(curview->read_view); ut_a(curview->heap); - /* Add cursor's tables to the global count of active tables that - belong to this transaction */ + /* Add cursor's tables to the global count of active tables that + belong to this transaction */ trx->n_mysql_tables_in_use += curview->n_mysql_tables_in_use; mutex_enter(&kernel_mutex); @@ -380,13 +506,13 @@ read_cursor_view_close_for_mysql( mem_heap_free(curview->heap); } - + /************************************************************************* This function sets a given consistent cursor view to a transaction read view if given consistent cursor view is not NULL. Otherwise, function restores a global read view to a transaction read view. */ -void +void read_cursor_set_for_mysql( /*======================*/ trx_t* trx, /* in: transaction where cursor is set */ diff --git a/storage/innobase/rem/rem0cmp.c b/storage/innobase/rem/rem0cmp.c index 7c33476fb9e..6c29ef58ea1 100644 --- a/storage/innobase/rem/rem0cmp.c +++ b/storage/innobase/rem/rem0cmp.c @@ -16,7 +16,7 @@ Created 7/1/1994 Heikki Tuuri /* ALPHABETICAL ORDER ================== - + The records are put into alphabetical order in the following way: let F be the first field where two records disagree. If there is a character in some position n where the the @@ -30,7 +30,7 @@ data type is not paddable, longer field is considered greater. Finally, the SQL null is bigger than any other value. At the present, the comparison functions return 0 in the case, -where two records disagree only in the way that one +where two records disagree only in the way that one has more fields than the other. */ #ifdef UNIV_DEBUG @@ -42,9 +42,9 @@ differ from dtuple in some of the m fields rec has. */ static int cmp_debug_dtuple_rec_with_match( -/*============================*/ - /* out: 1, 0, -1, if dtuple is greater, equal, - less than rec, respectively, when only the +/*============================*/ + /* out: 1, 0, -1, if dtuple is greater, equal, + less than rec, respectively, when only the common first fields are compared */ dtuple_t* dtuple, /* in: data tuple */ rec_t* rec, /* in: physical record which differs from @@ -52,11 +52,12 @@ cmp_debug_dtuple_rec_with_match( has an equal number or more fields than dtuple */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ - ulint* matched_fields);/* in/out: number of already + ulint* matched_fields);/* in/out: number of already completely matched fields; when function returns, contains the value for current comparison */ #endif /* UNIV_DEBUG */ +#ifndef UNIV_HOTBACKUP /***************************************************************** This function is used to compare two data fields for which the data type is such that we must use MySQL code to compare them. The prototype here @@ -75,7 +76,7 @@ innobase_mysql_cmp( unsigned char* b, /* in: data field */ unsigned int b_length); /* in: data field length, not UNIV_SQL_NULL */ - +#endif /* !UNIV_HOTBACKUP */ /************************************************************************* Transforms the character code so that it is ordered appropriately for the language. This is only used for the latin1 char set. MySQL does the @@ -86,7 +87,7 @@ cmp_collate( /*========*/ /* out: collation order position */ ulint code) /* in: code of a character stored in database record */ -{ +{ return((ulint) srv_latin1_ordering[code]); } @@ -99,61 +100,63 @@ cmp_types_are_equal( /* out: TRUE if the types are considered equal in comparisons */ dtype_t* type1, /* in: type 1 */ - dtype_t* type2) /* in: type 2 */ + dtype_t* type2, /* in: type 2 */ + ibool check_charsets) /* in: whether to check charsets */ { if (dtype_is_non_binary_string_type(type1->mtype, type1->prtype) - && dtype_is_non_binary_string_type(type2->mtype, type2->prtype)) { + && dtype_is_non_binary_string_type(type2->mtype, type2->prtype)) { /* Both are non-binary string types: they can be compared if and only if the charset-collation is the same */ - if (dtype_get_charset_coll(type1->prtype) - == dtype_get_charset_coll(type2->prtype)) { + if (check_charsets) { + return(dtype_get_charset_coll(type1->prtype) + == dtype_get_charset_coll(type2->prtype)); + } else { return(TRUE); } - - return(FALSE); - } + } if (dtype_is_binary_string_type(type1->mtype, type1->prtype) - && dtype_is_binary_string_type(type2->mtype, type2->prtype)) { + && dtype_is_binary_string_type(type2->mtype, type2->prtype)) { /* Both are binary string types: they can be compared */ return(TRUE); } - - if (type1->mtype != type2->mtype) { + + if (type1->mtype != type2->mtype) { return(FALSE); } - if (type1->mtype == DATA_INT - && (type1->prtype & DATA_UNSIGNED) + if (type1->mtype == DATA_INT + && (type1->prtype & DATA_UNSIGNED) != (type2->prtype & DATA_UNSIGNED)) { /* The storage format of an unsigned integer is different from a signed integer: in a signed integer we OR 0x8000... to the value of positive integers. */ - + return(FALSE); } - if (type1->mtype == DATA_INT && type1->len != type2->len) { - + if (type1->mtype == DATA_INT && type1->len != type2->len) { + return(FALSE); } return(TRUE); } +#ifndef UNIV_HOTBACKUP /***************************************************************** Innobase uses this function to compare two data fields for which the data type is such that we must compare whole fields or call MySQL to do the comparison */ static int cmp_whole_field( -/*============*/ +/*============*/ /* out: 1, 0, -1, if a is greater, equal, less than b, respectively */ dtype_t* type, /* in: data type */ @@ -175,36 +178,36 @@ cmp_whole_field( switch (data_type) { - case DATA_DECIMAL: + case DATA_DECIMAL: /* Remove preceding spaces */ for (; a_length && *a == ' '; a++, a_length--); for (; b_length && *b == ' '; b++, b_length--); - if (*a == '-') { + if (*a == '-') { if (*b != '-') { - return(-1); - } + return(-1); + } a++; b++; a_length--; b_length--; swap_flag = -1; - - } else if (*b == '-') { + + } else if (*b == '-') { return(1); } - - while (a_length > 0 && (*a == '+' || *a == '0')) { + + while (a_length > 0 && (*a == '+' || *a == '0')) { a++; a_length--; - } + } - while (b_length > 0 && (*b == '+' || *b == '0')) { + while (b_length > 0 && (*b == '+' || *b == '0')) { b++; b_length--; - } - - if (a_length != b_length) { + } + + if (a_length != b_length) { if (a_length < b_length) { return(-swap_flag); } @@ -216,7 +219,7 @@ cmp_whole_field( a++; b++; a_length--; } - + if (a_length == 0) { return(0); @@ -227,54 +230,55 @@ cmp_whole_field( } return(-swap_flag); - case DATA_DOUBLE: + case DATA_DOUBLE: d_1 = mach_double_read(a); d_2 = mach_double_read(b); - - if (d_1 > d_2) { - return(1); - } else if (d_2 > d_1) { - return(-1); - } - - return(0); - + + if (d_1 > d_2) { + return(1); + } else if (d_2 > d_1) { + return(-1); + } + + return(0); + case DATA_FLOAT: f_1 = mach_float_read(a); f_2 = mach_float_read(b); - if (f_1 > f_2) { - return(1); - } else if (f_2 > f_1) { - return(-1); - } + if (f_1 > f_2) { + return(1); + } else if (f_2 > f_1) { + return(-1); + } - return(0); + return(0); case DATA_VARMYSQL: case DATA_MYSQL: case DATA_BLOB: if (data_type == DATA_BLOB - && 0 != (type->prtype & DATA_BINARY_TYPE)) { + && 0 != (type->prtype & DATA_BINARY_TYPE)) { ut_print_timestamp(stderr); - fprintf(stderr, + fprintf(stderr, " InnoDB: Error: comparing a binary BLOB with a character set sensitive\n" "InnoDB: comparison!\n"); - } + } return(innobase_mysql_cmp( (int)(type->prtype & DATA_MYSQL_TYPE_MASK), (uint)dtype_get_charset_coll(type->prtype), a, a_length, b, b_length)); default: - fprintf(stderr, + fprintf(stderr, "InnoDB: unknown type number %lu\n", (ulong) data_type); - ut_error; + ut_error; } return(0); } +#endif /* !UNIV_HOTBACKUP */ /***************************************************************** This function is used to compare two data fields for which we know the @@ -282,8 +286,8 @@ data type. */ int cmp_data_data_slow( -/*===============*/ - /* out: 1, 0, -1, if data1 is greater, equal, +/*===============*/ + /* out: 1, 0, -1, if data1 is greater, equal, less than data2, respectively */ dtype_t* cur_type,/* in: data type of the fields */ byte* data1, /* in: data field (== a pointer to a memory @@ -293,6 +297,7 @@ cmp_data_data_slow( buffer) */ ulint len2) /* in: data field length or UNIV_SQL_NULL */ { +#ifndef UNIV_HOTBACKUP ulint data1_byte; ulint data2_byte; ulint cur_bytes; @@ -315,18 +320,18 @@ cmp_data_data_slow( return(1); } - + if (cur_type->mtype >= DATA_FLOAT - || (cur_type->mtype == DATA_BLOB - && 0 == (cur_type->prtype & DATA_BINARY_TYPE) - && dtype_get_charset_coll(cur_type->prtype) != - DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) { + || (cur_type->mtype == DATA_BLOB + && 0 == (cur_type->prtype & DATA_BINARY_TYPE) + && dtype_get_charset_coll(cur_type->prtype) != + DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) { return(cmp_whole_field(cur_type, data1, (unsigned) len1, data2, (unsigned) len2)); } - + /* Compare then the fields */ cur_bytes = 0; @@ -337,7 +342,7 @@ cmp_data_data_slow( return(0); } - + data1_byte = dtype_get_pad_char(cur_type); if (data1_byte == ULINT_UNDEFINED) { @@ -358,7 +363,7 @@ cmp_data_data_slow( } else { data2_byte = *data2; } - + if (data1_byte == data2_byte) { /* If the bytes are equal, they will remain such even after the collation transformation below */ @@ -367,13 +372,13 @@ cmp_data_data_slow( } if (cur_type->mtype <= DATA_CHAR - || (cur_type->mtype == DATA_BLOB - && 0 == (cur_type->prtype & DATA_BINARY_TYPE))) { + || (cur_type->mtype == DATA_BLOB + && 0 == (cur_type->prtype & DATA_BINARY_TYPE))) { data1_byte = cmp_collate(data1_byte); data2_byte = cmp_collate(data2_byte); } - + if (data1_byte > data2_byte) { return(1); @@ -387,6 +392,12 @@ cmp_data_data_slow( data1++; data2++; } +#else /* !UNIV_HOTBACKUP */ + /* This function depends on MySQL code that is not included in + InnoDB Hot Backup builds. Besides, this function should never + be called in InnoDB Hot Backup. */ + ut_error; +#endif /* !UNIV_HOTBACKUP */ return(0); /* Not reached */ } @@ -402,9 +413,9 @@ made. */ int cmp_dtuple_rec_with_match( -/*======================*/ - /* out: 1, 0, -1, if dtuple is greater, equal, - less than rec, respectively, when only the +/*======================*/ + /* out: 1, 0, -1, if dtuple is greater, equal, + less than rec, respectively, when only the common first fields are compared, or until the first externally stored field in rec */ @@ -414,30 +425,31 @@ cmp_dtuple_rec_with_match( has an equal number or more fields than dtuple */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ - ulint* matched_fields, /* in/out: number of already completely + ulint* matched_fields, /* in/out: number of already completely matched fields; when function returns, contains the value for current comparison */ - ulint* matched_bytes) /* in/out: number of already matched + ulint* matched_bytes) /* in/out: number of already matched bytes within the first field not completely matched; when function returns, contains the value for current comparison */ { +#ifndef UNIV_HOTBACKUP dtype_t* cur_type; /* pointer to type of the current field in dtuple */ dfield_t* dtuple_field; /* current field in logical record */ - ulint dtuple_f_len; /* the length of the current field + ulint dtuple_f_len; /* the length of the current field in the logical record */ - byte* dtuple_b_ptr; /* pointer to the current byte in + byte* dtuple_b_ptr; /* pointer to the current byte in logical field data */ - ulint dtuple_byte; /* value of current byte to be compared + ulint dtuple_byte; /* value of current byte to be compared in dtuple*/ ulint rec_f_len; /* length of current field in rec */ - byte* rec_b_ptr; /* pointer to the current byte in + byte* rec_b_ptr; /* pointer to the current byte in rec field */ - ulint rec_byte; /* value of current byte to be + ulint rec_byte; /* value of current byte to be compared in rec */ ulint cur_field; /* current field number */ - ulint cur_bytes; /* number of already matched bytes + ulint cur_bytes; /* number of already matched bytes in current field */ int ret = 3333; /* return value */ @@ -473,7 +485,7 @@ cmp_dtuple_rec_with_match( dtuple_field = dtuple_get_nth_field(dtuple, cur_field); cur_type = dfield_get_type(dtuple_field); - dtuple_f_len = dfield_get_len(dtuple_field); + dtuple_f_len = dfield_get_len(dtuple_field); rec_b_ptr = rec_get_nth_field(rec, offsets, cur_field, &rec_f_len); @@ -493,7 +505,7 @@ cmp_dtuple_rec_with_match( goto order_resolved; } - if (dtuple_f_len == UNIV_SQL_NULL) { + if (dtuple_f_len == UNIV_SQL_NULL) { if (rec_f_len == UNIV_SQL_NULL) { goto next_field; @@ -512,9 +524,9 @@ cmp_dtuple_rec_with_match( } if (cur_type->mtype >= DATA_FLOAT - || (cur_type->mtype == DATA_BLOB - && 0 == (cur_type->prtype & DATA_BINARY_TYPE) - && dtype_get_charset_coll(cur_type->prtype) != + || (cur_type->mtype == DATA_BLOB + && 0 == (cur_type->prtype & DATA_BINARY_TYPE) + && dtype_get_charset_coll(cur_type->prtype) != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) { ret = cmp_whole_field( @@ -531,21 +543,21 @@ cmp_dtuple_rec_with_match( goto next_field; } } - + /* Set the pointers at the current byte */ rec_b_ptr = rec_b_ptr + cur_bytes; - dtuple_b_ptr = (byte*)dfield_get_data(dtuple_field) + dtuple_b_ptr = (byte*)dfield_get_data(dtuple_field) + cur_bytes; - /* Compare then the fields */ - + /* Compare then the fields */ + for (;;) { if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) { if (dtuple_f_len <= cur_bytes) { goto next_field; } - + rec_byte = dtype_get_pad_char(cur_type); if (rec_byte == ULINT_UNDEFINED) { @@ -568,7 +580,7 @@ cmp_dtuple_rec_with_match( } else { dtuple_byte = *dtuple_b_ptr; } - + if (dtuple_byte == rec_byte) { /* If the bytes are equal, they will remain such even after the collation @@ -578,9 +590,9 @@ cmp_dtuple_rec_with_match( } if (cur_type->mtype <= DATA_CHAR - || (cur_type->mtype == DATA_BLOB - && 0 == - (cur_type->prtype & DATA_BINARY_TYPE))) { + || (cur_type->mtype == DATA_BLOB + && 0 == + (cur_type->prtype & DATA_BINARY_TYPE))) { rec_byte = cmp_collate(rec_byte); dtuple_byte = cmp_collate(dtuple_byte); @@ -623,6 +635,13 @@ order_resolved: *matched_bytes = cur_bytes; return(ret); +#else /* !UNIV_HOTBACKUP */ + /* This function depends on MySQL code that is not included in + InnoDB Hot Backup builds. Besides, this function should never + be called in InnoDB Hot Backup. */ + ut_error; + return(0); +#endif /* !UNIV_HOTBACKUP */ } /****************************************************************** @@ -631,10 +650,10 @@ Compares a data tuple to a physical record. */ int cmp_dtuple_rec( /*===========*/ - /* out: 1, 0, -1, if dtuple is greater, equal, + /* out: 1, 0, -1, if dtuple is greater, equal, less than rec, respectively; see the comments for cmp_dtuple_rec_with_match */ - dtuple_t* dtuple, /* in: data tuple */ + dtuple_t* dtuple, /* in: data tuple */ rec_t* rec, /* in: physical record */ const ulint* offsets)/* in: array returned by rec_get_offsets() */ { @@ -664,12 +683,12 @@ cmp_dtuple_is_prefix_of_rec( ut_ad(rec_offs_validate(rec, NULL, offsets)); n_fields = dtuple_get_n_fields(dtuple); - + if (n_fields > rec_offs_n_fields(offsets)) { return(FALSE); } - + cmp_dtuple_rec_with_match(dtuple, rec, offsets, &matched_fields, &matched_bytes); if (matched_fields == n_fields) { @@ -683,7 +702,7 @@ cmp_dtuple_is_prefix_of_rec( return(TRUE); } - return(FALSE); + return(FALSE); } /***************************************************************** @@ -693,7 +712,7 @@ encountered, then 0 is returned. */ int cmp_rec_rec_with_match( -/*===================*/ +/*===================*/ /* out: 1, 0 , -1 if rec1 is greater, equal, less, respectively, than rec2; only the common first fields are compared */ @@ -702,15 +721,16 @@ cmp_rec_rec_with_match( const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */ dict_index_t* index, /* in: data dictionary index */ - ulint* matched_fields, /* in/out: number of already completely + ulint* matched_fields, /* in/out: number of already completely matched fields; when the function returns, contains the value the for current comparison */ - ulint* matched_bytes) /* in/out: number of already matched + ulint* matched_bytes) /* in/out: number of already matched bytes within the first field not completely matched; when the function returns, contains the value for the current comparison */ { +#ifndef UNIV_HOTBACKUP dtype_t* cur_type; /* pointer to type struct of the current field in index */ ulint rec1_n_fields; /* the number of fields in rec */ @@ -724,7 +744,7 @@ cmp_rec_rec_with_match( ulint rec2_byte; /* value of current byte to be compared in rec */ ulint cur_field; /* current field number */ - ulint cur_bytes; /* number of already matched bytes in current + ulint cur_bytes; /* number of already matched bytes in current field */ int ret = 3333; /* return value */ ulint comp; @@ -749,8 +769,8 @@ cmp_rec_rec_with_match( cur_type = dtype_binary; } else { cur_type = dict_col_get_type( - dict_field_get_col( - dict_index_get_nth_field(index, cur_field))); + dict_field_get_col( + dict_index_get_nth_field(index, cur_field))); } rec1_b_ptr = rec_get_nth_field(rec1, offsets1, @@ -764,27 +784,27 @@ cmp_rec_rec_with_match( record */ if (rec_get_info_bits(rec1, comp) & REC_INFO_MIN_REC_FLAG) { - + if (rec_get_info_bits(rec2, comp) - & REC_INFO_MIN_REC_FLAG) { + & REC_INFO_MIN_REC_FLAG) { ret = 0; } else { ret = -1; } - + goto order_resolved; - + } else if (rec_get_info_bits(rec2, comp) & REC_INFO_MIN_REC_FLAG) { - + ret = 1; - + goto order_resolved; } } if (rec_offs_nth_extern(offsets1, cur_field) - || rec_offs_nth_extern(offsets2, cur_field)) { + || rec_offs_nth_extern(offsets2, cur_field)) { /* We do not compare to an externally stored field */ @@ -792,9 +812,9 @@ cmp_rec_rec_with_match( goto order_resolved; } - - if (rec1_f_len == UNIV_SQL_NULL - || rec2_f_len == UNIV_SQL_NULL) { + + if (rec1_f_len == UNIV_SQL_NULL + || rec2_f_len == UNIV_SQL_NULL) { if (rec1_f_len == rec2_f_len) { @@ -802,8 +822,8 @@ cmp_rec_rec_with_match( } else if (rec2_f_len == UNIV_SQL_NULL) { - /* We define the SQL null to be the - smallest possible value of a field + /* We define the SQL null to be the + smallest possible value of a field in the alphabetical order */ ret = 1; @@ -816,9 +836,9 @@ cmp_rec_rec_with_match( } if (cur_type->mtype >= DATA_FLOAT - || (cur_type->mtype == DATA_BLOB - && 0 == (cur_type->prtype & DATA_BINARY_TYPE) - && dtype_get_charset_coll(cur_type->prtype) != + || (cur_type->mtype == DATA_BLOB + && 0 == (cur_type->prtype & DATA_BINARY_TYPE) + && dtype_get_charset_coll(cur_type->prtype) != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) { ret = cmp_whole_field(cur_type, @@ -868,19 +888,19 @@ cmp_rec_rec_with_match( } else { rec1_byte = *rec1_b_ptr; } - + if (rec1_byte == rec2_byte) { /* If the bytes are equal, they will remain - such even after the collation transformation + such even after the collation transformation below */ goto next_byte; } if (cur_type->mtype <= DATA_CHAR - || (cur_type->mtype == DATA_BLOB - && 0 == - (cur_type->prtype & DATA_BINARY_TYPE))) { + || (cur_type->mtype == DATA_BLOB + && 0 == + (cur_type->prtype & DATA_BINARY_TYPE))) { rec1_byte = cmp_collate(rec1_byte); rec2_byte = cmp_collate(rec2_byte); @@ -914,10 +934,17 @@ order_resolved: ut_ad((ret >= - 1) && (ret <= 1)); - *matched_fields = cur_field; + *matched_fields = cur_field; *matched_bytes = cur_bytes; return(ret); +#else /* !UNIV_HOTBACKUP */ + /* This function depends on MySQL code that is not included in + InnoDB Hot Backup builds. Besides, this function should never + be called in InnoDB Hot Backup. */ + ut_error; + return(0); +#endif /* !UNIV_HOTBACKUP */ } #ifdef UNIV_DEBUG @@ -930,9 +957,9 @@ externally stored field, returns 0. */ static int cmp_debug_dtuple_rec_with_match( -/*============================*/ - /* out: 1, 0, -1, if dtuple is greater, equal, - less than rec, respectively, when only the +/*============================*/ + /* out: 1, 0, -1, if dtuple is greater, equal, + less than rec, respectively, when only the common first fields are compared */ dtuple_t* dtuple, /* in: data tuple */ rec_t* rec, /* in: physical record which differs from @@ -940,7 +967,7 @@ cmp_debug_dtuple_rec_with_match( has an equal number or more fields than dtuple */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ - ulint* matched_fields) /* in/out: number of already + ulint* matched_fields) /* in/out: number of already completely matched fields; when function returns, contains the value for current comparison */ @@ -948,7 +975,7 @@ cmp_debug_dtuple_rec_with_match( dtype_t* cur_type; /* pointer to type of the current field in dtuple */ dfield_t* dtuple_field; /* current field in logical record */ - ulint dtuple_f_len; /* the length of the current field + ulint dtuple_f_len; /* the length of the current field in the logical record */ byte* dtuple_f_data; /* pointer to the current logical field data */ @@ -956,11 +983,11 @@ cmp_debug_dtuple_rec_with_match( byte* rec_f_data; /* pointer to the current rec field */ int ret = 3333; /* return value */ ulint cur_field; /* current field number */ - + ut_ad(dtuple && rec && matched_fields); ut_ad(dtuple_check_typed(dtuple)); ut_ad(rec_offs_validate(rec, NULL, offsets)); - + ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple)); ut_ad(*matched_fields <= rec_offs_n_fields(offsets)); @@ -971,13 +998,13 @@ cmp_debug_dtuple_rec_with_match( & REC_INFO_MIN_REC_FLAG) { ret = !(dtuple_get_info_bits(dtuple) - & REC_INFO_MIN_REC_FLAG); + & REC_INFO_MIN_REC_FLAG); goto order_resolved; } if (dtuple_get_info_bits(dtuple) & REC_INFO_MIN_REC_FLAG) { - ret = -1; + ret = -1; goto order_resolved; } @@ -993,7 +1020,7 @@ cmp_debug_dtuple_rec_with_match( dtuple_f_data = dfield_get_data(dtuple_field); dtuple_f_len = dfield_get_len(dtuple_field); - + rec_f_data = rec_get_nth_field(rec, offsets, cur_field, &rec_f_len); @@ -1009,7 +1036,7 @@ cmp_debug_dtuple_rec_with_match( rec_f_data, rec_f_len); if (ret != 0) { goto order_resolved; - } + } cur_field++; } diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index 9480c978755..f7ee53aeda2 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -28,7 +28,7 @@ represented on a higher text line): if the offset is 2-byte, then the second most significant bit is set to 1 if the field is stored on another page: mostly this will occur in the case of big BLOB fields | -... +... | offset of the end of the first field of data + the SQL-null bit | | 4 bits used to delete mark a record, and mark a predefined minimum record in alphabetical order | @@ -41,18 +41,18 @@ represented on a higher text line): one byte format, 0 if in two byte format | | two bytes giving an absolute pointer to the next record in the page | ORIGIN of the record -| first field of data | -... +| first field of data | +... | last field of data | -The origin of the record is the start address of the first field -of data. The offsets are given relative to the origin. +The origin of the record is the start address of the first field +of data. The offsets are given relative to the origin. The offsets of the data fields are stored in an inverted -order because then the offset of the first fields are near the +order because then the offset of the first fields are near the origin, giving maybe a better processor cache hit rate in searches. -The offsets of the data fields are given as one-byte -(if there are less than 127 bytes of data in the record) +The offsets of the data fields are given as one-byte +(if there are less than 127 bytes of data in the record) or two-byte unsigned integers. The most significant bit is not part of the offset, instead it indicates the SQL-null if the bit is set to 1. */ @@ -102,7 +102,7 @@ if the bit is set to 1. */ string of 'characters' in the following way: catenate the bytes in each field, in the order of fields. An SQL-null field is taken to be an empty sequence of bytes. Then after -the position of each field insert in the string +the position of each field insert in the string the 'character' <FIELD-END>, except that after an SQL-null field insert <NULL-FIELD-END>. Now the ordinal position of each byte in this canonical string is its canonical coordinate. @@ -138,9 +138,9 @@ rec_validate_old( /********************************************************** The following function determines the offsets to each field in the -record. The offsets are written to a previously allocated array of +record. The offsets are written to a previously allocated array of ulint, where rec_offs_n_fields(offsets) has been initialized to the -number of fields in the record. The rest of the array will be +number of fields in the record. The rest of the array will be initialized by this function. rec_offs_base(offsets)[0] will be set to the extra size (if REC_OFFS_COMPACT is set, the record is in the new format), and rec_offs_base(offsets)[1..n_fields] will be set to @@ -164,7 +164,7 @@ rec_init_offsets( rec_offs_make_valid(rec, index, offsets); - if (UNIV_LIKELY(index->table->comp)) { + if (dict_table_is_comp(index->table)) { const byte* nulls; const byte* lens; dict_field_t* field; @@ -230,8 +230,8 @@ rec_init_offsets( dict_field_get_col(field)); len = *lens--; if (UNIV_UNLIKELY(dtype_get_len(type) > 255) - || UNIV_UNLIKELY(dtype_get_mtype(type) - == DATA_BLOB)) { + || UNIV_UNLIKELY(dtype_get_mtype(type) + == DATA_BLOB)) { if (len & 0x80) { /* 1exxxxxxx xxxxxxxx */ len <<= 8; @@ -297,7 +297,7 @@ rec_init_offsets( /********************************************************** The following function determines the offsets to each field -in the record. It can reuse a previously returned array. */ +in the record. It can reuse a previously returned array. */ ulint* rec_get_offsets_func( @@ -321,7 +321,7 @@ rec_get_offsets_func( ut_ad(index); ut_ad(heap); - if (UNIV_LIKELY(index->table->comp)) { + if (dict_table_is_comp(index->table)) { switch (UNIV_EXPECT(rec_get_status(rec), REC_STATUS_ORDINARY)) { case REC_STATUS_ORDINARY: @@ -371,9 +371,9 @@ data field in an old-style record. */ byte* rec_get_nth_field_old( /*==================*/ - /* out: pointer to the field */ - rec_t* rec, /* in: record */ - ulint n, /* in: index of the field */ + /* out: pointer to the field */ + rec_t* rec, /* in: record */ + ulint n, /* in: index of the field */ ulint* len) /* out: length of the field; UNIV_SQL_NULL if SQL null */ { @@ -393,7 +393,7 @@ rec_get_nth_field_old( fputs("Error: rec is NULL pointer\n", stderr); ut_error; } - + if (rec_get_1byte_offs_flag(rec)) { os = rec_1_get_field_start_offs(rec, n); @@ -408,7 +408,7 @@ rec_get_nth_field_old( next_os = next_os & ~REC_1BYTE_SQL_NULL_MASK; } else { os = rec_2_get_field_start_offs(rec, n); - + next_os = rec_2_get_field_end_info(rec, n); if (next_os & REC_2BYTE_SQL_NULL_MASK) { @@ -420,7 +420,7 @@ rec_get_nth_field_old( next_os = next_os & ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK); } - + *len = next_os - os; ut_ad(*len < UNIV_PAGE_SIZE); @@ -446,7 +446,7 @@ rec_get_converted_size_new( ulint i; ulint n_fields; ut_ad(index && dtuple); - ut_ad(index->table->comp); + ut_ad(dict_table_is_comp(index->table)); switch (dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK) { case REC_STATUS_ORDINARY: @@ -553,7 +553,7 @@ rec_set_nth_field_extern_bit_old( ut_a(!rec_get_1byte_offs_flag(rec)); ut_a(i < rec_get_n_fields_old(rec)); - + info = rec_2_get_field_end_info(rec, i); if (val) { @@ -592,7 +592,7 @@ rec_set_nth_field_extern_bit_new( ulint n_fields; ulint null_mask = 1; ut_ad(rec && index); - ut_ad(index->table->comp); + ut_ad(dict_table_is_comp(index->table)); ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY); n_fields = dict_index_get_n_fields(index); @@ -674,7 +674,7 @@ rec_set_field_extern_bits( { ulint i; - if (UNIV_LIKELY(index->table->comp)) { + if (dict_table_is_comp(index->table)) { for (i = 0; i < n_fields; i++) { rec_set_nth_field_extern_bit_new(rec, index, vec[i], TRUE, mtr); @@ -687,14 +687,14 @@ rec_set_field_extern_bits( } } -/*************************************************************** +/*************************************************************** Sets an old-style record field to SQL null. The physical size of the field is not changed. */ void rec_set_nth_field_sql_null( /*=======================*/ - rec_t* rec, /* in: record */ + rec_t* rec, /* in: record */ ulint n) /* in: index of the field */ { ulint offset; @@ -712,22 +712,22 @@ stores it beginning from the start of the given buffer. */ static rec_t* rec_convert_dtuple_to_rec_old( -/*==========================*/ +/*==========================*/ /* out: pointer to the origin of physical record */ byte* buf, /* in: start address of the physical record */ dtuple_t* dtuple)/* in: data tuple */ { - dfield_t* field; + dfield_t* field; ulint n_fields; ulint data_size; - rec_t* rec; + rec_t* rec; ulint end_offset; ulint ored_offset; byte* data; ulint len; ulint i; - + ut_ad(buf && dtuple); ut_ad(dtuple_validate(dtuple)); ut_ad(dtuple_check_typed(dtuple)); @@ -737,10 +737,10 @@ rec_convert_dtuple_to_rec_old( ut_ad(n_fields > 0); - /* Calculate the offset of the origin in the physical record */ + /* Calculate the offset of the origin in the physical record */ rec = buf + rec_get_converted_extra_size(data_size, n_fields); - + /* Store the number of fields */ rec_set_n_fields_old(rec, n_fields); @@ -754,57 +754,61 @@ rec_convert_dtuple_to_rec_old( if (data_size <= REC_1BYTE_OFFS_LIMIT) { - rec_set_1byte_offs_flag(rec, TRUE); + rec_set_1byte_offs_flag(rec, TRUE); - for (i = 0; i < n_fields; i++) { + for (i = 0; i < n_fields; i++) { - field = dtuple_get_nth_field(dtuple, i); + field = dtuple_get_nth_field(dtuple, i); - data = dfield_get_data(field); - len = dfield_get_len(field); - - if (len == UNIV_SQL_NULL) { - len = dtype_get_sql_null_size(dfield_get_type(field)); - data_write_sql_null(rec + end_offset, len); - - end_offset += len; - ored_offset = end_offset | REC_1BYTE_SQL_NULL_MASK; - } else { - /* If the data is not SQL null, store it */ - ut_memcpy(rec + end_offset, data, len); + data = dfield_get_data(field); + len = dfield_get_len(field); - end_offset += len; - ored_offset = end_offset; - } + if (len == UNIV_SQL_NULL) { + len = dtype_get_sql_null_size( + dfield_get_type(field)); + data_write_sql_null(rec + end_offset, len); + + end_offset += len; + ored_offset = end_offset + | REC_1BYTE_SQL_NULL_MASK; + } else { + /* If the data is not SQL null, store it */ + ut_memcpy(rec + end_offset, data, len); - rec_1_set_field_end_info(rec, i, ored_offset); - } + end_offset += len; + ored_offset = end_offset; + } + + rec_1_set_field_end_info(rec, i, ored_offset); + } } else { - rec_set_1byte_offs_flag(rec, FALSE); + rec_set_1byte_offs_flag(rec, FALSE); - for (i = 0; i < n_fields; i++) { + for (i = 0; i < n_fields; i++) { - field = dtuple_get_nth_field(dtuple, i); + field = dtuple_get_nth_field(dtuple, i); - data = dfield_get_data(field); - len = dfield_get_len(field); - - if (len == UNIV_SQL_NULL) { - len = dtype_get_sql_null_size(dfield_get_type(field)); - data_write_sql_null(rec + end_offset, len); - - end_offset += len; - ored_offset = end_offset | REC_2BYTE_SQL_NULL_MASK; - } else { - /* If the data is not SQL null, store it */ - ut_memcpy(rec + end_offset, data, len); + data = dfield_get_data(field); + len = dfield_get_len(field); - end_offset += len; - ored_offset = end_offset; - } + if (len == UNIV_SQL_NULL) { + len = dtype_get_sql_null_size( + dfield_get_type(field)); + data_write_sql_null(rec + end_offset, len); + + end_offset += len; + ored_offset = end_offset + | REC_2BYTE_SQL_NULL_MASK; + } else { + /* If the data is not SQL null, store it */ + ut_memcpy(rec + end_offset, data, len); - rec_2_set_field_end_info(rec, i, ored_offset); - } + end_offset += len; + ored_offset = end_offset; + } + + rec_2_set_field_end_info(rec, i, ored_offset); + } } return(rec); @@ -825,7 +829,7 @@ rec_convert_dtuple_to_rec_new( { dfield_t* field; dtype_t* type; - rec_t* rec = buf + REC_N_NEW_EXTRA_BYTES; + rec_t* rec = buf + REC_N_NEW_EXTRA_BYTES; byte* end; byte* nulls; byte* lens; @@ -837,12 +841,11 @@ rec_convert_dtuple_to_rec_new( const ulint n_fields = dtuple_get_n_fields(dtuple); const ulint status = dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK; - ut_ad(index->table->comp); - + ut_ad(dict_table_is_comp(index->table)); ut_ad(n_fields > 0); /* Try to ensure that the memset() between the for() loops - completes fast. The address is not exact, but UNIV_PREFETCH + completes fast. The address is not exact, but UNIV_PREFETCH should never generate a memory fault. */ UNIV_PREFETCH_RW(rec - REC_N_NEW_EXTRA_BYTES - n_fields); UNIV_PREFETCH_RW(rec); @@ -998,7 +1001,7 @@ rec_convert_dtuple_to_rec( ut_ad(dtuple_validate(dtuple)); ut_ad(dtuple_check_typed(dtuple)); - if (UNIV_LIKELY(index->table->comp)) { + if (dict_table_is_comp(index->table)) { rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple); } else { rec = rec_convert_dtuple_to_rec_old(buf, dtuple); @@ -1050,7 +1053,7 @@ rec_copy_prefix_to_dtuple( ut_ad(dtuple_check_typed(tuple)); dtuple_set_info_bits(tuple, - rec_get_info_bits(rec, index->table->comp)); + rec_get_info_bits(rec, dict_table_is_comp(index->table))); for (i = 0; i < n_fields; i++) { @@ -1138,7 +1141,7 @@ rec_copy_prefix_to_buf( UNIV_PREFETCH_RW(*buf); - if (UNIV_UNLIKELY(!index->table->comp)) { + if (!dict_table_is_comp(index->table)) { ut_ad(rec_validate_old(rec)); return(rec_copy_prefix_to_buf_old(rec, n_fields, rec_get_field_start_offs(rec, n_fields), @@ -1248,16 +1251,16 @@ rec_validate_old( (ulong) n_fields); return(FALSE); } - + for (i = 0; i < n_fields; i++) { data = rec_get_nth_field_old(rec, i, &len); - + if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) { fprintf(stderr, "InnoDB: Error: record field %lu len %lu\n", (ulong) i, (ulong) len); return(FALSE); - } + } if (len != UNIV_SQL_NULL) { len_sum += len; @@ -1274,7 +1277,7 @@ rec_validate_old( fprintf(stderr, "InnoDB: Error: record len should be %lu, len %lu\n", (ulong) len_sum, - rec_get_data_size_old(rec)); + rec_get_data_size_old(rec)); return(FALSE); } @@ -1338,7 +1341,7 @@ rec_validate( (ulong) len_sum, (ulong) (rec_get_end(rec, offsets) - rec)); return(FALSE); - } + } rec_dummy = sum; /* This is here only to fool the compiler */ @@ -1427,13 +1430,13 @@ rec_print_new( " compact format; info bits %lu\n", (ulong) rec_offs_n_fields(offsets), (ulong) rec_get_info_bits(rec, TRUE)); - + for (i = 0; i < rec_offs_n_fields(offsets); i++) { data = rec_get_nth_field(rec, offsets, i, &len); fprintf(file, " %lu:", (ulong) i); - + if (len != UNIV_SQL_NULL) { if (len <= 30) { @@ -1466,7 +1469,7 @@ rec_print( { ut_ad(index); - if (!index->table->comp) { + if (!dict_table_is_comp(index->table)) { rec_print_old(file, rec); return; } else { diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 128b46f9aa4..c80a61cc729 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -51,15 +51,15 @@ innobase_invalidate_query_cache( chars count */ /********************************************************************** -This function returns true if +This function returns true if 1) SQL-query in the current thread -is either REPLACE or LOAD DATA INFILE REPLACE. +is either REPLACE or LOAD DATA INFILE REPLACE. 2) SQL-query in the current thread is INSERT ON DUPLICATE KEY UPDATE. -NOTE that /mysql/innobase/row/row0ins.c must contain the +NOTE that /mysql/innobase/row/row0ins.c must contain the prototype for this function ! */ ibool @@ -73,7 +73,7 @@ ins_node_create( /*============*/ /* out, own: insert node struct */ ulint ins_type, /* in: INS_VALUES, ... */ - dict_table_t* table, /* in: table where to insert */ + dict_table_t* table, /* in: table where to insert */ mem_heap_t* heap) /* in: mem heap where created */ { ins_node_t* node; @@ -90,13 +90,13 @@ ins_node_create( node->entry = NULL; node->select = NULL; - + node->trx_id = ut_dulint_zero; - + node->entry_sys_heap = mem_heap_create(128); - node->magic_n = INS_NODE_MAGIC_N; - + node->magic_n = INS_NODE_MAGIC_N; + return(node); } @@ -116,7 +116,7 @@ ins_node_create_entry_list( UT_LIST_INIT(node->entry_list); index = dict_table_get_first_index(node->table); - + while (index != NULL) { entry = row_build_index_entry(node->row, index, node->entry_sys_heap); @@ -152,11 +152,11 @@ row_ins_alloc_sys_fields( /* 1. Allocate buffer for row id */ col = dict_table_get_sys_col(table, DATA_ROW_ID); - + dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); ptr = mem_heap_alloc(heap, DATA_ROW_ID_LEN); - + dfield_set_data(dfield, ptr, DATA_ROW_ID_LEN); node->row_id_buf = ptr; @@ -166,12 +166,12 @@ row_ins_alloc_sys_fields( /* 2. Fill in the dfield for mix id */ col = dict_table_get_sys_col(table, DATA_MIX_ID); - + dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); len = mach_dulint_get_compressed_size(table->mix_id); ptr = mem_heap_alloc(heap, DATA_MIX_ID_LEN); - + mach_dulint_write_compressed(ptr, table->mix_id); dfield_set_data(dfield, ptr, len); } @@ -179,10 +179,10 @@ row_ins_alloc_sys_fields( /* 3. Allocate buffer for trx id */ col = dict_table_get_sys_col(table, DATA_TRX_ID); - + dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); ptr = mem_heap_alloc(heap, DATA_TRX_ID_LEN); - + dfield_set_data(dfield, ptr, DATA_TRX_ID_LEN); node->trx_id_buf = ptr; @@ -190,10 +190,10 @@ row_ins_alloc_sys_fields( /* 4. Allocate buffer for roll ptr */ col = dict_table_get_sys_col(table, DATA_ROLL_PTR); - + dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); ptr = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN); - + dfield_set_data(dfield, ptr, DATA_ROLL_PTR_LEN); } @@ -217,7 +217,7 @@ ins_node_set_new_row( mem_heap_empty(node->entry_sys_heap); /* Create templates for index entries */ - + ins_node_create_entry_list(node); /* Allocate from entry_sys_heap buffers for sys fields */ @@ -252,19 +252,20 @@ row_ins_sec_index_entry_by_modify( upd_t* update; rec_t* rec; ulint err; - + rec = btr_cur_get_rec(cursor); - + ut_ad((cursor->index->type & DICT_CLUSTERED) == 0); - ut_ad(rec_get_deleted_flag(rec, cursor->index->table->comp)); - + ut_ad(rec_get_deleted_flag(rec, + dict_table_is_comp(cursor->index->table))); + /* We know that in the alphabetical ordering, entry and rec are identified. But in their binary form there may be differences if there are char fields in them. Therefore we have to calculate the difference. */ - + heap = mem_heap_create(1024); - + update = row_upd_build_sec_rec_difference_binary(cursor->index, entry, rec, thr_get_trx(thr), heap); if (mode == BTR_MODIFY_LEAF) { @@ -276,7 +277,7 @@ row_ins_sec_index_entry_by_modify( if (err == DB_OVERFLOW || err == DB_UNDERFLOW) { err = DB_FAIL; } - } else { + } else { ut_a(mode == BTR_MODIFY_TREE); err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG, cursor, &dummy_big_rec, update, 0, thr, mtr); @@ -314,21 +315,22 @@ row_ins_clust_index_entry_by_modify( rec_t* rec; upd_t* update; ulint err; - + ut_ad(cursor->index->type & DICT_CLUSTERED); - + *big_rec = NULL; rec = btr_cur_get_rec(cursor); - ut_ad(rec_get_deleted_flag(rec, cursor->index->table->comp)); + ut_ad(rec_get_deleted_flag(rec, + dict_table_is_comp(cursor->index->table))); heap = mem_heap_create(1024); - + /* Build an update vector containing all the fields to be modified; NOTE that this vector may NOT contain system columns trx_id or roll_ptr */ - + update = row_upd_build_difference_binary(cursor->index, entry, ext_vec, n_ext_vec, rec, thr_get_trx(thr), heap); if (mode == BTR_MODIFY_LEAF) { @@ -340,12 +342,12 @@ row_ins_clust_index_entry_by_modify( if (err == DB_OVERFLOW || err == DB_UNDERFLOW) { err = DB_FAIL; } - } else { + } else { ut_a(mode == BTR_MODIFY_TREE); err = btr_cur_pessimistic_update(0, cursor, big_rec, update, 0, thr, mtr); } - + mem_heap_free(heap); return(err); @@ -366,7 +368,7 @@ row_ins_cascade_ancestor_updates_table( upd_node_t* upd_node; parent = que_node_get_parent(node); - + while (que_node_get_type(parent) == QUE_NODE_UPDATE) { upd_node = parent; @@ -383,7 +385,7 @@ row_ins_cascade_ancestor_updates_table( return(FALSE); } - + /************************************************************************* Returns the number of ancestor UPDATE or DELETE nodes of a cascaded update/delete node. */ @@ -398,7 +400,7 @@ row_ins_cascade_n_ancestors( ulint n_ancestors = 0; parent = que_node_get_parent(node); - + while (que_node_get_type(parent) == QUE_NODE_UPDATE) { n_ancestors++; @@ -409,7 +411,7 @@ row_ins_cascade_n_ancestors( return(n_ancestors); } - + /********************************************************************** Calculates the update vector node->cascade->update for a child table in a cascaded update. */ @@ -442,15 +444,15 @@ row_ins_cascade_calc_update_vec( upd_t* parent_update; upd_field_t* parent_ufield; ulint n_fields_updated; - ulint parent_field_no; + ulint parent_field_no; dtype_t* type; ulint i; ulint j; - + ut_a(node && foreign && cascade && table && index); /* Calculate the appropriate update vector which will set the fields - in the child index record to the same value (possibly padded with + in the child index record to the same value (possibly padded with spaces if the column is a fixed length CHAR or FIXBINARY column) as the referenced index record will get in the update. */ @@ -458,12 +460,12 @@ row_ins_cascade_calc_update_vec( ut_a(parent_table == foreign->referenced_table); parent_index = foreign->referenced_index; parent_update = node->update; - + update = cascade->update; update->info_bits = 0; update->n_fields = foreign->n_fields; - + n_fields_updated = 0; for (i = 0; i < foreign->n_fields; i++) { @@ -475,7 +477,7 @@ row_ins_cascade_calc_update_vec( for (j = 0; j < parent_update->n_fields; j++) { parent_ufield = parent_update->fields + j; - + if (parent_ufield->field_no == parent_field_no) { ulint min_size; @@ -484,7 +486,7 @@ row_ins_cascade_calc_update_vec( updated. Let us make the update vector field for the child table. */ - ufield = update->fields + n_fields_updated; + ufield = update->fields + n_fields_updated; ufield->field_no = dict_table_get_nth_col_pos(table, @@ -499,20 +501,20 @@ row_ins_cascade_calc_update_vec( updated as NULL */ if (ufield->new_val.len == UNIV_SQL_NULL - && (type->prtype & DATA_NOT_NULL)) { + && (type->prtype & DATA_NOT_NULL)) { - return(ULINT_UNDEFINED); + return(ULINT_UNDEFINED); } /* If the new value would not fit in the column, do not allow the update */ if (ufield->new_val.len != UNIV_SQL_NULL - && dtype_get_at_most_n_mbchars( + && dtype_get_at_most_n_mbchars( type, dtype_get_len(type), ufield->new_val.len, ufield->new_val.data) - < ufield->new_val.len) { + < ufield->new_val.len) { return(ULINT_UNDEFINED); } @@ -525,12 +527,12 @@ row_ins_cascade_calc_update_vec( min_size = dtype_get_min_size(type); if (min_size - && ufield->new_val.len != UNIV_SQL_NULL - && ufield->new_val.len < min_size) { + && ufield->new_val.len != UNIV_SQL_NULL + && ufield->new_val.len < min_size) { char* pad_start; const char* pad_end; - ufield->new_val.data = + ufield->new_val.data = mem_heap_alloc(heap, min_size); pad_start = @@ -549,6 +551,15 @@ row_ins_cascade_calc_update_vec( default: ut_error; case 1: + if (UNIV_UNLIKELY( + dtype_get_charset_coll( + dtype_get_prtype(type)) + == DATA_MYSQL_BINARY_CHARSET_COLL)) { + /* Do not pad BINARY + columns. */ + return(ULINT_UNDEFINED); + } + /* space=0x20 */ memset(pad_start, 0x20, pad_end - pad_start); @@ -588,20 +599,21 @@ row_ins_set_detailed( trx_t* trx, /* in: transaction */ dict_foreign_t* foreign) /* in: foreign key constraint */ { - - FILE* tf = os_file_create_tmpfile(); - - if (tf) { - ut_print_name(tf, trx, foreign->foreign_table_name); - dict_print_info_on_foreign_key_in_create_format(tf, trx, - foreign, FALSE); - - trx_set_detailed_error_from_file(trx, tf); - - fclose(tf); + mutex_enter(&srv_misc_tmpfile_mutex); + rewind(srv_misc_tmpfile); + + if (os_file_set_eof(srv_misc_tmpfile)) { + ut_print_name(srv_misc_tmpfile, trx, + foreign->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format( + srv_misc_tmpfile, + trx, foreign, FALSE); + trx_set_detailed_error_from_file(trx, srv_misc_tmpfile); } else { - trx_set_detailed_error(trx, "temp file creation failed"); + trx_set_detailed_error(trx, "temp file operation failed"); } + + mutex_exit(&srv_misc_tmpfile_mutex); } /************************************************************************* @@ -677,9 +689,9 @@ row_ins_foreign_report_add_err( child table */ { FILE* ef = dict_foreign_err_file; - + row_ins_set_detailed(trx, foreign); - + mutex_enter(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); @@ -709,7 +721,7 @@ row_ins_foreign_report_add_err( } if (rec) { - rec_print(ef, rec, foreign->foreign_index); + rec_print(ef, rec, foreign->referenced_index); } putc('\n', ef); @@ -803,7 +815,7 @@ row_ins_foreign_check_on_constraint( thr, foreign, btr_pcur_get_rec(pcur), entry); - return(DB_ROW_IS_REFERENCED); + return(DB_ROW_IS_REFERENCED); } if (!node->is_delete && 0 == (foreign->type & @@ -811,12 +823,12 @@ row_ins_foreign_check_on_constraint( | DICT_FOREIGN_ON_UPDATE_SET_NULL))) { /* This is an UPDATE */ - + row_ins_foreign_report_err("Trying to update", thr, foreign, btr_pcur_get_rec(pcur), entry); - return(DB_ROW_IS_REFERENCED); + return(DB_ROW_IS_REFERENCED); } if (node->cascade_node == NULL) { @@ -836,13 +848,13 @@ row_ins_foreign_check_on_constraint( several child tables to the table where the delete is done! */ cascade = node->cascade_node; - + cascade->table = table; cascade->foreign = foreign; - + if (node->is_delete - && (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)) { + && (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)) { cascade->is_delete = TRUE; } else { cascade->is_delete = FALSE; @@ -865,12 +877,12 @@ row_ins_foreign_check_on_constraint( of the parent table in an inconsistent state! */ if (!cascade->is_delete - && row_ins_cascade_ancestor_updates_table(cascade, table)) { + && row_ins_cascade_ancestor_updates_table(cascade, table)) { - /* We do not know if this would break foreign key - constraints, but play safe and return an error */ + /* We do not know if this would break foreign key + constraints, but play safe and return an error */ - err = DB_ROW_IS_REFERENCED; + err = DB_ROW_IS_REFERENCED; row_ins_foreign_report_err( "Trying an update, possibly causing a cyclic cascaded update\n" @@ -892,13 +904,13 @@ row_ins_foreign_check_on_constraint( index = btr_pcur_get_btr_cur(pcur)->index; ut_a(index == foreign->foreign_index); - + rec = btr_pcur_get_rec(pcur); if (index->type & DICT_CLUSTERED) { /* pcur is already positioned in the clustered index of the child table */ - + clust_index = index; clust_rec = rec; } else { @@ -908,7 +920,7 @@ row_ins_foreign_check_on_constraint( clust_index = dict_table_get_first_index(table); tmp_heap = mem_heap_create(256); - + ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec, tmp_heap); btr_pcur_open_with_no_init(clust_index, ref, @@ -918,8 +930,8 @@ row_ins_foreign_check_on_constraint( clust_rec = btr_pcur_get_rec(cascade->pcur); if (!page_rec_is_user_rec(clust_rec) - || btr_pcur_get_low_match(cascade->pcur) - < dict_index_get_n_unique(clust_index)) { + || btr_pcur_get_low_match(cascade->pcur) + < dict_index_get_n_unique(clust_index)) { fputs( "InnoDB: error in cascade of a foreign key op\n" @@ -953,26 +965,26 @@ row_ins_foreign_check_on_constraint( err = lock_clust_rec_read_check_and_lock_alt(0, clust_rec, clust_index, LOCK_X, LOCK_REC_NOT_GAP, thr); } - + if (err != DB_SUCCESS) { goto nonstandard_exit_func; } - if (rec_get_deleted_flag(clust_rec, table->comp)) { + if (rec_get_deleted_flag(clust_rec, dict_table_is_comp(table))) { /* This can happen if there is a circular reference of rows such that cascading delete comes to delete a row already in the process of being delete marked */ - err = DB_SUCCESS; + err = DB_SUCCESS; goto nonstandard_exit_func; } if ((node->is_delete - && (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)) - || (!node->is_delete - && (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL))) { - + && (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)) + || (!node->is_delete + && (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL))) { + /* Build the appropriate update vector which sets foreign->n_fields first fields in rec to SQL NULL */ @@ -980,7 +992,7 @@ row_ins_foreign_check_on_constraint( update->info_bits = 0; update->n_fields = foreign->n_fields; - + for (i = 0; i < foreign->n_fields; i++) { (update->fields + i)->field_no = dict_table_get_nth_col_pos(table, @@ -993,7 +1005,7 @@ row_ins_foreign_check_on_constraint( } if (!node->is_delete - && (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)) { + && (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)) { /* Build the appropriate update vector which sets changing foreign->n_fields first fields in rec to new values */ @@ -1001,9 +1013,9 @@ row_ins_foreign_check_on_constraint( upd_vec_heap = mem_heap_create(256); n_to_update = row_ins_cascade_calc_update_vec(node, foreign, - upd_vec_heap); + upd_vec_heap); if (n_to_update == ULINT_UNDEFINED) { - err = DB_ROW_IS_REFERENCED; + err = DB_ROW_IS_REFERENCED; row_ins_foreign_report_err( "Trying a cascaded update where the updated value in the child\n" @@ -1011,7 +1023,7 @@ row_ins_foreign_check_on_constraint( "be NULL and the column is declared as not NULL in the child table,", thr, foreign, btr_pcur_get_rec(pcur), entry); - goto nonstandard_exit_func; + goto nonstandard_exit_func; } if (cascade->update->n_fields == 0) { @@ -1020,29 +1032,29 @@ row_ins_foreign_check_on_constraint( to in this foreign key constraint: no need to do anything */ - err = DB_SUCCESS; + err = DB_SUCCESS; - goto nonstandard_exit_func; + goto nonstandard_exit_func; } } - + /* Store pcur position and initialize or store the cascade node pcur stored position */ - + btr_pcur_store_position(pcur, mtr); - + if (index == clust_index) { btr_pcur_copy_stored_position(cascade->pcur, pcur); } else { btr_pcur_store_position(cascade->pcur, mtr); } - + mtr_commit(mtr); ut_a(cascade->pcur->rel_pos == BTR_PCUR_ON); cascade->state = UPD_NODE_UPDATE_CLUSTERED; - + err = row_update_cascade_for_mysql(thr, cascade, foreign->foreign_table); @@ -1065,7 +1077,7 @@ row_ins_foreign_check_on_constraint( mtr_start(mtr); /* Restore pcur position */ - + btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr); if (tmp_heap) { @@ -1073,7 +1085,7 @@ row_ins_foreign_check_on_constraint( } if (upd_vec_heap) { - mem_heap_free(upd_vec_heap); + mem_heap_free(upd_vec_heap); } return(err); @@ -1084,7 +1096,7 @@ nonstandard_exit_func: } if (upd_vec_heap) { - mem_heap_free(upd_vec_heap); + mem_heap_free(upd_vec_heap); } btr_pcur_store_position(pcur, mtr); @@ -1105,12 +1117,12 @@ ulint row_ins_set_shared_rec_lock( /*========================*/ /* out: DB_SUCCESS or error code */ - ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or + ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOCK_REC_NOT_GAP type lock */ rec_t* rec, /* in: record */ dict_index_t* index, /* in: index */ const ulint* offsets,/* in: rec_get_offsets(rec, index) */ - que_thr_t* thr) /* in: query thread */ + que_thr_t* thr) /* in: query thread */ { ulint err; @@ -1127,20 +1139,21 @@ row_ins_set_shared_rec_lock( return(err); } +#ifndef UNIV_HOTBACKUP /************************************************************************* Sets a exclusive lock on a record. Used in locking possible duplicate key records */ static ulint row_ins_set_exclusive_rec_lock( -/*============================*/ +/*===========================*/ /* out: DB_SUCCESS or error code */ - ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or + ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOCK_REC_NOT_GAP type lock */ rec_t* rec, /* in: record */ dict_index_t* index, /* in: index */ const ulint* offsets,/* in: rec_get_offsets(rec, index) */ - que_thr_t* thr) /* in: query thread */ + que_thr_t* thr) /* in: query thread */ { ulint err; @@ -1156,7 +1169,8 @@ row_ins_set_exclusive_rec_lock( return(err); } - +#endif /* !UNIV_HOTBACKUP */ + /******************************************************************* Checks if foreign key constraint fails for an index entry. Sets shared locks which lock either the success or the failure of the constraint. NOTE that @@ -1179,7 +1193,7 @@ row_ins_check_foreign_constraint( dtuple_t* entry, /* in: index entry for index */ que_thr_t* thr) /* in: query thread */ { - upd_node_t* upd_node; + upd_node_t* upd_node; dict_table_t* check_table; dict_index_t* check_index; ulint n_fields_cmp; @@ -1215,17 +1229,17 @@ run_again: for (i = 0; i < foreign->n_fields; i++) { if (UNIV_SQL_NULL == dfield_get_len( - dtuple_get_nth_field(entry, i))) { + dtuple_get_nth_field(entry, i))) { goto exit_func; } } if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) { - upd_node = thr->run_node; + upd_node = thr->run_node; - if (!(upd_node->is_delete) && upd_node->foreign == foreign) { - /* If a cascaded update is done as defined by a + if (!(upd_node->is_delete) && upd_node->foreign == foreign) { + /* If a cascaded update is done as defined by a foreign key constraint, do not check that constraint for the child row. In ON UPDATE CASCADE the update of the parent row is only half done when @@ -1258,7 +1272,7 @@ run_again: FILE* ef = dict_foreign_err_file; row_ins_set_detailed(trx, foreign); - + mutex_enter(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); @@ -1289,7 +1303,7 @@ run_again: if (check_table != table) { /* We already have a LOCK_IX on table, but not necessarily on check_table */ - + err = lock_table(0, check_table, LOCK_IS, thr); if (err != DB_SUCCESS) { @@ -1320,7 +1334,7 @@ run_again: goto next_rec; } - + offsets = rec_get_offsets(rec, check_index, offsets, ULINT_UNDEFINED, &heap); @@ -1352,7 +1366,7 @@ run_again: /* Found a matching record. Lock only a record because we can allow inserts into gaps */ - + err = row_ins_set_shared_rec_lock( LOCK_REC_NOT_GAP, rec, check_index, offsets, thr); @@ -1362,7 +1376,7 @@ run_again: break; } - if (check_ref) { + if (check_ref) { err = DB_SUCCESS; break; @@ -1387,9 +1401,9 @@ run_again: key errors resulting from FK constraints to a separate error code. */ - + if (err == DB_DUPLICATE_KEY) { - err = DB_FOREIGN_DUPLICATE_KEY; + err = DB_FOREIGN_DUPLICATE_KEY; } break; @@ -1413,7 +1427,7 @@ run_again: break; } - if (check_ref) { + if (check_ref) { err = DB_NO_REFERENCED_ROW; row_ins_foreign_report_add_err( trx, foreign, rec, entry); @@ -1429,7 +1443,7 @@ next_rec: moved = btr_pcur_move_to_next(&pcur, &mtr); if (!moved) { - if (check_ref) { + if (check_ref) { rec = btr_pcur_get_rec(&pcur); row_ins_foreign_report_add_err( trx, foreign, rec, entry); @@ -1456,10 +1470,10 @@ do_possible_lock_wait: que_thr_stop_for_mysql(thr); srv_suspend_mysql_thread(thr); - + if (trx->error_state == DB_SUCCESS) { - goto run_again; + goto run_again; } err = trx->error_state; @@ -1542,7 +1556,7 @@ row_ins_check_foreign_constraints( if (got_s_lock) { row_mysql_unfreeze_data_dictionary(trx); } - + if (err != DB_SUCCESS) { return(err); } @@ -1554,6 +1568,7 @@ row_ins_check_foreign_constraints( return(DB_SUCCESS); } +#ifndef UNIV_HOTBACKUP /******************************************************************* Checks if a unique key violation to rec would occur at the index entry insert. */ @@ -1572,7 +1587,7 @@ row_ins_dupl_error_with_rec( ulint matched_fields; ulint matched_bytes; ulint n_unique; - ulint i; + ulint i; ut_ad(rec_offs_validate(rec, index, offsets)); @@ -1586,7 +1601,7 @@ row_ins_dupl_error_with_rec( if (matched_fields < n_unique) { - return(FALSE); + return(FALSE); } /* In a unique secondary index we allow equal key values if they @@ -1594,17 +1609,18 @@ row_ins_dupl_error_with_rec( if (!(index->type & DICT_CLUSTERED)) { - for (i = 0; i < n_unique; i++) { - if (UNIV_SQL_NULL == dfield_get_len( - dtuple_get_nth_field(entry, i))) { + for (i = 0; i < n_unique; i++) { + if (UNIV_SQL_NULL == dfield_get_len( + dtuple_get_nth_field(entry, i))) { - return(FALSE); - } - } + return(FALSE); + } + } } return(!rec_get_deleted_flag(rec, rec_offs_comp(offsets))); -} +} +#endif /* !UNIV_HOTBACKUP */ /******************************************************************* Scans a unique non-clustered index at a given index entry to determine @@ -1643,7 +1659,7 @@ row_ins_scan_sec_index_for_duplicate( for (i = 0; i < n_unique; i++) { if (UNIV_SQL_NULL == dfield_get_len( - dtuple_get_nth_field(entry, i))) { + dtuple_get_nth_field(entry, i))) { return(DB_SUCCESS); } @@ -1656,7 +1672,7 @@ row_ins_scan_sec_index_for_duplicate( n_fields_cmp = dtuple_get_n_fields_cmp(entry); dtuple_set_n_fields_cmp(entry, dict_index_get_n_unique(index)); - + btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); /* Scan index records and check if there is a duplicate */ @@ -1668,17 +1684,17 @@ row_ins_scan_sec_index_for_duplicate( goto next_rec; } - + offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); if (innobase_query_is_update()) { /* If the SQL-query will update or replace - duplicate key we will take X-lock for - duplicates ( REPLACE, LOAD DATAFILE REPLACE, + duplicate key we will take X-lock for + duplicates ( REPLACE, LOAD DATAFILE REPLACE, INSERT ON DUPLICATE KEY UPDATE). */ - + err = row_ins_set_exclusive_rec_lock(LOCK_ORDINARY, rec, index, offsets, thr); } else { @@ -1693,7 +1709,7 @@ row_ins_scan_sec_index_for_duplicate( } if (page_rec_is_supremum(rec)) { - + goto next_rec; } @@ -1737,6 +1753,7 @@ next_rec: InnoDB Hot Backup builds. Besides, this function should never be called in InnoDB Hot Backup. */ ut_error; + return(DB_FAIL); #endif /* UNIV_HOTBACKUP */ } @@ -1768,7 +1785,7 @@ row_ins_duplicate_error_in_clust( *offsets_ = (sizeof offsets_) / sizeof *offsets_; UT_NOT_USED(mtr); - + ut_a(cursor->index->type & DICT_CLUSTERED); ut_ad(cursor->index->type & DICT_UNIQUE); @@ -1779,16 +1796,16 @@ row_ins_duplicate_error_in_clust( clustered index key fields. For such a secondary index record, to avoid race condition, we must FIRST do the insertion and after that check that the uniqueness condition is not breached! */ - + /* NOTE: A problem is that in the B-tree node pointers on an upper level may match more to the entry than the actual existing user records on the leaf level. So, even if low_match would suggest that a duplicate key violation may occur, this may not be the case. */ n_unique = dict_index_get_n_unique(cursor->index); - + if (cursor->low_match >= n_unique) { - + rec = btr_cur_get_rec(cursor); if (!page_rec_is_infimum(rec)) { @@ -1803,19 +1820,19 @@ row_ins_duplicate_error_in_clust( if (innobase_query_is_update()) { /* If the SQL-query will update or replace - duplicate key we will take X-lock for - duplicates ( REPLACE, LOAD DATAFILE REPLACE, + duplicate key we will take X-lock for + duplicates ( REPLACE, LOAD DATAFILE REPLACE, INSERT ON DUPLICATE KEY UPDATE). */ - + err = row_ins_set_exclusive_rec_lock( LOCK_REC_NOT_GAP,rec,cursor->index, offsets, thr); } else { - + err = row_ins_set_shared_rec_lock( - LOCK_REC_NOT_GAP,rec, cursor->index, + LOCK_REC_NOT_GAP,rec, cursor->index, offsets, thr); - } + } if (err != DB_SUCCESS) { goto func_exit; @@ -1841,8 +1858,8 @@ row_ins_duplicate_error_in_clust( if (innobase_query_is_update()) { /* If the SQL-query will update or replace - duplicate key we will take X-lock for - duplicates ( REPLACE, LOAD DATAFILE REPLACE, + duplicate key we will take X-lock for + duplicates ( REPLACE, LOAD DATAFILE REPLACE, INSERT ON DUPLICATE KEY UPDATE). */ err = row_ins_set_exclusive_rec_lock( @@ -1880,6 +1897,7 @@ func_exit: InnoDB Hot Backup builds. Besides, this function should never be called in InnoDB Hot Backup. */ ut_error; + return(DB_FAIL); #endif /* UNIV_HOTBACKUP */ } @@ -1902,7 +1920,7 @@ row_ins_must_modify( { ulint enough_match; rec_t* rec; - + /* NOTE: (compare to the note in row_ins_duplicate_error) Because node pointers on upper levels of the B-tree may match more to entry than to actual user records on the leaf level, we have to check if the @@ -1911,7 +1929,7 @@ row_ins_must_modify( of a secondary index, all fields of the index. */ enough_match = dict_index_get_n_unique_in_tree(cursor->index); - + if (cursor->low_match >= enough_match) { rec = btr_cur_get_rec(cursor); @@ -1973,7 +1991,7 @@ row_ins_index_entry_low( /* Note that we use PAGE_CUR_LE as the search mode, because then the function will return in both low_match and up_match of the cursor sensible values */ - + if (!(thr_get_trx(thr)->check_unique_secondary)) { ignore_sec_unique = BTR_IGNORE_SEC_UNIQUE; } @@ -2009,7 +2027,7 @@ row_ins_index_entry_low( if (index->type & DICT_UNIQUE && (cursor.up_match >= n_unique || cursor.low_match >= n_unique)) { - if (index->type & DICT_CLUSTERED) { + if (index->type & DICT_CLUSTERED) { /* Note that the following may return also DB_LOCK_WAIT */ @@ -2035,11 +2053,11 @@ row_ins_index_entry_low( prevent any insertion of a duplicate by another transaction. Let us now reposition the cursor and continue the insertion. */ - + btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, mode | BTR_INSERT, &cursor, 0, &mtr); - } + } } modify = row_ins_must_modify(&cursor); @@ -2066,7 +2084,7 @@ row_ins_index_entry_low( entry, thr, &mtr); } - + } else { if (mode == BTR_MODIFY_LEAF) { err = btr_cur_optimistic_insert(0, &cursor, entry, @@ -2091,7 +2109,7 @@ function_exit: if (big_rec) { rec_t* rec; mtr_start(&mtr); - + btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, BTR_MODIFY_TREE, &cursor, 0, &mtr); rec = btr_cur_get_rec(&cursor); @@ -2177,7 +2195,7 @@ row_ins_index_entry_set_vals( dfield_t* row_field; ulint n_fields; ulint i; - dtype_t* cur_type; + dtype_t* cur_type; ut_ad(entry && row); @@ -2191,7 +2209,7 @@ row_ins_index_entry_set_vals( /* Check column prefix indexes */ if (ind_field->prefix_len > 0 - && dfield_get_len(row_field) != UNIV_SQL_NULL) { + && dfield_get_len(row_field) != UNIV_SQL_NULL) { cur_type = dict_col_get_type( dict_field_get_col(ind_field)); @@ -2200,7 +2218,7 @@ row_ins_index_entry_set_vals( ind_field->prefix_len, dfield_get_len(row_field), row_field->data); } else { - field->len = row_field->len; + field->len = row_field->len; } field->data = row_field->data; @@ -2221,9 +2239,9 @@ row_ins_index_entry_step( ulint err; ut_ad(dtuple_check_typed(node->row)); - + row_ins_index_entry_set_vals(node->index, node->entry, node->row); - + ut_ad(dtuple_check_typed(node->entry)); err = row_ins_index_entry(node->index, node->entry, NULL, 0, thr); @@ -2240,16 +2258,16 @@ row_ins_alloc_row_id_step( ins_node_t* node) /* in: row insert node */ { dulint row_id; - + ut_ad(node->state == INS_NODE_ALLOC_ROW_ID); - + if (dict_table_get_first_index(node->table)->type & DICT_UNIQUE) { /* No row id is stored if the clustered index is unique */ return; } - + /* Fill in row id value to row */ row_id = dict_sys_get_new_row_id(); @@ -2269,12 +2287,12 @@ row_ins_get_row_from_values( dfield_t* dfield; dtuple_t* row; ulint i; - + /* The field values are copied in the buffers of the select node and it is safe to use them until we fetch from select again: therefore we can just copy the pointers */ - row = node->row; + row = node->row; i = 0; list_node = node->values_list; @@ -2307,7 +2325,7 @@ row_ins_get_row_from_select( it is safe to use them until we fetch from select again: therefore we can just copy the pointers */ - row = node->row; + row = node->row; i = 0; list_node = node->select->select_list; @@ -2320,7 +2338,7 @@ row_ins_get_row_from_select( list_node = que_node_get_next(list_node); } } - + /*************************************************************** Inserts a row to a table. */ @@ -2333,13 +2351,13 @@ row_ins( que_thr_t* thr) /* in: query thread */ { ulint err; - + ut_ad(node && thr); if (node->state == INS_NODE_ALLOC_ROW_ID) { row_ins_alloc_row_id_step(node); - + node->index = dict_table_get_first_index(node->table); node->entry = UT_LIST_GET_FIRST(node->entry_list); @@ -2359,7 +2377,7 @@ row_ins( while (node->index != NULL) { err = row_ins_index_entry_step(node, thr); - + if (err != DB_SUCCESS) { return(err); @@ -2370,9 +2388,9 @@ row_ins( } ut_ad(node->entry == NULL); - + node->state = INS_NODE_ALLOC_ROW_ID; - + return(DB_SUCCESS); } @@ -2393,11 +2411,11 @@ row_ins_step( ulint err; ut_ad(thr); - + trx = thr_get_trx(thr); trx_start_if_not_started(trx); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_INSERT); @@ -2417,12 +2435,12 @@ row_ins_step( /* It may be that the current session has not yet started its transaction, or it has been committed: */ - + if (UT_DULINT_EQ(trx->id, node->trx_id)) { /* No need to do IX-locking or write trx id to buf */ goto same_trx; - } + } trx_write_trx_id(node->trx_id_buf, trx->id); @@ -2434,17 +2452,17 @@ row_ins_step( } node->trx_id = trx->id; - same_trx: + same_trx: node->state = INS_NODE_ALLOC_ROW_ID; if (node->ins_type == INS_SEARCHED) { /* Reset the cursor */ sel_node->state = SEL_NODE_OPEN; - + /* Fetch a row to insert */ - + thr->run_node = sel_node; - + return(thr); } } @@ -2456,7 +2474,7 @@ row_ins_step( /* No more rows to insert */ thr->run_node = parent; - + return(thr); } @@ -2476,7 +2494,7 @@ error_handling: if (node->ins_type == INS_SEARCHED) { /* Fetch a row to insert */ - + thr->run_node = sel_node; } else { thr->run_node = que_node_get_parent(node); diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index a16ffc5aa41..4dbe5128974 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -45,7 +45,7 @@ struct row_mysql_drop_struct{ }; UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list; -ibool row_mysql_drop_list_inited = FALSE; +ibool row_mysql_drop_list_inited = FALSE; /* Magic table names for invoking various monitor threads */ static const char S_innodb_monitor[] = "innodb_monitor"; @@ -89,8 +89,8 @@ row_mysql_is_system_table( return(FALSE); } return(0 == strcmp(name + 6, "host") - || 0 == strcmp(name + 6, "user") - || 0 == strcmp(name + 6, "db")); + || 0 == strcmp(name + 6, "user") + || 0 == strcmp(name + 6, "db")); } /*********************************************************************** @@ -207,7 +207,7 @@ row_mysql_store_blob_ref( mach_write_to_n_little_endian(dest, col_len - 8, len); - ut_memcpy(dest + col_len - 8, (byte*)&data, sizeof(byte*)); + ut_memcpy(dest + col_len - 8, &data, sizeof(byte*)); } /*********************************************************************** @@ -226,7 +226,7 @@ row_mysql_read_blob_ref( *len = mach_read_from_n_little_endian(ref, col_len - 8); - ut_memcpy((byte*)&data, ref + col_len - 8, sizeof(byte*)); + ut_memcpy(&data, ref + col_len - 8, sizeof(byte*)); return(data); } @@ -267,7 +267,7 @@ row_mysql_store_col_in_innobase_format( VARCHAR then this is irrelevant */ ulint comp) /* in: nonzero=compact format */ { - byte* ptr = mysql_data; + byte* ptr = mysql_data; dtype_t* dtype; ulint type; ulint lenlen; @@ -299,13 +299,13 @@ row_mysql_store_col_in_innobase_format( buf += col_len; } else if ((type == DATA_VARCHAR - || type == DATA_VARMYSQL - || type == DATA_BINARY)) { + || type == DATA_VARMYSQL + || type == DATA_BINARY)) { if (dtype_get_mysql_type(dtype) == DATA_MYSQL_TRUE_VARCHAR) { /* The length of the actual data is stored to 1 or 2 bytes at the start of the field */ - + if (row_format_col) { if (dtype->prtype & DATA_LONG_TRUE_VARCHAR) { lenlen = 2; @@ -318,7 +318,7 @@ row_mysql_store_col_in_innobase_format( } ptr = row_mysql_read_true_varchar(&col_len, mysql_data, - lenlen); + lenlen); } else { /* Remove trailing spaces from old style VARCHAR columns. */ @@ -361,12 +361,12 @@ row_mysql_store_col_in_innobase_format( Consider a CHAR(n) field, a field of n characters. It will contain between n * mbminlen and n * mbmaxlen bytes. We will try to truncate it to n bytes by stripping - space padding. If the field contains single-byte + space padding. If the field contains single-byte characters only, it will be truncated to n characters. Consider a CHAR(5) field containing the string ".a " where "." denotes a 3-byte character represented by the bytes "$%&". After our stripping, the string will - be stored as "$%&a " (5 bytes). The string ".abc " + be stored as "$%&a " (5 bytes). The string ".abc " will be stored as "$%&abc" (6 bytes). The space padding will be restored in row0sel.c, function @@ -410,10 +410,10 @@ row_mysql_convert_row_to_innobase( row is used, as row may contain pointers to this record! */ { - mysql_row_templ_t* templ; + mysql_row_templ_t* templ; dfield_t* dfield; ulint i; - + ut_ad(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW); ut_ad(prebuilt->mysql_template); @@ -426,7 +426,7 @@ row_mysql_convert_row_to_innobase( /* Column may be SQL NULL */ if (mysql_rec[templ->mysql_null_byte_offset] & - (byte) (templ->mysql_null_bit_mask)) { + (byte) (templ->mysql_null_bit_mask)) { /* It is SQL NULL */ @@ -434,18 +434,18 @@ row_mysql_convert_row_to_innobase( goto next_column; } - } - + } + row_mysql_store_col_in_innobase_format(dfield, - prebuilt->ins_upd_rec_buff - + templ->mysql_col_offset, - TRUE, /* MySQL row format data */ - mysql_rec + templ->mysql_col_offset, - templ->mysql_col_len, - prebuilt->table->comp); + prebuilt->ins_upd_rec_buff + + templ->mysql_col_offset, + TRUE, /* MySQL row format data */ + mysql_rec + templ->mysql_col_offset, + templ->mysql_col_len, + dict_table_is_comp(prebuilt->table)); next_column: ; - } + } } /******************************************************************** @@ -469,21 +469,21 @@ row_mysql_handle_errors( handle_new_error: err = trx->error_state; - + ut_a(err != DB_SUCCESS); - + trx->error_state = DB_SUCCESS; - + if ((err == DB_DUPLICATE_KEY) || (err == DB_FOREIGN_DUPLICATE_KEY)) { - if (savept) { + if (savept) { /* Roll back the latest, possibly incomplete insertion or update */ trx_general_rollback_for_mysql(trx, TRUE, savept); } } else if (err == DB_TOO_BIG_RECORD) { - if (savept) { + if (savept) { /* Roll back the latest, possibly incomplete insertion or update */ @@ -493,7 +493,7 @@ handle_new_error: } else if (err == DB_ROW_IS_REFERENCED || err == DB_NO_REFERENCED_ROW || err == DB_CANNOT_ADD_CONSTRAINT) { - if (savept) { + if (savept) { /* Roll back the latest, possibly incomplete insertion or update */ @@ -520,10 +520,10 @@ handle_new_error: to version 3.23.43 */ trx_general_rollback_for_mysql(trx, FALSE, NULL); - + } else if (err == DB_OUT_OF_FILE_SPACE || err == DB_LOCK_WAIT_TIMEOUT) { - if (savept) { + if (savept) { /* Roll back the latest, possibly incomplete insertion or update */ @@ -537,32 +537,32 @@ handle_new_error: "InnoDB: The database cannot continue operation because of\n" "InnoDB: lack of space. You must add a new data file to\n" "InnoDB: my.cnf and restart the database.\n", stderr); - + exit(1); } else if (err == DB_CORRUPTION) { - fputs( - "InnoDB: We detected index corruption in an InnoDB type table.\n" - "InnoDB: You have to dump + drop + reimport the table or, in\n" - "InnoDB: a case of widespread corruption, dump all InnoDB\n" - "InnoDB: tables and recreate the whole InnoDB tablespace.\n" - "InnoDB: If the mysqld server crashes after the startup or when\n" - "InnoDB: you dump the tables, look at\n" - "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html" - " for help.\n", stderr); + fputs( + "InnoDB: We detected index corruption in an InnoDB type table.\n" + "InnoDB: You have to dump + drop + reimport the table or, in\n" + "InnoDB: a case of widespread corruption, dump all InnoDB\n" + "InnoDB: tables and recreate the whole InnoDB tablespace.\n" + "InnoDB: If the mysqld server crashes after the startup or when\n" + "InnoDB: you dump the tables, look at\n" + "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html" + " for help.\n", stderr); } else { fprintf(stderr, "InnoDB: unknown error code %lu\n", (ulong) err); ut_error; - } + } if (trx->error_state != DB_SUCCESS) { *new_err = trx->error_state; } else { *new_err = err; } - + trx->error_state = DB_SUCCESS; return(FALSE); @@ -571,6 +571,7 @@ handle_new_error: InnoDB Hot Backup builds. Besides, this function should never be called in InnoDB Hot Backup. */ ut_error; + return(FALSE); #endif /* UNIV_HOTBACKUP */ } @@ -589,7 +590,7 @@ row_create_prebuilt( dtuple_t* ref; ulint ref_len; ulint i; - + heap = mem_heap_create(128); prebuilt = mem_heap_alloc(heap, sizeof(row_prebuilt_t)); @@ -616,13 +617,13 @@ row_create_prebuilt( prebuilt->ins_node = NULL; prebuilt->ins_upd_rec_buff = NULL; - + prebuilt->upd_node = NULL; prebuilt->ins_graph = NULL; prebuilt->upd_graph = NULL; - prebuilt->pcur = btr_pcur_create_for_mysql(); - prebuilt->clust_pcur = btr_pcur_create_for_mysql(); + prebuilt->pcur = btr_pcur_create_for_mysql(); + prebuilt->clust_pcur = btr_pcur_create_for_mysql(); prebuilt->select_lock_type = LOCK_NONE; prebuilt->stored_select_lock_type = 99999999; @@ -633,7 +634,7 @@ row_create_prebuilt( prebuilt->search_tuple = dtuple_create(heap, 2 * dict_table_get_n_cols(table)); - + clust_index = dict_table_get_first_index(table); /* Make sure that search_tuple is long enough for clustered index */ @@ -671,7 +672,7 @@ row_prebuilt_free( ulint i; if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED - || prebuilt->magic_n2 != ROW_PREBUILT_ALLOCATED) { + || prebuilt->magic_n2 != ROW_PREBUILT_ALLOCATED) { fprintf(stderr, "InnoDB: Error: trying to free a corrupt\n" "InnoDB: table handle. Magic n %lu, magic n2 %lu, table name", @@ -680,7 +681,7 @@ row_prebuilt_free( ut_print_name(stderr, NULL, prebuilt->table->name); putc('\n', stderr); - mem_analyze_corruption((byte*)prebuilt); + mem_analyze_corruption(prebuilt); ut_error; } @@ -702,11 +703,11 @@ row_prebuilt_free( if (prebuilt->sel_graph) { que_graph_free_recursive(prebuilt->sel_graph); } - + if (prebuilt->upd_graph) { que_graph_free_recursive(prebuilt->upd_graph); } - + if (prebuilt->blob_heap) { mem_heap_free(prebuilt->blob_heap); } @@ -714,15 +715,15 @@ row_prebuilt_free( if (prebuilt->old_vers_heap) { mem_heap_free(prebuilt->old_vers_heap); } - + for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) { if (prebuilt->fetch_cache[i] != NULL) { if ((ROW_PREBUILT_FETCH_MAGIC_N != - mach_read_from_4((prebuilt->fetch_cache[i]) - 4)) - || (ROW_PREBUILT_FETCH_MAGIC_N != - mach_read_from_4((prebuilt->fetch_cache[i]) - + prebuilt->mysql_row_len))) { + mach_read_from_4((prebuilt->fetch_cache[i]) - 4)) + || (ROW_PREBUILT_FETCH_MAGIC_N != + mach_read_from_4((prebuilt->fetch_cache[i]) + + prebuilt->mysql_row_len))) { fputs( "InnoDB: Error: trying to free a corrupt\n" "InnoDB: fetch buffer.\n", stderr); @@ -753,14 +754,14 @@ row_update_prebuilt_trx( row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL handle */ trx_t* trx) /* in: transaction handle */ -{ +{ if (trx->magic_n != TRX_MAGIC_N) { fprintf(stderr, "InnoDB: Error: trying to use a corrupt\n" "InnoDB: trx handle. Magic n %lu\n", (ulong) trx->magic_n); - mem_analyze_corruption((byte*)trx); + mem_analyze_corruption(trx); ut_error; } @@ -773,7 +774,7 @@ row_update_prebuilt_trx( ut_print_name(stderr, NULL, prebuilt->table->name); putc('\n', stderr); - mem_analyze_corruption((byte*)prebuilt); + mem_analyze_corruption(prebuilt); ut_error; } @@ -790,7 +791,7 @@ row_update_prebuilt_trx( if (prebuilt->sel_graph) { prebuilt->sel_graph->trx = trx; - } + } } /************************************************************************* @@ -802,7 +803,7 @@ dtuple_t* row_get_prebuilt_insert_row( /*========================*/ /* out: prebuilt dtuple; the column - type information is also set in it */ + type information is also set in it */ row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL handle */ { @@ -812,14 +813,14 @@ row_get_prebuilt_insert_row( ulint i; ut_ad(prebuilt && table && prebuilt->trx); - + if (prebuilt->ins_node == NULL) { /* Not called before for this handle: create an insert node and query graph to the prebuilt struct */ node = ins_node_create(INS_DIRECT, table, prebuilt->heap); - + prebuilt->ins_node = node; if (prebuilt->ins_upd_rec_buff == NULL) { @@ -827,7 +828,7 @@ row_get_prebuilt_insert_row( prebuilt->heap, prebuilt->mysql_row_len); } - + row = dtuple_create(prebuilt->heap, dict_table_get_n_cols(table)); @@ -837,8 +838,8 @@ row_get_prebuilt_insert_row( a debug assertion from failing */ for (i = 0; i < dtuple_get_n_fields(row); i++) { - - dtuple_get_nth_field(row, i)->len = UNIV_SQL_NULL; + + dtuple_get_nth_field(row, i)->len = UNIV_SQL_NULL; } ins_node_set_new_row(node, row); @@ -851,7 +852,7 @@ row_get_prebuilt_insert_row( prebuilt->ins_graph->state = QUE_FORK_ACTIVE; } - return(prebuilt->ins_node->row); + return(prebuilt->ins_node->row); } /************************************************************************* @@ -864,7 +865,7 @@ row_update_statistics_if_needed( dict_table_t* table) /* in: table */ { ulint counter; - + counter = table->stat_modified_counter; table->stat_modified_counter = counter + 1; @@ -876,16 +877,16 @@ row_update_statistics_if_needed( a counter table which is very small and updated very often. */ if (counter > 2000000000 - || ((ib_longlong)counter > 16 + table->stat_n_rows / 16)) { + || ((ib_longlong)counter > 16 + table->stat_n_rows / 16)) { dict_update_statistics(table); - } + } } - + /************************************************************************* Unlocks an AUTO_INC type lock possibly reserved by trx. */ -void +void row_unlock_table_autoinc_for_mysql( /*===============================*/ trx_t* trx) /* in: transaction */ @@ -912,15 +913,15 @@ row_lock_table_autoinc_for_mysql( row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL table handle */ { - trx_t* trx = prebuilt->trx; + trx_t* trx = prebuilt->trx; ins_node_t* node = prebuilt->ins_node; que_thr_t* thr; ulint err; ibool was_lock_wait; - + ut_ad(trx); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - + if (trx->auto_inc_lock) { return(DB_SUCCESS); @@ -990,11 +991,11 @@ row_lock_table_for_mysql( ulint mode) /* in: lock mode of table (ignored if table==NULL) */ { - trx_t* trx = prebuilt->trx; + trx_t* trx = prebuilt->trx; que_thr_t* thr; ulint err; ibool was_lock_wait; - + ut_ad(trx); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); @@ -1045,12 +1046,12 @@ run_again: } que_thr_stop_for_mysql_no_error(thr, trx); - + trx->op_info = ""; - return((int) err); + return((int) err); } - + /************************************************************************* Does an insert for MySQL. */ @@ -1066,15 +1067,15 @@ row_insert_for_mysql( que_thr_t* thr; ulint err; ibool was_lock_wait; - trx_t* trx = prebuilt->trx; + trx_t* trx = prebuilt->trx; ins_node_t* node = prebuilt->ins_node; - + ut_ad(trx); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); if (prebuilt->table->ibd_file_missing) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Error:\n" + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Error:\n" "InnoDB: MySQL is trying to use a table handle but the .ibd file for\n" "InnoDB: table %s does not exist.\n" "InnoDB: Have you deleted the .ibd file from the database directory under\n" @@ -1094,7 +1095,7 @@ row_insert_for_mysql( ut_print_name(stderr, prebuilt->trx, prebuilt->table->name); putc('\n', stderr); - mem_analyze_corruption((byte*)prebuilt); + mem_analyze_corruption(prebuilt); ut_error; } @@ -1123,9 +1124,9 @@ row_insert_for_mysql( } row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec); - + savept = trx_savept_take(trx); - + thr = que_fork_get_first_thr(prebuilt->ins_graph); if (prebuilt->sql_stat_start) { @@ -1134,7 +1135,7 @@ row_insert_for_mysql( } else { node->state = INS_NODE_ALLOC_ROW_ID; } - + que_thr_move_to_run_state_for_mysql(thr, trx); run_again: @@ -1142,7 +1143,7 @@ run_again: thr->prev_node = node; row_ins_step(thr); - + err = trx->error_state; if (err != DB_SUCCESS) { @@ -1164,15 +1165,15 @@ run_again: } que_thr_stop_for_mysql_no_error(thr, trx); - + prebuilt->table->stat_n_rows++; srv_n_rows_inserted++; - + if (prebuilt->table->stat_n_rows == 0) { /* Avoid wrap-over */ prebuilt->table->stat_n_rows--; - } + } row_update_statistics_if_needed(prebuilt->table); trx->op_info = ""; @@ -1192,11 +1193,11 @@ row_prebuild_sel_graph( sel_node_t* node; ut_ad(prebuilt && prebuilt->trx); - + if (prebuilt->sel_graph == NULL) { node = sel_node_create(prebuilt->heap); - + prebuilt->sel_graph = que_node_get_parent( pars_complete_graph_for_exec(node, @@ -1221,7 +1222,7 @@ row_create_update_node_for_mysql( upd_node_t* node; node = upd_node_create(heap); - + node->in_mysql_interface = TRUE; node->is_delete = FALSE; node->searched_update = FALSE; @@ -1233,7 +1234,7 @@ row_create_update_node_for_mysql( node->update = upd_create(dict_table_get_n_cols(table), heap); node->update_n_fields = dict_table_get_n_cols(table); - + UT_LIST_INIT(node->columns); node->has_clust_rec_x_lock = TRUE; node->cmpl_info = 0; @@ -1260,7 +1261,7 @@ row_get_prebuilt_update_vector( upd_node_t* node; ut_ad(prebuilt && table && prebuilt->trx); - + if (prebuilt->upd_node == NULL) { /* Not called before for this handle: create an update node @@ -1269,7 +1270,7 @@ row_get_prebuilt_update_vector( node = row_create_update_node_for_mysql(table, prebuilt->heap); prebuilt->upd_node = node; - + prebuilt->upd_graph = que_node_get_parent( pars_complete_graph_for_exec(node, @@ -1297,7 +1298,7 @@ row_update_for_mysql( ulint err; que_thr_t* thr; ibool was_lock_wait; - dict_index_t* clust_index; + dict_index_t* clust_index; /* ulint ref_len; */ upd_node_t* node; dict_table_t* table = prebuilt->table; @@ -1306,10 +1307,10 @@ row_update_for_mysql( ut_ad(prebuilt && trx); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); UT_NOT_USED(mysql_rec); - + if (prebuilt->table->ibd_file_missing) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Error:\n" + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Error:\n" "InnoDB: MySQL is trying to use a table handle but the .ibd file for\n" "InnoDB: table %s does not exist.\n" "InnoDB: Have you deleted the .ibd file from the database directory under\n" @@ -1329,7 +1330,7 @@ row_update_for_mysql( ut_print_name(stderr, prebuilt->trx, prebuilt->table->name); putc('\n', stderr); - mem_analyze_corruption((byte*)prebuilt); + mem_analyze_corruption(prebuilt); ut_error; } @@ -1362,9 +1363,9 @@ row_update_for_mysql( btr_pcur_copy_stored_position(node->pcur, prebuilt->clust_pcur); } - + ut_a(node->pcur->rel_pos == BTR_PCUR_ON); - + /* MySQL seems to call rnd_pos before updating each row it has cached: we can get the correct cursor position from prebuilt->pcur; NOTE that we cannot build the row reference @@ -1373,7 +1374,7 @@ row_update_for_mysql( the row id used as the clustered index key */ savept = trx_savept_take(trx); - + thr = que_fork_get_first_thr(prebuilt->upd_graph); node->state = UPD_NODE_UPDATE_CLUSTERED; @@ -1392,7 +1393,7 @@ run_again: if (err != DB_SUCCESS) { que_thr_stop_for_mysql(thr); - + if (err == DB_RECORD_NOT_FOUND) { trx->error_state = DB_SUCCESS; trx->op_info = ""; @@ -1400,10 +1401,11 @@ run_again: return((int) err); } - thr->lock_state= QUE_THR_LOCK_ROW; + thr->lock_state= QUE_THR_LOCK_ROW; was_lock_wait = row_mysql_handle_errors(&err, trx, thr, - &savept); - thr->lock_state= QUE_THR_LOCK_NOLOCK;; + &savept); + thr->lock_state= QUE_THR_LOCK_NOLOCK; + if (was_lock_wait) { goto run_again; } @@ -1459,11 +1461,11 @@ row_unlock_for_mysql( btr_pcur_t* clust_pcur = prebuilt->clust_pcur; trx_t* trx = prebuilt->trx; rec_t* rec; - mtr_t mtr; - + mtr_t mtr; + ut_ad(prebuilt && trx); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - + if (!srv_locks_unsafe_for_binlog) { fprintf(stderr, @@ -1480,9 +1482,9 @@ row_unlock_for_mysql( if (index != NULL && trx_new_rec_locks_contain(trx, index)) { mtr_start(&mtr); - + /* Restore the cursor position and find the record */ - + if (!has_latches_on_recs) { btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, &mtr); } @@ -1499,7 +1501,7 @@ row_unlock_for_mysql( garbage! */ if (index->type & DICT_CLUSTERED) { - + goto func_exit; } } @@ -1509,7 +1511,7 @@ row_unlock_for_mysql( if (index != NULL && trx_new_rec_locks_contain(trx, index)) { mtr_start(&mtr); - + /* Restore the cursor position and find the record */ if (!has_latches_on_recs) { @@ -1523,10 +1525,10 @@ row_unlock_for_mysql( mtr_commit(&mtr); } - + func_exit: trx->op_info = ""; - + return(DB_SUCCESS); } @@ -1560,7 +1562,7 @@ run_again: if (err == DB_LOCK_WAIT) { /* Handle lock wait here */ - + que_thr_stop_for_mysql(thr); srv_suspend_mysql_thread(thr); @@ -1575,7 +1577,7 @@ run_again: } /* Retry operation after a normal lock wait */ - + goto run_again; } @@ -1613,8 +1615,8 @@ row_table_got_default_clust_index( clust_index = dict_table_get_first_index(table); if (dtype_get_mtype(dict_index_get_nth_type(clust_index, 0)) - == DATA_SYS) { - return(TRUE); + == DATA_SYS) { + return(TRUE); } return(FALSE); @@ -1700,7 +1702,7 @@ row_mysql_freeze_data_dictionary( trx_t* trx) /* in: transaction */ { ut_a(trx->dict_operation_lock_mode == 0); - + rw_lock_s_lock(&dict_operation_lock); trx->dict_operation_lock_mode = RW_S_LATCH; @@ -1731,8 +1733,8 @@ row_mysql_lock_data_dictionary( trx_t* trx) /* in: transaction */ { ut_a(trx->dict_operation_lock_mode == 0 - || trx->dict_operation_lock_mode == RW_X_LATCH); - + || trx->dict_operation_lock_mode == RW_X_LATCH); + /* Serialize data dictionary operations with dictionary mutex: no deadlocks or lock waits can occur then in these operations */ @@ -1787,7 +1789,7 @@ row_create_table_for_mysql( ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH); - + if (srv_created_new_raw) { fputs( "InnoDB: A new raw disk partition was initialized or\n" @@ -1803,7 +1805,7 @@ row_create_table_for_mysql( } trx->op_info = "creating table"; - + if (row_mysql_is_system_table(table->name)) { fprintf(stderr, @@ -1826,7 +1828,7 @@ row_create_table_for_mysql( #sql-table in the tablespace. We have here a special mechanism to recover such tables by renaming them to rsql... */ - + return(row_mysql_recover_tmp_table(table, trx)); } @@ -1845,7 +1847,7 @@ row_create_table_for_mysql( /* Table equals "innodb_monitor": start monitor prints */ - + srv_print_innodb_monitor = TRUE; /* The lock timeout monitor thread also takes care @@ -1874,7 +1876,7 @@ row_create_table_for_mysql( } else if (table_name_len == sizeof S_innodb_mem_validate && !memcmp(table_name, S_innodb_mem_validate, sizeof S_innodb_mem_validate)) { - /* We define here a debugging feature intended for + /* We define here a debugging feature intended for developers */ fputs("Validating InnoDB memory:\n" @@ -1894,7 +1896,7 @@ row_create_table_for_mysql( heap = mem_heap_create(512); trx->dict_operation = TRUE; - + node = tab_create_graph_create(table, heap); thr = pars_complete_graph_for_exec(node, trx, heap); @@ -1906,27 +1908,27 @@ row_create_table_for_mysql( if (err != DB_SUCCESS) { /* We have special error handling here */ - + trx->error_state = DB_SUCCESS; - + trx_general_rollback_for_mysql(trx, FALSE, NULL); if (err == DB_OUT_OF_FILE_SPACE) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); - fputs(" InnoDB: Warning: cannot create table ", + fputs(" InnoDB: Warning: cannot create table ", stderr); ut_print_name(stderr, trx, table->name); fputs(" because tablespace full\n", stderr); if (dict_table_get_low(table->name)) { - row_drop_table_for_mysql(table->name, trx, + row_drop_table_for_mysql(table->name, trx, FALSE); } } else if (err == DB_DUPLICATE_KEY) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); ut_print_name(stderr, trx, table->name); @@ -1944,7 +1946,7 @@ row_create_table_for_mysql( "InnoDB: http://dev.mysql.com/doc/mysql/en/" "InnoDB_troubleshooting_datadict.html\n", stderr); } - + /* We may also get err == DB_ERROR if the .ibd file for the table already exists */ @@ -1982,13 +1984,13 @@ row_create_index_for_mysql( ulint err; ulint i, j; ulint len; - + #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - + trx->op_info = "creating index"; trx_start_if_not_started(trx); @@ -2000,8 +2002,8 @@ row_create_index_for_mysql( for (i = 0; i < dict_index_get_n_fields(index); i++) { for (j = 0; j < i; j++) { if (0 == ut_strcmp( - dict_index_get_nth_field(index, j)->name, - dict_index_get_nth_field(index, i)->name)) { + dict_index_get_nth_field(index, j)->name, + dict_index_get_nth_field(index, i)->name)) { ut_print_timestamp(stderr); @@ -2019,7 +2021,7 @@ row_create_index_for_mysql( goto error_handling; } } - + /* Check also that prefix_len and actual length < DICT_MAX_INDEX_COL_LEN */ @@ -2028,7 +2030,7 @@ row_create_index_for_mysql( if (field_lengths) { len = ut_max(len, field_lengths[i]); } - + if (len >= DICT_MAX_INDEX_COL_LEN) { err = DB_TOO_BIG_RECORD; @@ -2055,14 +2057,14 @@ row_create_index_for_mysql( ut_a(thr == que_fork_start_command(que_node_get_parent(thr))); que_run_threads(thr); - err = trx->error_state; + err = trx->error_state; que_graph_free((que_t*) que_node_get_parent(thr)); error_handling: if (err != DB_SUCCESS) { /* We have special error handling here */ - + trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, FALSE, NULL); @@ -2071,7 +2073,7 @@ error_handling: trx->error_state = DB_SUCCESS; } - + trx->op_info = ""; return((int) err); @@ -2110,7 +2112,7 @@ row_table_add_foreign_constraints( ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ ut_a(sql_string); - + trx->op_info = "adding foreign keys"; trx_start_if_not_started(trx); @@ -2127,12 +2129,12 @@ row_table_add_foreign_constraints( if (err == DB_SUCCESS) { /* Check that also referencing constraints are ok */ - err = dict_load_foreigns(name, trx->check_foreigns); + err = dict_load_foreigns(name, TRUE); } if (err != DB_SUCCESS) { /* We have special error handling here */ - + trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, FALSE, NULL); @@ -2174,19 +2176,19 @@ row_drop_table_for_mysql_in_background( ut_print_name(stderr, name); fputs(" in background drop list\n", stderr); */ - /* Try to drop the table in InnoDB */ + /* Try to drop the table in InnoDB */ + + error = row_drop_table_for_mysql(name, trx, FALSE); - error = row_drop_table_for_mysql(name, trx, FALSE); - /* Flush the log to reduce probability that the .frm files and the InnoDB data dictionary get out-of-sync if the user runs with innodb_flush_log_at_trx_commit = 0 */ - + log_buffer_flush_to_disk(); - trx_commit_for_mysql(trx); + trx_commit_for_mysql(trx); - trx_free_for_background(trx); + trx_free_for_background(trx); return((int) error); } @@ -2206,7 +2208,7 @@ row_drop_tables_for_mysql_in_background(void) dict_table_t* table; ulint n_tables; ulint n_tables_dropped = 0; -loop: +loop: mutex_enter(&kernel_mutex); if (!row_mysql_drop_list_inited) { @@ -2216,7 +2218,7 @@ loop: } drop = UT_LIST_GET_FIRST(row_mysql_drop_list); - + n_tables = UT_LIST_GET_LEN(row_mysql_drop_list); mutex_exit(&kernel_mutex); @@ -2232,12 +2234,12 @@ loop: mutex_exit(&(dict_sys->mutex)); if (table == NULL) { - /* If for some reason the table has already been dropped + /* If for some reason the table has already been dropped through some other mechanism, do not try to drop it */ - goto already_dropped; + goto already_dropped; } - + if (DB_SUCCESS != row_drop_table_for_mysql_in_background( drop->table_name)) { /* If the DROP fails for some table, we return, and let the @@ -2253,7 +2255,7 @@ already_dropped: UT_LIST_REMOVE(row_mysql_drop_list, row_mysql_drop_list, drop); - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Dropped table %s in background drop queue.\n", drop->table_name); @@ -2285,7 +2287,7 @@ row_get_background_drop_list_len_low(void) UT_LIST_INIT(row_mysql_drop_list); row_mysql_drop_list_inited = TRUE; } - + return(UT_LIST_GET_LEN(row_mysql_drop_list)); } @@ -2304,7 +2306,7 @@ row_add_table_to_background_drop_list( dict_table_t* table) /* in: table */ { row_mysql_drop_t* drop; - + mutex_enter(&kernel_mutex); if (!row_mysql_drop_list_inited) { @@ -2312,14 +2314,14 @@ row_add_table_to_background_drop_list( UT_LIST_INIT(row_mysql_drop_list); row_mysql_drop_list_inited = TRUE; } - + /* Look if the table already is in the drop list */ drop = UT_LIST_GET_FIRST(row_mysql_drop_list); while (drop != NULL) { if (strcmp(drop->table_name, table->name) == 0) { /* Already in the list */ - + mutex_exit(&kernel_mutex); return(FALSE); @@ -2331,9 +2333,9 @@ row_add_table_to_background_drop_list( drop = mem_alloc(sizeof(row_mysql_drop_t)); drop->table_name = mem_strdup(table->name); - + UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop); - + /* fputs("InnoDB: Adding table ", stderr); ut_print_name(stderr, drop->table_name); fputs(" to background drop list\n", stderr); */ @@ -2403,8 +2405,8 @@ do not allow the discard. We also reserve the data dictionary latch. */ "FROM SYS_TABLES\n" "WHERE NAME = table_name;\n" "IF (SQL %% NOTFOUND) THEN\n" - " COMMIT WORK;\n" - " RETURN;\n" + " COMMIT WORK;\n" + " RETURN;\n" "END IF;\n" "UPDATE SYS_TABLES SET ID = new_id\n" "WHERE ID = old_id;\n" @@ -2446,8 +2448,8 @@ do not allow the discard. We also reserve the data dictionary latch. */ if (table->n_foreign_key_checks_running > 0) { - ut_print_timestamp(stderr); - fputs(" InnoDB: You are trying to DISCARD table ", stderr); + ut_print_timestamp(stderr); + fputs(" InnoDB: You are trying to DISCARD table ", stderr); ut_print_name(stderr, trx, table->name); fputs("\n" "InnoDB: though there is a foreign key check running on it.\n" @@ -2463,7 +2465,7 @@ do not allow the discard. We also reserve the data dictionary latch. */ some other table (not the table itself) */ foreign = UT_LIST_GET_FIRST(table->referenced_list); - + while (foreign && foreign->foreign_table == table) { foreign = UT_LIST_GET_NEXT(referenced_list, foreign); } @@ -2510,7 +2512,7 @@ do not allow the discard. We also reserve the data dictionary latch. */ ut_a(graph); /* Remove any locks there are on the table or its records */ - + lock_reset_all_on_table(table); graph->trx = trx; @@ -2546,14 +2548,14 @@ do not allow the discard. We also reserve the data dictionary latch. */ table->ibd_file_missing = TRUE; } } -funct_exit: +funct_exit: row_mysql_unlock_data_dictionary(trx); if (graph) { que_graph_free(graph); } - trx_commit_for_mysql(trx); + trx_commit_for_mysql(trx); trx->op_info = ""; @@ -2583,7 +2585,7 @@ row_import_tablespace_for_mysql( trx->op_info = "importing tablespace"; current_lsn = log_get_lsn(); - + /* It is possible, though very improbable, that the lsn's in the tablespace to be imported have risen above the current system lsn, if a lengthy purge, ibuf merge, or rollback was performed on a backup @@ -2683,10 +2685,10 @@ row_import_tablespace_for_mysql( err = DB_ERROR; } -funct_exit: +funct_exit: row_mysql_unlock_data_dictionary(trx); - trx_commit_for_mysql(trx); + trx_commit_for_mysql(trx); trx->op_info = ""; @@ -2777,7 +2779,7 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */ "InnoDB: database modifications by the user. Shut down\n" "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" "InnoDB: with raw, and innodb_force_... is removed.\n", - stderr); + stderr); return(DB_ERROR); } @@ -2839,7 +2841,7 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */ if (table->n_foreign_key_checks_running > 0) { ut_print_timestamp(stderr); - fputs(" InnoDB: Cannot truncate table ", stderr); + fputs(" InnoDB: Cannot truncate table ", stderr); ut_print_name(stderr, trx, table->name); fputs(" by DROP+CREATE\n" "InnoDB: because there is a foreign key check running on it.\n", @@ -2962,7 +2964,7 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */ trx_general_rollback_for_mysql(trx, FALSE, NULL); trx->error_state = DB_SUCCESS; ut_print_timestamp(stderr); -fputs(" InnoDB: Unable to assign a new identifier to table ", stderr); +fputs(" InnoDB: Unable to assign a new identifier to table ", stderr); ut_print_name(stderr, trx, table->name); fputs("\n" "InnoDB: after truncating it. Background processes may corrupt the table!\n", @@ -2975,7 +2977,7 @@ fputs(" InnoDB: Unable to assign a new identifier to table ", stderr); dict_table_autoinc_initialize(table, 0); dict_update_statistics(table); - trx_commit_for_mysql(trx); + trx_commit_for_mysql(trx); funct_exit: @@ -3037,46 +3039,46 @@ row_drop_table_for_mysql( "FROM SYS_TABLES\n" "WHERE NAME = table_name;\n" "IF (SQL % NOTFOUND) THEN\n" - " COMMIT WORK;\n" - " RETURN;\n" + " COMMIT WORK;\n" + " RETURN;\n" "END IF;\n" "found := 1;\n" "SELECT ID INTO sys_foreign_id\n" "FROM SYS_TABLES\n" "WHERE NAME = 'SYS_FOREIGN';\n" "IF (SQL % NOTFOUND) THEN\n" - " found := 0;\n" + " found := 0;\n" "END IF;\n" "IF (table_name = 'SYS_FOREIGN') THEN\n" - " found := 0;\n" + " found := 0;\n" "END IF;\n" "IF (table_name = 'SYS_FOREIGN_COLS') THEN\n" - " found := 0;\n" + " found := 0;\n" "END IF;\n" "WHILE found = 1 LOOP\n" - " SELECT ID INTO foreign_id\n" - " FROM SYS_FOREIGN\n" - " WHERE FOR_NAME = table_name\n" - " AND TO_BINARY(FOR_NAME) = TO_BINARY(table_name);\n" - " IF (SQL % NOTFOUND) THEN\n" - " found := 0;\n" - " ELSE" - " DELETE FROM SYS_FOREIGN_COLS WHERE ID = foreign_id;\n" - " DELETE FROM SYS_FOREIGN WHERE ID = foreign_id;\n" - " END IF;\n" + " SELECT ID INTO foreign_id\n" + " FROM SYS_FOREIGN\n" + " WHERE FOR_NAME = table_name\n" + " AND TO_BINARY(FOR_NAME) = TO_BINARY(table_name);\n" + " IF (SQL % NOTFOUND) THEN\n" + " found := 0;\n" + " ELSE" + " DELETE FROM SYS_FOREIGN_COLS WHERE ID = foreign_id;\n" + " DELETE FROM SYS_FOREIGN WHERE ID = foreign_id;\n" + " END IF;\n" "END LOOP;\n" "found := 1;\n" "WHILE found = 1 LOOP\n" - " SELECT ID INTO index_id\n" - " FROM SYS_INDEXES\n" - " WHERE TABLE_ID = table_id;\n" - " IF (SQL % NOTFOUND) THEN\n" - " found := 0;\n" - " ELSE" - " DELETE FROM SYS_FIELDS WHERE INDEX_ID = index_id;\n" - " DELETE FROM SYS_INDEXES WHERE ID = index_id\n" - " AND TABLE_ID = table_id;\n" - " END IF;\n" + " SELECT ID INTO index_id\n" + " FROM SYS_INDEXES\n" + " WHERE TABLE_ID = table_id;\n" + " IF (SQL % NOTFOUND) THEN\n" + " found := 0;\n" + " ELSE" + " DELETE FROM SYS_FIELDS WHERE INDEX_ID = index_id;\n" + " DELETE FROM SYS_INDEXES WHERE ID = index_id\n" + " AND TABLE_ID = table_id;\n" + " END IF;\n" "END LOOP;\n" "DELETE FROM SYS_COLUMNS WHERE TABLE_ID = table_id;\n" "DELETE FROM SYS_TABLES WHERE ID = table_id;\n" @@ -3092,7 +3094,7 @@ row_drop_table_for_mysql( "InnoDB: database modifications by the user. Shut down\n" "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" "InnoDB: with raw, and innodb_force_... is removed.\n", - stderr); + stderr); return(DB_ERROR); } @@ -3116,7 +3118,7 @@ row_drop_table_for_mysql( /* Table name equals "innodb_monitor": stop monitor prints */ - + srv_print_innodb_monitor = FALSE; srv_print_innodb_lock_monitor = FALSE; } else if (namelen == sizeof S_innodb_lock_monitor @@ -3160,7 +3162,7 @@ row_drop_table_for_mysql( ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - + graph = pars_sql(sql); ut_a(graph); @@ -3175,13 +3177,13 @@ row_drop_table_for_mysql( if (!table) { err = DB_TABLE_NOT_FOUND; - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); ut_print_name(stderr, trx, name); fputs(" does not exist in the InnoDB internal\n" - "InnoDB: data dictionary though MySQL is trying to drop it.\n" - "InnoDB: Have you copied the .frm file of the table to the\n" + "InnoDB: data dictionary though MySQL is trying to drop it.\n" + "InnoDB: Have you copied the .frm file of the table to the\n" "InnoDB: MySQL database directory from another database?\n" "InnoDB: You can look for further help from\n" "InnoDB: http://dev.mysql.com/doc/mysql/en/" @@ -3193,7 +3195,7 @@ row_drop_table_for_mysql( some other table (not the table itself) */ foreign = UT_LIST_GET_FIRST(table->referenced_list); - + while (foreign && foreign->foreign_table == table) { check_next_foreign: foreign = UT_LIST_GET_NEXT(referenced_list, foreign); @@ -3233,15 +3235,15 @@ row_drop_table_for_mysql( added = row_add_table_to_background_drop_list(table); - if (added) { + if (added) { ut_print_timestamp(stderr); -fputs(" InnoDB: Warning: MySQL is trying to drop table ", stderr); +fputs(" InnoDB: Warning: MySQL is trying to drop table ", stderr); ut_print_name(stderr, trx, table->name); fputs("\n" "InnoDB: though there are still open handles to it.\n" "InnoDB: Adding the table to the background drop queue.\n", stderr); - + /* We return DB_SUCCESS to MySQL though the drop will happen lazily later */ @@ -3267,8 +3269,8 @@ fputs(" InnoDB: Warning: MySQL is trying to drop table ", stderr); added = row_add_table_to_background_drop_list(table); if (added) { - ut_print_timestamp(stderr); -fputs(" InnoDB: You are trying to drop table ", stderr); + ut_print_timestamp(stderr); +fputs(" InnoDB: You are trying to drop table ", stderr); ut_print_name(stderr, trx, table->name); fputs("\n" "InnoDB: though there is a foreign key check running on it.\n" @@ -3286,9 +3288,9 @@ fputs(" InnoDB: You are trying to drop table ", stderr); goto funct_exit; } - + /* Remove any locks there are on the table or its records */ - + lock_reset_all_on_table(table); trx->dict_operation = TRUE; @@ -3304,7 +3306,7 @@ fputs(" InnoDB: You are trying to drop table ", stderr); ut_a(err == DB_OUT_OF_FILE_SPACE); err = DB_MUST_GET_MORE_FILE_SPACE; - + row_mysql_handle_errors(&err, trx, thr, NULL); ut_error; @@ -3313,7 +3315,7 @@ fputs(" InnoDB: You are trying to drop table ", stderr); const char* name_or_path; space_id = table->space; - + if (table->dir_path_of_temp_table != NULL) { dir_path_of_temp_table = mem_strdup(table->dir_path_of_temp_table); @@ -3347,7 +3349,7 @@ fputs(" InnoDB: You are trying to drop table ", stderr); fprintf(stderr, "InnoDB: We removed now the InnoDB internal data dictionary entry\n" -"InnoDB: of table "); +"InnoDB: of table "); ut_print_name(stderr, trx, name); fprintf(stderr, ".\n"); @@ -3359,7 +3361,7 @@ fputs(" InnoDB: You are trying to drop table ", stderr); if (!success) { fprintf(stderr, "InnoDB: We removed now the InnoDB internal data dictionary entry\n" -"InnoDB: of table "); +"InnoDB: of table "); ut_print_name(stderr, trx, name); fprintf(stderr, ".\n"); @@ -3376,7 +3378,7 @@ fputs(" InnoDB: You are trying to drop table ", stderr); funct_exit: if (locked_dictionary) { - row_mysql_unlock_data_dictionary(trx); + row_mysql_unlock_data_dictionary(trx); } if (dir_path_of_temp_table) { @@ -3384,8 +3386,8 @@ funct_exit: } que_graph_free(graph); - - trx_commit_for_mysql(trx); + + trx_commit_for_mysql(trx); trx->op_info = ""; @@ -3406,17 +3408,17 @@ row_drop_database_for_mysql( const char* name, /* in: database name which ends to '/' */ trx_t* trx) /* in: transaction handle */ { - dict_table_t* table; + dict_table_t* table; char* table_name; int err = DB_SUCCESS; ulint namelen = strlen(name); - + ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_a(name != NULL); ut_a(name[namelen - 1] == '/'); - + trx->op_info = "dropping database"; - + trx_start_if_not_started(trx); loop: row_mysql_lock_data_dictionary(trx); @@ -3443,11 +3445,11 @@ loop: ut_print_name(stderr, trx, table_name); fputs(".\n", stderr); - os_thread_sleep(1000000); + os_thread_sleep(1000000); - mem_free(table_name); + mem_free(table_name); - goto loop; + goto loop; } err = row_drop_table_for_mysql(table_name, trx, TRUE); @@ -3466,7 +3468,7 @@ loop: } row_mysql_unlock_data_dictionary(trx); - + trx_commit_for_mysql(trx); trx->op_info = ""; @@ -3542,54 +3544,55 @@ row_rename_table_for_mysql( "old_t_name_len := LENGTH(old_table_name);\n" "gen_constr_prefix := CONCAT(old_table_name, '_ibfk_');\n" "WHILE found = 1 LOOP\n" - " SELECT ID INTO foreign_id\n" - " FROM SYS_FOREIGN\n" - " WHERE FOR_NAME = old_table_name\n" - " AND TO_BINARY(FOR_NAME) = TO_BINARY(old_table_name);\n" - " IF (SQL % NOTFOUND) THEN\n" - " found := 0;\n" - " ELSE\n" - " UPDATE SYS_FOREIGN\n" - " SET FOR_NAME = new_table_name\n" - " WHERE ID = foreign_id;\n" - " id_len := LENGTH(foreign_id);\n" - " IF (INSTR(foreign_id, '/') > 0) THEN\n" - " IF (INSTR(foreign_id,\n" - " gen_constr_prefix) > 0)\n" - " THEN\n" - " new_foreign_id :=\n" - " CONCAT(new_table_name,\n" - " SUBSTR(foreign_id, old_t_name_len,\n" - " id_len - old_t_name_len));\n" - " ELSE\n" - " new_foreign_id :=\n" - " CONCAT(new_db_name,\n" - " SUBSTR(foreign_id,\n" - " old_db_name_len,\n" - " id_len - old_db_name_len));\n" - " END IF;\n" - " UPDATE SYS_FOREIGN\n" - " SET ID = new_foreign_id\n" - " WHERE ID = foreign_id;\n" - " UPDATE SYS_FOREIGN_COLS\n" - " SET ID = new_foreign_id\n" - " WHERE ID = foreign_id;\n" - " END IF;\n" - " END IF;\n" + " SELECT ID INTO foreign_id\n" + " FROM SYS_FOREIGN\n" + " WHERE FOR_NAME = old_table_name\n" + " AND TO_BINARY(FOR_NAME) = TO_BINARY(old_table_name);\n" + " IF (SQL % NOTFOUND) THEN\n" + " found := 0;\n" + " ELSE\n" + " UPDATE SYS_FOREIGN\n" + " SET FOR_NAME = new_table_name\n" + " WHERE ID = foreign_id;\n" + " id_len := LENGTH(foreign_id);\n" + " IF (INSTR(foreign_id, '/') > 0) THEN\n" + " IF (INSTR(foreign_id,\n" + " gen_constr_prefix) > 0)\n" + " THEN\n" + " new_foreign_id :=\n" + " CONCAT(new_table_name,\n" + " SUBSTR(foreign_id, old_t_name_len,\n" + " id_len - old_t_name_len));\n" + " ELSE\n" + " new_foreign_id :=\n" + " CONCAT(new_db_name,\n" + " SUBSTR(foreign_id,\n" + " old_db_name_len,\n" + " id_len - old_db_name_len));\n" + " END IF;\n" + " UPDATE SYS_FOREIGN\n" + " SET ID = new_foreign_id\n" + " WHERE ID = foreign_id;\n" + " UPDATE SYS_FOREIGN_COLS\n" + " SET ID = new_foreign_id\n" + " WHERE ID = foreign_id;\n" + " END IF;\n" + " END IF;\n" "END LOOP;\n" "UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n" "WHERE REF_NAME = old_table_name\n" - " AND TO_BINARY(REF_NAME) = TO_BINARY(old_table_name);\n"; + " AND TO_BINARY(REF_NAME) = TO_BINARY(old_table_name);\n"; static const char str5[] = "END;\n"; mem_heap_t* heap = NULL; const char** constraints_to_drop = NULL; ulint n_constraints_to_drop = 0; - ibool recovering_temp_table = FALSE; + ibool recovering_temp_table = FALSE; + ibool old_is_tmp, new_is_tmp; ulint len; ulint i; - ibool success; + ibool success; /* length of database name; 0 if not renaming to a temporary table */ ulint db_name_len; char* sql; @@ -3608,28 +3611,31 @@ row_rename_table_for_mysql( "InnoDB: with raw, and innodb_force_... is removed.\n", stderr); - trx_commit_for_mysql(trx); + trx_commit_for_mysql(trx); return(DB_ERROR); } - + if (row_mysql_is_system_table(new_name)) { - + fprintf(stderr, "InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n" "InnoDB: MySQL system tables must be of the MyISAM type!\n", new_name); - trx_commit_for_mysql(trx); + trx_commit_for_mysql(trx); return(DB_ERROR); } trx->op_info = "renaming table"; trx_start_if_not_started(trx); + old_is_tmp = row_is_mysql_tmp_table_name(old_name); + new_is_tmp = row_is_mysql_tmp_table_name(new_name); + if (row_mysql_is_recovered_tmp_table(new_name)) { - recovering_temp_table = TRUE; - } else { + recovering_temp_table = TRUE; + } else { /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ @@ -3640,30 +3646,30 @@ row_rename_table_for_mysql( if (!table) { err = DB_TABLE_NOT_FOUND; - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); - fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, old_name); - fputs(" does not exist in the InnoDB internal\n" - "InnoDB: data dictionary though MySQL is trying to rename the table.\n" - "InnoDB: Have you copied the .frm file of the table to the\n" + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, trx, old_name); + fputs(" does not exist in the InnoDB internal\n" + "InnoDB: data dictionary though MySQL is trying to rename the table.\n" + "InnoDB: Have you copied the .frm file of the table to the\n" "InnoDB: MySQL database directory from another database?\n" "InnoDB: You can look for further help from\n" - "InnoDB: http://dev.mysql.com/doc/mysql/en/" + "InnoDB: http://dev.mysql.com/doc/mysql/en/" "InnoDB_troubleshooting_datadict.html\n", stderr); goto funct_exit; } if (table->ibd_file_missing) { err = DB_TABLE_NOT_FOUND; - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); - fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, old_name); - fputs( + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, trx, old_name); + fputs( " does not have an .ibd file in the database directory.\n" "InnoDB: You can look for further help from\n" - "InnoDB: http://dev.mysql.com/doc/mysql/en/" + "InnoDB: http://dev.mysql.com/doc/mysql/en/" "InnoDB_troubleshooting_datadict.html\n", stderr); goto funct_exit; } @@ -3672,7 +3678,7 @@ row_rename_table_for_mysql( len = (sizeof str1) + (sizeof str2) + (sizeof str3) + (sizeof str5) - 4 + ut_strlenq(new_name, '\'') + ut_strlenq(old_name, '\''); - if (row_is_mysql_tmp_table_name(new_name)) { + if (new_is_tmp) { db_name_len = dict_get_db_name_len(old_name) + 1; /* MySQL is doing an ALTER TABLE command and it renames the @@ -3682,7 +3688,7 @@ row_rename_table_for_mysql( the ALTER TABLE contained DROP FOREIGN KEY <foreign key id>.*/ heap = mem_heap_create(100); - + err = dict_foreign_parse_drop_constraints(heap, trx, table, &n_constraints_to_drop, @@ -3691,7 +3697,7 @@ row_rename_table_for_mysql( goto funct_exit; } - + /* reserve space for all database names */ len += 2 * n_constraints_to_drop * (ut_strlenq(old_name, '\'') @@ -3738,7 +3744,7 @@ row_rename_table_for_mysql( sqlend += (sizeof str4a2) - 1; sqlend = ut_memcpyq(sqlend, '\'', old_name, db_name_len); - sqlend = ut_strcpyq(sqlend, '\'', + sqlend = ut_strcpyq(sqlend, '\'', constraints_to_drop[i]); memcpy(sqlend, str4a3, (sizeof str4a3) - 1); sqlend += (sizeof str4a3) - 1; @@ -3755,7 +3761,7 @@ row_rename_table_for_mysql( constraints_to_drop[i]); memcpy(sqlend, str4a2, (sizeof str4a2) - 1); sqlend += (sizeof str4a2) - 1; - sqlend = ut_strcpyq(sqlend, '\'', + sqlend = ut_strcpyq(sqlend, '\'', constraints_to_drop[i]); memcpy(sqlend, str4a3, (sizeof str4a3) - 1); sqlend += (sizeof str4a3) - 1; @@ -3771,7 +3777,7 @@ row_rename_table_for_mysql( sqlend += sizeof str5; ut_a(sqlend == sql + len + 1); - + graph = pars_sql(sql); ut_a(graph); @@ -3790,16 +3796,16 @@ row_rename_table_for_mysql( if (err != DB_SUCCESS) { if (err == DB_DUPLICATE_KEY) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fputs( " InnoDB: Error; possible reasons:\n" "InnoDB: 1) Table rename would cause two FOREIGN KEY constraints\n" "InnoDB: to have the same internal name in case-insensitive comparison.\n" "InnoDB: 2) table ", stderr); - ut_print_name(stderr, trx, new_name); - fputs(" exists in the InnoDB internal data\n" + ut_print_name(stderr, trx, new_name); + fputs(" exists in the InnoDB internal data\n" "InnoDB: dictionary though MySQL is trying rename table ", stderr); - ut_print_name(stderr, trx, old_name); + ut_print_name(stderr, trx, old_name); fputs(" to it.\n" "InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n" "InnoDB: You can look for further help from\n" @@ -3825,7 +3831,7 @@ row_rename_table_for_mysql( the table is stored in a single-table tablespace */ success = dict_table_rename_in_cache(table, new_name, - !row_is_mysql_tmp_table_name(new_name)); + !new_is_tmp); if (!success) { trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, FALSE, NULL); @@ -3842,19 +3848,16 @@ row_rename_table_for_mysql( goto funct_exit; } - err = dict_load_foreigns(new_name, trx->check_foreigns); + /* We only want to switch off some of the type checking in + an ALTER, not in a RENAME. */ - if (row_is_mysql_tmp_table_name(old_name)) { + err = dict_load_foreigns(new_name, + old_is_tmp ? trx->check_foreigns : TRUE); - /* MySQL is doing an ALTER TABLE command and it - renames the created temporary table to the name - of the original table. In the ALTER TABLE we maybe - created some FOREIGN KEY constraints for the temporary - table. But we want to load also the foreign key - constraint definitions for the original table name. */ + if (err != DB_SUCCESS) { + ut_print_timestamp(stderr); - if (err != DB_SUCCESS) { - ut_print_timestamp(stderr); + if (old_is_tmp) { fputs(" InnoDB: Error: in ALTER TABLE ", stderr); ut_print_name(stderr, trx, new_name); @@ -3862,39 +3865,26 @@ row_rename_table_for_mysql( "InnoDB: has or is referenced in foreign key constraints\n" "InnoDB: which are not compatible with the new table definition.\n", stderr); - - ut_a(dict_table_rename_in_cache(table, - old_name, FALSE)); - trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, - NULL); - trx->error_state = DB_SUCCESS; - } - } else { - if (err != DB_SUCCESS) { - - ut_print_timestamp(stderr); - + } else { fputs( " InnoDB: Error: in RENAME TABLE table ", stderr); ut_print_name(stderr, trx, new_name); fputs("\n" - "InnoDB: is referenced in foreign key constraints\n" - "InnoDB: which are not compatible with the new table definition.\n", + "InnoDB: is referenced in foreign key constraints\n" + "InnoDB: which are not compatible with the new table definition.\n", stderr); - - ut_a(dict_table_rename_in_cache(table, - old_name, FALSE)); - - trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, - NULL); - trx->error_state = DB_SUCCESS; } + + ut_a(dict_table_rename_in_cache(table, + old_name, FALSE)); + trx->error_state = DB_SUCCESS; + trx_general_rollback_for_mysql(trx, FALSE, + NULL); + trx->error_state = DB_SUCCESS; } } -funct_exit: +funct_exit: if (!recovering_temp_table) { row_mysql_unlock_data_dictionary(trx); } @@ -3906,8 +3896,8 @@ funct_exit: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } - - trx_commit_for_mysql(trx); + + trx_commit_for_mysql(trx); trx->op_info = ""; @@ -3945,10 +3935,10 @@ row_scan_and_check_index( *offsets_ = (sizeof offsets_) / sizeof *offsets_; *n_rows = 0; - + buf = mem_alloc(UNIV_PAGE_SIZE); heap = mem_heap_create(100); - + /* Make a dummy template in prebuilt, which we will use in scanning the index entries */ @@ -3958,7 +3948,7 @@ row_scan_and_check_index( prebuilt->n_template = 0; prebuilt->need_to_access_clustered = FALSE; - dtuple_set_n_fields(prebuilt->search_tuple, 0); + dtuple_set_n_fields(prebuilt->search_tuple, 0); prebuilt->select_lock_type = LOCK_NONE; cnt = 1000; @@ -3981,11 +3971,11 @@ loop: } *n_rows = *n_rows + 1; - + /* row_search... returns the index record in buf, record origin offset within buf stored in the first 4 bytes, because we have built a dummy template */ - + rec = buf + mach_read_from_4(buf); if (prev_entry != NULL) { @@ -4002,15 +3992,15 @@ loop: /* In a unique secondary index we allow equal key values if they contain SQL NULLs */ - for (i = 0; - i < dict_index_get_n_ordering_defined_by_user(index); + for (i = 0; + i < dict_index_get_n_ordering_defined_by_user(index); i++) { - if (UNIV_SQL_NULL == dfield_get_len( - dtuple_get_nth_field(prev_entry, i))) { + if (UNIV_SQL_NULL == dfield_get_len( + dtuple_get_nth_field(prev_entry, i))) { - contains_null = TRUE; - } - } + contains_null = TRUE; + } + } if (cmp > 0) { fputs("InnoDB: index records in a wrong order in ", @@ -4038,12 +4028,12 @@ loop: mem_heap_empty(heap); offsets = offsets_; - + prev_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, ROW_SEL_NEXT); - goto loop; + goto loop; } /************************************************************************* @@ -4060,12 +4050,12 @@ row_check_table_for_mysql( dict_index_t* index; ulint n_rows; ulint n_rows_in_table = ULINT_UNDEFINED; - ulint ret = DB_SUCCESS; + ulint ret = DB_SUCCESS; ulint old_isolation_level; if (prebuilt->table->ibd_file_missing) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Error:\n" + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Error:\n" "InnoDB: MySQL is trying to use a table handle but the .ibd file for\n" "InnoDB: table %s does not exist.\n" "InnoDB: Have you deleted the .ibd file from the database directory under\n" @@ -4099,7 +4089,7 @@ row_check_table_for_mysql( /* fputs("Validating index ", stderr); ut_print_name(stderr, index->name); putc('\n', stderr); */ - + if (!btr_validate_tree(index->tree, prebuilt->trx)) { ret = DB_ERROR; } else { @@ -4120,7 +4110,7 @@ row_check_table_for_mysql( } else if (n_rows != n_rows_in_table) { ret = DB_ERROR; - + fputs("Error: ", stderr); dict_index_name_print(stderr, prebuilt->trx, index); @@ -4136,7 +4126,7 @@ row_check_table_for_mysql( /* Restore the original isolation level */ prebuilt->trx->isolation_level = old_isolation_level; - + /* We validate also the whole adaptive hash index for all tables at every CHECK TABLE */ diff --git a/storage/innobase/row/row0purge.c b/storage/innobase/row/row0purge.c index abcf97110d9..b7581fa3644 100644 --- a/storage/innobase/row/row0purge.c +++ b/storage/innobase/row/row0purge.c @@ -105,7 +105,7 @@ row_purge_remove_clust_if_poss_low( *offsets_ = (sizeof offsets_) / sizeof *offsets_; index = dict_table_get_first_index(node->table); - + pcur = &(node->pcur); btr_cur = btr_pcur_get_btr_cur(pcur); @@ -158,7 +158,7 @@ row_purge_remove_clust_if_poss_low( return(success); } - + /*************************************************************** Removes a clustered index record if it has not been modified after the delete marking. */ @@ -170,7 +170,7 @@ row_purge_remove_clust_if_poss( { ibool success; ulint n_tries = 0; - + /* fputs("Purge: Removing clustered record\n", stderr); */ success = row_purge_remove_clust_if_poss_low(node, BTR_MODIFY_LEAF); @@ -188,13 +188,13 @@ retry: n_tries++; os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME); - + goto retry; } ut_a(success); } - + /*************************************************************** Removes a secondary index entry if possible. */ static @@ -206,7 +206,7 @@ row_purge_remove_sec_if_poss_low( dict_index_t* index, /* in: index */ dtuple_t* entry, /* in: index entry */ ulint mode) /* in: latch mode BTR_MODIFY_LEAF or - BTR_MODIFY_TREE */ + BTR_MODIFY_TREE */ { btr_pcur_t pcur; btr_cur_t* btr_cur; @@ -216,10 +216,10 @@ row_purge_remove_sec_if_poss_low( ulint err; mtr_t mtr; mtr_t* mtr_vers; - + log_free_check(); mtr_start(&mtr); - + found = row_search_index_entry(index, entry, mode, &pcur, &mtr); if (!found) { @@ -235,18 +235,18 @@ row_purge_remove_sec_if_poss_low( } btr_cur = btr_pcur_get_btr_cur(&pcur); - + /* We should remove the index record if no later version of the row, which cannot be purged yet, requires its existence. If some requires, we should do nothing. */ mtr_vers = mem_alloc(sizeof(mtr_t)); - + mtr_start(mtr_vers); success = row_purge_reposition_pcur(BTR_SEARCH_LEAF, node, mtr_vers); - if (success) { + if (success) { old_has = row_vers_old_has_index_entry(TRUE, btr_pcur_get_rec(&(node->pcur)), mtr_vers, index, entry); @@ -255,11 +255,11 @@ row_purge_remove_sec_if_poss_low( btr_pcur_commit_specify_mtr(&(node->pcur), mtr_vers); mem_free(mtr_vers); - + if (!success || !old_has) { /* Remove the index record */ - if (mode == BTR_MODIFY_LEAF) { + if (mode == BTR_MODIFY_LEAF) { success = btr_cur_optimistic_delete(btr_cur, &mtr); } else { ut_ad(mode == BTR_MODIFY_TREE); @@ -293,7 +293,7 @@ row_purge_remove_sec_if_poss( { ibool success; ulint n_tries = 0; - + /* fputs("Purge: Removing secondary record\n", stderr); */ success = row_purge_remove_sec_if_poss_low(node, index, entry, @@ -310,11 +310,11 @@ retry: and restart with more file space */ if (!success && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) { - + n_tries++; os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME); - + goto retry; } @@ -332,7 +332,7 @@ row_purge_del_mark( mem_heap_t* heap; dtuple_t* entry; dict_index_t* index; - + ut_ad(node); heap = mem_heap_create(1024); @@ -348,11 +348,11 @@ row_purge_del_mark( node->index = dict_table_get_next_index(node->index); } - mem_heap_free(heap); + mem_heap_free(heap); row_purge_remove_clust_if_poss(node); } - + /*************************************************************** Purges an update of an existing record. Also purges an update of a delete marked record if that record contained an externally stored field. */ @@ -375,7 +375,7 @@ row_purge_upd_exist_or_extern( ulint data_field_len; ulint i; mtr_t mtr; - + ut_ad(node); if (node->rec_type == TRX_UNDO_UPD_DEL_REC) { @@ -399,7 +399,7 @@ row_purge_upd_exist_or_extern( node->index = dict_table_get_next_index(node->index); } - mem_heap_free(heap); + mem_heap_free(heap); skip_secondaries: /* Free possible externally stored fields */ @@ -416,7 +416,7 @@ skip_secondaries: internal_offset = ((byte*)ufield->new_val.data) - node->undo_rec; - + ut_a(internal_offset < UNIV_PAGE_SIZE); trx_undo_decode_roll_ptr(node->roll_ptr, @@ -439,20 +439,20 @@ skip_secondaries: latch on an undo log page, we would break the latching order if we would only later latch the root page of such a tree! */ - + btr_root_get(index->tree, &mtr); /* We assume in purge of externally stored fields that the space id of the undo log record is 0! */ data_field = buf_page_get(0, page_no, RW_X_LATCH, &mtr) - + offset + internal_offset; + + offset + internal_offset; #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(buf_frame_align(data_field), SYNC_TRX_UNDO_PAGE); #endif /* UNIV_SYNC_DEBUG */ - + data_field_len = ufield->new_val.len; btr_free_externally_stored_field(index, data_field, @@ -487,11 +487,11 @@ row_purge_parse_undo_rec( ulint info_bits; ulint type; ulint cmpl_info; - + ut_ad(node && thr); trx = thr_get_trx(thr); - + ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info, updated_extern, &undo_no, &table_id); node->rec_type = type; @@ -499,20 +499,20 @@ row_purge_parse_undo_rec( if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) { return(FALSE); - } + } ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, &info_bits); node->table = NULL; if (type == TRX_UNDO_UPD_EXIST_REC - && cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) { + && cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) { - /* Purge requires no changes to indexes: we may return */ + /* Purge requires no changes to indexes: we may return */ - return(FALSE); + return(FALSE); } - + /* Prevent DROP TABLE etc. from running when we are doing the purge for this row */ @@ -521,7 +521,7 @@ row_purge_parse_undo_rec( mutex_enter(&(dict_sys->mutex)); node->table = dict_table_get_on_id_low(table_id, trx); - + mutex_exit(&(dict_sys->mutex)); if (node->table == NULL) { @@ -565,7 +565,7 @@ row_purge_parse_undo_rec( ptr = trx_undo_rec_get_partial_row(ptr, clust_index, &(node->row), node->heap); } - + return(TRUE); } @@ -586,11 +586,11 @@ row_purge( ibool purge_needed; ibool updated_extern; trx_t* trx; - + ut_ad(node && thr); trx = thr_get_trx(thr); - + node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr, &(node->reservation), node->heap); @@ -615,7 +615,7 @@ row_purge( if (purge_needed) { node->found_clust = FALSE; - + node->index = dict_table_get_next_index( dict_table_get_first_index(node->table)); @@ -623,7 +623,7 @@ row_purge( row_purge_del_mark(node); } else if (updated_extern - || node->rec_type == TRX_UNDO_UPD_EXIST_REC) { + || node->rec_type == TRX_UNDO_UPD_EXIST_REC) { row_purge_upd_exist_or_extern(node); } @@ -638,7 +638,7 @@ row_purge( /* Do some cleanup */ trx_purge_rec_release(node->reservation); mem_heap_empty(node->heap); - + thr->run_node = node; return(DB_SUCCESS); @@ -658,7 +658,7 @@ row_purge_step( ulint err; ut_ad(thr); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_PURGE); @@ -668,4 +668,4 @@ row_purge_step( ut_ad(err == DB_SUCCESS); return(thr); -} +} diff --git a/storage/innobase/row/row0row.c b/storage/innobase/row/row0row.c index 9a74397dc08..24464ab5b99 100644 --- a/storage/innobase/row/row0row.c +++ b/storage/innobase/row/row0row.c @@ -103,9 +103,9 @@ dtuple_t* row_build_index_entry( /*==================*/ /* out: index entry which should be inserted */ - dtuple_t* row, /* in: row which should be inserted to the + dtuple_t* row, /* in: row which should be inserted to the table */ - dict_index_t* index, /* in: index on the table */ + dict_index_t* index, /* in: index on the table */ mem_heap_t* heap) /* in: memory heap from which the memory for the index entry is allocated */ { @@ -116,12 +116,12 @@ row_build_index_entry( dfield_t* dfield2; dict_col_t* col; ulint i; - ulint storage_len; + ulint storage_len; dtype_t* cur_type; ut_ad(row && index && heap); ut_ad(dtuple_check_typed(row)); - + entry_len = dict_index_get_n_fields(index); entry = dtuple_create(heap, entry_len); @@ -144,8 +144,8 @@ row_build_index_entry( /* If a column prefix index, take only the prefix */ if (ind_field->prefix_len > 0 - && dfield_get_len(dfield2) != UNIV_SQL_NULL) { - + && dfield_get_len(dfield2) != UNIV_SQL_NULL) { + cur_type = dict_col_get_type( dict_field_get_col(ind_field)); @@ -161,7 +161,7 @@ row_build_index_entry( ut_ad(dtuple_check_typed(entry)); return(entry); -} +} /*********************************************************************** An inverse function to dict_row_build_index_entry. Builds a row from a @@ -172,7 +172,7 @@ row_build( /*======*/ /* out, own: row built; see the NOTE below! */ ulint type, /* in: ROW_COPY_POINTERS, ROW_COPY_DATA, or - ROW_COPY_ALSO_EXTERNALS, + ROW_COPY_ALSO_EXTERNALS, the two last copy also the data fields to heap as the first only places pointers to data fields on the index page, and thus is @@ -200,7 +200,7 @@ row_build( byte* field; ulint len; ulint row_len; - byte* buf; + byte* buf; ulint i; mem_heap_t* tmp_heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; @@ -229,26 +229,27 @@ row_build( row = dtuple_create(heap, row_len); - dtuple_set_info_bits(row, rec_get_info_bits(rec, table->comp)); + dtuple_set_info_bits(row, rec_get_info_bits(rec, + dict_table_is_comp(table))); n_fields = rec_offs_n_fields(offsets); dict_table_copy_types(row, table); for (i = 0; i < n_fields; i++) { - ind_field = dict_index_get_nth_field(index, i); + ind_field = dict_index_get_nth_field(index, i); if (ind_field->prefix_len == 0) { - col = dict_field_get_col(ind_field); + col = dict_field_get_col(ind_field); dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); field = rec_get_nth_field(rec, offsets, i, &len); if (type == ROW_COPY_ALSO_EXTERNALS - && rec_offs_nth_extern(offsets, i)) { + && rec_offs_nth_extern(offsets, i)) { - field = btr_rec_copy_externally_stored_field( + field = btr_rec_copy_externally_stored_field( rec, offsets, i, &len, heap); } @@ -302,7 +303,7 @@ row_rec_to_index_entry( *offsets_ = (sizeof offsets_) / sizeof *offsets_; ut_ad(rec && heap && index); - + offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &tmp_heap); @@ -315,7 +316,7 @@ row_rec_to_index_entry( } rec_len = rec_offs_n_fields(offsets); - + entry = dtuple_create(heap, rec_len); dtuple_set_n_fields_cmp(entry, @@ -399,7 +400,7 @@ row_build_row_ref( } table = index->table; - + clust_index = dict_table_get_first_index(table); ref_len = dict_index_get_n_unique(clust_index); @@ -414,7 +415,7 @@ row_build_row_ref( pos = dict_index_get_nth_field_pos(index, clust_index, i); ut_a(pos != ULINT_UNDEFINED); - + field = rec_get_nth_field(rec, offsets, pos, &len); dfield_set_data(dfield, field, len); @@ -428,7 +429,7 @@ row_build_row_ref( dict_index_get_nth_field(clust_index, i)->prefix_len; if (clust_col_prefix_len > 0) { - if (len != UNIV_SQL_NULL) { + if (len != UNIV_SQL_NULL) { dfield_set_len(dfield, dtype_get_at_most_n_mbchars( @@ -478,7 +479,7 @@ row_build_row_ref_in_tuple( *offsets_ = (sizeof offsets_) / sizeof *offsets_; ut_a(ref && index && rec); - + if (!index->table) { fputs("InnoDB: table ", stderr); notfound: @@ -488,9 +489,9 @@ row_build_row_ref_in_tuple( fputs(" not found\n", stderr); ut_error; } - + clust_index = dict_table_get_first_index(index->table); - + if (!clust_index) { fputs("InnoDB: clust index for table ", stderr); goto notfound; @@ -501,7 +502,7 @@ row_build_row_ref_in_tuple( ref_len = dict_index_get_n_unique(clust_index); ut_ad(ref_len == dtuple_get_n_fields(ref)); - + dict_index_copy_types(ref, clust_index, ref_len); for (i = 0; i < ref_len; i++) { @@ -524,7 +525,7 @@ row_build_row_ref_in_tuple( dict_index_get_nth_field(clust_index, i)->prefix_len; if (clust_col_prefix_len > 0) { - if (len != UNIV_SQL_NULL) { + if (len != UNIV_SQL_NULL) { dfield_set_len(dfield, dtype_get_at_most_n_mbchars( @@ -563,28 +564,28 @@ row_build_row_ref_from_row( ulint ref_len; ulint i; dtype_t* cur_type; - + ut_ad(ref && table && row); - + clust_index = dict_table_get_first_index(table); ref_len = dict_index_get_n_unique(clust_index); ut_ad(ref_len == dtuple_get_n_fields(ref)); - + for (i = 0; i < ref_len; i++) { dfield = dtuple_get_nth_field(ref, i); - + field = dict_index_get_nth_field(clust_index, i); - + col = dict_field_get_col(field); - + dfield2 = dtuple_get_nth_field(row, dict_col_get_no(col)); dfield_copy(dfield, dfield2); if (field->prefix_len > 0 - && dfield->len != UNIV_SQL_NULL) { + && dfield->len != UNIV_SQL_NULL) { cur_type = dict_col_get_type( dict_field_get_col(field)); @@ -613,7 +614,7 @@ row_search_on_row_ref( dtuple_t* ref, /* in: row reference */ mtr_t* mtr) /* in: mtr */ { - ulint low_match; + ulint low_match; rec_t* rec; dict_index_t* index; @@ -624,7 +625,7 @@ row_search_on_row_ref( ut_a(dtuple_get_n_fields(ref) == dict_index_get_n_unique(index)); btr_pcur_open(index, ref, PAGE_CUR_LE, mode, pcur, mtr); - + low_match = btr_pcur_get_low_match(pcur); rec = btr_pcur_get_rec(pcur); @@ -662,7 +663,7 @@ row_get_clust_rec( btr_pcur_t pcur; ibool found; rec_t* clust_rec; - + ut_ad((index->type & DICT_CLUSTERED) == 0); table = index->table; @@ -703,7 +704,7 @@ row_search_index_entry( rec_t* rec; ut_ad(dtuple_check_typed(entry)); - + btr_pcur_open(index, entry, PAGE_CUR_LE, mode, pcur, mtr); low_match = btr_pcur_get_low_match(pcur); diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index b08d27d2916..0809d2872a5 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -70,13 +70,13 @@ row_sel_sec_rec_is_for_clust_rec( dict_index_t* clust_index) /* in: clustered index */ { dict_field_t* ifield; - dict_col_t* col; - byte* sec_field; - ulint sec_len; - byte* clust_field; - ulint clust_len; - ulint n; - ulint i; + dict_col_t* col; + byte* sec_field; + ulint sec_len; + byte* clust_field; + ulint clust_len; + ulint n; + ulint i; dtype_t* cur_type; mem_heap_t* heap = NULL; ulint clust_offsets_[REC_OFFS_NORMAL_SIZE]; @@ -93,19 +93,19 @@ row_sel_sec_rec_is_for_clust_rec( sec_offs = rec_get_offsets(sec_rec, sec_index, sec_offs, ULINT_UNDEFINED, &heap); - n = dict_index_get_n_ordering_defined_by_user(sec_index); + n = dict_index_get_n_ordering_defined_by_user(sec_index); - for (i = 0; i < n; i++) { + for (i = 0; i < n; i++) { ifield = dict_index_get_nth_field(sec_index, i); - col = dict_field_get_col(ifield); - + col = dict_field_get_col(ifield); + clust_field = rec_get_nth_field(clust_rec, clust_offs, - dict_col_get_clust_pos(col), - &clust_len); + dict_col_get_clust_pos(col), + &clust_len); sec_field = rec_get_nth_field(sec_rec, sec_offs, i, &sec_len); if (ifield->prefix_len > 0 - && clust_len != UNIV_SQL_NULL) { + && clust_len != UNIV_SQL_NULL) { cur_type = dict_col_get_type( dict_field_get_col(ifield)); @@ -116,13 +116,13 @@ row_sel_sec_rec_is_for_clust_rec( clust_len, (char*) clust_field); } - if (0 != cmp_data_data(dict_col_get_type(col), - clust_field, clust_len, - sec_field, sec_len)) { + if (0 != cmp_data_data(dict_col_get_type(col), + clust_field, clust_len, + sec_field, sec_len)) { is_equal = FALSE; goto func_exit; - } - } + } + } func_exit: if (UNIV_LIKELY_NULL(heap)) { @@ -150,7 +150,7 @@ sel_node_create( node->latch_mode = BTR_SEARCH_LEAF; node->plans = NULL; - + return(node); } @@ -248,7 +248,7 @@ sel_reset_aggregate_vals( eval_node_set_int_val(func_node, 0); func_node = que_node_get_next(func_node); - } + } node->aggregate_already_fetched = FALSE; } @@ -292,7 +292,7 @@ row_sel_fetch_columns( ulint field_no; byte* data; ulint len; - + ut_ad(rec_offs_validate(rec, index, offsets)); if (index->type & DICT_CLUSTERED) { @@ -305,9 +305,9 @@ row_sel_fetch_columns( field_no = column->field_nos[index_type]; if (field_no != ULINT_UNDEFINED) { - + data = rec_get_nth_field(rec, offsets, field_no, &len); - + if (column->copy_val) { eval_node_copy_and_alloc_val(column, data, len); @@ -333,7 +333,7 @@ sel_col_prefetch_buf_alloc( ulint i; ut_ad(que_node_get_type(column) == QUE_NODE_SYMBOL); - + column->prefetch_buf = mem_alloc(SEL_MAX_N_PREFETCH * sizeof(sel_buf_t)); for (i = 0; i < SEL_MAX_N_PREFETCH; i++) { @@ -382,7 +382,7 @@ sel_pop_prefetched_row( byte* data; ulint len; ulint val_buf_size; - + ut_ad(plan->n_rows_prefetched > 0); column = UT_LIST_GET_FIRST(plan->columns); @@ -417,7 +417,7 @@ sel_pop_prefetched_row( sel_buf->data = dfield_get_data(val); sel_buf->len = dfield_get_len(val); sel_buf->val_buf_size = que_node_get_val_buf_size(column); - + dfield_set_data(val, data, len); que_node_set_val_buf_size(column, val_buf_size); next_col: @@ -454,14 +454,14 @@ sel_push_prefetched_row( /* We have the convention that pushing new rows starts only after the prefetch stack has been emptied: */ - + ut_ad(plan->first_prefetched == 0); } plan->n_rows_prefetched++; - + ut_ad(pos < SEL_MAX_N_PREFETCH); - + column = UT_LIST_GET_FIRST(plan->columns); while (column) { @@ -471,7 +471,7 @@ sel_push_prefetched_row( goto next_col; } - + if (!column->prefetch_buf) { /* Allocate a new prefetch buffer */ @@ -492,11 +492,11 @@ sel_push_prefetched_row( dfield_set_data(val, sel_buf->data, sel_buf->len); que_node_set_val_buf_size(column, sel_buf->val_buf_size); - + sel_buf->data = data; sel_buf->len = len; sel_buf->val_buf_size = val_buf_size; -next_col: +next_col: column = UT_LIST_GET_NEXT(col_var_list, column); } } @@ -528,7 +528,7 @@ row_sel_build_prev_vers( } else { plan->old_vers_heap = mem_heap_create(512); } - + err = row_vers_build_for_consistent_read(rec, mtr, plan->index, offsets, read_view, offset_heap, plan->old_vers_heap, old_vers); @@ -563,7 +563,7 @@ row_sel_build_committed_vers_for_mysql( } else { prebuilt->old_vers_heap = mem_heap_create(200); } - + err = row_vers_build_for_semi_consistent_read(rec, mtr, clust_index, offsets, offset_heap, prebuilt->old_vers_heap, old_vers); @@ -577,7 +577,7 @@ UNIV_INLINE ibool row_sel_test_end_conds( /*===================*/ - /* out: TRUE if row passed the tests */ + /* out: TRUE if row passed the tests */ plan_t* plan) /* in: plan for the table; the column values must already have been retrieved and the right sides of comparisons evaluated */ @@ -586,7 +586,7 @@ row_sel_test_end_conds( /* All conditions in end_conds are comparisons of a column to an expression */ - + cond = UT_LIST_GET_FIRST(plan->end_conds); while (cond) { @@ -619,7 +619,7 @@ row_sel_test_other_conds( already have been retrieved */ { func_node_t* cond; - + cond = UT_LIST_GET_FIRST(plan->other_conds); while (cond) { @@ -670,11 +670,11 @@ row_sel_get_clust_rec( offsets = rec_get_offsets(rec, btr_pcur_get_btr_cur(&plan->pcur)->index, offsets, ULINT_UNDEFINED, &heap); - + row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets); index = dict_table_get_first_index(plan->table); - + btr_pcur_open_with_no_init(index, plan->clust_ref, PAGE_CUR_LE, node->latch_mode, &(plan->clust_pcur), 0, mtr); @@ -685,10 +685,11 @@ row_sel_get_clust_rec( low_match value the real match to the search tuple */ if (!page_rec_is_user_rec(clust_rec) - || btr_pcur_get_low_match(&(plan->clust_pcur)) - < dict_index_get_n_unique(index)) { - - ut_a(rec_get_deleted_flag(rec, plan->table->comp)); + || btr_pcur_get_low_match(&(plan->clust_pcur)) + < dict_index_get_n_unique(index)) { + + ut_a(rec_get_deleted_flag(rec, + dict_table_is_comp(plan->table))); ut_a(node->read_view); /* In a rare case it is possible that no clust rec is found @@ -708,8 +709,8 @@ row_sel_get_clust_rec( if (!node->read_view) { /* Try to place a lock on the index record */ - - /* If innodb_locks_unsafe_for_binlog option is used, + + /* If innodb_locks_unsafe_for_binlog option is used, we lock only the record, i.e., next-key locking is not used. */ ulint lock_type; @@ -764,10 +765,11 @@ row_sel_get_clust_rec( a wrong result if we would not drop rows which we come to visit through secondary index records that would not really exist in our snapshot. */ - - if ((old_vers || rec_get_deleted_flag(rec, plan->table->comp)) - && !row_sel_sec_rec_is_for_clust_rec(rec, plan->index, - clust_rec, index)) { + + if ((old_vers || rec_get_deleted_flag(rec, + dict_table_is_comp(plan->table))) + && !row_sel_sec_rec_is_for_clust_rec(rec, plan->index, + clust_rec, index)) { goto func_exit; } } @@ -797,17 +799,17 @@ sel_set_rec_lock( dict_index_t* index, /* in: index */ const ulint* offsets,/* in: rec_get_offsets(rec, index) */ ulint mode, /* in: lock mode */ - ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */ - que_thr_t* thr) /* in: query thread */ + ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */ + que_thr_t* thr) /* in: query thread */ { trx_t* trx; ulint err; - trx = thr_get_trx(thr); + trx = thr_get_trx(thr); if (UT_LIST_GET_LEN(trx->trx_locks) > 10000) { if (buf_LRU_buf_pool_running_out()) { - + return(DB_LOCK_TABLE_FULL); } } @@ -841,7 +843,7 @@ row_sel_open_pcur( func_node_t* cond; que_node_t* exp; ulint n_fields; - ulint has_search_latch = 0; /* RW_S_LATCH or 0 */ + ulint has_search_latch = 0; /* RW_S_LATCH or 0 */ ulint i; if (search_latch_locked) { @@ -858,29 +860,29 @@ row_sel_open_pcur( while (cond) { eval_exp(que_node_get_next(cond->args)); - + cond = UT_LIST_GET_NEXT(cond_list, cond); } - + if (plan->tuple) { n_fields = dtuple_get_n_fields(plan->tuple); - + if (plan->n_exact_match < n_fields) { /* There is a non-exact match field which must be evaluated separately */ - + eval_exp(plan->tuple_exps[n_fields - 1]); } - + for (i = 0; i < n_fields; i++) { exp = plan->tuple_exps[i]; - + dfield_copy_data(dtuple_get_nth_field(plan->tuple, i), que_node_get_val(exp)); } - + /* Open pcur to the index */ - + btr_pcur_open_with_no_init(index, plan->tuple, plan->mode, node->latch_mode, &(plan->pcur), has_search_latch, mtr); @@ -895,7 +897,7 @@ row_sel_open_pcur( ut_ad(plan->n_rows_prefetched == 0); ut_ad(plan->n_rows_fetched == 0); ut_ad(plan->cursor_at_end == FALSE); - + plan->pcur_is_open = TRUE; } @@ -918,14 +920,14 @@ row_sel_restore_pcur_pos( ulint relative_position; ut_ad(!plan->cursor_at_end); - + relative_position = btr_pcur_get_rel_pos(&(plan->pcur)); equal_position = btr_pcur_restore_position(node->latch_mode, &(plan->pcur), mtr); /* If the cursor is traveling upwards, and relative_position is - + (1) BTR_PCUR_BEFORE: this is not allowed, as we did not have a lock yet on the successor of the page infimum; (2) BTR_PCUR_AFTER: btr_pcur_restore_position placed the cursor on the @@ -952,13 +954,13 @@ row_sel_restore_pcur_pos( } ut_ad(relative_position == BTR_PCUR_AFTER - || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE); + || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE); return(FALSE); } /* If the cursor is traveling downwards, and relative_position is - + (1) BTR_PCUR_BEFORE: btr_pcur_restore_position placed the cursor on the last record LESS than the successor of a page infimum; we have not processed the cursor record: no need to move the cursor; @@ -975,7 +977,7 @@ row_sel_restore_pcur_pos( record, else there is no need to move the cursor. */ if (relative_position == BTR_PCUR_BEFORE - || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE) { + || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE) { return(FALSE); } @@ -991,7 +993,7 @@ row_sel_restore_pcur_pos( } ut_ad(relative_position == BTR_PCUR_AFTER - || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE); + || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE); return(TRUE); } @@ -1003,13 +1005,13 @@ void plan_reset_cursor( /*==============*/ plan_t* plan) /* in: plan */ -{ +{ plan->pcur_is_open = FALSE; - plan->cursor_at_end = FALSE; + plan->cursor_at_end = FALSE; plan->n_rows_fetched = 0; plan->n_rows_prefetched = 0; } - + /************************************************************************* Tries to do a shortcut to fetch a clustered index record with a unique key, using the hash index if possible (not always). */ @@ -1039,21 +1041,21 @@ row_sel_try_search_shortcut( #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); #endif /* UNIV_SYNC_DEBUG */ - + row_sel_open_pcur(node, plan, TRUE, mtr); rec = btr_pcur_get_rec(&(plan->pcur)); - + if (!page_rec_is_user_rec(rec)) { return(SEL_RETRY); } ut_ad(plan->mode == PAGE_CUR_GE); - + /* As the cursor is now placed on a user record after a search with the mode PAGE_CUR_GE, the up_match field in the cursor tells how many - fields in the user record matched to the search tuple */ + fields in the user record matched to the search tuple */ if (btr_pcur_get_up_match(&(plan->pcur)) < plan->n_exact_match) { @@ -1062,7 +1064,7 @@ row_sel_try_search_shortcut( /* This is a non-locking consistent read: if necessary, fetch a previous version of the record */ - + offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); if (index->type & DICT_CLUSTERED) { @@ -1082,14 +1084,14 @@ row_sel_try_search_shortcut( row_sel_fetch_columns(index, rec, offsets, UT_LIST_GET_FIRST(plan->columns)); - if (rec_get_deleted_flag(rec, plan->table->comp)) { + if (rec_get_deleted_flag(rec, dict_table_is_comp(plan->table))) { ret = SEL_EXHAUSTED; goto func_exit; } /* Test the rest of search conditions */ - + if (!row_sel_test_other_conds(plan)) { ret = SEL_EXHAUSTED; @@ -1125,7 +1127,7 @@ row_sel( rec_t* clust_rec; ibool search_latch_locked; ibool consistent_read; - + /* The following flag becomes TRUE when we are doing a consistent read from a non-clustered index and we must look at the clustered index to find out the previous delete mark @@ -1135,14 +1137,14 @@ row_sel( ulint cost_counter = 0; ibool cursor_just_opened; ibool must_go_to_next; - ibool leaf_contains_updates = FALSE; + ibool leaf_contains_updates = FALSE; /* TRUE if select_will_do_update is TRUE and the current clustered index leaf page has been updated during the current mtr: mtr must be committed at the same time as the leaf x-latch is released */ - ibool mtr_has_extra_clust_latch = FALSE; + ibool mtr_has_extra_clust_latch = FALSE; /* TRUE if the search was made using a non-clustered index, and we had to access the clustered record: now &mtr @@ -1203,7 +1205,7 @@ table_loop: } /* Open a cursor to index, or restore an open cursor position */ - + mtr_start(&mtr); if (consistent_read && plan->unique_search && !plan->pcur_is_open @@ -1235,7 +1237,7 @@ table_loop: goto table_exhausted; } - + ut_ad(found_flag == SEL_RETRY); plan_reset_cursor(plan); @@ -1270,11 +1272,11 @@ table_loop: if (must_go_to_next) { /* We have already processed the cursor record: move to the next */ - + goto next_rec; } } - + rec_loop: /* RECORD LOOP ----------- @@ -1287,11 +1289,11 @@ rec_loop: NOTE that if cursor_just_opened is TRUE here, it means that we came to this point right after row_sel_open_pcur. */ - + ut_ad(mtr_has_extra_clust_latch == FALSE); rec = btr_pcur_get_rec(&(plan->pcur)); - + /* PHASE 1: Set a lock if specified */ if (!node->asc && cursor_just_opened @@ -1302,7 +1304,7 @@ rec_loop: be possible to insert new records next to the cursor position, and it might be that these new records should appear in the search result set, resulting in the phantom problem. */ - + if (!consistent_read) { /* If innodb_locks_unsafe_for_binlog option is used, @@ -1327,7 +1329,7 @@ rec_loop: /* Note that in this case we will store in pcur the PREDECESSOR of the record we are waiting the lock for */ - + goto lock_wait_or_error; } } @@ -1346,7 +1348,7 @@ rec_loop: } if (!consistent_read) { - /* Try to place a lock on the index record */ + /* Try to place a lock on the index record */ /* If innodb_locks_unsafe_for_binlog option is used, we lock only the record, i.e., next-key locking is @@ -1382,7 +1384,7 @@ rec_loop: ut_ad(page_rec_is_user_rec(rec)); if (cost_counter > SEL_COST_LIMIT) { - + /* Now that we have placed the necessary locks, we can stop for a while and store the cursor position; NOTE that if we would store the cursor position BEFORE placing a record lock, @@ -1392,17 +1394,17 @@ rec_loop: goto stop_for_a_while; } - + /* PHASE 2: Check a mixed index mix id if needed */ if (plan->unique_search && cursor_just_opened) { ut_ad(plan->mode == PAGE_CUR_GE); - + /* As the cursor is now placed on a user record after a search with the mode PAGE_CUR_GE, the up_match field in the cursor tells how many fields in the user record matched to the search - tuple */ + tuple */ if (btr_pcur_get_up_match(&(plan->pcur)) < plan->n_exact_match) { @@ -1412,13 +1414,13 @@ rec_loop: /* Ok, no need to test end_conds or mix id */ } else if (plan->mixed_index) { - /* We have to check if the record in a mixed cluster belongs - to this table */ + /* We have to check if the record in a mixed cluster belongs + to this table */ - if (!dict_is_mixed_table_rec(plan->table, rec)) { + if (!dict_is_mixed_table_rec(plan->table, rec)) { - goto next_rec; - } + goto next_rec; + } } /* We are ready to look at a possible new index entry in the result @@ -1434,7 +1436,7 @@ rec_loop: a previous version of the record */ if (index->type & DICT_CLUSTERED) { - + if (!lock_clust_rec_cons_read_sees(rec, index, offsets, node->read_view)) { @@ -1452,8 +1454,8 @@ rec_loop: rec, index, offsets, ULINT_UNDEFINED, &heap); row_sel_fetch_columns(index, rec, - offsets, - UT_LIST_GET_FIRST(plan->columns)); + offsets, + UT_LIST_GET_FIRST(plan->columns)); if (!row_sel_test_end_conds(plan)) { @@ -1474,7 +1476,7 @@ rec_loop: /* PHASE 4: Test search end conditions and deleted flag */ /* Fetch the columns needed in test conditions */ - + row_sel_fetch_columns(index, rec, offsets, UT_LIST_GET_FIRST(plan->columns)); @@ -1491,7 +1493,7 @@ rec_loop: goto table_exhausted; } - if (rec_get_deleted_flag(rec, plan->table->comp) + if (rec_get_deleted_flag(rec, dict_table_is_comp(plan->table)) && !cons_read_requires_clust_rec) { /* The record is delete marked: we can skip it if this is @@ -1499,10 +1501,10 @@ rec_loop: of a non-clustered index record */ if (plan->unique_search) { - + goto table_exhausted; } - + goto next_rec; } @@ -1517,7 +1519,7 @@ rec_loop: err = row_sel_get_clust_rec(node, plan, rec, thr, &clust_rec, &mtr); mtr_has_extra_clust_latch = TRUE; - + if (err != DB_SUCCESS) { goto lock_wait_or_error; @@ -1535,7 +1537,8 @@ rec_loop: goto next_rec; } - if (rec_get_deleted_flag(clust_rec, plan->table->comp)) { + if (rec_get_deleted_flag(clust_rec, + dict_table_is_comp(plan->table))) { /* The record is delete marked: we can skip it */ @@ -1546,14 +1549,14 @@ rec_loop: btr_pcur_store_position(&(plan->clust_pcur), &mtr); } - } + } /* PHASE 6: Test the rest of search conditions */ - + if (!row_sel_test_other_conds(plan)) { if (plan->unique_search) { - + goto table_exhausted; } @@ -1562,7 +1565,7 @@ rec_loop: /* PHASE 7: We found a new qualifying row for the current table; push the row if prefetch is on, or move to the next table in the join */ - + plan->n_rows_fetched++; ut_ad(plan->pcur.latch_mode == node->latch_mode); @@ -1578,22 +1581,22 @@ rec_loop: /* When the database is in the online backup mode, the number of log records for a single mtr should be small: increment the cost counter to ensure it */ - + cost_counter += 1 + (SEL_COST_LIMIT / 8); if (plan->unique_search) { - goto table_exhausted; + goto table_exhausted; } goto next_rec; - } + } if ((plan->n_rows_fetched <= SEL_PREFETCH_LIMIT) || plan->unique_search || plan->no_prefetch) { /* No prefetch in operation: go to the next table */ - + goto next_table; } @@ -1602,13 +1605,13 @@ rec_loop: if (plan->n_rows_prefetched == SEL_MAX_N_PREFETCH) { /* The prefetch buffer is now full */ - + sel_pop_prefetched_row(plan); goto next_table; } -next_rec: +next_rec: ut_ad(!search_latch_locked); if (mtr_has_extra_clust_latch) { @@ -1620,7 +1623,7 @@ next_rec: goto commit_mtr_for_a_while; } - + if (leaf_contains_updates && btr_pcur_is_after_last_on_page(&(plan->pcur), &mtr)) { @@ -1641,7 +1644,7 @@ next_rec: } if (!moved) { - + goto table_exhausted; } @@ -1656,7 +1659,7 @@ next_table: the next table or return a row in the result set */ ut_ad(btr_pcur_is_on_user_rec(&(plan->pcur), &mtr)); - + if (plan->unique_search && !node->can_get_updated) { plan->cursor_at_end = TRUE; @@ -1676,18 +1679,18 @@ next_table: next_table_no_mtr: /* If we use 'goto' to this label, it means that the row was popped from the prefetched rows stack, and &mtr is already committed */ - + if (node->fetch_table + 1 == node->n_tables) { sel_eval_select_list(node); if (node->is_aggregate) { - goto table_loop; + goto table_loop; } sel_assign_into_var_values(node->into_list, node); - + thr->run_node = que_node_get_parent(node); if (search_latch_locked) { @@ -1702,14 +1705,14 @@ next_table_no_mtr: /* When we move to the next table, we first reset the plan cursor: we do not care about resetting it when we backtrack from a table */ - + plan_reset_cursor(sel_node_get_nth_plan(node, node->fetch_table)); - + goto table_loop; table_exhausted: /* The table cursor pcur reached the result set end: backtrack to the - previous table in the join if we do not have cached prefetched rows */ + previous table in the join if we do not have cached prefetched rows */ plan->cursor_at_end = TRUE; @@ -1717,10 +1720,10 @@ table_exhausted: leaf_contains_updates = FALSE; mtr_has_extra_clust_latch = FALSE; - + if (plan->n_rows_prefetched > 0) { /* The table became exhausted during a prefetch */ - + sel_pop_prefetched_row(plan); goto next_table_no_mtr; @@ -1741,18 +1744,18 @@ table_exhausted_no_mtr: if (search_latch_locked) { rw_lock_s_unlock(&btr_search_latch); } - + goto func_exit; } node->state = SEL_NODE_NO_MORE_ROWS; - + thr->run_node = que_node_get_parent(node); if (search_latch_locked) { rw_lock_s_unlock(&btr_search_latch); } - + goto func_exit; } @@ -1767,7 +1770,7 @@ stop_for_a_while: record lock on the cursor record or its successor: when we reposition the cursor, this record lock guarantees that nobody can meanwhile have inserted new records which should have appeared in the result set, - which would result in the phantom problem. */ + which would result in the phantom problem. */ ut_ad(!search_latch_locked); @@ -1775,7 +1778,7 @@ stop_for_a_while: btr_pcur_store_position(&(plan->pcur), &mtr); mtr_commit(&mtr); - + ut_ad(sync_thread_levels_empty_gen(TRUE)); err = DB_SUCCESS; goto func_exit; @@ -1783,7 +1786,7 @@ stop_for_a_while: commit_mtr_for_a_while: /* Stores the cursor position and commits &mtr; this is used if &mtr may contain latches which would break the latching order if - &mtr would not be committed and the latches released. */ + &mtr would not be committed and the latches released. */ plan->stored_cursor_rec_processed = TRUE; @@ -1794,7 +1797,7 @@ commit_mtr_for_a_while: leaf_contains_updates = FALSE; mtr_has_extra_clust_latch = FALSE; - + ut_ad(sync_thread_levels_empty_gen(TRUE)); goto table_loop; @@ -1808,9 +1811,9 @@ lock_wait_or_error: plan->stored_cursor_rec_processed = FALSE; btr_pcur_store_position(&(plan->pcur), &mtr); - + mtr_commit(&mtr); - + ut_ad(sync_thread_levels_empty_gen(TRUE)); func_exit: @@ -1836,7 +1839,7 @@ row_sel_step( ulint err; ut_ad(thr); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_SELECT); @@ -1869,23 +1872,23 @@ row_sel_step( } else { i_lock_mode = LOCK_IS; } - + table_node = node->table_list; - + while (table_node) { err = lock_table(0, table_node->table, i_lock_mode, thr); if (err != DB_SUCCESS) { - + que_thr_handle_error(thr, DB_ERROR, NULL, 0); return(NULL); } - + table_node = que_node_get_next(table_node); } } - + /* If this is an explicit cursor, copy stored procedure variable values, so that the values cannot change between fetches (currently, we copy them also for non-explicit @@ -1896,7 +1899,7 @@ row_sel_step( row_sel_copy_input_variable_vals(node); } - + node->state = SEL_NODE_FETCH; node->fetch_table = 0; @@ -1911,7 +1914,7 @@ row_sel_step( /* NOTE! if queries are parallelized, the following assignment may have problems; the assignment should be made only if thr is the only top-level thr in the graph: */ - + thr->graph->last_sel_node = node; if (err == DB_SUCCESS) { @@ -1930,7 +1933,7 @@ row_sel_step( } return(thr); -} +} /************************************************************************** Performs a fetch for a cursor. */ @@ -1945,16 +1948,16 @@ fetch_step( fetch_node_t* node; ut_ad(thr); - + node = thr->run_node; sel_node = node->cursor_def; - + ut_ad(que_node_get_type(node) == QUE_NODE_FETCH); if (thr->prev_node != que_node_get_parent(node)) { if (sel_node->state != SEL_NODE_NO_MORE_ROWS) { - + sel_assign_into_var_values(node->into_list, sel_node); } @@ -1967,9 +1970,9 @@ fetch_step( the time of the fetch, so that execution knows to return to this fetch node after a row has been selected or we know that there is no row left */ - + sel_node->common.parent = node; - + if (sel_node->state == SEL_NODE_CLOSED) { /* SQL error detected */ fprintf(stderr, "SQL error %lu\n", (ulong)DB_ERROR); @@ -1982,7 +1985,7 @@ fetch_step( thr->run_node = sel_node; return(thr); -} +} /*************************************************************** Prints a row in a select result. */ @@ -1998,22 +2001,22 @@ row_printf_step( que_node_t* arg; ut_ad(thr); - + node = thr->run_node; - + sel_node = node->sel_node; ut_ad(que_node_get_type(node) == QUE_NODE_ROW_PRINTF); if (thr->prev_node == que_node_get_parent(node)) { - + /* Reset the cursor */ sel_node->state = SEL_NODE_OPEN; /* Fetch next row to print */ thr->run_node = sel_node; - + return(thr); } @@ -2024,7 +2027,7 @@ row_printf_step( /* No more rows to print */ thr->run_node = que_node_get_parent(node); - + return(thr); } @@ -2045,7 +2048,7 @@ row_printf_step( thr->run_node = sel_node; return(thr); -} +} /******************************************************************** Converts a key value stored in MySQL format to an Innobase dtuple. The last @@ -2081,14 +2084,14 @@ row_sel_convert_mysql_key_to_innobase( byte* key_end; ulint n_fields = 0; ulint type; - + /* For documentation of the key value storage format in MySQL, see ha_innobase::store_key_val_for_row() in ha_innodb.cc. */ key_end = key_ptr + key_len; /* Permit us to access any field in the tuple (ULINT_MAX): */ - + dtuple_set_n_fields(tuple, ULINT_MAX); dfield = dtuple_get_nth_field(tuple, 0); @@ -2104,7 +2107,7 @@ row_sel_convert_mysql_key_to_innobase( ut_a(key_len == DATA_ROW_ID_LEN); dfield_set_data(dfield, key_ptr, DATA_ROW_ID_LEN); - + dtuple_set_n_fields(tuple, 1); return; @@ -2113,28 +2116,28 @@ row_sel_convert_mysql_key_to_innobase( while (key_ptr < key_end) { ut_a(dict_col_get_type(field->col)->mtype - == dfield_get_type(dfield)->mtype); + == dfield_get_type(dfield)->mtype); data_offset = 0; is_null = FALSE; - if (!(dfield_get_type(dfield)->prtype & DATA_NOT_NULL)) { - /* The first byte in the field tells if this is - an SQL NULL value */ - + if (!(dfield_get_type(dfield)->prtype & DATA_NOT_NULL)) { + /* The first byte in the field tells if this is + an SQL NULL value */ + data_offset = 1; - if (*key_ptr != 0) { - dfield_set_data(dfield, NULL, UNIV_SQL_NULL); + if (*key_ptr != 0) { + dfield_set_data(dfield, NULL, UNIV_SQL_NULL); is_null = TRUE; - } - } + } + } type = dfield_get_type(dfield)->mtype; /* Calculate data length and data field total length */ - + if (type == DATA_BLOB) { /* The key field is a column prefix of a BLOB or TEXT */ @@ -2171,16 +2174,16 @@ row_sel_convert_mysql_key_to_innobase( with the full prefix_len bytes. How do characters 0xff in UTF-8 behave? */ - data_len = field->prefix_len; + data_len = field->prefix_len; data_field_len = data_offset + data_len; } else { data_len = dfield_get_type(dfield)->len; data_field_len = data_offset + data_len; } - if (dtype_get_mysql_type(dfield_get_type(dfield)) + if (dtype_get_mysql_type(dfield_get_type(dfield)) == DATA_MYSQL_TRUE_VARCHAR - && dfield_get_type(dfield)->mtype != DATA_INT) { + && dfield_get_type(dfield)->mtype != DATA_INT) { /* In a MySQL key value format, a true VARCHAR is always preceded by 2 bytes of a length field. dfield_get_type(dfield)->len returns the maximum @@ -2195,32 +2198,32 @@ row_sel_convert_mysql_key_to_innobase( } /* Storing may use at most data_len bytes of buf */ - + if (!is_null) { - row_mysql_store_col_in_innobase_format( + row_mysql_store_col_in_innobase_format( dfield, buf, FALSE, /* MySQL key value format col */ key_ptr + data_offset, data_len, - index->table->comp); + dict_table_is_comp(index->table)); buf += data_len; } - key_ptr += data_field_len; + key_ptr += data_field_len; if (key_ptr > key_end) { /* The last field in key was not a complete key field but a prefix of it. - Print a warning about this! HA_READ_PREFIX_LAST does + Print a warning about this! HA_READ_PREFIX_LAST does not currently work in InnoDB with partial-field key value prefixes. Since MySQL currently uses a padding trick to calculate LIKE 'abc%' type queries there should never be partial-field prefixes in searches. */ - ut_print_timestamp(stderr); - + ut_print_timestamp(stderr); + fputs( " InnoDB: Warning: using a partial-field key prefix in search.\n" "InnoDB: ", stderr); @@ -2235,21 +2238,21 @@ row_sel_convert_mysql_key_to_innobase( fprintf(stderr, "\n"); if (!is_null) { - dfield->len -= (ulint)(key_ptr - key_end); + dfield->len -= (ulint)(key_ptr - key_end); } } - n_fields++; - field++; + n_fields++; + field++; dfield++; - } + } ut_a(buf <= original_buf + buf_len); - /* We set the length of tuple to n_fields: we assume that the memory + /* We set the length of tuple to n_fields: we assume that the memory area allocated for it is big enough (usually bigger than n_fields). */ - - dtuple_set_n_fields(tuple, n_fields); + + dtuple_set_n_fields(tuple, n_fields); } /****************************************************************** @@ -2273,12 +2276,13 @@ row_sel_store_row_id_to_prebuilt( dict_index_get_sys_col_pos(index, DATA_ROW_ID), &len); if (len != DATA_ROW_ID_LEN) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: Row id field is wrong length %lu in ", (ulong) len); dict_index_name_print(stderr, prebuilt->trx, index); fprintf(stderr, "\n" "InnoDB: Field number %lu, record:\n", - (ulong) dict_index_get_sys_col_pos(index, DATA_ROW_ID)); + (ulong) dict_index_get_sys_col_pos(index, + DATA_ROW_ID)); rec_print_new(stderr, index_rec, offsets); putc('\n', stderr); ut_error; @@ -2331,7 +2335,7 @@ row_sel_field_store_in_mysql_format( ut_ad(templ->mysql_col_len == len); } else if (templ->type == DATA_VARCHAR - || templ->type == DATA_VARMYSQL + || templ->type == DATA_VARMYSQL || templ->type == DATA_BINARY) { field_end = dest + templ->mysql_col_len; @@ -2340,18 +2344,18 @@ row_sel_field_store_in_mysql_format( /* This is a >= 5.0.3 type true VARCHAR. Store the length of the data to the first byte or the first two bytes of dest. */ - + dest = row_mysql_store_true_var_len(dest, len, templ->mysql_length_bytes); } /* Copy the actual data */ ut_memcpy(dest, data, len); - + /* Pad with trailing spaces. We pad with spaces also the unused end of a >= 5.0.3 true VARCHAR column, just in case MySQL expects its contents to be deterministic. */ - + pad_ptr = dest + len; ut_ad(templ->mbminlen <= templ->mbmaxlen); @@ -2363,13 +2367,13 @@ row_sel_field_store_in_mysql_format( if (len & 1) { /* A 0x20 has been stripped from the column. Pad it back. */ - + if (pad_ptr < field_end) { *pad_ptr = 0x20; pad_ptr++; } } - + /* Pad the rest of the string with 0x0020 */ while (pad_ptr < field_end) { @@ -2393,16 +2397,18 @@ row_sel_field_store_in_mysql_format( } else if (templ->type == DATA_MYSQL) { memcpy(dest, data, len); +#if defined(UNIV_RELEASE_NOT_YET_STABLE) || defined(UNIV_DEBUG) ut_a(templ->mysql_col_len >= len); ut_a(templ->mbmaxlen >= templ->mbminlen); ut_a(templ->mbmaxlen > templ->mbminlen || templ->mysql_col_len == len); + ut_a(len * templ->mbmaxlen >= templ->mysql_col_len); +#endif /* UNIV_RELEASE_NOT_YET_STABLE || UNIV_DEBUG */ /* The following assertion would fail for old tables containing UTF-8 ENUM columns due to Bug #9526. */ ut_ad(!templ->mbmaxlen || !(templ->mysql_col_len % templ->mbmaxlen)); - ut_a(len * templ->mbmaxlen >= templ->mysql_col_len); if (templ->mbminlen != templ->mbmaxlen) { /* Pad with spaces. This undoes the stripping @@ -2412,6 +2418,7 @@ row_sel_field_store_in_mysql_format( memset(dest + len, 0x20, templ->mysql_col_len - len); } } else { +#if defined(UNIV_RELEASE_NOT_YET_STABLE) || defined(UNIV_DEBUG) ut_a(templ->type == DATA_CHAR || templ->type == DATA_FIXBINARY /*|| templ->type == DATA_SYS_CHILD @@ -2419,6 +2426,7 @@ row_sel_field_store_in_mysql_format( || templ->type == DATA_FLOAT || templ->type == DATA_DOUBLE || templ->type == DATA_DECIMAL); +#endif /* UNIV_RELEASE_NOT_YET_STABLE || UNIV_DEBUG */ ut_ad(templ->mysql_col_len == len); memcpy(dest, data, len); @@ -2451,7 +2459,7 @@ row_sel_store_mysql_rec( byte* data; ulint len; ulint i; - + ut_ad(prebuilt->mysql_template); ut_ad(rec_offs_validate(rec, NULL, offsets)); @@ -2499,8 +2507,8 @@ row_sel_store_mysql_rec( CPU time, we do not use it for small BLOBs. */ if (UNIV_UNLIKELY(len > 2000000) - && UNIV_UNLIKELY(!ut_test_malloc( - len + 1000000))) { + && UNIV_UNLIKELY(!ut_test_malloc( + len + 1000000))) { ut_print_timestamp(stderr); fprintf(stderr, @@ -2530,17 +2538,17 @@ row_sel_store_mysql_rec( prebuilt->blob_heap, len), data, len); } - + row_sel_field_store_in_mysql_format( mysql_rec + templ->mysql_col_offset, templ, data, len); /* Cleanup */ if (extern_field_heap) { - mem_heap_free(extern_field_heap); + mem_heap_free(extern_field_heap); extern_field_heap = NULL; - } - + } + if (templ->mysql_null_bit_mask) { /* It is a nullable column with a non-NULL value */ @@ -2548,11 +2556,11 @@ row_sel_store_mysql_rec( ~(byte) (templ->mysql_null_bit_mask); } } else { - /* MySQL seems to assume the field for an SQL NULL - value is set to zero or space. Not taking this into + /* MySQL seems to assume the field for an SQL NULL + value is set to zero or space. Not taking this into account caused seg faults with NULL BLOB fields, and - bug number 154 in the MySQL bug database: GROUP BY - and DISTINCT could treat NULL values inequal. */ + bug number 154 in the MySQL bug database: GROUP BY + and DISTINCT could treat NULL values inequal. */ int pad_char; mysql_rec[templ->mysql_null_byte_offset] |= @@ -2562,7 +2570,7 @@ row_sel_store_mysql_rec( case DATA_BINARY: case DATA_VARMYSQL: if (templ->mysql_type - == DATA_MYSQL_TRUE_VARCHAR) { + == DATA_MYSQL_TRUE_VARCHAR) { /* This is a >= 5.0.3 type true VARCHAR. Zero the field. */ pad_char = 0x00; @@ -2572,7 +2580,7 @@ row_sel_store_mysql_rec( case DATA_CHAR: case DATA_FIXBINARY: case DATA_MYSQL: - /* MySQL pads all string types (except + /* MySQL pads all string types (except BLOB, TEXT and true VARCHAR) with space. */ if (UNIV_UNLIKELY(templ->mbminlen == 2)) { /* Treat UCS2 as a special case. */ @@ -2601,7 +2609,7 @@ row_sel_store_mysql_rec( memset(mysql_rec + templ->mysql_col_offset, pad_char, templ->mysql_col_len); } - } + } return(TRUE); } @@ -2634,7 +2642,7 @@ row_sel_build_prev_vers_for_mysql( } else { prebuilt->old_vers_heap = mem_heap_create(200); } - + err = row_vers_build_for_consistent_read(rec, mtr, clust_index, offsets, read_view, offset_heap, prebuilt->old_vers_heap, old_vers); @@ -2677,11 +2685,11 @@ row_sel_get_clust_rec_for_mysql( *out_rec = NULL; trx = thr_get_trx(thr); - + row_build_row_ref_in_tuple(prebuilt->clust_ref, sec_index, rec, trx); clust_index = dict_table_get_first_index(sec_index->table); - + btr_pcur_open_with_no_init(clust_index, prebuilt->clust_ref, PAGE_CUR_LE, BTR_SEARCH_LEAF, prebuilt->clust_pcur, 0, mtr); @@ -2694,9 +2702,9 @@ row_sel_get_clust_rec_for_mysql( low_match value the real match to the search tuple */ if (!page_rec_is_user_rec(clust_rec) - || btr_pcur_get_low_match(prebuilt->clust_pcur) - < dict_index_get_n_unique(clust_index)) { - + || btr_pcur_get_low_match(prebuilt->clust_pcur) + < dict_index_get_n_unique(clust_index)) { + /* In a rare case it is possible that no clust rec is found for a delete-marked secondary index record: if in row0umod.c in row_undo_mod_remove_clust_low() we have already removed @@ -2706,9 +2714,10 @@ row_sel_get_clust_rec_for_mysql( clustered index record did not exist in the read view of trx. */ - if (!rec_get_deleted_flag(rec, sec_index->table->comp) - || prebuilt->select_lock_type != LOCK_NONE) { - ut_print_timestamp(stderr); + if (!rec_get_deleted_flag(rec, + dict_table_is_comp(sec_index->table)) + || prebuilt->select_lock_type != LOCK_NONE) { + ut_print_timestamp(stderr); fputs(" InnoDB: error clustered record" " for sec rec not found\n" "InnoDB: ", stderr); @@ -2738,7 +2747,7 @@ row_sel_get_clust_rec_for_mysql( /* Try to place a lock on the index record; we are searching the clust rec with a unique condition, hence we set a LOCK_REC_NOT_GAP type lock */ - + err = lock_clust_rec_read_check_and_lock(0, clust_rec, clust_index, *offsets, prebuilt->select_lock_type, @@ -2757,9 +2766,9 @@ row_sel_get_clust_rec_for_mysql( then we never look for an earlier version */ if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED - && !lock_clust_rec_cons_read_sees(clust_rec, clust_index, - *offsets, trx->read_view)) { - + && !lock_clust_rec_cons_read_sees(clust_rec, + clust_index, *offsets, trx->read_view)) { + /* The following call returns 'offsets' associated with 'old_vers' */ err = row_sel_build_prev_vers_for_mysql( @@ -2767,7 +2776,7 @@ row_sel_get_clust_rec_for_mysql( prebuilt, clust_rec, offsets, offset_heap, &old_vers, mtr); - + if (err != DB_SUCCESS) { goto err_exit; @@ -2788,18 +2797,19 @@ row_sel_get_clust_rec_for_mysql( a wrong result if we would not drop rows which we come to visit through secondary index records that would not really exist in our snapshot. */ - + if (clust_rec && (old_vers - || rec_get_deleted_flag(rec, sec_index->table->comp)) - && !row_sel_sec_rec_is_for_clust_rec(rec, sec_index, - clust_rec, clust_index)) { + || rec_get_deleted_flag(rec, + dict_table_is_comp(sec_index->table))) + && !row_sel_sec_rec_is_for_clust_rec(rec, sec_index, + clust_rec, clust_index)) { clust_rec = NULL; } else { #ifdef UNIV_SEARCH_DEBUG ut_a(clust_rec == NULL || - row_sel_sec_rec_is_for_clust_rec(rec, sec_index, - clust_rec, clust_index)); -#endif + row_sel_sec_rec_is_for_clust_rec(rec, + sec_index, clust_rec, clust_index)); +#endif } } @@ -2808,7 +2818,7 @@ func_exit: if (prebuilt->select_lock_type == LOCK_X) { /* We may use the cursor in update: store its position */ - + btr_pcur_store_position(prebuilt->clust_pcur, mtr); } @@ -2846,7 +2856,7 @@ sel_restore_position_for_mysql( ulint relative_position; relative_position = pcur->rel_pos; - + success = btr_pcur_restore_position(latch_mode, pcur, mtr); *same_user_rec = success; @@ -2864,12 +2874,12 @@ sel_restore_position_for_mysql( } if (relative_position == BTR_PCUR_AFTER - || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE) { + || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE) { if (moves_up) { return(TRUE); } - + if (btr_pcur_is_on_user_rec(pcur, mtr)) { btr_pcur_move_to_prev(pcur, mtr); } @@ -2878,8 +2888,8 @@ sel_restore_position_for_mysql( } ut_ad(relative_position == BTR_PCUR_BEFORE - || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE); - + || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE); + if (moves_up && btr_pcur_is_on_user_rec(pcur, mtr)) { btr_pcur_move_to_next(pcur, mtr); } @@ -2900,26 +2910,24 @@ row_sel_pop_cached_row_for_mysql( ulint i; mysql_row_templ_t* templ; byte* cached_rec; - ut_ad(prebuilt->n_fetch_cached > 0); + ut_ad(prebuilt->n_fetch_cached > 0); ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len); - - if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) - { - /* Copy cache record field by field, don't touch fields that + + if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) { + /* Copy cache record field by field, don't touch fields that are not covered by current key */ - cached_rec = + cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first]; for (i = 0; i < prebuilt->n_template; i++) { templ = prebuilt->mysql_template + i; ut_memcpy( - buf + templ->mysql_col_offset, + buf + templ->mysql_col_offset, cached_rec + templ->mysql_col_offset, templ->mysql_col_len); - /* Copy NULL bit of the current field from cached_rec + /* Copy NULL bit of the current field from cached_rec to buf */ - if (templ->mysql_null_bit_mask) - { + if (templ->mysql_null_bit_mask) { buf[templ->mysql_null_byte_offset] ^= (buf[templ->mysql_null_byte_offset] ^ cached_rec[templ->mysql_null_byte_offset]) & @@ -2927,8 +2935,7 @@ row_sel_pop_cached_row_for_mysql( } } } - else - { + else { ut_memcpy(buf, prebuilt->fetch_cache[prebuilt->fetch_cache_first], prebuilt->mysql_prefix_len); } @@ -2965,11 +2972,11 @@ row_sel_push_cache_row_for_mysql( /* A user has reported memory corruption in these buffers in Linux. Put magic numbers there to help to track a possible bug. */ - + buf = mem_alloc(prebuilt->mysql_row_len + 8); prebuilt->fetch_cache[i] = buf + 4; - + mach_write_to_4(buf, ROW_PREBUILT_FETCH_MAGIC_N); mach_write_to_4(buf + 4 + prebuilt->mysql_row_len, ROW_PREBUILT_FETCH_MAGIC_N); @@ -3008,10 +3015,10 @@ row_sel_try_search_shortcut_for_mysql( btr_pcur_t* pcur = prebuilt->pcur; trx_t* trx = prebuilt->trx; rec_t* rec; - + ut_ad(index->type & DICT_CLUSTERED); ut_ad(!prebuilt->templ_contains_blob); - + btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, pcur, #ifndef UNIV_SEARCH_DEBUG @@ -3021,7 +3028,7 @@ row_sel_try_search_shortcut_for_mysql( #endif mtr); rec = btr_pcur_get_rec(pcur); - + if (!page_rec_is_user_rec(rec)) { return(SEL_RETRY); @@ -3029,7 +3036,7 @@ row_sel_try_search_shortcut_for_mysql( /* As the cursor is now placed on a user record after a search with the mode PAGE_CUR_GE, the up_match field in the cursor tells how many - fields in the user record matched to the search tuple */ + fields in the user record matched to the search tuple */ if (btr_pcur_get_up_match(pcur) < dtuple_get_n_fields(search_tuple)) { @@ -3048,13 +3055,13 @@ row_sel_try_search_shortcut_for_mysql( return(SEL_RETRY); } - if (rec_get_deleted_flag(rec, index->table->comp)) { + if (rec_get_deleted_flag(rec, dict_table_is_comp(index->table))) { return(SEL_EXHAUSTED); } *out_rec = rec; - + return(SEL_FOUND); } @@ -3069,7 +3076,7 @@ ulint row_search_for_mysql( /*=================*/ /* out: DB_SUCCESS, - DB_RECORD_NOT_FOUND, + DB_RECORD_NOT_FOUND, DB_END_OF_INDEX, DB_DEADLOCK, DB_LOCK_TABLE_FULL, DB_CORRUPTION, or DB_TOO_BIG_RECORD */ @@ -3084,7 +3091,7 @@ row_search_for_mysql( the end of the index, depending on 'mode' */ ulint match_mode, /* in: 0 or ROW_SEL_EXACT or - ROW_SEL_EXACT_PREFIX */ + ROW_SEL_EXACT_PREFIX */ ulint direction) /* in: 0 or ROW_SEL_NEXT or ROW_SEL_PREV; NOTE: if this is != 0, then prebuilt must have a pcur @@ -3092,7 +3099,7 @@ row_search_for_mysql( cursor 'direction' should be 0. */ { dict_index_t* index = prebuilt->index; - ibool comp = index->table->comp; + ibool comp = dict_table_is_comp(index->table); dtuple_t* search_tuple = prebuilt->search_tuple; btr_pcur_t* pcur = prebuilt->pcur; trx_t* trx = prebuilt->trx; @@ -3104,8 +3111,8 @@ row_search_for_mysql( ulint err = DB_SUCCESS; ibool unique_search = FALSE; ibool unique_search_from_clust_index = FALSE; - ibool mtr_has_extra_clust_latch = FALSE; - ibool moves_up = FALSE; + ibool mtr_has_extra_clust_latch = FALSE; + ibool moves_up = FALSE; ibool set_also_gap_locks = TRUE; /* if the query is a plain locking SELECT, and the isolation @@ -3132,8 +3139,8 @@ row_search_for_mysql( ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Error:\n" + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Error:\n" "InnoDB: MySQL is trying to use a table handle but the .ibd file for\n" "InnoDB: table %s does not exist.\n" "InnoDB: Have you deleted the .ibd file from the database directory under\n" @@ -3154,13 +3161,13 @@ row_search_for_mysql( ut_print_name(stderr, trx, prebuilt->table->name); putc('\n', stderr); - mem_analyze_corruption((byte*)prebuilt); + mem_analyze_corruption(prebuilt); ut_error; } if (trx->n_mysql_tables_in_use == 0 - && UNIV_UNLIKELY(prebuilt->select_lock_type == LOCK_NONE)) { + && UNIV_UNLIKELY(prebuilt->select_lock_type == LOCK_NONE)) { /* Note that if MySQL uses an InnoDB temp table that it created inside LOCK TABLES, then n_mysql_tables_in_use can be zero; in that case select_lock_type is set to LOCK_X in @@ -3172,16 +3179,16 @@ cursor lock count is done correctly. See bugs #12263 and #12456! fputs( "InnoDB: Error: MySQL is trying to perform a SELECT\n" "InnoDB: but it has not locked any tables in ::external_lock()!\n", - stderr); +stderr); trx_print(stderr, trx, 600); - fputc('\n', stderr); + fputc('\n', stderr); */ } /* fprintf(stderr, "Match mode %lu\n search tuple ", (ulong) match_mode); dtuple_print(search_tuple); - + fprintf(stderr, "N tables locked %lu\n", trx->mysql_n_tables_locked); */ /*-------------------------------------------------------------*/ @@ -3189,7 +3196,7 @@ cursor lock count is done correctly. See bugs #12263 and #12456! adaptive hash index latch if there is someone waiting behind */ if (UNIV_UNLIKELY(btr_search_latch.writer != RW_LOCK_NOT_LOCKED) - && trx->has_search_latch) { + && trx->has_search_latch) { /* There is an x-latch request on the adaptive hash index: release the s-latch to reduce starvation and wait for @@ -3201,13 +3208,13 @@ cursor lock count is done correctly. See bugs #12263 and #12456! trx->search_latch_timeout = BTR_SEA_TIMEOUT; } - + /* Reset the new record lock info if srv_locks_unsafe_for_binlog is set. Then we are able to remove the record locks set here on an individual row. */ if (srv_locks_unsafe_for_binlog - && prebuilt->select_lock_type != LOCK_NONE) { + && prebuilt->select_lock_type != LOCK_NONE) { trx_reset_new_rec_lock_info(trx); } @@ -3217,7 +3224,7 @@ cursor lock count is done correctly. See bugs #12263 and #12456! if (UNIV_UNLIKELY(direction == 0)) { trx->op_info = "starting index read"; - + prebuilt->n_rows_fetched = 0; prebuilt->n_fetch_cached = 0; prebuilt->fetch_cache_first = 0; @@ -3241,7 +3248,7 @@ cursor lock count is done correctly. See bugs #12263 and #12456! or better: prevent caching for a scroll cursor! */ } - + prebuilt->n_rows_fetched = 0; prebuilt->n_fetch_cached = 0; prebuilt->fetch_cache_first = 0; @@ -3257,16 +3264,16 @@ cursor lock count is done correctly. See bugs #12263 and #12456! } if (prebuilt->fetch_cache_first > 0 - && prebuilt->fetch_cache_first < MYSQL_FETCH_CACHE_SIZE) { + && prebuilt->fetch_cache_first < MYSQL_FETCH_CACHE_SIZE) { - /* The previous returned row was popped from the fetch - cache, but the cache was not full at the time of the - popping: no more rows can exist in the result set */ + /* The previous returned row was popped from the fetch + cache, but the cache was not full at the time of the + popping: no more rows can exist in the result set */ err = DB_RECORD_NOT_FOUND; goto func_exit; } - + prebuilt->n_rows_fetched++; if (prebuilt->n_rows_fetched > 1000000000) { @@ -3285,13 +3292,13 @@ cursor lock count is done correctly. See bugs #12263 and #12456! marked versions of a record where only the primary key values differ: thus in a secondary index we must use next-key locks when locking delete-marked records. */ - + if (match_mode == ROW_SEL_EXACT - && index->type & DICT_UNIQUE - && dtuple_get_n_fields(search_tuple) - == dict_index_get_n_unique(index) - && (index->type & DICT_CLUSTERED - || !dtuple_contains_null(search_tuple))) { + && index->type & DICT_UNIQUE + && dtuple_get_n_fields(search_tuple) + == dict_index_get_n_unique(index) + && (index->type & DICT_CLUSTERED + || !dtuple_contains_null(search_tuple))) { /* Note above that a UNIQUE secondary index can contain many rows with the same key value if one of the columns is the SQL @@ -3308,7 +3315,7 @@ cursor lock count is done correctly. See bugs #12263 and #12456! if (UNIV_UNLIKELY(direction != 0 && !prebuilt->used_in_HANDLER)) { - + err = DB_RECORD_NOT_FOUND; goto func_exit; } @@ -3326,20 +3333,20 @@ cursor lock count is done correctly. See bugs #12263 and #12456! may be long and there may be externally stored fields */ if (UNIV_UNLIKELY(direction == 0) - && unique_search - && index->type & DICT_CLUSTERED - && !prebuilt->templ_contains_blob - && !prebuilt->used_in_HANDLER - && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) { + && unique_search + && index->type & DICT_CLUSTERED + && !prebuilt->templ_contains_blob + && !prebuilt->used_in_HANDLER + && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) { mode = PAGE_CUR_GE; unique_search_from_clust_index = TRUE; if (trx->mysql_n_tables_locked == 0 - && prebuilt->select_lock_type == LOCK_NONE - && trx->isolation_level > TRX_ISO_READ_UNCOMMITTED - && trx->read_view) { + && prebuilt->select_lock_type == LOCK_NONE + && trx->isolation_level > TRX_ISO_READ_UNCOMMITTED + && trx->read_view) { /* This is a SELECT query done as a consistent read, and the read view has already been allocated: @@ -3353,7 +3360,7 @@ cursor lock count is done correctly. See bugs #12263 and #12456! and if we try that, we can deadlock on the adaptive hash index semaphore! */ -#ifndef UNIV_SEARCH_DEBUG +#ifndef UNIV_SEARCH_DEBUG if (!trx->has_search_latch) { rw_lock_s_lock(&btr_search_latch); trx->has_search_latch = TRUE; @@ -3365,49 +3372,49 @@ cursor lock count is done correctly. See bugs #12263 and #12456! #ifdef UNIV_SEARCH_DEBUG ut_a(0 == cmp_dtuple_rec(search_tuple, rec, offsets)); -#endif +#endif if (!row_sel_store_mysql_rec(buf, prebuilt, rec, offsets)) { - err = DB_TOO_BIG_RECORD; + err = DB_TOO_BIG_RECORD; /* We let the main loop to do the error handling */ - goto shortcut_fails_too_big_rec; + goto shortcut_fails_too_big_rec; } - - mtr_commit(&mtr); + + mtr_commit(&mtr); /* ut_print_name(stderr, index->name); fputs(" shortcut\n", stderr); */ srv_n_rows_read++; - + if (trx->search_latch_timeout > 0 - && trx->has_search_latch) { + && trx->has_search_latch) { trx->search_latch_timeout--; - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(&btr_search_latch); trx->has_search_latch = FALSE; - } - + } + /* NOTE that we do NOT store the cursor position */ err = DB_SUCCESS; goto func_exit; case SEL_EXHAUSTED: - mtr_commit(&mtr); + mtr_commit(&mtr); /* ut_print_name(stderr, index->name); fputs(" record not found 2\n", stderr); */ if (trx->search_latch_timeout > 0 - && trx->has_search_latch) { + && trx->has_search_latch) { trx->search_latch_timeout--; - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(&btr_search_latch); trx->has_search_latch = FALSE; } @@ -3429,16 +3436,16 @@ shortcut_fails_too_big_rec: if (trx->has_search_latch) { rw_lock_s_unlock(&btr_search_latch); trx->has_search_latch = FALSE; - } + } trx_start_if_not_started(trx); if (trx->isolation_level <= TRX_ISO_READ_COMMITTED - && prebuilt->select_lock_type != LOCK_NONE - && trx->mysql_query_str) { + && prebuilt->select_lock_type != LOCK_NONE + && trx->mysql_query_str) { /* Scan the MySQL query string; check if SELECT is the first - word there */ + word there */ ibool success; dict_accept(*trx->mysql_query_str, "SELECT", &success); @@ -3450,11 +3457,11 @@ shortcut_fails_too_big_rec: set_also_gap_locks = FALSE; } } - + /* Note that if the search mode was GE or G, then the cursor naturally moves upward (in fetch next) in alphabetical order, otherwise downward */ - + if (UNIV_UNLIKELY(direction == 0)) { if (mode == PAGE_CUR_GE || mode == PAGE_CUR_G) { moves_up = TRUE; @@ -3516,24 +3523,24 @@ shortcut_fails_too_big_rec: /* No need to set an intention lock or assign a read view */ if (trx->read_view == NULL - && prebuilt->select_lock_type == LOCK_NONE) { + && prebuilt->select_lock_type == LOCK_NONE) { fputs( "InnoDB: Error: MySQL is trying to perform a consistent read\n" "InnoDB: but the read view is not assigned!\n", stderr); trx_print(stderr, trx, 600); - fputc('\n', stderr); + fputc('\n', stderr); ut_a(0); } } else if (prebuilt->select_lock_type == LOCK_NONE) { - /* This is a consistent read */ + /* This is a consistent read */ /* Assign a read view for the query */ trx_assign_read_view(trx); prebuilt->sql_stat_start = FALSE; } else { ulint lock_mode; - if (prebuilt->select_lock_type == LOCK_S) { + if (prebuilt->select_lock_type == LOCK_S) { lock_mode = LOCK_IS; } else { lock_mode = LOCK_IX; @@ -3550,7 +3557,7 @@ shortcut_fails_too_big_rec: rec_loop: /*-------------------------------------------------------------*/ /* PHASE 4: Look for matching records in a loop */ - + rec = btr_pcur_get_rec(pcur); ut_ad(!!page_rec_is_comp(rec) == comp); #ifdef UNIV_SEARCH_DEBUG @@ -3575,15 +3582,15 @@ rec_loop: if (page_rec_is_supremum(rec)) { if (set_also_gap_locks - && !srv_locks_unsafe_for_binlog - && prebuilt->select_lock_type != LOCK_NONE) { + && !srv_locks_unsafe_for_binlog + && prebuilt->select_lock_type != LOCK_NONE) { /* Try to place a lock on the index record */ /* If innodb_locks_unsafe_for_binlog option is used, we do not lock gaps. Supremum record is really a gap and therefore we do not set locks there. */ - + offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); err = sel_set_rec_lock(rec, index, offsets, @@ -3597,14 +3604,14 @@ rec_loop: } /* A page supremum record cannot be in the result set: skip it now that we have placed a possible lock on it */ - + goto next_rec; } /*-------------------------------------------------------------*/ /* Do sanity checks in case our cursor has bumped into page corruption */ - + if (comp) { next_offs = rec_get_next_offs(rec, TRUE); if (UNIV_UNLIKELY(next_offs < PAGE_NEW_SUPREMUM)) { @@ -3640,8 +3647,8 @@ wrong_offs: dict_index_name_print(stderr, trx, index); fputs(". Run CHECK TABLE. You may need to\n" "InnoDB: restore from a backup, or dump + drop + reimport the table.\n", - stderr); - + stderr); + err = DB_CORRUPTION; goto lock_wait_or_error; @@ -3697,14 +3704,14 @@ wrong_offs: in prebuilt: if not, then we return with DB_RECORD_NOT_FOUND */ /* fputs("Comparing rec and search tuple\n", stderr); */ - + if (0 != cmp_dtuple_rec(search_tuple, rec, offsets)) { if (set_also_gap_locks - && !srv_locks_unsafe_for_binlog - && prebuilt->select_lock_type != LOCK_NONE) { + && !srv_locks_unsafe_for_binlog + && prebuilt->select_lock_type != LOCK_NONE) { - /* Try to place a gap lock on the index + /* Try to place a gap lock on the index record only if innodb_locks_unsafe_for_binlog option is not set */ @@ -3723,19 +3730,19 @@ wrong_offs: err = DB_RECORD_NOT_FOUND; /* ut_print_name(stderr, index->name); fputs(" record not found 3\n", stderr); */ - + goto normal_return; } } else if (match_mode == ROW_SEL_EXACT_PREFIX) { if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec, offsets)) { - + if (set_also_gap_locks - && !srv_locks_unsafe_for_binlog - && prebuilt->select_lock_type != LOCK_NONE) { + && !srv_locks_unsafe_for_binlog + && prebuilt->select_lock_type != LOCK_NONE) { - /* Try to place a gap lock on the index + /* Try to place a gap lock on the index record only if innodb_locks_unsafe_for_binlog option is not set */ @@ -3775,9 +3782,9 @@ wrong_offs: ulint lock_type; if (!set_also_gap_locks - || srv_locks_unsafe_for_binlog - || (unique_search && !UNIV_UNLIKELY(rec_get_deleted_flag( - rec, comp)))) { + || srv_locks_unsafe_for_binlog + || (unique_search && !UNIV_UNLIKELY( + rec_get_deleted_flag(rec, comp)))) { goto no_gap_lock; } else { @@ -3796,11 +3803,11 @@ wrong_offs: need to lock the gap before that record. */ if (index == clust_index - && mode == PAGE_CUR_GE - && direction == 0 - && dtuple_get_n_fields_cmp(search_tuple) - == dict_index_get_n_unique(index) - && 0 == cmp_dtuple_rec(search_tuple, rec, offsets)) { + && mode == PAGE_CUR_GE + && direction == 0 + && dtuple_get_n_fields_cmp(search_tuple) + == dict_index_get_n_unique(index) + && 0 == cmp_dtuple_rec(search_tuple, rec, offsets)) { no_gap_lock: lock_type = LOCK_REC_NOT_GAP; } @@ -3815,8 +3822,8 @@ no_gap_lock: break; case DB_LOCK_WAIT: if (UNIV_LIKELY(prebuilt->row_read_type - != ROW_READ_TRY_SEMI_CONSISTENT) - || index != clust_index) { + != ROW_READ_TRY_SEMI_CONSISTENT) + || index != clust_index) { goto lock_wait_or_error; } @@ -3878,17 +3885,17 @@ no_gap_lock: /* Do nothing: we let a non-locking SELECT read the latest version of the record */ - + } else if (index == clust_index) { - + /* Fetch a previous version of the row if the current one is not visible in the snapshot; if we have a very high force recovery level set, we try to avoid crashes by skipping this lookup */ if (UNIV_LIKELY(srv_force_recovery < 5) - && !lock_clust_rec_cons_read_sees(rec, index, - offsets, trx->read_view)) { + && !lock_clust_rec_cons_read_sees(rec, index, + offsets, trx->read_view)) { rec_t* old_vers; /* The following call returns 'offsets' @@ -3898,7 +3905,7 @@ no_gap_lock: prebuilt, rec, &offsets, &heap, &old_vers, &mtr); - + if (err != DB_SUCCESS) { goto lock_wait_or_error; @@ -3937,15 +3944,15 @@ no_gap_lock: /* The record is delete-marked: we can skip it */ if (srv_locks_unsafe_for_binlog - && prebuilt->select_lock_type != LOCK_NONE - && !did_semi_consistent_read) { + && prebuilt->select_lock_type != LOCK_NONE + && !did_semi_consistent_read) { /* No need to keep a lock on a delete-marked record if we do not want to use next-key locking. */ row_unlock_for_mysql(prebuilt, TRUE); } - + goto next_rec; } @@ -3969,7 +3976,7 @@ requires_clust_rec: /* The following call returns 'offsets' associated with 'clust_rec'. Note that 'clust_rec' can be an old version built for a consistent read. */ - + err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec, thr, &clust_rec, &offsets, &heap, &mtr); @@ -3990,7 +3997,7 @@ requires_clust_rec: /* The record is delete marked: we can skip it */ if (srv_locks_unsafe_for_binlog - && prebuilt->select_lock_type != LOCK_NONE) { + && prebuilt->select_lock_type != LOCK_NONE) { /* No need to keep a lock on a delete-marked record if we do not want to use next-key @@ -4001,10 +4008,10 @@ requires_clust_rec: goto next_rec; } - + if (prebuilt->need_to_access_clustered) { - result_rec = clust_rec; + result_rec = clust_rec; ut_ad(rec_offs_validate(result_rec, clust_index, offsets)); @@ -4032,8 +4039,8 @@ requires_clust_rec: && !prebuilt->templ_contains_blob && !prebuilt->clust_index_was_generated && !prebuilt->used_in_HANDLER - && prebuilt->template_type - != ROW_MYSQL_DUMMY_TEMPLATE) { + && prebuilt->template_type + != ROW_MYSQL_DUMMY_TEMPLATE) { /* Inside an update, for example, we do not cache rows, since we may use the cursor position to do the actual @@ -4047,7 +4054,7 @@ requires_clust_rec: row_sel_push_cache_row_for_mysql(prebuilt, result_rec, offsets); if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) { - + goto got_row; } @@ -4085,13 +4092,13 @@ got_row: /* We have an optimization to save CPU time: if this is a consistent read on a unique condition on the clustered index, then we do not store the pcur position, because any fetch next or prev will anyway - return 'end of file'. An exception is the MySQL HANDLER command - where the user can move the cursor with PREV or NEXT even after - a unique search. */ + return 'end of file'. Exceptions are locking reads and the MySQL + HANDLER command where the user can move the cursor with PREV or NEXT + even after a unique search. */ if (!unique_search_from_clust_index - || prebuilt->select_lock_type != LOCK_NONE - || prebuilt->used_in_HANDLER) { + || prebuilt->select_lock_type != LOCK_NONE + || prebuilt->used_in_HANDLER) { /* Inside an update always store the cursor position */ @@ -4111,7 +4118,7 @@ next_rec: did_semi_consistent_read = FALSE; if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog) - && prebuilt->select_lock_type != LOCK_NONE) { + && prebuilt->select_lock_type != LOCK_NONE) { trx_reset_new_rec_lock_info(trx); } @@ -4129,7 +4136,7 @@ next_rec: mtr_commit(&mtr); mtr_has_extra_clust_latch = FALSE; - + mtr_start(&mtr); if (sel_restore_position_for_mysql(&same_user_rec, BTR_SEARCH_LEAF, @@ -4142,7 +4149,7 @@ next_rec: } } - if (moves_up) { + if (moves_up) { if (UNIV_UNLIKELY(!btr_pcur_move_to_next(pcur, &mtr))) { not_moved: btr_pcur_store_position(pcur, &mtr); @@ -4176,11 +4183,12 @@ lock_wait_or_error: did_semi_consistent_read = FALSE; /*-------------------------------------------------------------*/ + btr_pcur_store_position(pcur, &mtr); mtr_commit(&mtr); mtr_has_extra_clust_latch = FALSE; - + trx->error_state = err; /* The following is a patch for MySQL */ @@ -4217,7 +4225,7 @@ lock_wait_or_error: trx_reset_new_rec_lock_info(trx); } - + mode = pcur->search_mode; goto rec_loop; @@ -4289,7 +4297,7 @@ row_search_check_if_query_cache_permitted( '/' char, table name */ { dict_table_t* table; - ibool ret = FALSE; + ibool ret = FALSE; table = dict_table_get(norm_name, trx); @@ -4310,22 +4318,23 @@ row_search_check_if_query_cache_permitted( IX type locks actually would require ret = FALSE. */ if (UT_LIST_GET_LEN(table->locks) == 0 - && ut_dulint_cmp(trx->id, table->query_cache_inv_trx_id) >= 0) { + && ut_dulint_cmp(trx->id, + table->query_cache_inv_trx_id) >= 0) { ret = TRUE; - + /* If the isolation level is high, assign a read view for the transaction if it does not yet have one */ if (trx->isolation_level >= TRX_ISO_REPEATABLE_READ - && !trx->read_view) { + && !trx->read_view) { - trx->read_view = read_view_open_now(trx, + trx->read_view = read_view_open_now(trx->id, trx->global_read_view_heap); trx->global_read_view = trx->read_view; } } - + mutex_exit(&kernel_mutex); return(ret); diff --git a/storage/innobase/row/row0uins.c b/storage/innobase/row/row0uins.c index 9dc860d70b1..2bf4b0e5c65 100644 --- a/storage/innobase/row/row0uins.c +++ b/storage/innobase/row/row0uins.c @@ -39,14 +39,14 @@ row_undo_ins_remove_clust_rec( /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ undo_node_t* node) /* in: undo node */ { - btr_cur_t* btr_cur; + btr_cur_t* btr_cur; ibool success; ulint err; ulint n_tries = 0; mtr_t mtr; - + mtr_start(&mtr); - + success = btr_pcur_restore_position(BTR_MODIFY_LEAF, &(node->pcur), &mtr); ut_a(success); @@ -55,7 +55,7 @@ row_undo_ins_remove_clust_rec( /* Drop the index tree associated with the row in SYS_INDEXES table: */ - + dict_drop_index_tree(btr_pcur_get_rec(&(node->pcur)), &mtr); mtr_commit(&mtr); @@ -66,9 +66,9 @@ row_undo_ins_remove_clust_rec( &(node->pcur), &mtr); ut_a(success); } - + btr_cur = btr_pcur_get_btr_cur(&(node->pcur)); - + success = btr_cur_optimistic_delete(btr_cur, &mtr); btr_pcur_commit_specify_mtr(&(node->pcur), &mtr); @@ -81,7 +81,7 @@ row_undo_ins_remove_clust_rec( retry: /* If did not succeed, try pessimistic descent to tree */ mtr_start(&mtr); - + success = btr_pcur_restore_position(BTR_MODIFY_TREE, &(node->pcur), &mtr); ut_a(success); @@ -100,7 +100,7 @@ retry: n_tries++; os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME); - + goto retry; } @@ -125,13 +125,13 @@ row_undo_ins_remove_sec_low( dict_index_t* index, /* in: index */ dtuple_t* entry) /* in: index entry to remove */ { - btr_pcur_t pcur; + btr_pcur_t pcur; btr_cur_t* btr_cur; ibool found; ibool success; ulint err; mtr_t mtr; - + log_free_check(); mtr_start(&mtr); @@ -181,11 +181,11 @@ row_undo_ins_remove_sec( { ulint err; ulint n_tries = 0; - + /* Try first optimistic descent to the B-tree */ err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry); - + if (err == DB_SUCCESS) { return(err); @@ -204,7 +204,7 @@ retry: n_tries++; os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME); - + goto retry; } @@ -228,7 +228,7 @@ row_undo_ins_parse_undo_rec( ibool dummy_extern; ut_ad(node); - + ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy, &dummy_extern, &undo_no, &table_id); ut_ad(type == TRX_UNDO_INSERT_REC); @@ -249,11 +249,11 @@ row_undo_ins_parse_undo_rec( } clust_index = dict_table_get_first_index(node->table); - + ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref), node->heap); } - + /*************************************************************** Undoes a fresh insert of a row to a table. A fresh insert means that the same clustered index unique key did not have any record, even delete @@ -271,17 +271,17 @@ row_undo_ins( ut_ad(node); ut_ad(node->state == UNDO_NODE_INSERT); - + row_undo_ins_parse_undo_rec(node); if (node->table == NULL) { - found = FALSE; + found = FALSE; } else { - found = row_undo_search_clust_to_pcur(node); + found = row_undo_search_clust_to_pcur(node); } if (!found) { - trx_undo_rec_release(node->trx, node->undo_no); + trx_undo_rec_release(node->trx, node->undo_no); return(DB_SUCCESS); } @@ -298,11 +298,11 @@ row_undo_ins( return(err); } - + node->index = dict_table_get_next_index(node->index); } err = row_undo_ins_remove_clust_rec(node); - + return(err); } diff --git a/storage/innobase/row/row0umod.c b/storage/innobase/row/row0umod.c index f906027033f..9c871def661 100644 --- a/storage/innobase/row/row0umod.c +++ b/storage/innobase/row/row0umod.c @@ -51,14 +51,14 @@ row_undo_mod_undo_also_prev_vers( /*=============================*/ /* out: TRUE if also previous modify or insert of this row should be undone */ - undo_node_t* node, /* in: row undo node */ + undo_node_t* node, /* in: row undo node */ dulint* undo_no)/* out: the undo number */ { trx_undo_rec_t* undo_rec; trx_t* trx; trx = node->trx; - + if (0 != ut_dulint_cmp(node->new_trx_id, trx->id)) { *undo_no = ut_dulint_zero; @@ -71,7 +71,7 @@ row_undo_mod_undo_also_prev_vers( return(ut_dulint_cmp(trx->roll_limit, *undo_no) <= 0); } - + /*************************************************************** Undoes a modify in a clustered index record. */ static @@ -117,7 +117,7 @@ row_undo_mod_clust_low( return(err); } - + /*************************************************************** Removes a clustered index record after undo if possible. */ static @@ -135,7 +135,7 @@ row_undo_mod_remove_clust_low( btr_cur_t* btr_cur; ulint err; ibool success; - + pcur = &(node->pcur); btr_cur = btr_pcur_get_btr_cur(pcur); @@ -149,13 +149,13 @@ row_undo_mod_remove_clust_low( /* Find out if we can remove the whole clustered index record */ if (node->rec_type == TRX_UNDO_UPD_DEL_REC - && !row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) { + && !row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) { /* Ok, we can remove */ } else { return(DB_SUCCESS); } - + if (mode == BTR_MODIFY_LEAF) { success = btr_cur_optimistic_delete(btr_cur, mtr); @@ -180,7 +180,7 @@ row_undo_mod_remove_clust_low( return(err); } - + /*************************************************************** Undoes a modify in a clustered index record. Sets also the node state for the next round of undo. */ @@ -199,7 +199,7 @@ row_undo_mod_clust( ibool success; ibool more_vers; dulint new_undo_no; - + ut_ad(node && thr); /* Check if also the previous version of the clustered index record @@ -230,7 +230,7 @@ row_undo_mod_clust( btr_pcur_commit_specify_mtr(pcur, &mtr); if (err == DB_SUCCESS && node->rec_type == TRX_UNDO_UPD_DEL_REC) { - + mtr_start(&mtr); err = row_undo_mod_remove_clust_low(node, thr, &mtr, @@ -251,8 +251,8 @@ row_undo_mod_clust( } node->state = UNDO_NODE_FETCH_NEXT; - - trx_undo_rec_release(node->trx, node->undo_no); + + trx_undo_rec_release(node->trx, node->undo_no); if (more_vers && err == DB_SUCCESS) { @@ -284,7 +284,7 @@ row_undo_mod_del_mark_or_remove_sec_low( dict_index_t* index, /* in: index */ dtuple_t* entry, /* in: index entry */ ulint mode) /* in: latch mode BTR_MODIFY_LEAF or - BTR_MODIFY_TREE */ + BTR_MODIFY_TREE */ { ibool found; btr_pcur_t pcur; @@ -294,10 +294,10 @@ row_undo_mod_del_mark_or_remove_sec_low( ulint err; mtr_t mtr; mtr_t mtr_vers; - + log_free_check(); mtr_start(&mtr); - + found = row_search_index_entry(index, entry, mode, &pcur, &mtr); btr_cur = btr_pcur_get_btr_cur(&pcur); @@ -316,11 +316,11 @@ row_undo_mod_del_mark_or_remove_sec_low( we should delete mark the record. */ mtr_start(&mtr_vers); - + success = btr_pcur_restore_position(BTR_SEARCH_LEAF, &(node->pcur), &mtr_vers); ut_a(success); - + old_has = row_vers_old_has_index_entry(FALSE, btr_pcur_get_rec(&(node->pcur)), &mtr_vers, index, entry); @@ -331,7 +331,7 @@ row_undo_mod_del_mark_or_remove_sec_low( } else { /* Remove the index record */ - if (mode == BTR_MODIFY_LEAF) { + if (mode == BTR_MODIFY_LEAF) { success = btr_cur_optimistic_delete(btr_cur, &mtr); if (success) { err = DB_SUCCESS; @@ -376,17 +376,17 @@ row_undo_mod_del_mark_or_remove_sec( dtuple_t* entry) /* in: index entry */ { ulint err; - + err = row_undo_mod_del_mark_or_remove_sec_low(node, thr, index, - entry, BTR_MODIFY_LEAF); + entry, BTR_MODIFY_LEAF); if (err == DB_SUCCESS) { return(err); } err = row_undo_mod_del_mark_or_remove_sec_low(node, thr, index, - entry, BTR_MODIFY_TREE); - return(err); + entry, BTR_MODIFY_TREE); + return(err); } /*************************************************************** @@ -417,7 +417,7 @@ row_undo_mod_del_unmark_sec_and_undo_update( log_free_check(); mtr_start(&mtr); - + found = row_search_index_entry(index, entry, mode, &pcur, &mtr); if (!found) { @@ -437,34 +437,34 @@ row_undo_mod_del_unmark_sec_and_undo_update( } else { btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur); - err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG, + err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG, btr_cur, FALSE, thr, &mtr); - ut_a(err == DB_SUCCESS); + ut_a(err == DB_SUCCESS); heap = mem_heap_create(100); update = row_upd_build_sec_rec_difference_binary(index, entry, btr_cur_get_rec(btr_cur), trx, heap); - if (upd_get_n_fields(update) == 0) { + if (upd_get_n_fields(update) == 0) { /* Do nothing */ - + } else if (mode == BTR_MODIFY_LEAF) { - /* Try an optimistic updating of the record, keeping + /* Try an optimistic updating of the record, keeping changes within the page */ - err = btr_cur_optimistic_update(BTR_KEEP_SYS_FLAG + err = btr_cur_optimistic_update(BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG, - btr_cur, update, 0, thr, &mtr); - if (err == DB_OVERFLOW || err == DB_UNDERFLOW) { - err = DB_FAIL; - } - } else { - ut_a(mode == BTR_MODIFY_TREE); - err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG + btr_cur, update, 0, thr, &mtr); + if (err == DB_OVERFLOW || err == DB_UNDERFLOW) { + err = DB_FAIL; + } + } else { + ut_a(mode == BTR_MODIFY_TREE); + err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG, btr_cur, &dummy_big_rec, update, 0, thr, &mtr); - } + } mem_heap_free(heap); } @@ -489,7 +489,7 @@ row_undo_mod_upd_del_sec( dtuple_t* entry; dict_index_t* index; ulint err; - + heap = mem_heap_create(1024); while (node->index != NULL) { @@ -505,7 +505,7 @@ row_undo_mod_upd_del_sec( return(err); } - + node->index = dict_table_get_next_index(node->index); } @@ -535,7 +535,7 @@ row_undo_mod_del_mark_sec( index = node->index; entry = row_build_index_entry(node->row, index, heap); - + err = row_undo_mod_del_unmark_sec_and_undo_update( BTR_MODIFY_LEAF, thr, index, entry); @@ -555,7 +555,7 @@ row_undo_mod_del_mark_sec( node->index = dict_table_get_next_index(node->index); } - mem_heap_free(heap); + mem_heap_free(heap); return(DB_SUCCESS); } @@ -577,10 +577,10 @@ row_undo_mod_upd_exist_sec( if (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) { /* No change in secondary indexes */ - + return(DB_SUCCESS); } - + heap = mem_heap_create(1024); while (node->index != NULL) { @@ -670,15 +670,15 @@ row_undo_mod_parse_undo_rec( ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info, &dummy_extern, &undo_no, &table_id); node->rec_type = type; - + node->table = dict_table_get_on_id(table_id, trx); /* TODO: other fixes associated with DROP TABLE + rollback in the same table by another user */ if (node->table == NULL) { - /* Table was dropped */ - return; + /* Table was dropped */ + return; } if (node->table->ibd_file_missing) { @@ -703,7 +703,7 @@ row_undo_mod_parse_undo_rec( node->new_trx_id = trx_id; node->cmpl_info = cmpl_info; } - + /*************************************************************** Undoes a modify operation on a row of a table. */ @@ -716,7 +716,7 @@ row_undo_mod( { ibool found; ulint err; - + ut_ad(node && thr); ut_ad(node->state == UNDO_NODE_MODIFY); @@ -731,8 +731,8 @@ row_undo_mod( if (!found) { /* It is already undone, or will be undone by another query thread, or table was dropped */ - - trx_undo_rec_release(node->trx, node->undo_no); + + trx_undo_rec_release(node->trx, node->undo_no); node->state = UNDO_NODE_FETCH_NEXT; return(DB_SUCCESS); @@ -742,7 +742,7 @@ row_undo_mod( dict_table_get_first_index(node->table)); if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) { - + err = row_undo_mod_upd_exist_sec(node, thr); } else if (node->rec_type == TRX_UNDO_DEL_MARK_REC) { @@ -757,8 +757,8 @@ row_undo_mod( return(err); } - + err = row_undo_mod_clust(node, thr); - + return(err); } diff --git a/storage/innobase/row/row0undo.c b/storage/innobase/row/row0undo.c index 435c0279dbb..3454f6e3274 100644 --- a/storage/innobase/row/row0undo.c +++ b/storage/innobase/row/row0undo.c @@ -159,7 +159,7 @@ row_undo_search_clust_to_pcur( mtr_start(&mtr); clust_index = dict_table_get_first_index(node->table); - + found = row_search_on_row_ref(&(node->pcur), BTR_MODIFY_LEAF, node->table, node->ref, &mtr); @@ -175,10 +175,10 @@ row_undo_search_clust_to_pcur( BEFORE releasing the latch on the clustered index page: this is to make sure that some thread will eventually undo the modification corresponding to node->roll_ptr. */ - + /* fputs("--------------------undoing a previous version\n", stderr); */ - + ret = FALSE; } else { node->row = row_build(ROW_COPY_DATA, clust_index, rec, @@ -195,7 +195,7 @@ row_undo_search_clust_to_pcur( } return(ret); } - + /*************************************************************** Fetches an undo log record and does the undo for the recorded operation. If none left, or a partial rollback completed, returns control to the @@ -213,9 +213,9 @@ row_undo( trx_t* trx; dulint roll_ptr; ibool froze_data_dict = FALSE; - + ut_ad(node && thr); - + trx = node->trx; if (node->state == UNDO_NODE_FETCH_NEXT) { @@ -248,12 +248,12 @@ row_undo( again in this same rollback, restoring the previous version */ roll_ptr = node->new_roll_ptr; - + node->undo_rec = trx_undo_get_undo_rec_low(roll_ptr, node->heap); node->roll_ptr = roll_ptr; node->undo_no = trx_undo_rec_get_undo_no(node->undo_rec); - + if (trx_undo_roll_ptr_is_insert(roll_ptr)) { node->state = UNDO_NODE_INSERT; @@ -263,15 +263,15 @@ row_undo( } /* Prevent DROP TABLE etc. while we are rolling back this row. - If we are doing a TABLE CREATE or some other dictionary operation, - then we already have dict_operation_lock locked in x-mode. Do not - try to lock again in s-mode, because that would cause a hang. */ + If we are doing a TABLE CREATE or some other dictionary operation, + then we already have dict_operation_lock locked in x-mode. Do not + try to lock again in s-mode, because that would cause a hang. */ if (trx->dict_operation_lock_mode == 0) { - - row_mysql_freeze_data_dictionary(trx); - froze_data_dict = TRUE; + row_mysql_freeze_data_dictionary(trx); + + froze_data_dict = TRUE; } if (node->state == UNDO_NODE_INSERT) { @@ -286,14 +286,14 @@ row_undo( if (froze_data_dict) { - row_mysql_unfreeze_data_dictionary(trx); + row_mysql_unfreeze_data_dictionary(trx); } /* Do some cleanup */ btr_pcur_close(&(node->pcur)); mem_heap_empty(node->heap); - + thr->run_node = node; return(err); @@ -316,9 +316,9 @@ row_undo_step( ut_ad(thr); srv_activity_count++; - + trx = thr_get_trx(thr); - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_UNDO); @@ -338,13 +338,13 @@ row_undo_step( "InnoDB: Error 13 means out of tablespace.\n" "InnoDB: Consider increasing your tablespace.\n"); - exit(1); + exit(1); } - + ut_error; return(NULL); } return(thr); -} +} diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index ff1ad1dfd05..23be601a17b 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -130,7 +130,7 @@ row_upd_index_is_referenced( foreign = UT_LIST_GET_NEXT(referenced_list, foreign); } - + if (froze_data_dict) { row_mysql_unfreeze_data_dictionary(trx); } @@ -176,16 +176,16 @@ row_upd_check_references_constraints( entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); - mtr_commit(mtr); + mtr_commit(mtr); + + mtr_start(mtr); - mtr_start(mtr); - if (trx->dict_operation_lock_mode == 0) { got_s_lock = TRUE; row_mysql_freeze_data_dictionary(trx); } - + foreign = UT_LIST_GET_FIRST(table->referenced_list); while (foreign) { @@ -195,10 +195,11 @@ row_upd_check_references_constraints( NOT break the constraint. */ if (foreign->referenced_index == index - && (node->is_delete - || row_upd_changes_first_fields_binary(entry, index, - node->update, foreign->n_fields))) { - + && (node->is_delete + || row_upd_changes_first_fields_binary( + entry, index, node->update, + foreign->n_fields))) { + if (foreign->foreign_table == NULL) { dict_table_get(foreign->foreign_table_name, trx); @@ -217,7 +218,7 @@ row_upd_check_references_constraints( we will release dict_operation_lock temporarily! But the counter on the table protects 'foreign' from being dropped while the check is running. */ - + err = row_ins_check_foreign_constraint(FALSE, foreign, table, entry, thr); @@ -253,7 +254,7 @@ row_upd_check_references_constraints( } mem_heap_free(heap); - + return(DB_SUCCESS); } @@ -279,18 +280,18 @@ upd_node_create( node->ext_vec = NULL; node->index = NULL; node->update = NULL; - + node->foreign = NULL; node->cascade_heap = NULL; node->cascade_node = NULL; - + node->select = NULL; - + node->heap = mem_heap_create(128); - node->magic_n = UPD_NODE_MAGIC_N; + node->magic_n = UPD_NODE_MAGIC_N; node->cmpl_info = 0; - + return(node); } @@ -396,7 +397,8 @@ row_upd_changes_field_size_or_external( old_len = rec_offs_nth_size(offsets, upd_field->field_no); if (rec_offs_comp(offsets) - && rec_offs_nth_sql_null(offsets, upd_field->field_no)) { + && rec_offs_nth_sql_null(offsets, + upd_field->field_no)) { /* Note that in the compact table format, for a variable length field, an SQL NULL will use zero bytes in the offset array at the start of the physical @@ -411,7 +413,7 @@ row_upd_changes_field_size_or_external( return(TRUE); } - + if (rec_offs_nth_extern(offsets, upd_field->field_no)) { return(TRUE); @@ -452,7 +454,7 @@ row_upd_rec_in_place( for (i = 0; i < n_fields; i++) { upd_field = upd_get_nth_field(update, i); new_val = &(upd_field->new_val); - + rec_set_nth_field(rec, offsets, upd_field->field_no, dfield_get_data(new_val), dfield_get_len(new_val)); @@ -481,7 +483,7 @@ row_upd_write_sys_vals_to_log( dict_index_get_sys_col_pos(index, DATA_TRX_ID)); trx_write_roll_ptr(log_ptr, roll_ptr); - log_ptr += DATA_ROLL_PTR_LEN; + log_ptr += DATA_ROLL_PTR_LEN; log_ptr += mach_dulint_write_compressed(log_ptr, trx->id); @@ -512,9 +514,9 @@ row_upd_parse_sys_vals( return(NULL); } - + *roll_ptr = trx_read_roll_ptr(ptr); - ptr += DATA_ROLL_PTR_LEN; + ptr += DATA_ROLL_PTR_LEN; ptr = mach_dulint_parse_compressed(ptr, end_ptr, trx_id); @@ -543,18 +545,20 @@ row_upd_index_write_log( n_fields = upd_get_n_fields(update); buf_end = log_ptr + MLOG_BUF_MARGIN; - + mach_write_to_1(log_ptr, update->info_bits); log_ptr++; log_ptr += mach_write_compressed(log_ptr, n_fields); - + for (i = 0; i < n_fields; i++) { - ut_ad(MLOG_BUF_MARGIN > 30); +#if MLOG_BUF_MARGIN <= 30 +# error "MLOG_BUF_MARGIN <= 30" +#endif if (log_ptr + 30 > buf_end) { mlog_close(mtr, log_ptr); - + log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN); buf_end = log_ptr + MLOG_BUF_MARGIN; } @@ -575,7 +579,7 @@ row_upd_index_write_log( log_ptr += len; } else { mlog_close(mtr, log_ptr); - + mlog_catenate_string(mtr, new_val->data, len); log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN); @@ -694,7 +698,7 @@ upd_ext_vec_contains( return(FALSE); } - + /******************************************************************* Builds an update vector from those fields which in a secondary index entry differ from a record that has the equal ordering fields. NOTE: we compare @@ -828,10 +832,10 @@ row_upd_build_difference_binary( } extern_bit = upd_ext_vec_contains(ext_vec, n_ext_vec, i); - + if (UNIV_UNLIKELY(extern_bit == - (ibool)!rec_offs_nth_extern(offsets, i)) - || !dfield_data_is_binary_equal(dfield, len, data)) { + (ibool)!rec_offs_nth_extern(offsets, i)) + || !dfield_data_is_binary_equal(dfield, len, data)) { upd_field = upd_get_nth_field(update, n_diff); @@ -883,36 +887,36 @@ row_upd_index_replace_new_col_vals_index_pos( for (j = 0; j < dict_index_get_n_fields(index); j++) { - field = dict_index_get_nth_field(index, j); + field = dict_index_get_nth_field(index, j); for (i = 0; i < upd_get_n_fields(update); i++) { - upd_field = upd_get_nth_field(update, i); + upd_field = upd_get_nth_field(update, i); if (upd_field->field_no == j) { - dfield = dtuple_get_nth_field(entry, j); + dfield = dtuple_get_nth_field(entry, j); new_val = &(upd_field->new_val); dfield_set_data(dfield, new_val->data, new_val->len); if (heap && new_val->len != UNIV_SQL_NULL) { - dfield->data = mem_heap_alloc(heap, + dfield->data = mem_heap_alloc(heap, new_val->len); ut_memcpy(dfield->data, new_val->data, new_val->len); } if (field->prefix_len > 0 - && new_val->len != UNIV_SQL_NULL) { + && new_val->len != UNIV_SQL_NULL) { - cur_type = dict_col_get_type( + cur_type = dict_col_get_type( dict_field_get_col(field)); - dfield->len = - dtype_get_at_most_n_mbchars( - cur_type, + dfield->len = + dtype_get_at_most_n_mbchars( + cur_type, field->prefix_len, new_val->len, new_val->data); @@ -953,36 +957,36 @@ row_upd_index_replace_new_col_vals( for (j = 0; j < dict_index_get_n_fields(index); j++) { - field = dict_index_get_nth_field(index, j); + field = dict_index_get_nth_field(index, j); for (i = 0; i < upd_get_n_fields(update); i++) { - upd_field = upd_get_nth_field(update, i); + upd_field = upd_get_nth_field(update, i); if (upd_field->field_no == field->col->clust_pos) { - dfield = dtuple_get_nth_field(entry, j); + dfield = dtuple_get_nth_field(entry, j); new_val = &(upd_field->new_val); dfield_set_data(dfield, new_val->data, new_val->len); if (heap && new_val->len != UNIV_SQL_NULL) { - dfield->data = mem_heap_alloc(heap, + dfield->data = mem_heap_alloc(heap, new_val->len); ut_memcpy(dfield->data, new_val->data, new_val->len); } if (field->prefix_len > 0 - && new_val->len != UNIV_SQL_NULL) { + && new_val->len != UNIV_SQL_NULL) { cur_type = dict_col_get_type( dict_field_get_col(field)); - dfield->len = - dtype_get_at_most_n_mbchars( - cur_type, + dfield->len = + dtype_get_at_most_n_mbchars( + cur_type, field->prefix_len, new_val->len, new_val->data); @@ -1022,7 +1026,7 @@ row_upd_changes_ord_field_binary( ulint col_pos; ulint col_no; ulint i, j; - + ut_ad(update && index); n_unique = dict_index_get_n_unique(index); @@ -1045,10 +1049,11 @@ row_upd_changes_ord_field_binary( the datas */ if (col_pos == upd_field->field_no - && (row == NULL - || ind_field->prefix_len > 0 - || !dfield_datas_are_binary_equal( - dtuple_get_nth_field(row, col_no), + && (row == NULL + || ind_field->prefix_len > 0 + || !dfield_datas_are_binary_equal( + dtuple_get_nth_field(row, + col_no), &(upd_field->new_val)))) { return(TRUE); } @@ -1073,21 +1078,21 @@ row_upd_changes_some_index_ord_field_binary( upd_field_t* upd_field; dict_index_t* index; ulint i; - + index = dict_table_get_first_index(table); - + for (i = 0; i < upd_get_n_fields(update); i++) { upd_field = upd_get_nth_field(update, i); if (dict_field_get_col(dict_index_get_nth_field(index, - upd_field->field_no)) - ->ord_part) { + upd_field->field_no)) + ->ord_part) { - return(TRUE); + return(TRUE); } } - + return(FALSE); } @@ -1111,10 +1116,10 @@ row_upd_changes_first_fields_binary( ulint n_upd_fields; ulint col_pos; ulint i, j; - + ut_a(update && index); ut_a(n <= dict_index_get_n_fields(index)); - + n_upd_fields = upd_get_n_fields(update); for (i = 0; i < n; i++) { @@ -1130,9 +1135,10 @@ row_upd_changes_first_fields_binary( upd_field = upd_get_nth_field(update, j); if (col_pos == upd_field->field_no - && !dfield_datas_are_binary_equal( - dtuple_get_nth_field(entry, i), - &(upd_field->new_val))) { + && !dfield_datas_are_binary_equal( + dtuple_get_nth_field(entry, i), + &(upd_field->new_val))) { + return(TRUE); } } @@ -1214,11 +1220,11 @@ row_upd_store_row( mem_heap_empty(node->heap); node->row = NULL; } - + clust_index = dict_table_get_first_index(node->table); rec = btr_pcur_get_rec(node->pcur); - + offsets = rec_get_offsets(rec, clust_index, offsets_, ULINT_UNDEFINED, &heap); node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets, @@ -1230,7 +1236,7 @@ row_upd_store_row( } else { update = node->update; } - + node->n_ext_vec = btr_push_update_extern_fields(node->ext_vec, offsets, update); if (UNIV_LIKELY_NULL(heap)) { @@ -1262,7 +1268,7 @@ row_upd_sec_index_entry( trx_t* trx = thr_get_trx(thr); index = node->index; - + check_ref = row_upd_index_is_referenced(index, trx); heap = mem_heap_create(1024); @@ -1272,7 +1278,7 @@ row_upd_sec_index_entry( log_free_check(); mtr_start(&mtr); - + found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur, &mtr); btr_cur = btr_pcur_get_btr_cur(&pcur); @@ -1296,15 +1302,16 @@ row_upd_sec_index_entry( fputs("\n" "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); } else { - /* Delete mark the old index record; it can already be - delete marked if we return after a lock wait in - row_ins_index_entry below */ + /* Delete mark the old index record; it can already be + delete marked if we return after a lock wait in + row_ins_index_entry below */ - if (!rec_get_deleted_flag(rec, index->table->comp)) { + if (!rec_get_deleted_flag(rec, + dict_table_is_comp(index->table))) { err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE, thr, &mtr); if (err == DB_SUCCESS && check_ref) { - + /* NOTE that the following call loses the position of pcur ! */ err = row_upd_check_references_constraints( @@ -1317,7 +1324,7 @@ row_upd_sec_index_entry( } } - } + } } close_cur: btr_pcur_close(&pcur); @@ -1325,9 +1332,9 @@ close_cur: if (node->is_delete || err != DB_SUCCESS) { - mem_heap_free(heap); + mem_heap_free(heap); - return(err); + return(err); } /* Build a new index entry */ @@ -1336,9 +1343,9 @@ close_cur: /* Insert new index entry */ err = row_ins_index_entry(index, entry, NULL, 0, thr); - mem_heap_free(heap); + mem_heap_free(heap); - return(err); + return(err); } /*************************************************************** @@ -1358,10 +1365,10 @@ row_upd_sec_step( ut_ad((node->state == UPD_NODE_UPDATE_ALL_SEC) || (node->state == UPD_NODE_UPDATE_SOME_SEC)); ut_ad(!(node->index->type & DICT_CLUSTERED)); - + if (node->state == UPD_NODE_UPDATE_ALL_SEC - || row_upd_changes_ord_field_binary(node->row, node->index, - node->update)) { + || row_upd_changes_ord_field_binary(node->row, node->index, + node->update)) { err = row_upd_sec_index_entry(node, thr); return(err); @@ -1395,7 +1402,7 @@ row_upd_clust_rec_by_insert( dict_table_t* table; dtuple_t* entry; ulint err; - + ut_ad(node); ut_ad(index->type & DICT_CLUSTERED); @@ -1403,7 +1410,7 @@ row_upd_clust_rec_by_insert( table = node->table; pcur = node->pcur; btr_cur = btr_pcur_get_btr_cur(pcur); - + if (node->state != UPD_NODE_INSERT_CLUSTERED) { ulint offsets_[REC_OFFS_NORMAL_SIZE]; *offsets_ = (sizeof offsets_) / sizeof *offsets_; @@ -1439,7 +1446,7 @@ row_upd_clust_rec_by_insert( } } - } + } mtr_commit(mtr); @@ -1451,26 +1458,26 @@ row_upd_clust_rec_by_insert( entry = row_build_index_entry(node->row, index, heap); row_upd_index_replace_new_col_vals(entry, index, node->update, NULL); - + row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id); - + /* If we return from a lock wait, for example, we may have extern fields marked as not-owned in entry (marked in the if-branch above). We must unmark them. */ - + btr_cur_unmark_dtuple_extern_fields(entry, node->ext_vec, node->n_ext_vec); /* We must mark non-updated extern fields in entry as inherited, so that a possible rollback will not free them */ - + btr_cur_mark_dtuple_inherited_extern(entry, node->ext_vec, node->n_ext_vec, node->update); - + err = row_ins_index_entry(index, entry, node->ext_vec, node->n_ext_vec, thr); mem_heap_free(heap); - + return(err); } @@ -1492,7 +1499,7 @@ row_upd_clust_rec( btr_pcur_t* pcur; btr_cur_t* btr_cur; ulint err; - + ut_ad(node); ut_ad(index->type & DICT_CLUSTERED); @@ -1500,8 +1507,8 @@ row_upd_clust_rec( btr_cur = btr_pcur_get_btr_cur(pcur); ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur), - index->table->comp)); - + dict_table_is_comp(index->table))); + /* Try optimistic updating of the record, keeping changes within the page; we do not check locks because we assume the x-lock on the record to update */ @@ -1517,7 +1524,7 @@ row_upd_clust_rec( } mtr_commit(mtr); - + if (err == DB_SUCCESS) { return(err); @@ -1527,7 +1534,7 @@ row_upd_clust_rec( down the index tree */ mtr_start(mtr); - + /* NOTE: this transaction has an s-lock or x-lock on the record and therefore other transactions cannot modify the record when we have no latch on the page. In addition, we assume that other query threads of @@ -1537,8 +1544,8 @@ row_upd_clust_rec( ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr)); ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur), - index->table->comp)); - + dict_table_is_comp(index->table))); + err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur, &big_rec, node->update, node->cmpl_info, thr, mtr); @@ -1567,7 +1574,7 @@ row_upd_clust_rec( if (big_rec) { dtuple_big_rec_free(big_rec); } - + return(err); } @@ -1589,7 +1596,7 @@ row_upd_del_mark_clust_rec( btr_pcur_t* pcur; btr_cur_t* btr_cur; ulint err; - + ut_ad(node); ut_ad(index->type & DICT_CLUSTERED); ut_ad(node->is_delete); @@ -1599,7 +1606,7 @@ row_upd_del_mark_clust_rec( /* Store row because we have to build also the secondary index entries */ - + row_upd_store_row(node); /* Mark the clustered index record deleted; we do not have to check @@ -1621,7 +1628,7 @@ row_upd_del_mark_clust_rec( } mtr_commit(mtr); - + return(err); } @@ -1660,7 +1667,7 @@ row_upd_clust_step( mtr = &mtr_buf; mtr_start(mtr); - + /* If the restoration does not succeed, then the same transaction has deleted the record on which the cursor was, and that is an SQL error. If the restoration succeeds, it may @@ -1668,7 +1675,7 @@ row_upd_clust_step( and inserted a record with the same ordering fields, but in that case we know that the transaction has at least an implicit x-lock on the record. */ - + ut_a(pcur->rel_pos == BTR_PCUR_ON); success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr); @@ -1686,7 +1693,7 @@ row_upd_clust_step( with the index */ if (node->is_delete - && ut_dulint_cmp(node->table->id, DICT_INDEXES_ID) == 0) { + && ut_dulint_cmp(node->table->id, DICT_INDEXES_ID) == 0) { dict_drop_index_tree(btr_pcur_get_rec(pcur), mtr); @@ -1703,7 +1710,7 @@ row_upd_clust_step( return(err); } - } + } rec = btr_pcur_get_rec(pcur); offsets = rec_get_offsets(rec, index, offsets_, @@ -1733,10 +1740,10 @@ row_upd_clust_step( } return(err); } - + /* If the update is made for MySQL, we already have the update vector ready, else we have to do some evaluation: */ - + if (!node->in_mysql_interface) { /* Copy the necessary columns from clust_rec and calculate the new values to set */ @@ -1748,13 +1755,13 @@ row_upd_clust_step( if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } - + if (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) { err = row_upd_clust_rec(node, index, thr, mtr); return(err); } - + row_upd_store_row(node); if (row_upd_changes_ord_field_binary(node->row, index, node->update)) { @@ -1808,18 +1815,18 @@ row_upd( que_thr_t* thr) /* in: query thread */ { ulint err = DB_SUCCESS; - + ut_ad(node && thr); if (node->in_mysql_interface) { - + /* We do not get the cmpl_info value from the MySQL interpreter: we must calculate it on the fly: */ - + if (node->is_delete || row_upd_changes_some_index_ord_field_binary( node->table, node->update)) { - node->cmpl_info = 0; + node->cmpl_info = 0; } else { node->cmpl_info = UPD_NODE_NO_ORD_CHANGE; } @@ -1829,7 +1836,7 @@ row_upd( || node->state == UPD_NODE_INSERT_CLUSTERED) { err = row_upd_clust_step(node, thr); - + if (err != DB_SUCCESS) { goto function_exit; @@ -1850,7 +1857,7 @@ row_upd( } node->index = dict_table_get_next_index(node->index); - } + } function_exit: if (err == DB_SUCCESS) { @@ -1865,7 +1872,7 @@ function_exit: node->state = UPD_NODE_UPDATE_CLUSTERED; } - return(err); + return(err); } /*************************************************************** @@ -1885,19 +1892,19 @@ row_upd_step( trx_t* trx; ut_ad(thr); - + trx = thr_get_trx(thr); trx_start_if_not_started(trx); node = thr->run_node; - + sel_node = node->select; parent = que_node_get_parent(node); - + ut_ad(que_node_get_type(node) == QUE_NODE_UPDATE); - + if (thr->prev_node == parent) { node->state = UPD_NODE_SET_IX_LOCK; } @@ -1915,23 +1922,23 @@ row_upd_step( goto error_handling; } } - + node->state = UPD_NODE_UPDATE_CLUSTERED; if (node->searched_update) { /* Reset the cursor */ sel_node->state = SEL_NODE_OPEN; - + /* Fetch a row to update */ - + thr->run_node = sel_node; - + return(thr); } } /* sel_node is NULL if we are in the MySQL interface */ - + if (sel_node && (sel_node->state != SEL_NODE_FETCH)) { if (!node->searched_update) { @@ -1939,7 +1946,7 @@ row_upd_step( to update */ ut_error; - + err = DB_ERROR; goto error_handling; @@ -1951,12 +1958,12 @@ row_upd_step( updates directly in-place */ thr->run_node = parent; - + return(thr); } /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */ - + err = row_upd(node, thr); error_handling: @@ -1986,7 +1993,7 @@ error_handling: node->state = UPD_NODE_UPDATE_CLUSTERED; return(thr); -} +} /************************************************************************* Performs an in-place update for the current clustered index record in @@ -2031,8 +2038,8 @@ row_upd_in_place_in_select( row_upd_eval_new_vals(node->update); ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur), - btr_cur->index->table->comp)); - + dict_table_is_comp(btr_cur->index->table))); + ut_ad(node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE); ut_ad(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE); ut_ad(node->select_will_do_update); diff --git a/storage/innobase/row/row0vers.c b/storage/innobase/row/row0vers.c index b32ab8822f4..ab3b6385146 100644 --- a/storage/innobase/row/row0vers.c +++ b/storage/innobase/row/row0vers.c @@ -62,7 +62,7 @@ row_vers_impl_x_locked_off_kernel( ulint err; mtr_t mtr; ulint comp; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED)); @@ -71,12 +71,12 @@ row_vers_impl_x_locked_off_kernel( mutex_exit(&kernel_mutex); mtr_start(&mtr); - + /* Search for the clustered index record: this is a time-consuming operation: therefore we release the kernel mutex; also, the release is required by the latching order convention. The latch on the clustered index locks the top of the stack of versions. We also - reserve purge_latch to lock the bottom of the version stack. */ + reserve purge_latch to lock the bottom of the version stack. */ clust_rec = row_get_clust_rec(BTR_SEARCH_LEAF, rec, index, &clust_index, &mtr); @@ -96,7 +96,7 @@ row_vers_impl_x_locked_off_kernel( mutex_enter(&kernel_mutex); mtr_commit(&mtr); - return(NULL); + return(NULL); } heap = mem_heap_create(1024); @@ -107,7 +107,7 @@ row_vers_impl_x_locked_off_kernel( mtr_s_lock(&(purge_sys->latch), &mtr); mutex_enter(&kernel_mutex); - + trx = NULL; if (!trx_is_active(trx_id)) { /* The transaction that modified or inserted clust_rec is no @@ -123,7 +123,7 @@ row_vers_impl_x_locked_off_kernel( comp = page_rec_is_comp(rec); ut_ad(index->table == clust_index->table); - ut_ad(!!comp == index->table->comp); + ut_ad(!!comp == dict_table_is_comp(index->table)); ut_ad(!comp == !page_rec_is_comp(clust_rec)); /* We look up if some earlier version, which was modified by the trx_id @@ -179,7 +179,7 @@ row_vers_impl_x_locked_off_kernel( may assert the following: */ ut_ad(err == DB_SUCCESS); - + if (prev_version == NULL) { /* It was a freshly inserted version: there is an implicit x-lock on rec */ @@ -273,7 +273,7 @@ row_vers_must_preserve_del_marked( /* A purge operation is not yet allowed to remove this delete marked record */ - + return(TRUE); } @@ -313,7 +313,7 @@ row_vers_old_has_index_entry( ulint comp; ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains(mtr, buf_block_align(rec), + || mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_S_FIX)); #ifdef UNIV_SYNC_DEBUG ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED)); @@ -323,7 +323,7 @@ row_vers_old_has_index_entry( clust_index = dict_table_get_first_index(index->table); comp = page_rec_is_comp(rec); - ut_ad(!index->table->comp == !comp); + ut_ad(!dict_table_is_comp(index->table) == !comp); heap = mem_heap_create(1024); clust_offsets = rec_get_offsets(rec, clust_index, NULL, ULINT_UNDEFINED, &heap); @@ -333,7 +333,7 @@ row_vers_old_has_index_entry( rec, clust_offsets, heap); entry = row_build_index_entry(row, index, heap); - /* NOTE that we cannot do the comparison as binary + /* NOTE that we cannot do the comparison as binary fields because the row is maybe being modified so that the clustered index record has already been updated to a different binary value in a char field, but the @@ -373,7 +373,7 @@ row_vers_old_has_index_entry( prev_version, clust_offsets, heap); entry = row_build_index_entry(row, index, heap); - /* NOTE that we cannot do the comparison as binary + /* NOTE that we cannot do the comparison as binary fields because maybe the secondary index record has already been updated to a different binary value in a char field, but the collation identifies the old @@ -421,14 +421,14 @@ row_vers_build_for_consistent_read( { rec_t* version; rec_t* prev_version; - dulint prev_trx_id; + dulint trx_id; mem_heap_t* heap = NULL; byte* buf; ulint err; ut_ad(index->type & DICT_CLUSTERED); ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains(mtr, buf_block_align(rec), + || mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_S_FIX)); #ifdef UNIV_SYNC_DEBUG ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED)); @@ -436,16 +436,48 @@ row_vers_build_for_consistent_read( ut_ad(rec_offs_validate(rec, index, *offsets)); - ut_ad(!read_view_sees_trx_id(view, - row_get_rec_trx_id(rec, index, *offsets))); + trx_id = row_get_rec_trx_id(rec, index, *offsets); + + ut_ad(!read_view_sees_trx_id(view, trx_id)); rw_lock_s_lock(&(purge_sys->latch)); version = rec; for (;;) { mem_heap_t* heap2 = heap; + trx_undo_rec_t* undo_rec; + dulint roll_ptr; + dulint undo_no; heap = mem_heap_create(1024); + /* If we have high-granularity consistent read view and + creating transaction of the view is the same as trx_id in + the record we see this record only in the case when + undo_no of the record is < undo_no in the view. */ + + if (view->type == VIEW_HIGH_GRANULARITY + && ut_dulint_cmp(view->creator_trx_id, trx_id) == 0) { + + roll_ptr = row_get_rec_roll_ptr(version, index, + *offsets); + undo_rec = trx_undo_get_undo_rec_low(roll_ptr, heap); + undo_no = trx_undo_rec_get_undo_no(undo_rec); + mem_heap_empty(heap); + + if (ut_dulint_cmp(view->undo_no, undo_no) > 0) { + /* The view already sees this version: we can + copy it to in_heap and return */ + + buf = mem_heap_alloc(in_heap, + rec_offs_size(*offsets)); + *old_vers = rec_copy(buf, version, *offsets); + rec_offs_make_valid(*old_vers, index, *offsets); + err = DB_SUCCESS; + + break; + } + } + err = trx_undo_prev_version_build(rec, mtr, version, index, *offsets, heap, &prev_version); if (heap2) { @@ -466,10 +498,10 @@ row_vers_build_for_consistent_read( *offsets = rec_get_offsets(prev_version, index, *offsets, ULINT_UNDEFINED, offset_heap); - prev_trx_id = row_get_rec_trx_id(prev_version, index, - *offsets); - if (read_view_sees_trx_id(view, prev_trx_id)) { + trx_id = row_get_rec_trx_id(prev_version, index, *offsets); + + if (read_view_sees_trx_id(view, trx_id)) { /* The view already sees this version: we can copy it to in_heap and return */ @@ -558,8 +590,8 @@ row_vers_build_for_semi_consistent_read( mutex_exit(&kernel_mutex); if (!version_trx - || version_trx->conc_state == TRX_NOT_STARTED - || version_trx->conc_state == TRX_COMMITTED_IN_MEMORY) { + || version_trx->conc_state == TRX_NOT_STARTED + || version_trx->conc_state == TRX_COMMITTED_IN_MEMORY) { /* We found a version that belongs to a committed transaction: return it. */ diff --git a/storage/innobase/srv/srv0que.c b/storage/innobase/srv/srv0que.c index 9dc9ae453d9..9c261cbb00e 100644 --- a/storage/innobase/srv/srv0que.c +++ b/storage/innobase/srv/srv0que.c @@ -38,7 +38,7 @@ srv_que_task_queue_check(void) } UT_LIST_REMOVE(queue, srv_sys->tasks, thr); - + mutex_exit(&kernel_mutex); que_run_threads(thr); @@ -62,11 +62,11 @@ srv_que_round_robin( ut_ad(thr->state == QUE_THR_RUNNING); mutex_enter(&kernel_mutex); - + UT_LIST_ADD_LAST(queue, srv_sys->tasks, thr); new_thr = UT_LIST_GET_FIRST(srv_sys->tasks); - + mutex_exit(&kernel_mutex); return(new_thr); @@ -106,8 +106,8 @@ srv_que_task_enqueue( ut_a(0); /* Under MySQL this is never called */ mutex_enter(&kernel_mutex); - + srv_que_task_enqueue_low(thr); - + mutex_exit(&kernel_mutex); } diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index c585536baee..1256dd21c87 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -73,22 +73,22 @@ const char* srv_main_thread_op_info = ""; /* The following three are dir paths which are catenated before file names, where the file name itself may also contain a path */ -char* srv_data_home = NULL; +char* srv_data_home = NULL; #ifdef UNIV_LOG_ARCHIVE -char* srv_arch_dir = NULL; +char* srv_arch_dir = NULL; #endif /* UNIV_LOG_ARCHIVE */ ibool srv_file_per_table = FALSE; /* store to its own file each table created by an user; data dictionary tables are in the system tablespace 0 */ -ibool srv_locks_unsafe_for_binlog = FALSE; /* Place locks to records only - i.e. do not use next-key locking - except on duplicate key checking and - foreign key checking */ +ibool srv_locks_unsafe_for_binlog = FALSE; /* Place locks to records only + i.e. do not use next-key locking + except on duplicate key checking and + foreign key checking */ ulint srv_n_data_files = 0; char** srv_data_file_names = NULL; -ulint* srv_data_file_sizes = NULL; /* size in database pages */ +ulint* srv_data_file_sizes = NULL; /* size in database pages */ ibool srv_auto_extend_last_data_file = FALSE; /* if TRUE, then we auto-extend the last data @@ -100,19 +100,19 @@ ulint srv_last_file_size_max = 0; /* if != 0, this tells ulong srv_auto_extend_increment = 8; /* If the last data file is auto-extended, we add this many pages to it at a time */ -ulint* srv_data_file_is_raw_partition = NULL; +ulint* srv_data_file_is_raw_partition = NULL; /* If the following is TRUE we do not allow inserts etc. This protects the user from forgetting the 'newraw' keyword to my.cnf */ ibool srv_created_new_raw = FALSE; -char** srv_log_group_home_dirs = NULL; +char** srv_log_group_home_dirs = NULL; ulint srv_n_log_groups = ULINT_MAX; ulint srv_n_log_files = ULINT_MAX; -ulint srv_log_file_size = ULINT_MAX; /* size in database pages */ -ulint srv_log_buffer_size = ULINT_MAX; /* size in database pages */ +ulint srv_log_file_size = ULINT_MAX; /* size in database pages */ +ulint srv_log_buffer_size = ULINT_MAX; /* size in database pages */ ulint srv_flush_log_at_trx_commit = 1; byte srv_latin1_ordering[256] /* The sort order table of the latin1 @@ -152,16 +152,16 @@ byte srv_latin1_ordering[256] /* The sort order table of the latin1 , 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x5D, 0xF7 , 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xFF }; - + ulint srv_pool_size = ULINT_MAX; /* size in pages; MySQL inits this to size in kilobytes but we normalize this to pages in srv_boot() */ -ulint srv_awe_window_size = 0; /* size in pages; MySQL inits +ulint srv_awe_window_size = 0; /* size in pages; MySQL inits this to bytes, but we normalize it to pages in srv_boot() */ -ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */ +ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */ ulint srv_lock_table_size = ULINT_MAX; ulint srv_n_file_io_threads = ULINT_MAX; @@ -174,9 +174,9 @@ dulint srv_archive_recovery_limit_lsn; ulint srv_lock_wait_timeout = 1024 * 1024 * 1024; -char* srv_file_flush_method_str = NULL; -ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC; -ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; +char* srv_file_flush_method_str = NULL; +ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC; +ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; ulint srv_max_n_open_files = 300; @@ -251,17 +251,18 @@ ulint srv_force_recovery = 0; a semaphore inside InnoDB. innobase_start_or_create_for_mysql() sets the value. */ -ulint srv_max_n_threads = 0; +ulint srv_max_n_threads = 0; /* The following controls how many threads we let inside InnoDB concurrently: threads waiting for locks are not counted into the number because otherwise we could get a deadlock. MySQL creates a thread for each user session, and semaphore contention and convoy problems can occur withput this restriction. Value 10 should be good if there are less than 4 processors + 4 disks in the -computer. Bigger computers need bigger values. */ +computer. Bigger computers need bigger values. Value 0 will disable the +concurrency check. */ -ulong srv_thread_concurrency = SRV_CONCURRENCY_THRESHOLD; -ulong srv_commit_concurrency = 0; +ulong srv_thread_concurrency = 0; +ulong srv_commit_concurrency = 0; os_fast_mutex_t srv_conc_mutex; /* this mutex protects srv_conc data structures */ @@ -313,13 +314,13 @@ ibool srv_innodb_status = FALSE; ibool srv_use_doublewrite_buf = TRUE; ibool srv_use_checksums = TRUE; -ibool srv_set_thread_priorities = TRUE; -int srv_query_thread_priority = 0; +ibool srv_set_thread_priorities = TRUE; +int srv_query_thread_priority = 0; /* TRUE if the Address Windowing Extensions of Windows are used; then we must disable adaptive hash indexes */ ibool srv_use_awe = FALSE; -ibool srv_use_adaptive_hash_indexes = TRUE; +ibool srv_use_adaptive_hash_indexes = TRUE; /*-------------------------------------------*/ ulong srv_n_spin_wait_rounds = 20; @@ -338,10 +339,12 @@ ulint srv_n_rows_inserted = 0; ulint srv_n_rows_updated = 0; ulint srv_n_rows_deleted = 0; ulint srv_n_rows_read = 0; +#ifndef UNIV_HOTBACKUP static ulint srv_n_rows_inserted_old = 0; static ulint srv_n_rows_updated_old = 0; static ulint srv_n_rows_deleted_old = 0; static ulint srv_n_rows_read_old = 0; +#endif /* !UNIV_HOTBACKUP */ ulint srv_n_lock_wait_count = 0; ulint srv_n_lock_wait_current_count = 0; @@ -355,9 +358,9 @@ ulint srv_n_lock_max_wait_time = 0; */ ibool srv_print_verbose_log = TRUE; ibool srv_print_innodb_monitor = FALSE; -ibool srv_print_innodb_lock_monitor = FALSE; -ibool srv_print_innodb_tablespace_monitor = FALSE; -ibool srv_print_innodb_table_monitor = FALSE; +ibool srv_print_innodb_lock_monitor = FALSE; +ibool srv_print_innodb_tablespace_monitor = FALSE; +ibool srv_print_innodb_table_monitor = FALSE; /* The parameters below are obsolete: */ @@ -370,7 +373,7 @@ ibool srv_sim_disk_wait_by_wait = FALSE; ibool srv_measure_contention = FALSE; ibool srv_measure_by_spin = FALSE; - + ibool srv_test_extra_mutexes = FALSE; ibool srv_test_nocache = FALSE; ibool srv_test_cache_evict = FALSE; @@ -397,6 +400,18 @@ mutex_t srv_innodb_monitor_mutex; mutex_t srv_monitor_file_mutex; /* Temporary file for innodb monitor output */ FILE* srv_monitor_file; +/* Mutex for locking srv_dict_tmpfile. +This mutex has a very high rank; threads reserving it should not +be holding any InnoDB latches. */ +mutex_t srv_dict_tmpfile_mutex; +/* Temporary file for output from the data dictionary */ +FILE* srv_dict_tmpfile; +/* Mutex for locking srv_misc_tmpfile. +This mutex has a very low rank; threads reserving it should not +acquire any further latches or sleep before releasing this one. */ +mutex_t srv_misc_tmpfile_mutex; +/* Temporary file for miscellanous diagnostic output */ +FILE* srv_misc_tmpfile; ulint srv_main_thread_process_no = 0; ulint srv_main_thread_id = 0; @@ -423,7 +438,7 @@ kernel -- kernel; query thread execution: (a) without kernel mutex -reserved -- process executing in user mode; +reserved -- process executing in user mode; (b) with kernel mutex reserved -- process executing in kernel mode; @@ -518,7 +533,7 @@ keep record of which thread owns which resource and in the above case boost the priority of the background thread so that it will be scheduled and it can release the resource. This solution is called priority inheritance in real-time programming. -A drawback of this solution is that the overhead of acquiring a mutex +A drawback of this solution is that the overhead of acquiring a mutex increases slightly, maybe 0.2 microseconds on a 100 MHz Pentium, because the thread has to call os_thread_get_curr_id. This may be compared to 0.5 microsecond overhead for a mutex lock-unlock @@ -650,6 +665,7 @@ srv_table_get_nth_slot( return(srv_sys->threads + index); } +#ifndef UNIV_HOTBACKUP /************************************************************************* Gets the number of threads in the system. */ @@ -663,7 +679,7 @@ srv_get_n_threads(void) mutex_enter(&kernel_mutex); for (i = SRV_COM; i < SRV_MASTER + 1; i++) { - + n_threads += srv_n_threads[i]; } @@ -685,7 +701,7 @@ srv_table_reserve_slot( { srv_slot_t* slot; ulint i; - + ut_a(type > 0); ut_a(type <= SRV_MASTER); @@ -698,7 +714,7 @@ srv_table_reserve_slot( } ut_a(slot->in_use == FALSE); - + slot->in_use = TRUE; slot->suspended = FALSE; slot->id = os_thread_get_curr_id(); @@ -729,7 +745,7 @@ srv_suspend_thread(void) #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - + slot_no = thr_local_get_slot_no(os_thread_get_curr_id()); if (srv_print_thread_releases) { @@ -747,7 +763,7 @@ srv_suspend_thread(void) ut_ad(type <= SRV_MASTER); event = slot->event; - + slot->suspended = TRUE; ut_ad(srv_n_threads_active[type] > 0); @@ -758,6 +774,7 @@ srv_suspend_thread(void) return(event); } +#endif /* !UNIV_HOTBACKUP */ /************************************************************************* Releases threads of the type given from suspension in the thread table. @@ -782,13 +799,13 @@ srv_release_threads( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - + for (i = 0; i < OS_THREAD_MAX_N; i++) { - + slot = srv_table_get_nth_slot(i); if (slot->in_use && slot->type == type && slot->suspended) { - + slot->suspended = FALSE; srv_n_threads_active[type]++; @@ -799,7 +816,7 @@ srv_release_threads( fprintf(stderr, "Releasing thread %lu type %lu from slot %lu meter %lu\n", (ulong) slot->id, (ulong) type, (ulong) i, - (ulong) srv_meter[SRV_RECOVERY]); + (ulong) srv_meter[SRV_RECOVERY]); } count++; @@ -826,7 +843,7 @@ srv_get_thread_type(void) ulint type; mutex_enter(&kernel_mutex); - + slot_no = thr_local_get_slot_no(os_thread_get_curr_id()); slot = srv_table_get_nth_slot(slot_no); @@ -848,7 +865,7 @@ void srv_init(void) /*==========*/ { - srv_conc_slot_t* conc_slot; + srv_conc_slot_t* conc_slot; srv_slot_t* slot; dict_table_t* table; ulint i; @@ -861,13 +878,13 @@ srv_init(void) mutex_create(&srv_innodb_monitor_mutex); mutex_set_level(&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK); - + srv_sys->threads = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t)); for (i = 0; i < OS_THREAD_MAX_N; i++) { slot = srv_table_get_nth_slot(i); slot->in_use = FALSE; - slot->type=0; /* Avoid purify errors */ + slot->type=0; /* Avoid purify errors */ slot->event = os_event_create(NULL); ut_a(slot->event); } @@ -883,7 +900,7 @@ srv_init(void) } srv_lock_timeout_thread_event = os_event_create(NULL); - + for (i = 0; i < SRV_MASTER + 1; i++) { srv_n_threads_active[i] = 0; srv_n_threads[i] = 0; @@ -893,7 +910,7 @@ srv_init(void) srv_meter_high_water2[i] = 200; srv_meter_foreground[i] = 250; } - + srv_sys->operational = os_event_create(NULL); ut_a(srv_sys->operational); @@ -902,24 +919,24 @@ srv_init(void) /* create dummy table and index for old-style infimum and supremum */ table = dict_mem_table_create("SYS_DUMMY1", - DICT_HDR_SPACE, 1, FALSE); + DICT_HDR_SPACE, 1, 0); dict_mem_table_add_col(table, "DUMMY", DATA_CHAR, DATA_ENGLISH | DATA_NOT_NULL, 8, 0); srv_sys->dummy_ind1 = dict_mem_index_create("SYS_DUMMY1", "SYS_DUMMY1", DICT_HDR_SPACE, 0, 1); dict_index_add_col(srv_sys->dummy_ind1, - dict_table_get_nth_col(table, 0), 0, 0); + dict_table_get_nth_col(table, 0), 0); srv_sys->dummy_ind1->table = table; /* create dummy table and index for new-style infimum and supremum */ table = dict_mem_table_create("SYS_DUMMY2", - DICT_HDR_SPACE, 1, TRUE); + DICT_HDR_SPACE, 1, DICT_TF_COMPACT); dict_mem_table_add_col(table, "DUMMY", DATA_CHAR, DATA_ENGLISH | DATA_NOT_NULL, 8, 0); srv_sys->dummy_ind2 = dict_mem_index_create("SYS_DUMMY2", "SYS_DUMMY2", DICT_HDR_SPACE, 0, 1); dict_index_add_col(srv_sys->dummy_ind2, - dict_table_get_nth_col(table, 0), 0, 0); + dict_table_get_nth_col(table, 0), 0); srv_sys->dummy_ind2->table = table; /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */ @@ -928,7 +945,7 @@ srv_init(void) /* Init the server concurrency restriction data structures */ os_fast_mutex_init(&srv_conc_mutex); - + UT_LIST_INIT(srv_conc_queue); srv_conc_slots = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_conc_slot_t)); @@ -939,7 +956,7 @@ srv_init(void) conc_slot->event = os_event_create(NULL); ut_a(conc_slot->event); } -} +} /************************************************************************* Frees the OS fast mutex created in srv_init(). */ @@ -996,7 +1013,7 @@ srv_conc_enter_innodb( os_fast_mutex_lock(&srv_conc_mutex); retry: if (trx->declared_to_be_inside_innodb) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fputs( " InnoDB: Error: trying to declare trx to enter InnoDB, but\n" "InnoDB: it already is declared.\n", stderr); @@ -1012,19 +1029,19 @@ retry: srv_conc_n_threads++; trx->declared_to_be_inside_innodb = TRUE; trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER; - + os_fast_mutex_unlock(&srv_conc_mutex); return; } - /* If the transaction is not holding resources, + /* If the transaction is not holding resources, let it sleep for SRV_THREAD_SLEEP_DELAY microseconds, and try again then */ - + if (!has_slept && !trx->has_search_latch - && NULL == UT_LIST_GET_FIRST(trx->trx_locks)) { + && NULL == UT_LIST_GET_FIRST(trx->trx_locks)) { - has_slept = TRUE; /* We let is sleep only once to avoid + has_slept = TRUE; /* We let is sleep only once to avoid starvation */ srv_conc_n_waiting_threads++; @@ -1038,10 +1055,9 @@ retry: situations of lots of thread switches. Simply put some threads aside for a while to reduce the number of thread switches. */ - if (SRV_THREAD_SLEEP_DELAY > 0) - { - os_thread_sleep(SRV_THREAD_SLEEP_DELAY); - } + if (SRV_THREAD_SLEEP_DELAY > 0) { + os_thread_sleep(SRV_THREAD_SLEEP_DELAY); + } trx->op_info = ""; @@ -1050,7 +1066,7 @@ retry: srv_conc_n_waiting_threads--; goto retry; - } + } /* Too many threads inside: put the current thread to a queue */ @@ -1084,7 +1100,7 @@ retry: /* Add to the queue */ slot->reserved = TRUE; slot->wait_ended = FALSE; - + UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot); os_event_reset(slot->event); @@ -1129,8 +1145,8 @@ srv_conc_force_enter_innodb( trx_t* trx) /* in: transaction object associated with the thread */ { - if (srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD) { - + if (UNIV_LIKELY(!srv_thread_concurrency)) { + return; } @@ -1155,13 +1171,13 @@ srv_conc_force_exit_innodb( { srv_conc_slot_t* slot = NULL; - if (srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD) { - + if (UNIV_LIKELY(!srv_thread_concurrency)) { + return; } if (trx->declared_to_be_inside_innodb == FALSE) { - + return; } @@ -1174,7 +1190,7 @@ srv_conc_force_exit_innodb( if (srv_conc_n_threads < (lint)srv_thread_concurrency) { /* Look for a slot where a thread is waiting and no other thread has yet released the thread */ - + slot = UT_LIST_GET_FIRST(srv_conc_queue); while (slot && slot->wait_ended == TRUE) { @@ -1235,15 +1251,15 @@ srv_normalize_init_values(void) ulint i; n = srv_n_data_files; - + for (i = 0; i < n; i++) { srv_data_file_sizes[i] = srv_data_file_sizes[i] * ((1024 * 1024) / UNIV_PAGE_SIZE); - } + } srv_last_file_size_max = srv_last_file_size_max * ((1024 * 1024) / UNIV_PAGE_SIZE); - + srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE; srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE; @@ -1251,15 +1267,15 @@ srv_normalize_init_values(void) srv_pool_size = srv_pool_size / (UNIV_PAGE_SIZE / 1024); srv_awe_window_size = srv_awe_window_size / UNIV_PAGE_SIZE; - + if (srv_use_awe) { - /* If we are using AWE we must save memory in the 32-bit + /* If we are using AWE we must save memory in the 32-bit address space of the process, and cannot bind the lock table size to the real buffer pool size. */ - srv_lock_table_size = 20 * srv_awe_window_size; + srv_lock_table_size = 20 * srv_awe_window_size; } else { - srv_lock_table_size = 5 * srv_pool_size; + srv_lock_table_size = 5 * srv_pool_size; } return(DB_SUCCESS); @@ -1277,16 +1293,16 @@ srv_boot(void) /* Transform the init parameter values given by MySQL to use units we use inside InnoDB: */ - + err = srv_normalize_init_values(); if (err != DB_SUCCESS) { return(err); } - + /* Initialize synchronization primitives, memory management, and thread local storage */ - + srv_general_init(); /* Initialize this module */ @@ -1321,9 +1337,9 @@ srv_table_reserve_slot_for_mysql(void) if (i >= OS_THREAD_MAX_N) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); - fprintf(stderr, + fprintf(stderr, " InnoDB: There appear to be %lu MySQL threads currently waiting\n" "InnoDB: inside InnoDB, which is the upper limit. Cannot continue operation.\n" "InnoDB: We intentionally generate a seg fault to print a stack trace\n" @@ -1331,9 +1347,9 @@ srv_table_reserve_slot_for_mysql(void) for (i = 0; i < OS_THREAD_MAX_N; i++) { - slot = srv_mysql_table + i; + slot = srv_mysql_table + i; - fprintf(stderr, + fprintf(stderr, "Slot %lu: thread id %lu, type %lu, in use %lu, susp %lu, time %lu\n", (ulong) i, (ulong) os_thread_pf(slot->id), (ulong) slot->type, (ulong) slot->in_use, @@ -1341,14 +1357,14 @@ srv_table_reserve_slot_for_mysql(void) (ulong) difftime(ut_time(), slot->suspend_time)); } - ut_error; + ut_error; } - + slot = srv_mysql_table + i; } ut_a(slot->in_use == FALSE); - + slot->in_use = TRUE; slot->id = os_thread_get_curr_id(); slot->handle = os_thread_get_curr(); @@ -1388,7 +1404,7 @@ srv_suspend_mysql_thread( #endif /* UNIV_SYNC_DEBUG */ trx = thr_get_trx(thr); - + os_event_set(srv_lock_timeout_thread_event); mutex_enter(&kernel_mutex); @@ -1398,7 +1414,7 @@ srv_suspend_mysql_thread( if (thr->state == QUE_THR_RUNNING) { ut_ad(thr->is_active == TRUE); - + /* The lock has already been released or this transaction was chosen as a deadlock victim: no need to suspend */ @@ -1412,16 +1428,16 @@ srv_suspend_mysql_thread( return; } - + ut_ad(thr->is_active == FALSE); slot = srv_table_reserve_slot_for_mysql(); event = slot->event; - + slot->thr = thr; - os_event_reset(event); + os_event_reset(event); slot->suspend_time = ut_time(); @@ -1435,17 +1451,17 @@ srv_suspend_mysql_thread( /* Wake the lock timeout monitor thread, if it is suspended */ os_event_set(srv_lock_timeout_thread_event); - + mutex_exit(&kernel_mutex); if (trx->declared_to_be_inside_innodb) { was_declared_inside_innodb = TRUE; - + /* We must declare this OS thread to exit InnoDB, since a possible other thread holding a lock which this thread waits for must be allowed to enter, sooner or later */ - + srv_conc_force_exit_innodb(trx); } @@ -1460,7 +1476,7 @@ srv_suspend_mysql_thread( ut_a(trx->dict_operation_lock_mode == 0); /* Wait for the release */ - + os_event_wait(event); if (had_dict_lock) { @@ -1471,14 +1487,14 @@ srv_suspend_mysql_thread( if (was_declared_inside_innodb) { /* Return back inside InnoDB */ - + srv_conc_force_enter_innodb(trx); } mutex_enter(&kernel_mutex); /* Release the slot for others to use */ - + slot->in_use = FALSE; wait_time = ut_difftime(ut_time(), slot->suspend_time); @@ -1488,7 +1504,7 @@ srv_suspend_mysql_thread( 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) { @@ -1504,10 +1520,10 @@ srv_suspend_mysql_thread( mutex_exit(&kernel_mutex); - if (srv_lock_wait_timeout < 100000000 && - wait_time > (double)srv_lock_wait_timeout) { + if (srv_lock_wait_timeout < 100000000 && + wait_time > (double)srv_lock_wait_timeout) { - trx->error_state = DB_LOCK_WAIT_TIMEOUT; + trx->error_state = DB_LOCK_WAIT_TIMEOUT; } #else /* UNIV_HOTBACKUP */ /* This function depends on MySQL code that is not included in @@ -1525,12 +1541,12 @@ void srv_release_mysql_thread_if_suspended( /*==================================*/ que_thr_t* thr) /* in: query thread associated with the - MySQL OS thread */ + MySQL OS thread */ { #ifndef UNIV_HOTBACKUP srv_slot_t* slot; ulint i; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ @@ -1575,7 +1591,7 @@ srv_refresh_innodb_monitor_stats(void) btr_cur_n_non_sea_old = btr_cur_n_non_sea; log_refresh_stats(); - + buf_refresh_io_stats(); srv_n_rows_inserted_old = srv_n_rows_inserted; @@ -1600,7 +1616,7 @@ srv_printf_innodb_monitor( { double time_elapsed; time_t current_time; - ulint n_reserved; + ulint n_reserved; mutex_enter(&srv_innodb_monitor_mutex); @@ -1609,7 +1625,7 @@ srv_printf_innodb_monitor( /* We add 0.001 seconds to time_elapsed to prevent division by zero if two users happen to call SHOW INNODB STATUS at the same time */ - + time_elapsed = difftime(current_time, srv_last_monitor_time) + 0.001; @@ -1685,12 +1701,12 @@ srv_printf_innodb_monitor( btr_cur_n_non_sea_old = btr_cur_n_non_sea; fputs("---\n" - "LOG\n" + "LOG\n" "---\n", file); log_print(file); fputs("----------------------\n" - "BUFFER POOL AND MEMORY\n" + "BUFFER POOL AND MEMORY\n" "----------------------\n", file); fprintf(file, "Total memory allocated " ULINTPF @@ -1703,31 +1719,31 @@ srv_printf_innodb_monitor( "In addition to that %lu MB of AWE memory allocated\n", (ulong) (srv_pool_size / ((1024 * 1024) / UNIV_PAGE_SIZE))); } - + buf_print_io(file); fputs("--------------\n" "ROW OPERATIONS\n" "--------------\n", file); fprintf(file, "%ld queries inside InnoDB, %lu queries in queue\n", - (long) srv_conc_n_threads, - (ulong) srv_conc_n_waiting_threads); + (long) srv_conc_n_threads, + (ulong) srv_conc_n_waiting_threads); fprintf(file, "%lu read views open inside InnoDB\n", UT_LIST_GET_LEN(trx_sys->view_list)); - n_reserved = fil_space_get_n_reserved_extents(0); - if (n_reserved > 0) { - fprintf(file, - "%lu tablespace extents now reserved for B-tree split operations\n", - (ulong) n_reserved); - } + n_reserved = fil_space_get_n_reserved_extents(0); + if (n_reserved > 0) { + fprintf(file, + "%lu tablespace extents now reserved for B-tree split operations\n", + (ulong) n_reserved); + } #ifdef UNIV_LINUX fprintf(file, "Main thread process no. %lu, id %lu, state: %s\n", - (ulong) srv_main_thread_process_no, - (ulong) srv_main_thread_id, - srv_main_thread_op_info); + (ulong) srv_main_thread_process_no, + (ulong) srv_main_thread_id, + srv_main_thread_op_info); #else fprintf(file, "Main thread id %lu, state: %s\n", (ulong) srv_main_thread_id, @@ -1736,9 +1752,9 @@ srv_printf_innodb_monitor( fprintf(file, "Number of rows inserted " ULINTPF ", updated " ULINTPF ", deleted " ULINTPF ", read " ULINTPF "\n", - srv_n_rows_inserted, - srv_n_rows_updated, - srv_n_rows_deleted, + srv_n_rows_inserted, + srv_n_rows_updated, + srv_n_rows_deleted, srv_n_rows_read); fprintf(file, "%.2f inserts/s, %.2f updates/s, %.2f deletes/s, %.2f reads/s\n", @@ -1757,7 +1773,7 @@ srv_printf_innodb_monitor( srv_n_rows_read_old = srv_n_rows_read; fputs("----------------------------\n" - "END OF INNODB MONITOR OUTPUT\n" + "END OF INNODB MONITOR OUTPUT\n" "============================\n", file); mutex_exit(&srv_innodb_monitor_mutex); fflush(file); @@ -1770,58 +1786,58 @@ void srv_export_innodb_status(void) { - mutex_enter(&srv_innodb_monitor_mutex); - export_vars.innodb_data_pending_reads= os_n_pending_reads; - export_vars.innodb_data_pending_writes= os_n_pending_writes; - export_vars.innodb_data_pending_fsyncs= - fil_n_pending_log_flushes + fil_n_pending_tablespace_flushes; - export_vars.innodb_data_fsyncs= os_n_fsyncs; - export_vars.innodb_data_read= srv_data_read; - export_vars.innodb_data_reads= os_n_file_reads; - export_vars.innodb_data_writes= os_n_file_writes; - export_vars.innodb_data_written= srv_data_written; - export_vars.innodb_buffer_pool_read_requests= buf_pool->n_page_gets; - export_vars.innodb_buffer_pool_write_requests= srv_buf_pool_write_requests; - export_vars.innodb_buffer_pool_wait_free= srv_buf_pool_wait_free; - export_vars.innodb_buffer_pool_pages_flushed= srv_buf_pool_flushed; - export_vars.innodb_buffer_pool_reads= srv_buf_pool_reads; - export_vars.innodb_buffer_pool_read_ahead_rnd= srv_read_ahead_rnd; - export_vars.innodb_buffer_pool_read_ahead_seq= srv_read_ahead_seq; - export_vars.innodb_buffer_pool_pages_data= UT_LIST_GET_LEN(buf_pool->LRU); - export_vars.innodb_buffer_pool_pages_dirty= UT_LIST_GET_LEN(buf_pool->flush_list); - export_vars.innodb_buffer_pool_pages_free= UT_LIST_GET_LEN(buf_pool->free); - export_vars.innodb_buffer_pool_pages_latched= buf_get_latched_pages_number(); - export_vars.innodb_buffer_pool_pages_total= buf_pool->curr_size; - export_vars.innodb_buffer_pool_pages_misc= buf_pool->max_size - - UT_LIST_GET_LEN(buf_pool->LRU) - UT_LIST_GET_LEN(buf_pool->free); - export_vars.innodb_page_size= UNIV_PAGE_SIZE; - export_vars.innodb_log_waits= srv_log_waits; - export_vars.innodb_os_log_written= srv_os_log_written; - export_vars.innodb_os_log_fsyncs= fil_n_log_flushes; - export_vars.innodb_os_log_pending_fsyncs= fil_n_pending_log_flushes; - export_vars.innodb_os_log_pending_writes= srv_os_log_pending_writes; - export_vars.innodb_log_write_requests= srv_log_write_requests; - export_vars.innodb_log_writes= srv_log_writes; - export_vars.innodb_dblwr_pages_written= srv_dblwr_pages_written; - export_vars.innodb_dblwr_writes= srv_dblwr_writes; - export_vars.innodb_pages_created= buf_pool->n_pages_created; - export_vars.innodb_pages_read= buf_pool->n_pages_read; - export_vars.innodb_pages_written= buf_pool->n_pages_written; - export_vars.innodb_row_lock_waits= srv_n_lock_wait_count; - export_vars.innodb_row_lock_current_waits= srv_n_lock_wait_current_count; - export_vars.innodb_row_lock_time= srv_n_lock_wait_time / 10000; + mutex_enter(&srv_innodb_monitor_mutex); + export_vars.innodb_data_pending_reads= os_n_pending_reads; + export_vars.innodb_data_pending_writes= os_n_pending_writes; + export_vars.innodb_data_pending_fsyncs= + fil_n_pending_log_flushes + fil_n_pending_tablespace_flushes; + export_vars.innodb_data_fsyncs= os_n_fsyncs; + export_vars.innodb_data_read= srv_data_read; + export_vars.innodb_data_reads= os_n_file_reads; + export_vars.innodb_data_writes= os_n_file_writes; + export_vars.innodb_data_written= srv_data_written; + export_vars.innodb_buffer_pool_read_requests= buf_pool->n_page_gets; + export_vars.innodb_buffer_pool_write_requests= srv_buf_pool_write_requests; + export_vars.innodb_buffer_pool_wait_free= srv_buf_pool_wait_free; + export_vars.innodb_buffer_pool_pages_flushed= srv_buf_pool_flushed; + export_vars.innodb_buffer_pool_reads= srv_buf_pool_reads; + export_vars.innodb_buffer_pool_read_ahead_rnd= srv_read_ahead_rnd; + export_vars.innodb_buffer_pool_read_ahead_seq= srv_read_ahead_seq; + export_vars.innodb_buffer_pool_pages_data= UT_LIST_GET_LEN(buf_pool->LRU); + export_vars.innodb_buffer_pool_pages_dirty= UT_LIST_GET_LEN(buf_pool->flush_list); + export_vars.innodb_buffer_pool_pages_free= UT_LIST_GET_LEN(buf_pool->free); + export_vars.innodb_buffer_pool_pages_latched= buf_get_latched_pages_number(); + export_vars.innodb_buffer_pool_pages_total= buf_pool->curr_size; + export_vars.innodb_buffer_pool_pages_misc= buf_pool->max_size - + UT_LIST_GET_LEN(buf_pool->LRU) - UT_LIST_GET_LEN(buf_pool->free); + export_vars.innodb_page_size= UNIV_PAGE_SIZE; + export_vars.innodb_log_waits= srv_log_waits; + export_vars.innodb_os_log_written= srv_os_log_written; + export_vars.innodb_os_log_fsyncs= fil_n_log_flushes; + export_vars.innodb_os_log_pending_fsyncs= fil_n_pending_log_flushes; + export_vars.innodb_os_log_pending_writes= srv_os_log_pending_writes; + export_vars.innodb_log_write_requests= srv_log_write_requests; + export_vars.innodb_log_writes= srv_log_writes; + export_vars.innodb_dblwr_pages_written= srv_dblwr_pages_written; + export_vars.innodb_dblwr_writes= srv_dblwr_writes; + export_vars.innodb_pages_created= buf_pool->n_pages_created; + export_vars.innodb_pages_read= buf_pool->n_pages_read; + export_vars.innodb_pages_written= buf_pool->n_pages_written; + export_vars.innodb_row_lock_waits= srv_n_lock_wait_count; + export_vars.innodb_row_lock_current_waits= srv_n_lock_wait_current_count; + export_vars.innodb_row_lock_time= srv_n_lock_wait_time / 10000; if (srv_n_lock_wait_count > 0) { export_vars.innodb_row_lock_time_avg = (ulint) (srv_n_lock_wait_time / 10000 / srv_n_lock_wait_count); } else { export_vars.innodb_row_lock_time_avg = 0; } - export_vars.innodb_row_lock_time_max= srv_n_lock_max_wait_time / 10000; - export_vars.innodb_rows_read= srv_n_rows_read; - export_vars.innodb_rows_inserted= srv_n_rows_inserted; - export_vars.innodb_rows_updated= srv_n_rows_updated; - export_vars.innodb_rows_deleted= srv_n_rows_deleted; - mutex_exit(&srv_innodb_monitor_mutex); + export_vars.innodb_row_lock_time_max= srv_n_lock_max_wait_time / 10000; + export_vars.innodb_rows_read= srv_n_rows_read; + export_vars.innodb_rows_inserted= srv_n_rows_inserted; + export_vars.innodb_rows_updated= srv_n_rows_updated; + export_vars.innodb_rows_deleted= srv_n_rows_deleted; + mutex_exit(&srv_innodb_monitor_mutex); } @@ -1843,7 +1859,7 @@ srv_lock_timeout_and_monitor_thread( { srv_slot_t* slot; double time_elapsed; - time_t current_time; + time_t current_time; time_t last_table_monitor_time; time_t last_monitor_time; ibool some_waits; @@ -1852,7 +1868,7 @@ srv_lock_timeout_and_monitor_thread( #ifdef UNIV_DEBUG_THREAD_CREATION fprintf(stderr, "Lock timeout thread starts, id %lu\n", - os_thread_pf(os_thread_get_curr_id())); + os_thread_pf(os_thread_get_curr_id())); #endif UT_NOT_USED(arg); srv_last_monitor_time = time(NULL); @@ -1869,71 +1885,71 @@ loop: /* 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); - + if (time_elapsed > 15) { - last_monitor_time = time(NULL); + last_monitor_time = time(NULL); - if (srv_print_innodb_monitor) { - srv_printf_innodb_monitor(stderr, NULL, NULL); - } + if (srv_print_innodb_monitor) { + srv_printf_innodb_monitor(stderr, NULL, NULL); + } - if (srv_innodb_status) { - mutex_enter(&srv_monitor_file_mutex); - rewind(srv_monitor_file); - srv_printf_innodb_monitor(srv_monitor_file, NULL, NULL); - os_file_set_eof(srv_monitor_file); - mutex_exit(&srv_monitor_file_mutex); - } + if (srv_innodb_status) { + mutex_enter(&srv_monitor_file_mutex); + rewind(srv_monitor_file); + srv_printf_innodb_monitor(srv_monitor_file, NULL, NULL); + os_file_set_eof(srv_monitor_file); + mutex_exit(&srv_monitor_file_mutex); + } - if (srv_print_innodb_tablespace_monitor - && difftime(current_time, last_table_monitor_time) > 60) { + if (srv_print_innodb_tablespace_monitor + && difftime(current_time, last_table_monitor_time) > 60) { - last_table_monitor_time = time(NULL); + last_table_monitor_time = time(NULL); - fputs("================================================\n", - stderr); + fputs("================================================\n", + stderr); - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); - fputs(" INNODB TABLESPACE MONITOR OUTPUT\n" - "================================================\n", - stderr); - - fsp_print(0); - fputs("Validating tablespace\n", stderr); - fsp_validate(0); - fputs("Validation ok\n" - "---------------------------------------\n" - "END OF INNODB TABLESPACE MONITOR OUTPUT\n" - "=======================================\n", - stderr); - } + fputs(" INNODB TABLESPACE MONITOR OUTPUT\n" + "================================================\n", + stderr); - if (srv_print_innodb_table_monitor - && difftime(current_time, last_table_monitor_time) > 60) { + fsp_print(0); + fputs("Validating tablespace\n", stderr); + fsp_validate(0); + fputs("Validation ok\n" + "---------------------------------------\n" + "END OF INNODB TABLESPACE MONITOR OUTPUT\n" + "=======================================\n", + stderr); + } - last_table_monitor_time = time(NULL); + if (srv_print_innodb_table_monitor + && difftime(current_time, last_table_monitor_time) > 60) { - fputs("===========================================\n", stderr); + last_table_monitor_time = time(NULL); - ut_print_timestamp(stderr); + fputs("===========================================\n", stderr); + + ut_print_timestamp(stderr); - fputs(" INNODB TABLE MONITOR OUTPUT\n" - "===========================================\n", - stderr); - dict_print(); + fputs(" INNODB TABLE MONITOR OUTPUT\n" + "===========================================\n", + stderr); + dict_print(); - fputs("-----------------------------------\n" - "END OF INNODB TABLE MONITOR OUTPUT\n" - "==================================\n", - stderr); - } + fputs("-----------------------------------\n" + "END OF INNODB TABLE MONITOR OUTPUT\n" + "==================================\n", + stderr); + } } mutex_enter(&kernel_mutex); @@ -1942,7 +1958,7 @@ loop: /* Check of all slots if a thread is waiting there, and if it has exceeded the time limit */ - + for (i = 0; i < OS_THREAD_MAX_N; i++) { slot = srv_mysql_table + i; @@ -1951,9 +1967,9 @@ loop: some_waits = TRUE; wait_time = ut_difftime(ut_time(), slot->suspend_time); - - if (srv_lock_wait_timeout < 100000000 && - (wait_time > (double) srv_lock_wait_timeout + + if (srv_lock_wait_timeout < 100000000 && + (wait_time > (double) srv_lock_wait_timeout || wait_time < 0)) { /* Timeout exceeded or a wrap-around in system @@ -1963,10 +1979,10 @@ loop: possible that the lock has already been granted: in that case do nothing */ - if (thr_get_trx(slot->thr)->wait_lock) { - lock_cancel_waiting_and_release( - thr_get_trx(slot->thr)->wait_lock); - } + if (thr_get_trx(slot->thr)->wait_lock) { + lock_cancel_waiting_and_release( + thr_get_trx(slot->thr)->wait_lock); + } } } } @@ -2037,7 +2053,7 @@ srv_error_monitor_thread( #ifdef UNIV_DEBUG_THREAD_CREATION fprintf(stderr, "Error monitor thread starts, id %lu\n", - os_thread_pf(os_thread_get_curr_id())); + os_thread_pf(os_thread_get_curr_id())); #endif loop: srv_error_monitor_active = TRUE; @@ -2121,7 +2137,7 @@ srv_active_wake_master_thread(void) /*===============================*/ { srv_activity_count++; - + if (srv_n_threads_active[SRV_MASTER] == 0) { mutex_enter(&kernel_mutex); @@ -2140,7 +2156,7 @@ srv_wake_master_thread(void) /*========================*/ { srv_activity_count++; - + mutex_enter(&kernel_mutex); srv_release_threads(SRV_MASTER, 1); @@ -2164,8 +2180,8 @@ srv_master_thread( os_thread_create */ { os_event_t event; - time_t last_flush_time; - time_t current_time; + time_t last_flush_time; + time_t current_time; ulint old_activity_count; ulint n_pages_purged; ulint n_bytes_merged; @@ -2178,15 +2194,15 @@ srv_master_thread( ulint n_pend_ios; ibool skip_sleep = FALSE; ulint i; - + #ifdef UNIV_DEBUG_THREAD_CREATION fprintf(stderr, "Master thread starts, id %lu\n", - os_thread_pf(os_thread_get_curr_id())); + os_thread_pf(os_thread_get_curr_id())); #endif srv_main_thread_process_no = os_proc_get_number(); srv_main_thread_id = os_thread_pf(os_thread_get_curr_id()); - - srv_table_reserve_slot(SRV_MASTER); + + srv_table_reserve_slot(SRV_MASTER); mutex_enter(&kernel_mutex); @@ -2225,10 +2241,10 @@ loop: n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read + buf_pool->n_pages_written; srv_main_thread_op_info = "sleeping"; - + if (!skip_sleep) { - os_thread_sleep(1000000); + os_thread_sleep(1000000); } skip_sleep = FALSE; @@ -2277,19 +2293,19 @@ loop: } if (buf_get_modified_ratio_pct() > - srv_max_buf_pool_modified_pct) { + srv_max_buf_pool_modified_pct) { /* Try to keep the number of modified pages in the buffer pool under the limit wished by the user */ - + n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max); - /* If we had to do the flush, it may have taken + /* If we had to do the flush, it may have taken even more than 1 second, and also, there may be more to flush. Do not sleep 1 second during the next iteration of this loop. */ - + skip_sleep = TRUE; } @@ -2309,7 +2325,7 @@ loop: /* Check magic numbers of every allocated mem block once in 10 seconds */ mem_validate_all_blocks(); -#endif +#endif /* If there were less than 200 i/os during the 10 second period, we assume that there is free disk i/o capacity available, and it makes sense to flush 100 pages. */ @@ -2337,7 +2353,7 @@ loop: /* We run a full purge every 10 seconds, even if the server were active */ - + n_pages_purged = 1; last_flush_time = time(NULL); @@ -2357,11 +2373,11 @@ loop: if (difftime(current_time, last_flush_time) > 1) { srv_main_thread_op_info = "flushing log"; - log_buffer_flush_to_disk(); + log_buffer_flush_to_disk(); last_flush_time = current_time; } } - + srv_main_thread_op_info = "flushing buffer pool pages"; /* Flush a few oldest pages to make a new checkpoint younger */ @@ -2372,14 +2388,14 @@ loop: (> 70 %), we assume we can afford reserving the disk(s) for the time it requires to flush 100 pages */ - n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, + n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max); } else { - /* Otherwise, we only flush a small number of pages so that + /* Otherwise, we only flush a small number of pages so that we do not unnecessarily use much disk i/o capacity from other work */ - n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10, + n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10, ut_dulint_max); } @@ -2392,7 +2408,7 @@ loop: srv_main_thread_op_info = "reserving kernel mutex"; mutex_enter(&kernel_mutex); - + /* ---- When there is database activity, we jump from here back to the start of loop */ @@ -2400,7 +2416,7 @@ loop: mutex_exit(&kernel_mutex); goto loop; } - + mutex_exit(&kernel_mutex); /* If the database is quiet, we enter the background loop */ @@ -2413,24 +2429,24 @@ background_loop: /* The server has been quiet for a while: start running background operations */ - + srv_main_thread_op_info = "doing background drop tables"; n_tables_to_drop = row_drop_tables_for_mysql_in_background(); if (n_tables_to_drop > 0) { - /* Do not monopolize the CPU even if there are tables waiting + /* Do not monopolize the CPU even if there are tables waiting in the background drop queue. (It is essentially a bug if MySQL tries to drop a table while there are still open handles to it and we had to put it to the background drop queue.) */ os_thread_sleep(100000); } - + srv_main_thread_op_info = "purging"; /* Run a full purge */ - + n_pages_purged = 1; last_flush_time = time(NULL); @@ -2449,7 +2465,7 @@ background_loop: if (difftime(current_time, last_flush_time) > 1) { srv_main_thread_op_info = "flushing log"; - log_buffer_flush_to_disk(); + log_buffer_flush_to_disk(); last_flush_time = current_time; } } @@ -2466,9 +2482,9 @@ background_loop: srv_main_thread_op_info = "doing insert buffer merge"; if (srv_fast_shutdown && srv_shutdown_state > 0) { - n_bytes_merged = 0; + n_bytes_merged = 0; } else { - n_bytes_merged = ibuf_contract_for_n_pages(TRUE, 20); + n_bytes_merged = ibuf_contract_for_n_pages(TRUE, 20); } srv_main_thread_op_info = "reserving kernel mutex"; @@ -2479,7 +2495,7 @@ background_loop: goto loop; } mutex_exit(&kernel_mutex); - + flush_loop: srv_main_thread_op_info = "flushing buffer pool pages"; @@ -2501,7 +2517,7 @@ flush_loop: goto loop; } mutex_exit(&kernel_mutex); - + srv_main_thread_op_info = "waiting for buffer pool flush to end"; buf_flush_wait_batch_end(BUF_FLUSH_LIST); @@ -2517,7 +2533,7 @@ flush_loop: /* Try to keep the number of modified pages in the buffer pool under the limit wished by the user */ - + goto flush_loop; } @@ -2531,7 +2547,7 @@ flush_loop: mutex_exit(&kernel_mutex); /* srv_main_thread_op_info = "archiving log (if log archive is on)"; - + log_archive_do(FALSE, &n_bytes_archived); */ n_bytes_archived = 0; @@ -2559,10 +2575,10 @@ flush_loop: goto background_loop; } - + /* There is no work for background operations either: suspend master thread to wait for more server activity */ - + suspend_thread: srv_main_thread_op_info = "suspending"; @@ -2583,10 +2599,10 @@ suspend_thread: os_event_wait(event); if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { - /* This is only extra safety, the thread should exit + /* This is only extra safety, the thread should exit already when the event wait ends */ - os_thread_exit(NULL); + os_thread_exit(NULL); } /* When there is user activity, InnoDB will set the event and the main @@ -2598,11 +2614,11 @@ suspend_thread: thread should always use that to exit and not use return() to exit. The thread actually never comes here because it is exited in an os_event_wait(). */ - + os_thread_exit(NULL); #ifndef __WIN__ - return(NULL); /* Not reached */ + return(NULL); /* Not reached */ #else return(0); #endif diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c index e5151ebf631..c792d600500 100644 --- a/storage/innobase/srv/srv0start.c +++ b/storage/innobase/srv/srv0start.c @@ -66,22 +66,22 @@ dulint srv_shutdown_lsn; ibool srv_have_fullfsync = FALSE; #endif -ibool srv_start_raw_disk_in_use = FALSE; +ibool srv_start_raw_disk_in_use = FALSE; -static ibool srv_start_has_been_called = FALSE; +ulint srv_sizeof_trx_t_in_ha_innodb_cc; -ulint srv_sizeof_trx_t_in_ha_innodb_cc; - -ibool srv_startup_is_before_trx_rollback_phase = FALSE; -ibool srv_is_being_started = FALSE; -static ibool srv_was_started = FALSE; +ibool srv_startup_is_before_trx_rollback_phase = FALSE; +ibool srv_is_being_started = FALSE; +#ifndef UNIV_HOTBACKUP +static ibool srv_start_has_been_called = FALSE; +static ibool srv_was_started = FALSE; +#endif /* !UNIV_HOTBACKUP */ /* At a shutdown the value first climbs to SRV_SHUTDOWN_CLEANUP and then to SRV_SHUTDOWN_LAST_PHASE */ ulint srv_shutdown_state = 0; -ibool measure_cont = FALSE; - +#ifndef UNIV_HOTBACKUP static os_file_t files[1000]; static mutex_t ios_mutex; @@ -96,8 +96,9 @@ static os_fast_mutex_t srv_os_test_mutex; /* Name of srv_monitor_file */ static char* srv_monitor_file_name; +#endif /* !UNIV_HOTBACKUP */ -#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD +#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD #define SRV_MAX_N_PENDING_SYNC_IOS 100 @@ -105,7 +106,7 @@ static char* srv_monitor_file_name; #ifdef HAVE_purify static int inno_bcmp(register const char *s1, register const char *s2, - register uint len) + register uint len) { while (len-- != 0 && *s1++ == *s2++) ; return len+1; @@ -146,7 +147,7 @@ srv_parse_data_file_paths_and_sizes( *max_auto_extend_size = 0; input_str = str; - + /* First calculate the number of data files and check syntax: path:size[M | G];path:size[M | G]... . Note that a Windows path may contain a drive name and a ':'. */ @@ -155,9 +156,9 @@ srv_parse_data_file_paths_and_sizes( path = str; while ((*str != ':' && *str != '\0') - || (*str == ':' - && (*(str + 1) == '\\' || *(str + 1) == '/' - || *(str + 1) == ':'))) { + || (*str == ':' + && (*(str + 1) == '\\' || *(str + 1) == '/' + || *(str + 1) == ':'))) { str++; } @@ -174,17 +175,17 @@ srv_parse_data_file_paths_and_sizes( if (*str != 'M' && *str != 'G') { size = size / (1024 * 1024); } else if (*str == 'G') { - size = size * 1024; + size = size * 1024; str++; } else { - str++; + str++; } - if (0 == memcmp(str, ":autoextend", (sizeof ":autoextend") - 1)) { + if (0 == memcmp(str, ":autoextend", (sizeof ":autoextend") - 1)) { str += (sizeof ":autoextend") - 1; - if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) { + if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) { str += (sizeof ":max:") - 1; @@ -195,10 +196,10 @@ srv_parse_data_file_paths_and_sizes( if (*str != 'M' && *str != 'G') { size = size / (1024 * 1024); } else if (*str == 'G') { - size = size * 1024; + size = size * 1024; str++; } else { - str++; + str++; } } @@ -208,15 +209,15 @@ srv_parse_data_file_paths_and_sizes( } } - if (strlen(str) >= 6 + if (strlen(str) >= 6 && *str == 'n' - && *(str + 1) == 'e' - && *(str + 2) == 'w') { - str += 3; + && *(str + 1) == 'e' + && *(str + 2) == 'w') { + str += 3; } - if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') { - str += 3; + if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') { + str += 3; } if (size == 0) { @@ -233,6 +234,13 @@ srv_parse_data_file_paths_and_sizes( } } + if (i == 0) { + /* If innodb_data_file_path was defined it must contain + at least one data file definition */ + + return(FALSE); + } + *data_file_names = (char**)ut_malloc(i * sizeof(void*)); *data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint)); *data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint)); @@ -253,9 +261,9 @@ srv_parse_data_file_paths_and_sizes( \\.\C::1Gnewraw or \\.\PHYSICALDRIVE2:1Gnewraw */ while ((*str != ':' && *str != '\0') - || (*str == ':' - && (*(str + 1) == '\\' || *(str + 1) == '/' - || *(str + 1) == ':'))) { + || (*str == ':' + && (*(str + 1) == '\\' || *(str + 1) == '/' + || *(str + 1) == ':'))) { str++; } @@ -272,22 +280,22 @@ srv_parse_data_file_paths_and_sizes( if ((*str != 'M') && (*str != 'G')) { size = size / (1024 * 1024); } else if (*str == 'G') { - size = size * 1024; + size = size * 1024; str++; } else { - str++; + str++; } (*data_file_names)[i] = path; (*data_file_sizes)[i] = size; - if (0 == memcmp(str, ":autoextend", (sizeof ":autoextend") - 1)) { + if (0 == memcmp(str, ":autoextend", (sizeof ":autoextend") - 1)) { *is_auto_extending = TRUE; str += (sizeof ":autoextend") - 1; - if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) { + if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) { str += (sizeof ":max:") - 1; @@ -298,10 +306,10 @@ srv_parse_data_file_paths_and_sizes( if (*str != 'M' && *str != 'G') { size = size / (1024 * 1024); } else if (*str == 'G') { - size = size * 1024; + size = size * 1024; str++; } else { - str++; + str++; } *max_auto_extend_size = size; @@ -312,23 +320,23 @@ srv_parse_data_file_paths_and_sizes( return(FALSE); } } - + (*data_file_is_raw_partition)[i] = 0; - if (strlen(str) >= 6 + if (strlen(str) >= 6 && *str == 'n' - && *(str + 1) == 'e' - && *(str + 2) == 'w') { - str += 3; - (*data_file_is_raw_partition)[i] = SRV_NEW_RAW; + && *(str + 1) == 'e' + && *(str + 2) == 'w') { + str += 3; + (*data_file_is_raw_partition)[i] = SRV_NEW_RAW; } if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') { - str += 3; - - if ((*data_file_is_raw_partition)[i] == 0) { - (*data_file_is_raw_partition)[i] = SRV_OLD_RAW; - } + str += 3; + + if ((*data_file_is_raw_partition)[i] == 0) { + (*data_file_is_raw_partition)[i] = SRV_OLD_RAW; + } } i++; @@ -358,7 +366,7 @@ srv_parse_log_group_home_dirs( ulint i = 0; input_str = str; - + /* First calculate the number of directories and check syntax: path;path;... */ @@ -379,6 +387,13 @@ srv_parse_log_group_home_dirs( } } + if (i != 1) { + /* If innodb_log_group_home_dir was defined it must + contain exactly one path definition under current MySQL */ + + return(FALSE); + } + *log_group_home_dirs = (char**) ut_malloc(i * sizeof(void*)); /* Then store the actual values to our array */ @@ -406,6 +421,7 @@ srv_parse_log_group_home_dirs( return(TRUE); } +#ifndef UNIV_HOTBACKUP /************************************************************************ I/o-handler thread function. */ static @@ -421,7 +437,7 @@ io_handler_thread( { ulint segment; ulint i; - + segment = *((ulint*)arg); #ifdef UNIV_DEBUG_THREAD_CREATION @@ -449,6 +465,7 @@ io_handler_thread( return(0); #endif } +#endif /* !UNIV_HOTBACKUP */ #ifdef __WIN__ #define SRV_PATH_SEPARATOR '\\' @@ -474,7 +491,7 @@ srv_normalize_path_for_win( } #endif } - + /************************************************************************* Adds a slash or a backslash to the end of a string if it is missing and the string is not empty. */ @@ -502,6 +519,7 @@ srv_add_path_separator_if_needed( return(out_str); } +#ifndef UNIV_HOTBACKUP /************************************************************************* Calculates the low 32 bits when a file size which is given as a number database pages is converted to the number of bytes. */ @@ -530,7 +548,6 @@ srv_calc_high32( return(file_size >> (32 - UNIV_PAGE_SIZE_SHIFT)); } -#ifndef UNIV_HOTBACKUP /************************************************************************* Creates or opens the log files and closes them. */ static @@ -538,8 +555,8 @@ ulint open_or_create_log_file( /*====================*/ /* out: DB_SUCCESS or error code */ - ibool create_new_db, /* in: TRUE if we should create a - new database */ + ibool create_new_db, /* in: TRUE if we should create a + new database */ ibool* log_file_created, /* out: TRUE if new log file created */ ibool log_file_has_been_opened,/* in: TRUE if a log file has been @@ -570,7 +587,7 @@ open_or_create_log_file( if (ret == FALSE) { if (os_file_get_last_error(FALSE) != OS_FILE_ALREADY_EXISTS #ifdef UNIV_AIX - /* AIX 5.1 after security patch ML7 may have errno set + /* AIX 5.1 after security patch ML7 may have errno set to 0 here, which causes our function to return 100; work around that AIX problem */ && os_file_get_last_error(FALSE) != 100 @@ -578,7 +595,7 @@ open_or_create_log_file( ) { fprintf(stderr, "InnoDB: Error in creating or opening %s\n", name); - + return(DB_ERROR); } @@ -587,29 +604,29 @@ open_or_create_log_file( if (!ret) { fprintf(stderr, "InnoDB: Error in opening %s\n", name); - + return(DB_ERROR); } ret = os_file_get_size(files[i], &size, &size_high); ut_a(ret); - + if (size != srv_calc_low32(srv_log_file_size) - || size_high != srv_calc_high32(srv_log_file_size)) { - + || size_high != srv_calc_high32(srv_log_file_size)) { + fprintf(stderr, "InnoDB: Error: log file %s is of different size %lu %lu bytes\n" "InnoDB: than specified in the .cnf file %lu %lu bytes!\n", name, (ulong) size_high, (ulong) size, (ulong) srv_calc_high32(srv_log_file_size), (ulong) srv_calc_low32(srv_log_file_size)); - + return(DB_ERROR); - } + } } else { *log_file_created = TRUE; - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Log file %s did not exist: new to be created\n", @@ -620,11 +637,11 @@ open_or_create_log_file( } fprintf(stderr, "InnoDB: Setting log file %s size to %lu MB\n", - name, (ulong) srv_log_file_size + name, (ulong) srv_log_file_size >> (20 - UNIV_PAGE_SIZE_SHIFT)); fprintf(stderr, - "InnoDB: Database physically writes the file full: wait...\n"); + "InnoDB: Database physically writes the file full: wait...\n"); ret = os_file_set_size(name, files[i], srv_calc_low32(srv_log_file_size), @@ -644,7 +661,7 @@ open_or_create_log_file( if (i == 0) { /* Create in memory the file space object which is for this log group */ - + fil_space_create(name, 2 * k + SRV_LOG_SPACE_FIRST_ID, FIL_LOG); } @@ -661,7 +678,7 @@ open_or_create_log_file( if (k == 0 && i == 0) { arch_space_id = 2 * k + 1 + SRV_LOG_SPACE_FIRST_ID; - fil_space_create("arch_log_space", arch_space_id, FIL_LOG); + fil_space_create("arch_log_space", arch_space_id, FIL_LOG); } else { arch_space_id = ULINT_UNDEFINED; } @@ -713,7 +730,7 @@ open_or_create_data_files( } *sum_of_new_sizes = 0; - + *create_new_db = FALSE; srv_normalize_path_for_win(srv_data_home); @@ -725,7 +742,7 @@ open_or_create_data_files( ut_a(strlen(srv_data_home) + strlen(srv_data_file_names[i]) < (sizeof name) - 1); sprintf(name, "%s%s", srv_data_home, srv_data_file_names[i]); - + if (srv_data_file_is_raw_partition[i] == 0) { /* First we try to create the file: if it already @@ -737,10 +754,10 @@ open_or_create_data_files( if (ret == FALSE && os_file_get_last_error(FALSE) != OS_FILE_ALREADY_EXISTS #ifdef UNIV_AIX - /* AIX 5.1 after security patch ML7 may have + /* AIX 5.1 after security patch ML7 may have errno set to 0 here, which causes our function to return 100; work around that AIX problem */ - && os_file_get_last_error(FALSE) != 100 + && os_file_get_last_error(FALSE) != 100 #endif ) { fprintf(stderr, @@ -784,7 +801,7 @@ open_or_create_data_files( name); return(DB_ERROR); } - + if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) { files[i] = os_file_create( name, OS_FILE_OPEN_RAW, OS_FILE_NORMAL, @@ -816,20 +833,20 @@ open_or_create_data_files( ret = os_file_get_size(files[i], &size, &size_high); ut_a(ret); /* Round size downward to megabytes */ - + rounded_size_pages = (size / (1024 * 1024) - + 4096 * size_high) - << (20 - UNIV_PAGE_SIZE_SHIFT); + + 4096 * size_high) + << (20 - UNIV_PAGE_SIZE_SHIFT); if (i == srv_n_data_files - 1 - && srv_auto_extend_last_data_file) { + && srv_auto_extend_last_data_file) { if (srv_data_file_sizes[i] > - rounded_size_pages - || (srv_last_file_size_max > 0 - && srv_last_file_size_max < - rounded_size_pages)) { - + rounded_size_pages + || (srv_last_file_size_max > 0 + && srv_last_file_size_max < + rounded_size_pages)) { + fprintf(stderr, "InnoDB: Error: auto-extending data file %s is of a different size\n" "InnoDB: %lu pages (rounded down to MB) than specified in the .cnf file:\n" @@ -840,19 +857,19 @@ open_or_create_data_files( return(DB_ERROR); } - + srv_data_file_sizes[i] = rounded_size_pages; } - + if (rounded_size_pages != srv_data_file_sizes[i]) { fprintf(stderr, "InnoDB: Error: data file %s is of a different size\n" "InnoDB: %lu pages (rounded down to MB)\n" "InnoDB: than specified in the .cnf file %lu pages!\n", name, - (ulong) rounded_size_pages, - (ulong) srv_data_file_sizes[i]); - + (ulong) rounded_size_pages, + (ulong) srv_data_file_sizes[i]); + return(DB_ERROR); } skip_size_check: @@ -864,28 +881,28 @@ skip_size_check: min_flushed_lsn, max_flushed_lsn); one_opened = TRUE; } else { - /* We created the data file and now write it full of + /* We created the data file and now write it full of zeros */ one_created = TRUE; if (i > 0) { - ut_print_timestamp(stderr); - fprintf(stderr, + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Data file %s did not exist: new to be created\n", name); } else { - fprintf(stderr, - "InnoDB: The first specified data file %s did not exist:\n" + fprintf(stderr, + "InnoDB: The first specified data file %s did not exist:\n" "InnoDB: a new database to be created!\n", name); *create_new_db = TRUE; } - - ut_print_timestamp(stderr); - fprintf(stderr, + + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Setting file %s size to %lu MB\n", - name, (ulong) (srv_data_file_sizes[i] - >> (20 - UNIV_PAGE_SIZE_SHIFT))); + name, (ulong) (srv_data_file_sizes[i] + >> (20 - UNIV_PAGE_SIZE_SHIFT))); fprintf(stderr, "InnoDB: Database physically writes the file full: wait...\n"); @@ -895,7 +912,7 @@ skip_size_check: srv_calc_high32(srv_data_file_sizes[i])); if (!ret) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error in creating %s: probably out of disk space\n", name); return(DB_ERROR); @@ -916,9 +933,9 @@ skip_size_check: if (srv_data_file_is_raw_partition[i]) { - fil_node_create(name, srv_data_file_sizes[i], 0, TRUE); + fil_node_create(name, srv_data_file_sizes[i], 0, TRUE); } else { - fil_node_create(name, srv_data_file_sizes[i], 0, + fil_node_create(name, srv_data_file_sizes[i], 0, FALSE); } } @@ -952,13 +969,13 @@ innobase_start_or_create_for_mysql(void) ulint min_arch_log_no; ulint max_arch_log_no; #endif /* UNIV_LOG_ARCHIVE */ - ulint sum_of_new_sizes; + ulint sum_of_new_sizes; ulint sum_of_data_file_sizes; ulint tablespace_size_in_header; ulint err; ulint i; ibool srv_file_per_table_original_value = srv_file_per_table; - mtr_t mtr; + mtr_t mtr; #ifdef HAVE_DARWIN_THREADS # ifdef F_FULLFSYNC /* This executable has been compiled on Mac OS X 10.3 or later. @@ -994,30 +1011,30 @@ innobase_start_or_create_for_mysql(void) 0 */ #ifdef UNIV_DEBUG fprintf(stderr, -"InnoDB: !!!!!!!!!!!!!! UNIV_DEBUG switched on !!!!!!!!!!!!!!!\n"); +"InnoDB: !!!!!!!!!!!!!! UNIV_DEBUG switched on !!!!!!!!!!!!!!!\n"); #endif #ifdef UNIV_SYNC_DEBUG fprintf(stderr, -"InnoDB: !!!!!!!!!!!!!! UNIV_SYNC_DEBUG switched on !!!!!!!!!!!!!!!\n"); +"InnoDB: !!!!!!!!!!!!!! UNIV_SYNC_DEBUG switched on !!!!!!!!!!!!!!!\n"); #endif #ifdef UNIV_SEARCH_DEBUG fprintf(stderr, -"InnoDB: !!!!!!!!!!!!!! UNIV_SEARCH_DEBUG switched on !!!!!!!!!!!!!!!\n"); +"InnoDB: !!!!!!!!!!!!!! UNIV_SEARCH_DEBUG switched on !!!!!!!!!!!!!!!\n"); #endif #ifdef UNIV_MEM_DEBUG fprintf(stderr, -"InnoDB: !!!!!!!!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!!!!!!!\n"); +"InnoDB: !!!!!!!!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!!!!!!!\n"); #endif #ifdef UNIV_SIMULATE_AWE fprintf(stderr, "InnoDB: !!!!!!!!!!!!!! UNIV_SIMULATE_AWE switched on !!!!!!!!!!!!!!!!!\n"); #endif - if (srv_sizeof_trx_t_in_ha_innodb_cc != (ulint)sizeof(trx_t)) { - fprintf(stderr, + if (srv_sizeof_trx_t_in_ha_innodb_cc != (ulint)sizeof(trx_t)) { + fprintf(stderr, "InnoDB: Error: trx_t size is %lu in ha_innodb.cc but %lu in srv0start.c\n" "InnoDB: Check that pthread_mutex_t is defined in the same way in these\n" "InnoDB: compilation modules. Cannot continue.\n", @@ -1032,7 +1049,7 @@ innobase_start_or_create_for_mysql(void) second time during the process lifetime. */ if (srv_start_has_been_called) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error:startup called second time during the process lifetime.\n" "InnoDB: In the MySQL Embedded Server Library you cannot call server_init()\n" "InnoDB: more than once during the process lifetime.\n"); @@ -1046,83 +1063,83 @@ innobase_start_or_create_for_mysql(void) /* yydebug = TRUE; */ srv_is_being_started = TRUE; - srv_startup_is_before_trx_rollback_phase = TRUE; + srv_startup_is_before_trx_rollback_phase = TRUE; os_aio_use_native_aio = FALSE; #if !defined(__WIN2000__) && !defined(UNIV_SIMULATE_AWE) if (srv_use_awe) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: You have specified innodb_buffer_pool_awe_mem_mb\n" "InnoDB: in my.cnf, but AWE can only be used in Windows 2000 and later.\n" "InnoDB: To use AWE, InnoDB must be compiled with __WIN2000__ defined.\n"); - return(DB_ERROR); + return(DB_ERROR); } #endif #ifdef __WIN__ if (os_get_os_version() == OS_WIN95 - || os_get_os_version() == OS_WIN31 - || os_get_os_version() == OS_WINNT) { + || os_get_os_version() == OS_WIN31 + || os_get_os_version() == OS_WINNT) { - /* On Win 95, 98, ME, Win32 subsystem for Windows 3.1, + /* On Win 95, 98, ME, Win32 subsystem for Windows 3.1, and NT use simulated aio. In NT Windows provides async i/o, but when run in conjunction with InnoDB Hot Backup, it seemed to corrupt the data files. */ - os_aio_use_native_aio = FALSE; + os_aio_use_native_aio = FALSE; } else { - /* On Win 2000 and XP use async i/o */ - os_aio_use_native_aio = TRUE; + /* On Win 2000 and XP use async i/o */ + os_aio_use_native_aio = TRUE; } -#endif - if (srv_file_flush_method_str == NULL) { - /* These are the default options */ +#endif + if (srv_file_flush_method_str == NULL) { + /* These are the default options */ srv_unix_file_flush_method = SRV_UNIX_FDATASYNC; srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; -#ifndef __WIN__ +#ifndef __WIN__ } else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) { - srv_unix_file_flush_method = SRV_UNIX_FDATASYNC; + srv_unix_file_flush_method = SRV_UNIX_FDATASYNC; } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) { - srv_unix_file_flush_method = SRV_UNIX_O_DSYNC; + srv_unix_file_flush_method = SRV_UNIX_O_DSYNC; } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) { - srv_unix_file_flush_method = SRV_UNIX_O_DIRECT; + srv_unix_file_flush_method = SRV_UNIX_O_DIRECT; } else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) { - srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC; + srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC; } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) { - srv_unix_file_flush_method = SRV_UNIX_NOSYNC; + srv_unix_file_flush_method = SRV_UNIX_NOSYNC; #else } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) { - srv_win_file_flush_method = SRV_WIN_IO_NORMAL; - os_aio_use_native_aio = FALSE; + srv_win_file_flush_method = SRV_WIN_IO_NORMAL; + os_aio_use_native_aio = FALSE; } else if (0 == ut_strcmp(srv_file_flush_method_str, "unbuffered")) { - srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; - os_aio_use_native_aio = FALSE; + srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; + os_aio_use_native_aio = FALSE; } else if (0 == ut_strcmp(srv_file_flush_method_str, "async_unbuffered")) { - srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; + srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; #endif } else { - fprintf(stderr, - "InnoDB: Unrecognized value %s for innodb_flush_method\n", - srv_file_flush_method_str); - return(DB_ERROR); + fprintf(stderr, + "InnoDB: Unrecognized value %s for innodb_flush_method\n", + srv_file_flush_method_str); + return(DB_ERROR); } /* Note that the call srv_boot() also changes the values of srv_pool_size etc. to the units used by InnoDB internally */ - /* Set the maximum number of threads which can wait for a semaphore - inside InnoDB: this is the 'sync wait array' size, as well as the + /* Set the maximum number of threads which can wait for a semaphore + inside InnoDB: this is the 'sync wait array' size, as well as the maximum number of threads that can wait in the 'srv_conc array' for their time to enter InnoDB. */ @@ -1132,24 +1149,24 @@ innobase_start_or_create_for_mysql(void) 40000 event semaphores. Comment from Novell, Inc.: also, these just take a lot of memory on NetWare. */ - srv_max_n_threads = 1000; + srv_max_n_threads = 1000; #else - if (srv_pool_size >= 1000 * 1024) { - /* Here we still have srv_pool_size counted - in kilobytes (in 4.0 this was in bytes) + if (srv_pool_size >= 1000 * 1024) { + /* Here we still have srv_pool_size counted + in kilobytes (in 4.0 this was in bytes) srv_boot() converts the value to - pages; if buffer pool is less than 1000 MB, - assume fewer threads. */ - srv_max_n_threads = 50000; - - } else if (srv_pool_size >= 8 * 1024) { - - srv_max_n_threads = 10000; - } else { - srv_max_n_threads = 1000; /* saves several MB of memory, - especially in 64-bit - computers */ - } + pages; if buffer pool is less than 1000 MB, + assume fewer threads. */ + srv_max_n_threads = 50000; + + } else if (srv_pool_size >= 8 * 1024) { + + srv_max_n_threads = 10000; + } else { + srv_max_n_threads = 1000; /* saves several MB of memory, + especially in 64-bit + computers */ + } #endif err = srv_boot(); /* This changes srv_pool_size to units of a page */ @@ -1180,6 +1197,20 @@ NetWare. */ } } + mutex_create(&srv_dict_tmpfile_mutex); + mutex_set_level(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION); + srv_dict_tmpfile = os_file_create_tmpfile(); + if (!srv_dict_tmpfile) { + return(DB_ERROR); + } + + mutex_create(&srv_misc_tmpfile_mutex); + mutex_set_level(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH); + srv_misc_tmpfile = os_file_create_tmpfile(); + if (!srv_misc_tmpfile) { + return(DB_ERROR); + } + /* Restrict the maximum number of file i/o threads */ if (srv_n_file_io_threads > SRV_MAX_N_IO_THREADS) { @@ -1187,7 +1218,7 @@ NetWare. */ } if (!os_aio_use_native_aio) { - /* In simulated aio we currently have use only for 4 threads */ + /* In simulated aio we currently have use only for 4 threads */ srv_n_file_io_threads = 4; os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD @@ -1200,7 +1231,7 @@ NetWare. */ srv_n_file_io_threads, SRV_MAX_N_PENDING_SYNC_IOS); } - + fil_init(srv_max_n_open_files); if (srv_use_awe) { @@ -1211,7 +1242,7 @@ NetWare. */ /* We must disable adaptive hash indexes because they do not tolerate remapping of pages in AWE */ - + srv_use_adaptive_hash_indexes = FALSE; ret = buf_pool_init(srv_pool_size, srv_pool_size, srv_awe_window_size); @@ -1229,7 +1260,7 @@ NetWare. */ fsp_init(); log_init(); - + lock_sys_create(srv_lock_table_size); /* Create i/o-handler threads: */ @@ -1238,7 +1269,7 @@ NetWare. */ n[i] = i; os_thread_create(io_handler_thread, n + i, thread_ids + i); - } + } #ifdef UNIV_LOG_ARCHIVE if (0 != ut_strcmp(srv_log_group_home_dirs[0], srv_arch_dir)) { @@ -1258,15 +1289,15 @@ NetWare. */ } sum_of_new_sizes = 0; - + for (i = 0; i < srv_n_data_files; i++) { #ifndef __WIN__ if (sizeof(off_t) < 5 && srv_data_file_sizes[i] >= 262144) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: file size must be < 4 GB with this MySQL binary\n" "InnoDB: and operating system combination, in some OS's < 2 GB\n"); - return(DB_ERROR); + return(DB_ERROR); } #endif sum_of_new_sizes += srv_data_file_sizes[i]; @@ -1286,7 +1317,7 @@ NetWare. */ &min_flushed_lsn, &max_flushed_lsn, &sum_of_new_sizes); if (err != DB_SUCCESS) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Could not open or create data files.\n" "InnoDB: If you tried to add new data files, and it failed here,\n" "InnoDB: you should now edit innodb_data_file_path in my.cnf back\n" @@ -1302,10 +1333,10 @@ NetWare. */ srv_normalize_path_for_win(srv_arch_dir); srv_arch_dir = srv_add_path_separator_if_needed(srv_arch_dir); #endif /* UNIV_LOG_ARCHIVE */ - + for (i = 0; i < srv_n_log_files; i++) { err = open_or_create_log_file(create_new_db, &log_file_created, - log_opened, 0, i); + log_opened, 0, i); if (err != DB_SUCCESS) { return((int) err); @@ -1317,8 +1348,8 @@ NetWare. */ log_opened = TRUE; } if ((log_opened && create_new_db) - || (log_opened && log_created)) { - fprintf(stderr, + || (log_opened && log_created)) { + fprintf(stderr, "InnoDB: Error: all log files must be created at the same time.\n" "InnoDB: All log files must be created also in database creation.\n" "InnoDB: If you want bigger or smaller log files, shut down the\n" @@ -1345,7 +1376,7 @@ NetWare. */ || max_arch_log_no != min_arch_log_no #endif /* UNIV_LOG_ARCHIVE */ ) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Cannot initialize created log files because\n" "InnoDB: data files were not in sync with each other\n" "InnoDB: or the data files are corrupt.\n"); @@ -1354,8 +1385,8 @@ NetWare. */ } if (ut_dulint_cmp(max_flushed_lsn, ut_dulint_create(0, 1000)) - < 0) { - fprintf(stderr, + < 0) { + fprintf(stderr, "InnoDB: Cannot initialize created log files because\n" "InnoDB: data files are corrupt, or new data files were\n" "InnoDB: created when the database was started previous\n" @@ -1381,13 +1412,13 @@ NetWare. */ if (create_new_db) { mtr_start(&mtr); - fsp_header_init(0, sum_of_new_sizes, &mtr); + fsp_header_init(0, sum_of_new_sizes, &mtr); mtr_commit(&mtr); trx_sys_create(); dict_create(); - srv_startup_is_before_trx_rollback_phase = FALSE; + srv_startup_is_before_trx_rollback_phase = FALSE; #ifdef UNIV_LOG_ARCHIVE } else if (srv_archive_recovery) { @@ -1406,7 +1437,7 @@ NetWare. */ dict_boot(); trx_sys_init_at_db_start(); - srv_startup_is_before_trx_rollback_phase = FALSE; + srv_startup_is_before_trx_rollback_phase = FALSE; /* Initialize the fsp free limit global variable in the log system */ @@ -1417,7 +1448,7 @@ NetWare. */ } else { /* We always try to do a recovery, even if the database had been shut down normally: this is the normal startup path */ - + err = recv_recovery_from_checkpoint_start(LOG_CHECKPOINT, ut_dulint_max, min_flushed_lsn, @@ -1450,7 +1481,7 @@ NetWare. */ In a normal startup, we create the space objects for every table in the InnoDB data dictionary that has an .ibd file. - + We also determine the maximum tablespace id used. TODO: We may have incomplete transactions in the @@ -1461,7 +1492,7 @@ NetWare. */ recv_needed_recovery); } - srv_startup_is_before_trx_rollback_phase = FALSE; + srv_startup_is_before_trx_rollback_phase = FALSE; /* Initialize the fsp free limit global variable in the log system */ @@ -1472,12 +1503,12 @@ NetWare. */ recv_recovery_from_checkpoint_finish(); } - + if (!create_new_db && sum_of_new_sizes > 0) { /* New data file(s) were added */ mtr_start(&mtr); - fsp_header_inc_size(0, sum_of_new_sizes, &mtr); + fsp_header_inc_size(0, sum_of_new_sizes, &mtr); mtr_commit(&mtr); @@ -1510,8 +1541,8 @@ NetWare. */ #endif /* UNIV_LOG_ARCHIVE */ if (srv_measure_contention) { - /* os_thread_create(&test_measure_cont, NULL, thread_ids + - SRV_MAX_N_IO_THREADS); */ + /* os_thread_create(&test_measure_cont, NULL, thread_ids + + SRV_MAX_N_IO_THREADS); */ } /* fprintf(stderr, "Max allowed record size %lu\n", @@ -1519,28 +1550,28 @@ NetWare. */ /* Create the thread which watches the timeouts for lock waits and prints InnoDB monitor info */ - + os_thread_create(&srv_lock_timeout_and_monitor_thread, NULL, - thread_ids + 2 + SRV_MAX_N_IO_THREADS); + thread_ids + 2 + SRV_MAX_N_IO_THREADS); /* Create the thread which warns of long semaphore waits */ os_thread_create(&srv_error_monitor_thread, NULL, - thread_ids + 3 + SRV_MAX_N_IO_THREADS); + thread_ids + 3 + SRV_MAX_N_IO_THREADS); srv_was_started = TRUE; srv_is_being_started = FALSE; #ifdef UNIV_DEBUG - /* Wait a while so that the created threads have time to suspend + /* Wait a while so that the created threads have time to suspend themselves before we switch sync debugging on; otherwise a thread may execute mutex_enter() before the checks are on, and mutex_exit() after the checks are on, which will cause an assertion failure in sync debug. */ - os_thread_sleep(3000000); + os_thread_sleep(3000000); #endif sync_order_checks_on = TRUE; - if (trx_doublewrite == NULL) { + if (trx_doublewrite == NULL) { /* Create the doublewrite buffer to a new tablespace */ trx_sys_create_doublewrite_buf(); @@ -1551,7 +1582,7 @@ NetWare. */ if (err != DB_SUCCESS) { return((int)DB_ERROR); } - + /* Create the master thread which does purge and other utility operations */ @@ -1561,7 +1592,7 @@ NetWare. */ /* buf_debug_prints = TRUE; */ #endif /* UNIV_DEBUG */ sum_of_data_file_sizes = 0; - + for (i = 0; i < srv_n_data_files; i++) { sum_of_data_file_sizes += srv_data_file_sizes[i]; } @@ -1574,11 +1605,11 @@ NetWare. */ fprintf(stderr, "InnoDB: Error: tablespace size stored in header is %lu pages, but\n" "InnoDB: the sum of data file sizes is %lu pages\n", - (ulong) tablespace_size_in_header, + (ulong) tablespace_size_in_header, (ulong) sum_of_data_file_sizes); if (srv_force_recovery == 0 - && sum_of_data_file_sizes < tablespace_size_in_header) { + && sum_of_data_file_sizes < tablespace_size_in_header) { /* This is a fatal error, the tail of a tablespace is missing */ @@ -1599,7 +1630,7 @@ NetWare. */ fprintf(stderr, "InnoDB: Error: tablespace size stored in header is %lu pages, but\n" "InnoDB: the sum of data file sizes is only %lu pages\n", - (ulong) tablespace_size_in_header, + (ulong) tablespace_size_in_header, (ulong) sum_of_data_file_sizes); if (srv_force_recovery == 0) { @@ -1619,23 +1650,23 @@ NetWare. */ os_fast_mutex_init(&srv_os_test_mutex); if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: pthread_mutex_trylock returns an unexpected value on\n" "InnoDB: success! Cannot continue.\n"); - exit(1); + exit(1); } os_fast_mutex_unlock(&srv_os_test_mutex); - os_fast_mutex_lock(&srv_os_test_mutex); + os_fast_mutex_lock(&srv_os_test_mutex); os_fast_mutex_unlock(&srv_os_test_mutex); os_fast_mutex_free(&srv_os_test_mutex); if (srv_print_verbose_log) { - ut_print_timestamp(stderr); - fprintf(stderr, + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Started; log sequence number %lu %lu\n", (ulong) ut_dulint_get_high(srv_start_lsn), (ulong) ut_dulint_get_low(srv_start_lsn)); @@ -1658,7 +1689,7 @@ NetWare. */ history list in all cases so that it would become empty after a full purge. That mean that we may purge 4.0 type undo log even after this phase. - + The insert buffer record format changed between 4.0 and 4.1.1. It is essential that the insert buffer is emptied here! */ @@ -1674,14 +1705,14 @@ NetWare. */ "waiting for server activity")) { ut_a(ibuf_is_empty()); - + break; } } fprintf(stderr, "InnoDB: Full purge and insert buffer merge completed.\n"); - trx_sys_mark_upgraded_to_multiple_tablespaces(); + trx_sys_mark_upgraded_to_multiple_tablespaces(); fprintf(stderr, "InnoDB: You have now successfully upgraded to the multiple tablespaces\n" @@ -1709,23 +1740,23 @@ NetWare. */ Shuts down the InnoDB database. */ int -innobase_shutdown_for_mysql(void) +innobase_shutdown_for_mysql(void) /*=============================*/ /* out: DB_SUCCESS or error code */ { - ulint i; + ulint i; #ifdef __NETWARE__ extern ibool panic_shutdown; #endif - if (!srv_was_started) { - if (srv_is_being_started) { - ut_print_timestamp(stderr); - fprintf(stderr, + if (!srv_was_started) { + if (srv_is_being_started) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Warning: shutting down a not properly started\n" " InnoDB: or created database!\n"); - } + } - return(DB_SUCCESS); + return(DB_SUCCESS); } /* 1. Flush the buffer pool to disk, write the current lsn to @@ -1735,7 +1766,7 @@ innobase_shutdown_for_mysql(void) if (srv_fast_shutdown == 2) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: MySQL has requested a very fast shutdown without flushing " "the InnoDB buffer pool to data files. At the next mysqld startup " @@ -1744,7 +1775,7 @@ innobase_shutdown_for_mysql(void) #ifdef __NETWARE__ if(!panic_shutdown) -#endif +#endif logs_empty_and_mark_files_at_shutdown(); if (srv_conc_n_threads != 0) { @@ -1758,9 +1789,9 @@ innobase_shutdown_for_mysql(void) srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS; - /* In a 'very fast' shutdown, we do not need to wait for these threads - to die; all which counts is that we flushed the log; a 'very fast' - shutdown is essentially a crash. */ + /* In a 'very fast' shutdown, we do not need to wait for these threads + to die; all which counts is that we flushed the log; a 'very fast' + shutdown is essentially a crash. */ if (srv_fast_shutdown == 2) { return(DB_SUCCESS); @@ -1771,11 +1802,11 @@ innobase_shutdown_for_mysql(void) os_thread_event_wait(). */ for (i = 0; i < 1000; i++) { - /* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM - HERE OR EARLIER */ - + /* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM + HERE OR EARLIER */ + /* a. Let the lock timeout thread exit */ - os_event_set(srv_lock_timeout_thread_event); + os_event_set(srv_lock_timeout_thread_event); /* b. srv error monitor thread exits automatically, no need to do anything here */ @@ -1790,7 +1821,7 @@ innobase_shutdown_for_mysql(void) os_mutex_enter(os_sync_mutex); if (os_thread_count == 0) { - /* All the threads have exited or are just exiting; + /* All the threads have exited or are just exiting; NOTE that the threads may not have completed their exit yet. Should we use pthread_join() to make sure they have exited? Now we just sleep 0.1 seconds and @@ -1809,9 +1840,9 @@ innobase_shutdown_for_mysql(void) } if (i == 1000) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Warning: %lu threads created by InnoDB had not exited at shutdown!\n", - (ulong) os_thread_count); + (ulong) os_thread_count); } if (srv_monitor_file) { @@ -1822,8 +1853,19 @@ innobase_shutdown_for_mysql(void) mem_free(srv_monitor_file_name); } } - + if (srv_dict_tmpfile) { + fclose(srv_dict_tmpfile); + srv_dict_tmpfile = 0; + } + + if (srv_misc_tmpfile) { + fclose(srv_misc_tmpfile); + srv_misc_tmpfile = 0; + } + mutex_free(&srv_monitor_file_mutex); + mutex_free(&srv_dict_tmpfile_mutex); + mutex_free(&srv_misc_tmpfile_mutex); /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside them */ @@ -1838,7 +1880,7 @@ innobase_shutdown_for_mysql(void) by a purge. */ if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: all read views were not closed before shutdown:\n" "InnoDB: %lu read views open \n", UT_LIST_GET_LEN(trx_sys->view_list) - 1); @@ -1850,10 +1892,10 @@ innobase_shutdown_for_mysql(void) ut_free_all_mem(); if (os_thread_count != 0 - || os_event_count != 0 - || os_mutex_count != 0 - || os_fast_mutex_count != 0) { - fprintf(stderr, + || os_event_count != 0 + || os_mutex_count != 0 + || os_fast_mutex_count != 0) { + fprintf(stderr, "InnoDB: Warning: some resources were not cleaned up in shutdown:\n" "InnoDB: threads %lu, events %lu, os_mutexes %lu, os_fast_mutexes %lu\n", (ulong) os_thread_count, (ulong) os_event_count, @@ -1868,11 +1910,11 @@ innobase_shutdown_for_mysql(void) } if (srv_print_verbose_log) { - ut_print_timestamp(stderr); - fprintf(stderr, + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Shutdown completed; log sequence number %lu %lu\n", - (ulong) ut_dulint_get_high(srv_shutdown_lsn), - (ulong) ut_dulint_get_low(srv_shutdown_lsn)); + (ulong) ut_dulint_get_high(srv_shutdown_lsn), + (ulong) ut_dulint_get_low(srv_shutdown_lsn)); } return((int) DB_SUCCESS); diff --git a/storage/innobase/sync/sync0arr.c b/storage/innobase/sync/sync0arr.c index 198ef49ca9f..1f3d6df0403 100644 --- a/storage/innobase/sync/sync0arr.c +++ b/storage/innobase/sync/sync0arr.c @@ -46,13 +46,22 @@ algorithm, because 10 000 events are created fast, but until a resource is released. The suspending is implemented using an operating system event semaphore. */ struct sync_cell_struct { - void* wait_object; /* pointer to the object the - thread is waiting for; if NULL - the cell is free for use */ + /* 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. */ + 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 - object */ + ulint request_type; /* lock type requested on the + object */ const char* file; /* in debug version file where requested */ ulint line; /* in debug version line where @@ -63,17 +72,12 @@ struct sync_cell_struct { 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 */ + os_event_t event; /* operating system event + semaphore handle */ 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 */ @@ -106,8 +110,8 @@ ibool sync_array_detect_deadlock( /*=======================*/ /* out: TRUE if deadlock detected */ - sync_array_t* arr, /* in: wait array; NOTE! the caller must - own the mutex to array */ + sync_array_t* arr, /* in: wait array; NOTE! the caller must + own the mutex to array */ sync_cell_t* start, /* in: cell where recursive search started */ sync_cell_t* cell, /* in: cell to search */ ulint depth); /* in: recursion depth */ @@ -190,7 +194,7 @@ sync_array_create( sync_cell_t* cell_array; sync_cell_t* cell; ulint i; - + ut_a(n_cells > 0); /* Allocate memory for the data structures */ @@ -205,7 +209,7 @@ sync_array_create( arr->sg_count = 0; arr->res_count = 0; - /* Then create the mutex to protect the wait array complex */ + /* Then create the mutex to protect the wait array complex */ if (protection == SYNC_ARRAY_OS_MUTEX) { arr->os_mutex = os_mutex_create(NULL); } else if (protection == SYNC_ARRAY_MUTEX) { @@ -215,12 +219,13 @@ sync_array_create( ut_error; } - for (i = 0; i < n_cells; i++) { - cell = sync_array_get_nth_cell(arr, i); - cell->wait_object = NULL; + 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); + /* 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 */ } @@ -235,22 +240,22 @@ sync_array_free( /*============*/ sync_array_t* arr) /* in, own: sync wait array */ { - ulint i; - sync_cell_t* cell; + ulint i; + sync_cell_t* cell; ulint protection; - ut_a(arr->n_reserved == 0); - + 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); + + 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 */ + /* Release the mutex protecting the wait array complex */ if (protection == SYNC_ARRAY_OS_MUTEX) { os_mutex_free(arr->os_mutex); @@ -261,7 +266,7 @@ sync_array_free( } ut_free(arr->array); - ut_free(arr); + ut_free(arr); } /************************************************************************ @@ -273,48 +278,24 @@ sync_array_validate( /*================*/ sync_array_t* arr) /* in: sync wait array */ { - ulint i; - sync_cell_t* cell; - ulint count = 0; - - sync_array_enter(arr); - - for (i = 0; i < arr->n_cells; i++) { - cell = sync_array_get_nth_cell(arr, i); + ulint i; + sync_cell_t* cell; + ulint count = 0; - if (cell->wait_object != NULL) { - count++; - } - } + sync_array_enter(arr); - ut_a(count == arr->n_reserved); + for (i = 0; i < arr->n_cells; i++) { + cell = sync_array_get_nth_cell(arr, i); - sync_array_exit(arr); -} + if (cell->state == SC_RESERVED) { + count++; + } + } -/*********************************************************************** -Puts the cell event in set state. */ -static -void -sync_cell_event_set( -/*================*/ - sync_cell_t* cell) /* in: array cell */ -{ - os_event_set(cell->event); - cell->event_set = TRUE; -} + ut_a(count == arr->n_reserved); -/*********************************************************************** -Puts the cell event in reset state. */ -static -void -sync_cell_event_reset( -/*==================*/ - sync_cell_t* cell) /* in: array cell */ -{ - os_event_reset(cell->event); - cell->event_set = FALSE; -} + sync_array_exit(arr); +} /********************************************************************** Reserves a wait array cell for waiting for an object. @@ -323,34 +304,39 @@ The event of the cell is reset to nonsignalled state. */ void sync_array_reserve_cell( /*====================*/ - sync_array_t* arr, /* in: wait array */ - void* object, /* in: pointer to the object to wait for */ - ulint type, /* in: lock request type */ + sync_array_t* arr, /* in: wait array */ + void* object, /* in: pointer to the object to wait for */ + ulint type, /* in: lock request type */ const char* file, /* in: file where requested */ - ulint line, /* in: line where requested */ - ulint* index) /* out: index of the reserved cell */ + ulint line, /* in: line where requested */ + ulint* index) /* out: index of the reserved cell */ { - sync_cell_t* cell; - ulint i; - - ut_a(object); - ut_a(index); + sync_cell_t* cell; + ulint i; - sync_array_enter(arr); + ut_a(object); + ut_a(index); - arr->res_count++; + sync_array_enter(arr); + + arr->res_count++; /* Reserve a new cell. */ - for (i = 0; i < arr->n_cells; i++) { - cell = sync_array_get_nth_cell(arr, i); + for (i = 0; i < arr->n_cells; i++) { + cell = sync_array_get_nth_cell(arr, i); - if (cell->wait_object == NULL) { + if (cell->state == SC_FREE) { - /* Make sure the event is reset */ - if (cell->event_set) { - sync_cell_event_reset(cell); - } + /* 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(); @@ -361,29 +347,91 @@ sync_array_reserve_cell( } else { cell->old_wait_rw_lock = object; } - + cell->request_type = type; cell->waiting = FALSE; - + cell->file = file; cell->line = line; - + arr->n_reserved++; *index = i; sync_array_exit(arr); - - return; - } - } - ut_error; /* No free cell found */ + return; + } + } + + ut_error; /* No free cell found */ return; } /********************************************************************** +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 @@ -392,51 +440,51 @@ case prints info and asserts. */ void sync_array_wait_event( /*==================*/ - sync_array_t* arr, /* in: wait array */ - ulint index) /* in: index of the reserved cell */ + sync_array_t* arr, /* in: wait array */ + ulint index) /* in: index of the reserved cell */ { - sync_cell_t* cell; - os_event_t event; - - ut_a(arr); + sync_cell_t* cell; + os_event_t event; - sync_array_enter(arr); + ut_a(arr); - cell = sync_array_get_nth_cell(arr, index); + 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; + event = cell->event; + cell->waiting = TRUE; #ifdef UNIV_SYNC_DEBUG - + /* We use simple enter to the mutex below, because if we cannot acquire it at once, mutex_enter would call 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)) { fputs("########################################\n", stderr); ut_error; - } + } rw_lock_debug_mutex_exit(); + sync_array_exit(arr); #endif - sync_array_exit(arr); + os_event_wait(event); - os_event_wait(event); - - sync_array_free_cell(arr, index); + sync_array_free_cell(arr, index); } /********************************************************************** -Reports info of a wait array cell. */ +Reports info of a wait array cell. Note: sync_array_print_long_waits() +calls this without mutex protection. */ static void sync_array_cell_print( @@ -452,11 +500,20 @@ sync_array_cell_print( fprintf(file, "--Thread %lu has waited at %s line %lu for %.2f seconds the semaphore:\n", - (ulong) os_thread_pf(cell->thread), cell->file, - (ulong) cell->line, - difftime(time(NULL), cell->reservation_time)); + (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. */ - if (type == SYNC_MUTEX) { + } else if (type == SYNC_MUTEX) { /* We use old_wait_mutex in case the cell has already been freed meanwhile */ mutex = cell->old_wait_mutex; @@ -492,7 +549,7 @@ sync_array_cell_print( ? " exclusive\n" : " wait exclusive\n"); } - + fprintf(file, "number of readers %lu, waiters flag %lu\n" "Last time read locked in file %s line %lu\n" @@ -507,11 +564,7 @@ sync_array_cell_print( ut_error; } - if (!cell->waiting) { - fputs("wait has ended\n", file); - } - - if (cell->event_set) { + if (cell->event_set) { fputs("wait is ending\n", file); } } @@ -525,22 +578,22 @@ sync_array_find_thread( /*===================*/ /* out: pointer to cell or NULL if not found */ - sync_array_t* arr, /* in: wait array */ + sync_array_t* arr, /* in: wait array */ os_thread_id_t thread) /* in: thread id */ { - ulint i; - sync_cell_t* cell; + ulint i; + sync_cell_t* cell; - for (i = 0; i < arr->n_cells; i++) { + for (i = 0; i < arr->n_cells; i++) { - cell = sync_array_get_nth_cell(arr, i); + cell = sync_array_get_nth_cell(arr, i); - if (cell->wait_object != NULL - && os_thread_eq(cell->thread, thread)) { + if ((cell->state == SC_RESERVED) + && os_thread_eq(cell->thread, thread)) { - return(cell); /* Found */ - } - } + return(cell); /* Found */ + } + } return(NULL); /* Not found */ } @@ -552,8 +605,8 @@ ibool sync_array_deadlock_step( /*=====================*/ /* out: TRUE if deadlock detected */ - sync_array_t* arr, /* in: wait array; NOTE! the caller must - own the mutex to array */ + sync_array_t* arr, /* in: wait array; NOTE! the caller must + own the mutex to array */ sync_cell_t* start, /* in: cell where recursive search started */ os_thread_id_t thread, /* in: thread to look at */ @@ -572,7 +625,7 @@ sync_array_deadlock_step( return(FALSE); } - + new = sync_array_find_thread(arr, thread); if (new == start) { @@ -604,8 +657,8 @@ ibool sync_array_detect_deadlock( /*=======================*/ /* out: TRUE if deadlock detected */ - sync_array_t* arr, /* in: wait array; NOTE! the caller must - own the mutex to array */ + sync_array_t* arr, /* in: wait array; NOTE! the caller must + own the mutex to array */ sync_cell_t* start, /* in: cell where recursive search started */ sync_cell_t* cell, /* in: cell to search */ ulint depth) /* in: recursion depth */ @@ -615,19 +668,20 @@ sync_array_detect_deadlock( os_thread_id_t thread; ibool ret; rw_lock_debug_t*debug; - - ut_a(arr && start && cell); + + ut_a(arr && start && cell); + ut_ad(cell->state == SC_RESERVED); ut_ad(cell->wait_object); ut_ad(os_thread_get_curr_id() == start->thread); ut_ad(depth < 100); - + depth++; - + if (cell->event_set || !cell->waiting) { return(FALSE); /* No deadlock here */ } - + if (cell->request_type == SYNC_MUTEX) { mutex = cell->wait_object; @@ -649,7 +703,8 @@ sync_array_detect_deadlock( if (ret) { fprintf(stderr, "Mutex %p owned by thread %lu file %s line %lu\n", - mutex, (ulong) os_thread_pf(mutex->thread_id), + mutex, + (ulong) os_thread_pf(mutex->thread_id), mutex->file_name, (ulong) mutex->line); sync_array_cell_print(stderr, cell); @@ -661,76 +716,76 @@ sync_array_detect_deadlock( } else if (cell->request_type == RW_LOCK_EX) { - lock = cell->wait_object; + lock = cell->wait_object; - debug = UT_LIST_GET_FIRST(lock->debug_list); + debug = UT_LIST_GET_FIRST(lock->debug_list); - while (debug != NULL) { + while (debug != NULL) { - thread = debug->thread_id; + thread = debug->thread_id; - if (((debug->lock_type == RW_LOCK_EX) - && !os_thread_eq(thread, cell->thread)) - || ((debug->lock_type == RW_LOCK_WAIT_EX) - && !os_thread_eq(thread, cell->thread)) - || (debug->lock_type == RW_LOCK_SHARED)) { + if (((debug->lock_type == RW_LOCK_EX) + && !os_thread_eq(thread, cell->thread)) + || ((debug->lock_type == RW_LOCK_WAIT_EX) + && !os_thread_eq(thread, cell->thread)) + || (debug->lock_type == RW_LOCK_SHARED)) { - /* The (wait) x-lock request can block infinitely - only if someone (can be also cell thread) is holding - s-lock, or someone (cannot be cell thread) (wait) - x-lock, and he is blocked by start thread */ + /* The (wait) x-lock request can block + infinitely only if someone (can be also cell + thread) is holding s-lock, or someone + (cannot be cell thread) (wait) x-lock, and + he is blocked by start thread */ - ret = sync_array_deadlock_step(arr, start, thread, - debug->pass, - depth); - if (ret) { - print: - fprintf(stderr, "rw-lock %p ", lock); - sync_array_cell_print(stderr, cell); - rw_lock_debug_print(debug); - return(TRUE); + ret = sync_array_deadlock_step(arr, start, + thread, debug->pass, depth); + if (ret) { + print: + fprintf(stderr, "rw-lock %p ", lock); + sync_array_cell_print(stderr, cell); + rw_lock_debug_print(debug); + return(TRUE); + } } - } - debug = UT_LIST_GET_NEXT(list, debug); - } + debug = UT_LIST_GET_NEXT(list, debug); + } - return(FALSE); + return(FALSE); } else if (cell->request_type == RW_LOCK_SHARED) { - lock = cell->wait_object; - debug = UT_LIST_GET_FIRST(lock->debug_list); + lock = cell->wait_object; + debug = UT_LIST_GET_FIRST(lock->debug_list); - while (debug != NULL) { + while (debug != NULL) { - thread = debug->thread_id; + thread = debug->thread_id; - if ((debug->lock_type == RW_LOCK_EX) - || (debug->lock_type == RW_LOCK_WAIT_EX)) { + if ((debug->lock_type == RW_LOCK_EX) + || (debug->lock_type == RW_LOCK_WAIT_EX)) { - /* The s-lock request can block infinitely only if - someone (can also be cell thread) is holding (wait) - x-lock, and he is blocked by start thread */ + /* The s-lock request can block infinitely + only if someone (can also be cell thread) is + holding (wait) x-lock, and he is blocked by + start thread */ - ret = sync_array_deadlock_step(arr, start, thread, - debug->pass, - depth); - if (ret) { - goto print; + ret = sync_array_deadlock_step(arr, start, + thread, debug->pass, depth); + if (ret) { + goto print; + } } - } - debug = UT_LIST_GET_NEXT(list, debug); - } + debug = UT_LIST_GET_NEXT(list, debug); + } - return(FALSE); + return(FALSE); } else { ut_error; } - return(TRUE); /* Execution never reaches this line: for compiler + return(TRUE); /* Execution never reaches this line: for compiler fooling only */ } #endif /* UNIV_SYNC_DEBUG */ @@ -745,7 +800,7 @@ sync_arr_cell_can_wake_up( { mutex_t* mutex; rw_lock_t* lock; - + if (cell->request_type == SYNC_MUTEX) { mutex = cell->wait_object; @@ -757,26 +812,26 @@ sync_arr_cell_can_wake_up( } else if (cell->request_type == RW_LOCK_EX) { - lock = cell->wait_object; + lock = cell->wait_object; - if (rw_lock_get_reader_count(lock) == 0 - && rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) { + if (rw_lock_get_reader_count(lock) == 0 + && rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) { return(TRUE); } - if (rw_lock_get_reader_count(lock) == 0 - && rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX - && os_thread_eq(lock->writer_thread, cell->thread)) { + if (rw_lock_get_reader_count(lock) == 0 + && rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX + && os_thread_eq(lock->writer_thread, cell->thread)) { return(TRUE); } } else if (cell->request_type == RW_LOCK_SHARED) { - lock = cell->wait_object; + lock = cell->wait_object; if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) { - + return(TRUE); } } @@ -784,32 +839,6 @@ sync_arr_cell_can_wake_up( return(FALSE); } -/********************************************************************** -Frees the cell. NOTE! sync_array_wait_event frees the cell -automatically! */ - -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; - - sync_array_enter(arr); - - cell = sync_array_get_nth_cell(arr, index); - - ut_a(cell->wait_object != NULL); - - cell->wait_object = NULL; - - ut_a(arr->n_reserved > 0); - arr->n_reserved--; - - sync_array_exit(arr); -} - /************************************************************************** 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 @@ -822,73 +851,142 @@ sync_array_signal_object( sync_array_t* arr, /* in: wait array */ void* object) /* in: wait object */ { - sync_cell_t* cell; - ulint count; - ulint i; + 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); - sync_array_enter(arr); + ut_a(100 == cell_max_count); + + sync_array_enter(arr); arr->sg_count++; i = 0; count = 0; - while (count < arr->n_reserved) { + /* 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, i); + + if (cell->state == SC_RESERVED) { + + count++; + if (cell->wait_object == object) { + cell->state = SC_WAKING_UP; - cell = sync_array_get_nth_cell(arr, i); + ut_a(arr->n_reserved > 0); + arr->n_reserved--; - if (cell->wait_object != NULL) { + if (cell_count == cell_max_count) { + sync_cell_t** old_cell_ptr = cell_ptr; + size_t old_size, new_size; - count++; - if (cell->wait_object == object) { + old_size = cell_max_count * + sizeof(sync_cell_t*); + cell_max_count *= 2; + new_size = cell_max_count * + sizeof(sync_cell_t*); - sync_cell_event_set(cell); - } - } + cell_ptr = malloc(new_size); + ut_a(cell_ptr); + memcpy(cell_ptr, old_cell_ptr, + old_size); - i++; - } + if (old_cell_ptr != &cells[0]) { + free(old_cell_ptr); + } + } + + cell_ptr[cell_count] = cell; + cell_count++; + } + } + + i++; + } - sync_array_exit(arr); + 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); + } } /************************************************************************** If the wakeup algorithm does not work perfectly at semaphore relases, this function will do the waking (see the comment in mutex_exit). This -function should be called about every 1 second in the server. */ +function should be called about every 1 second in the server. + +Note that there's a race condition between this thread and mutex_exit +changing the lock_word and calling signal_object, so sometimes this finds +threads to wake up even when nothing has gone wrong. */ void sync_arr_wake_threads_if_sema_free(void) /*====================================*/ { - sync_array_t* arr = sync_primary_wait_array; - sync_cell_t* cell; - ulint count; - ulint i; + sync_array_t* arr = sync_primary_wait_array; + sync_cell_t* cell; + ulint count; + ulint i; + ulint res_count; - sync_array_enter(arr); + sync_array_enter(arr); i = 0; count = 0; - while (count < arr->n_reserved) { + /* We need to store this to a local variable because it is modified + inside the loop */ - cell = sync_array_get_nth_cell(arr, i); + res_count = arr->n_reserved; - if (cell->wait_object != NULL) { + while (count < res_count) { - count++; + cell = sync_array_get_nth_cell(arr, i); - if (sync_arr_cell_can_wake_up(cell)) { + if (cell->state == SC_RESERVED) { - sync_cell_event_set(cell); - } - } + count++; - i++; - } + if (sync_arr_cell_can_wake_up(cell)) { + cell->state = SC_WAKING_UP; + cell->event_set = TRUE; + os_event_set(cell->event); - sync_array_exit(arr); + ut_a(arr->n_reserved > 0); + arr->n_reserved--; + } + } + + i++; + } + + sync_array_exit(arr); } /************************************************************************** @@ -900,36 +998,36 @@ sync_array_print_long_waits(void) /* out: TRUE if fatal semaphore wait threshold was exceeded */ { - sync_cell_t* cell; - ibool old_val; + sync_cell_t* cell; + ibool old_val; ibool noticed = FALSE; - ulint i; + ulint i; ulint fatal_timeout = srv_fatal_semaphore_wait_threshold; ibool fatal = FALSE; - for (i = 0; i < sync_primary_wait_array->n_cells; i++) { + for (i = 0; i < sync_primary_wait_array->n_cells; i++) { - cell = sync_array_get_nth_cell(sync_primary_wait_array, i); + cell = sync_array_get_nth_cell(sync_primary_wait_array, i); - if (cell->wait_object != NULL - && difftime(time(NULL), cell->reservation_time) > 240) { + if ((cell->state != SC_FREE) + && difftime(time(NULL), cell->reservation_time) > 240) { fputs("InnoDB: Warning: a long semaphore wait:\n", stderr); sync_array_cell_print(stderr, cell); noticed = TRUE; - } + } - if (cell->wait_object != NULL - && difftime(time(NULL), cell->reservation_time) - > fatal_timeout) { + if ((cell->state != SC_FREE) + && difftime(time(NULL), cell->reservation_time) + > fatal_timeout) { fatal = TRUE; - } - } + } + } if (noticed) { fprintf(stderr, "InnoDB: ###### Starts InnoDB Monitor for 30 secs to print diagnostic info:\n"); - old_val = srv_print_innodb_monitor; + old_val = srv_print_innodb_monitor; /* If some crucial semaphore is reserved, then also the InnoDB Monitor can hang, and we do not get diagnostics. Since in @@ -941,12 +1039,12 @@ sync_array_print_long_waits(void) "InnoDB: Pending preads %lu, pwrites %lu\n", (ulong)os_file_n_pending_preads, (ulong)os_file_n_pending_pwrites); - srv_print_innodb_monitor = TRUE; + srv_print_innodb_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); - os_thread_sleep(30000000); + os_thread_sleep(30000000); - srv_print_innodb_monitor = old_val; + srv_print_innodb_monitor = old_val; fprintf(stderr, "InnoDB: ###### Diagnostic info printed to the standard error stream\n"); } @@ -964,27 +1062,21 @@ sync_array_output_info( sync_array_t* arr) /* in: wait array; NOTE! caller must own the mutex */ { - sync_cell_t* cell; - ulint count; - ulint i; + sync_cell_t* cell; + ulint i; fprintf(file, - "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) { + "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++) { - cell = sync_array_get_nth_cell(arr, i); + cell = sync_array_get_nth_cell(arr, i); - if (cell->wait_object != NULL) { - count++; + if (cell->state != SC_FREE) { sync_array_cell_print(file, cell); - } - - i++; - } + } + } } /************************************************************************** @@ -996,10 +1088,10 @@ sync_array_print_info( FILE* file, /* in: file where to print */ sync_array_t* arr) /* in: wait array */ { - sync_array_enter(arr); + sync_array_enter(arr); sync_array_output_info(file, arr); - - sync_array_exit(arr); + + sync_array_exit(arr); } diff --git a/storage/innobase/sync/sync0rw.c b/storage/innobase/sync/sync0rw.c index 973b46fdd50..b33c1553bae 100644 --- a/storage/innobase/sync/sync0rw.c +++ b/storage/innobase/sync/sync0rw.c @@ -90,7 +90,7 @@ rw_lock_create_func( /*================*/ rw_lock_t* lock, /* in: pointer to memory */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ + ulint cline, /* in: file line where created */ const char* cmutex_name) /* in: mutex name */ { /* If this is the very first time a synchronization @@ -106,7 +106,7 @@ rw_lock_create_func( lock->mutex.cmutex_name = cmutex_name; lock->mutex.mutex_type = 1; #endif /* !UNIV_HOTBACKUP */ - + rw_lock_set_waiters(lock, 0); rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED); lock->writer_count = 0; @@ -120,7 +120,7 @@ rw_lock_create_func( lock->level = SYNC_LEVEL_NONE; #endif /* UNIV_SYNC_DEBUG */ lock->magic_n = RW_LOCK_MAGIC_N; - + lock->cfile_name = cfile_name; lock->cline = cline; @@ -130,7 +130,7 @@ rw_lock_create_func( lock->last_x_line = 0; mutex_enter(&rw_lock_list_mutex); - + if (UT_LIST_GET_LEN(rw_lock_list) > 0) { ut_a(UT_LIST_GET_FIRST(rw_lock_list)->magic_n == RW_LOCK_MAGIC_N); @@ -157,7 +157,7 @@ rw_lock_free( ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED); ut_a(rw_lock_get_waiters(lock) == 0); ut_a(rw_lock_get_reader_count(lock) == 0); - + lock->magic_n = 0; mutex_free(rw_lock_get_mutex(lock)); @@ -191,14 +191,14 @@ rw_lock_validate( ut_a(lock->magic_n == RW_LOCK_MAGIC_N); ut_a((rw_lock_get_reader_count(lock) == 0) - || (rw_lock_get_writer(lock) != RW_LOCK_EX)); + || (rw_lock_get_writer(lock) != RW_LOCK_EX)); ut_a((rw_lock_get_writer(lock) == RW_LOCK_EX) - || (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX) - || (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)); + || (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX) + || (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)); ut_a((rw_lock_get_waiters(lock) == 0) - || (rw_lock_get_waiters(lock) == 1)); + || (rw_lock_get_waiters(lock) == 1)); ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0)); - + mutex_exit(rw_lock_get_mutex(lock)); return(TRUE); @@ -213,31 +213,31 @@ for the lock, before suspending the thread. */ void rw_lock_s_lock_spin( /*================*/ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ ulint pass, /* in: pass value; != 0, if the lock will be passed to another thread to unlock */ const char* file_name, /* in: file name where lock requested */ ulint line) /* in: line where requested */ { - ulint index; /* index of the reserved wait cell */ - ulint i; /* spin round count */ - - ut_ad(rw_lock_validate(lock)); + ulint index; /* index of the reserved wait cell */ + ulint i; /* spin round count */ + + ut_ad(rw_lock_validate(lock)); lock_loop: rw_s_spin_wait_count++; /* Spin waiting for the writer field to become free */ - i = 0; + i = 0; - while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED + while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED && i < SYNC_SPIN_ROUNDS) { - if (srv_spin_wait_delay) { - ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); - } + if (srv_spin_wait_delay) { + ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); + } - i++; - } + i++; + } if (i == SYNC_SPIN_ROUNDS) { os_thread_yield(); @@ -252,7 +252,7 @@ lock_loop: mutex_enter(rw_lock_get_mutex(lock)); - /* We try once again to obtain the lock */ + /* We try once again to obtain the lock */ if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) { mutex_exit(rw_lock_get_mutex(lock)); @@ -264,7 +264,7 @@ lock_loop: rw_s_system_call_count++; - sync_array_reserve_cell(sync_primary_wait_array, + sync_array_reserve_cell(sync_primary_wait_array, lock, RW_LOCK_SHARED, file_name, line, &index); @@ -277,16 +277,16 @@ lock_loop: fprintf(stderr, "Thread %lu OS wait rw-s-lock at %p cfile %s cline %lu\n", os_thread_pf(os_thread_get_curr_id()), - lock, lock->cfile_name, (ulong) lock->cline); + lock, lock->cfile_name, (ulong) lock->cline); } rw_s_system_call_count++; rw_s_os_wait_count++; - sync_array_wait_event(sync_primary_wait_array, index); + sync_array_wait_event(sync_primary_wait_array, index); - goto lock_loop; - } + goto lock_loop; + } } /********************************************************************** @@ -324,7 +324,7 @@ rw_lock_x_lock_low( /* out: RW_LOCK_NOT_LOCKED if did not succeed, RW_LOCK_EX if success, RW_LOCK_WAIT_EX, if got wait reservation */ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ ulint pass, /* in: pass value; != 0, if the lock will be passed to another thread to unlock */ const char* file_name,/* in: file name where lock requested */ @@ -336,19 +336,19 @@ rw_lock_x_lock_low( if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) { if (rw_lock_get_reader_count(lock) == 0) { - + rw_lock_set_writer(lock, RW_LOCK_EX); lock->writer_thread = os_thread_get_curr_id(); lock->writer_count++; lock->pass = pass; - + #ifdef UNIV_SYNC_DEBUG rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name, line); #endif lock->last_x_file_name = file_name; lock->last_x_line = line; - + /* Locking succeeded, we may return */ return(RW_LOCK_EX); } else { @@ -382,7 +382,7 @@ rw_lock_x_lock_low( rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name, line); #endif - + lock->last_x_file_name = file_name; lock->last_x_line = line; @@ -404,7 +404,7 @@ rw_lock_x_lock_low( rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name, line); #endif - + lock->last_x_file_name = file_name; lock->last_x_line = line; @@ -429,68 +429,68 @@ an s-lock, locking does not succeed! */ void rw_lock_x_lock_func( /*================*/ - rw_lock_t* lock, /* in: pointer to rw-lock */ + rw_lock_t* lock, /* in: pointer to rw-lock */ ulint pass, /* in: pass value; != 0, if the lock will be passed to another thread to unlock */ const char* file_name,/* in: file name where lock requested */ ulint line) /* in: line where requested */ { - ulint index; /* index of the reserved wait cell */ - ulint state; /* lock state acquired */ - ulint i; /* spin round count */ - - ut_ad(rw_lock_validate(lock)); + ulint index; /* index of the reserved wait cell */ + ulint state; /* lock state acquired */ + ulint i; /* spin round count */ + + ut_ad(rw_lock_validate(lock)); lock_loop: - /* Acquire the mutex protecting the rw-lock fields */ + /* Acquire the mutex protecting the rw-lock fields */ mutex_enter_fast(&(lock->mutex)); state = rw_lock_x_lock_low(lock, pass, file_name, line); - + mutex_exit(&(lock->mutex)); - + if (state == RW_LOCK_EX) { return; /* Locking succeeded */ } else if (state == RW_LOCK_NOT_LOCKED) { - /* Spin waiting for the writer field to become free */ + /* Spin waiting for the writer field to become free */ i = 0; - while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED - && i < SYNC_SPIN_ROUNDS) { - if (srv_spin_wait_delay) { + while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED + && i < SYNC_SPIN_ROUNDS) { + if (srv_spin_wait_delay) { ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); - } - - i++; - } + } + + i++; + } if (i == SYNC_SPIN_ROUNDS) { os_thread_yield(); } - } else if (state == RW_LOCK_WAIT_EX) { + } else if (state == RW_LOCK_WAIT_EX) { - /* Spin waiting for the reader count field to become zero */ + /* Spin waiting for the reader count field to become zero */ i = 0; - while (rw_lock_get_reader_count(lock) != 0 - && i < SYNC_SPIN_ROUNDS) { - if (srv_spin_wait_delay) { + while (rw_lock_get_reader_count(lock) != 0 + && i < SYNC_SPIN_ROUNDS) { + if (srv_spin_wait_delay) { ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); - } + } i++; - } + } if (i == SYNC_SPIN_ROUNDS) { os_thread_yield(); } - } else { + } else { i = 0; /* Eliminate a compiler warning */ ut_error; - } + } if (srv_print_latch_waits) { fprintf(stderr, @@ -501,7 +501,7 @@ lock_loop: rw_x_spin_wait_count++; - /* We try once again to obtain the lock. Acquire the mutex protecting + /* We try once again to obtain the lock. Acquire the mutex protecting the rw-lock fields */ mutex_enter(rw_lock_get_mutex(lock)); @@ -516,7 +516,7 @@ lock_loop: rw_x_system_call_count++; - sync_array_reserve_cell(sync_primary_wait_array, + sync_array_reserve_cell(sync_primary_wait_array, lock, RW_LOCK_EX, file_name, line, &index); @@ -535,9 +535,9 @@ lock_loop: rw_x_system_call_count++; rw_x_os_wait_count++; - sync_array_wait_event(sync_primary_wait_array, index); + sync_array_wait_event(sync_primary_wait_array, index); - goto lock_loop; + goto lock_loop; } #ifdef UNIV_SYNC_DEBUG @@ -569,7 +569,7 @@ loop: os_event_wait(rw_lock_debug_event); - goto loop; + goto loop; } /********************************************************************** @@ -609,19 +609,19 @@ rw_lock_add_debug_info( rw_lock_debug_mutex_enter(); info->file_name = file_name; - info->line = line; + info->line = line; info->lock_type = lock_type; info->thread_id = os_thread_get_curr_id(); info->pass = pass; - UT_LIST_ADD_FIRST(list, lock->debug_list, info); + UT_LIST_ADD_FIRST(list, lock->debug_list, info); rw_lock_debug_mutex_exit(); if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) { sync_thread_add_level(lock, lock->level); } -} +} /********************************************************************** Removes a debug information struct for an rw-lock. */ @@ -647,18 +647,18 @@ rw_lock_remove_debug_info( while (info != NULL) { if ((pass == info->pass) - && ((pass != 0) - || os_thread_eq(info->thread_id, - os_thread_get_curr_id())) - && (info->lock_type == lock_type)) { + && ((pass != 0) + || os_thread_eq(info->thread_id, + os_thread_get_curr_id())) + && (info->lock_type == lock_type)) { - /* Found! */ - UT_LIST_REMOVE(list, lock->debug_list, info); + /* Found! */ + UT_LIST_REMOVE(list, lock->debug_list, info); rw_lock_debug_mutex_exit(); - rw_lock_debug_free(info); + rw_lock_debug_free(info); - return; + return; } info = UT_LIST_GET_NEXT(list, info); @@ -705,13 +705,13 @@ rw_lock_own( while (info != NULL) { if (os_thread_eq(info->thread_id, os_thread_get_curr_id()) - && (info->pass == 0) - && (info->lock_type == lock_type)) { + && (info->pass == 0) + && (info->lock_type == lock_type)) { mutex_exit(&(lock->mutex)); - /* Found! */ + /* Found! */ - return(TRUE); + return(TRUE); } info = UT_LIST_GET_NEXT(list, info); @@ -737,7 +737,7 @@ rw_lock_is_locked( ut_ad(lock); ut_ad(rw_lock_validate(lock)); - + mutex_enter(&(lock->mutex)); if (lock_type == RW_LOCK_SHARED) { @@ -768,7 +768,7 @@ rw_lock_list_print_info(void) rw_lock_t* lock; ulint count = 0; rw_lock_debug_t* info; - + mutex_enter(&rw_lock_list_mutex); fputs("-------------\n" @@ -784,8 +784,8 @@ rw_lock_list_print_info(void) mutex_enter(&(lock->mutex)); if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) - || (rw_lock_get_reader_count(lock) != 0) - || (rw_lock_get_waiters(lock) != 0)) { + || (rw_lock_get_reader_count(lock) != 0) + || (rw_lock_get_waiters(lock) != 0)) { fprintf(stderr, "RW-LOCK: %p ", lock); @@ -794,9 +794,9 @@ rw_lock_list_print_info(void) } else { putc('\n', stderr); } - + info = UT_LIST_GET_FIRST(lock->debug_list); - while (info != NULL) { + while (info != NULL) { rw_lock_debug_print(info); info = UT_LIST_GET_NEXT(list, info); } @@ -819,24 +819,24 @@ rw_lock_print( rw_lock_t* lock) /* in: rw-lock */ { rw_lock_debug_t* info; - + fprintf(stderr, "-------------\n" "RW-LATCH INFO\n" "RW-LATCH: %p ", lock); if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) - || (rw_lock_get_reader_count(lock) != 0) - || (rw_lock_get_waiters(lock) != 0)) { + || (rw_lock_get_reader_count(lock) != 0) + || (rw_lock_get_waiters(lock) != 0)) { if (rw_lock_get_waiters(lock)) { fputs(" Waiters for the lock exist\n", stderr); } else { putc('\n', stderr); } - + info = UT_LIST_GET_FIRST(lock->debug_list); - while (info != NULL) { + while (info != NULL) { rw_lock_debug_print(info); info = UT_LIST_GET_NEXT(list, info); } @@ -853,11 +853,11 @@ rw_lock_debug_print( { ulint rwt; - rwt = info->lock_type; - + rwt = info->lock_type; + fprintf(stderr, "Locked: thread %ld file %s line %ld ", (ulong) os_thread_pf(info->thread_id), info->file_name, - (ulong) info->line); + (ulong) info->line); if (rwt == RW_LOCK_SHARED) { fputs("S-LOCK", stderr); } else if (rwt == RW_LOCK_EX) { @@ -883,7 +883,7 @@ rw_lock_n_locked(void) { rw_lock_t* lock; ulint count = 0; - + mutex_enter(&rw_lock_list_mutex); lock = UT_LIST_GET_FIRST(rw_lock_list); diff --git a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c index 43249f4b96f..86fa66d5112 100644 --- a/storage/innobase/sync/sync0sync.c +++ b/storage/innobase/sync/sync0sync.c @@ -27,7 +27,7 @@ implement our own efficient spin lock mutex. Future operating systems may provide efficient spin locks, but we cannot count on that. Another reason for implementing a spin lock is that on multiprocessor systems -it can be more efficient for a processor to run a loop waiting for the +it can be more efficient for a processor to run a loop waiting for the semaphore to be released than to switch to a different thread. A thread switch takes 25 us on both platforms mentioned above. See Gray and Reuter's book Transaction processing for background. @@ -35,7 +35,7 @@ Transaction processing for background. How long should the spin loop last before suspending the thread? On a uniprocessor, spinning does not help at all, because if the thread owning the mutex is not executing, it cannot be released. Spinning actually wastes -resources. +resources. On a multiprocessor, we do not know if the thread owning the mutex is executing or not. Thus it would make sense to spin as long as the operation @@ -52,12 +52,12 @@ system should work well on a multiprocessor. On a uniprocessor we have to make sure that thread swithches due to mutex collisions are not frequent, i.e., they do not happen every 100 us or so, because that wastes too much resources. If the thread switches are not frequent, the 20 us wasted in spin -loop is not too much. +loop is not too much. Empirical studies on the effect of spin time should be done for different platforms. - + IMPLEMENTATION OF THE MUTEX =========================== @@ -105,7 +105,7 @@ 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. +sync_array_signal_object with the mutex as an argument. Q.E.D. */ ulint sync_dummy = 0; @@ -203,12 +203,12 @@ mutex_create_func( /*==============*/ mutex_t* mutex, /* in: pointer to memory */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ + ulint cline, /* in: file line where created */ const char* cmutex_name) /* in: mutex name */ { #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) mutex_reset_lock_word(mutex); -#else +#else os_fast_mutex_init(&(mutex->os_fast_mutex)); mutex->lock_word = 0; #endif @@ -222,17 +222,17 @@ mutex_create_func( mutex->cfile_name = cfile_name; mutex->cline = cline; #ifndef UNIV_HOTBACKUP - mutex->cmutex_name= cmutex_name; - mutex->count_using= 0; - mutex->mutex_type= 0; - mutex->lspent_time= 0; - mutex->lmax_spent_time= 0; - mutex->count_spin_loop= 0; - mutex->count_spin_rounds= 0; - mutex->count_os_wait= 0; - mutex->count_os_yield= 0; + mutex->cmutex_name= cmutex_name; + mutex->count_using= 0; + mutex->mutex_type= 0; + mutex->lspent_time= 0; + mutex->lmax_spent_time= 0; + mutex->count_spin_loop= 0; + mutex->count_spin_rounds= 0; + mutex->count_os_wait= 0; + mutex->count_os_yield= 0; #endif /* !UNIV_HOTBACKUP */ - + /* Check that lock_word is aligned; this is important on Intel */ ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0); @@ -240,14 +240,14 @@ mutex_create_func( if ((mutex == &mutex_list_mutex) || (mutex == &sync_thread_mutex)) { - return; + return; } - + mutex_enter(&mutex_list_mutex); - if (UT_LIST_GET_LEN(mutex_list) > 0) { - ut_a(UT_LIST_GET_FIRST(mutex_list)->magic_n == MUTEX_MAGIC_N); - } + if (UT_LIST_GET_LEN(mutex_list) > 0) { + ut_a(UT_LIST_GET_FIRST(mutex_list)->magic_n == MUTEX_MAGIC_N); + } UT_LIST_ADD_FIRST(list, mutex_list, mutex); @@ -269,10 +269,10 @@ mutex_free( #endif /* UNIV_DEBUG */ ut_a(mutex_get_lock_word(mutex) == 0); ut_a(mutex_get_waiters(mutex) == 0); - + if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) { - mutex_enter(&mutex_list_mutex); + mutex_enter(&mutex_list_mutex); if (UT_LIST_GET_PREV(list, mutex)) { ut_a(UT_LIST_GET_PREV(list, mutex)->magic_n @@ -282,19 +282,19 @@ mutex_free( ut_a(UT_LIST_GET_NEXT(list, mutex)->magic_n == MUTEX_MAGIC_N); } - - UT_LIST_REMOVE(list, mutex_list, mutex); + + UT_LIST_REMOVE(list, mutex_list, mutex); mutex_exit(&mutex_list_mutex); } -#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER) +#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER) os_fast_mutex_free(&(mutex->os_fast_mutex)); #endif /* If we free the mutex protecting the mutex list (freeing is not necessary), we have to reset the magic number AFTER removing it from the list. */ - + mutex->magic_n = 0; } @@ -348,7 +348,7 @@ void mutex_set_waiters( /*==============*/ mutex_t* mutex, /* in: mutex */ - ulint n) /* in: value to set */ + ulint n) /* in: value to set */ { volatile ulint* ptr; /* declared volatile to ensure that the value is stored to memory */ @@ -368,188 +368,177 @@ for the mutex before suspending the thread. */ void mutex_spin_wait( /*============*/ - mutex_t* mutex, /* in: pointer to mutex */ - const char* file_name, /* in: file name where - mutex requested */ - ulint line) /* in: line where requested */ + mutex_t* mutex, /* in: pointer to mutex */ + const char* file_name, /* in: file name where mutex + requested */ + ulint line) /* in: line where requested */ { - ulint index; /* index of the reserved wait cell */ - ulint i; /* spin round count */ + ulint index; /* index of the reserved wait cell */ + ulint i; /* spin round count */ #ifndef UNIV_HOTBACKUP - ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */ - ulint ltime_diff; - ulint sec; - ulint ms; - uint timer_started = 0; + ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */ + ulint ltime_diff; + ulint sec; + ulint ms; + uint timer_started = 0; #endif /* !UNIV_HOTBACKUP */ - ut_ad(mutex); + ut_ad(mutex); mutex_loop: - i = 0; + i = 0; -/* Spin waiting for the lock word to become zero. Note that we do not - have to assume that the read access to the lock word is atomic, as the - actual locking is always committed with atomic test-and-set. In - reality, however, all processors probably have an atomic read of a - memory word. */ + /* Spin waiting for the lock word to become zero. Note that we do + not have to assume that the read access to the lock word is atomic, + as the actual locking is always committed with atomic test-and-set. + In reality, however, all processors probably have an atomic read of + a memory word. */ spin_loop: #ifndef UNIV_HOTBACKUP - mutex_spin_wait_count++; - mutex->count_spin_loop++; + mutex_spin_wait_count++; + mutex->count_spin_loop++; #endif /* !UNIV_HOTBACKUP */ - while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) - { - if (srv_spin_wait_delay) - { - ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); - } + while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) { + if (srv_spin_wait_delay) { + ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); + } - i++; - } + i++; + } - if (i == SYNC_SPIN_ROUNDS) - { + if (i == SYNC_SPIN_ROUNDS) { #ifndef UNIV_HOTBACKUP - mutex->count_os_yield++; - if (timed_mutexes == 1 && timer_started==0) - { - ut_usectime(&sec, &ms); - lstart_time= (ib_longlong)sec * 1000000 + ms; - timer_started = 1; - } + mutex->count_os_yield++; + if (timed_mutexes == 1 && timer_started==0) { + ut_usectime(&sec, &ms); + lstart_time= (ib_longlong)sec * 1000000 + ms; + timer_started = 1; + } #endif /* !UNIV_HOTBACKUP */ - os_thread_yield(); - } + os_thread_yield(); + } #ifdef UNIV_SRV_PRINT_LATCH_WAITS - fprintf(stderr, - "Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n", - (ulong) os_thread_pf(os_thread_get_curr_id()), mutex, - mutex->cfile_name, (ulong) mutex->cline, (ulong) i); + fprintf(stderr, + "Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n", + (ulong) os_thread_pf(os_thread_get_curr_id()), mutex, + mutex->cfile_name, (ulong) mutex->cline, (ulong) i); #endif - mutex_spin_round_count += i; + mutex_spin_round_count += i; #ifndef UNIV_HOTBACKUP - mutex->count_spin_rounds += i; + mutex->count_spin_rounds += i; #endif /* !UNIV_HOTBACKUP */ - if (mutex_test_and_set(mutex) == 0) - { - /* Succeeded! */ + if (mutex_test_and_set(mutex) == 0) { + /* Succeeded! */ #ifdef UNIV_SYNC_DEBUG - mutex_set_debug_info(mutex, file_name, line); + mutex_set_debug_info(mutex, file_name, line); #endif - goto finish_timing; - } + goto finish_timing; + } - /* We may end up with a situation where lock_word is - 0 but the OS fast mutex is still reserved. On FreeBSD - the OS does not seem to schedule a thread which is constantly - calling pthread_mutex_trylock (in mutex_test_and_set - implementation). Then we could end up spinning here indefinitely. - The following 'i++' stops this infinite spin. */ + /* We may end up with a situation where lock_word is 0 but the OS + fast mutex is still reserved. On FreeBSD the OS does not seem to + schedule a thread which is constantly calling pthread_mutex_trylock + (in mutex_test_and_set implementation). Then we could end up + spinning here indefinitely. The following 'i++' stops this infinite + spin. */ - i++; + i++; - if (i < SYNC_SPIN_ROUNDS) - { - goto spin_loop; - } + if (i < SYNC_SPIN_ROUNDS) { + goto spin_loop; + } - sync_array_reserve_cell(sync_primary_wait_array, mutex, - SYNC_MUTEX, file_name, line, &index); + sync_array_reserve_cell(sync_primary_wait_array, mutex, + SYNC_MUTEX, file_name, line, &index); - mutex_system_call_count++; + mutex_system_call_count++; - /* The memory order of the array reservation and the change in the - waiters field is important: when we suspend a thread, we first - reserve the cell and then set waiters field to 1. When threads are - released in mutex_exit, the waiters field is first set to zero and - then the event is set to the signaled state. */ + /* The memory order of the array reservation and the change in the + waiters field is important: when we suspend a thread, we first + reserve the cell and then set waiters field to 1. When threads are + released in mutex_exit, the waiters field is first set to zero and + then the event is set to the signaled state. */ - mutex_set_waiters(mutex, 1); + mutex_set_waiters(mutex, 1); - /* Try to reserve still a few times */ - for (i = 0; i < 4; i++) - { - if (mutex_test_and_set(mutex) == 0) - { - /* Succeeded! Free the reserved wait cell */ + /* Try to reserve still a few times */ + for (i = 0; i < 4; i++) { + if (mutex_test_and_set(mutex) == 0) { + /* Succeeded! Free the reserved wait cell */ - sync_array_free_cell(sync_primary_wait_array, index); + sync_array_free_cell_protected(sync_primary_wait_array, + index); #ifdef UNIV_SYNC_DEBUG - mutex_set_debug_info(mutex, file_name, line); + mutex_set_debug_info(mutex, file_name, line); #endif #ifdef UNIV_SRV_PRINT_LATCH_WAITS - fprintf(stderr, "Thread %lu spin wait succeeds at 2:" - " mutex at %p\n", - (ulong) os_thread_pf(os_thread_get_curr_id()), - mutex); + fprintf(stderr, "Thread %lu spin wait succeeds at 2:" + " mutex at %p\n", + (ulong) os_thread_pf(os_thread_get_curr_id()), + mutex); #endif - goto finish_timing; + goto finish_timing; - /* Note that in this case we leave the waiters field - set to 1. We cannot reset it to zero, as we do not know - if there are other waiters. */ - } - } + /* Note that in this case we leave the waiters field + set to 1. We cannot reset it to zero, as we do not + know if there are other waiters. */ + } + } - /* Now we know that there has been some thread holding the mutex - after the change in the wait array and the waiters field was made. -Now there is no risk of infinite wait on the event. */ + /* Now we know that there has been some thread holding the mutex + after the change in the wait array and the waiters field was made. + Now there is no risk of infinite wait on the event. */ #ifdef UNIV_SRV_PRINT_LATCH_WAITS - fprintf(stderr, - "Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n", - (ulong) os_thread_pf(os_thread_get_curr_id()), mutex, - mutex->cfile_name, (ulong) mutex->cline, (ulong) i); + fprintf(stderr, + "Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n", + (ulong) os_thread_pf(os_thread_get_curr_id()), mutex, + mutex->cfile_name, (ulong) mutex->cline, (ulong) i); #endif - mutex_system_call_count++; - mutex_os_wait_count++; + mutex_system_call_count++; + mutex_os_wait_count++; #ifndef UNIV_HOTBACKUP - mutex->count_os_wait++; - /* - !!!!! Sometimes os_wait can be called without os_thread_yield - */ - - if (timed_mutexes == 1 && timer_started==0) - { - ut_usectime(&sec, &ms); - lstart_time= (ib_longlong)sec * 1000000 + ms; - timer_started = 1; - } + mutex->count_os_wait++; + /* !!!!! Sometimes os_wait can be called without os_thread_yield */ + + if (timed_mutexes == 1 && timer_started==0) { + ut_usectime(&sec, &ms); + lstart_time= (ib_longlong)sec * 1000000 + ms; + timer_started = 1; + } #endif /* !UNIV_HOTBACKUP */ - sync_array_wait_event(sync_primary_wait_array, index); - goto mutex_loop; + sync_array_wait_event(sync_primary_wait_array, index); + goto mutex_loop; finish_timing: #ifndef UNIV_HOTBACKUP - if (timed_mutexes == 1 && timer_started==1) - { - ut_usectime(&sec, &ms); - lfinish_time= (ib_longlong)sec * 1000000 + ms; - - ltime_diff= (ulint) (lfinish_time - lstart_time); - mutex->lspent_time += ltime_diff; - if (mutex->lmax_spent_time < ltime_diff) - { - mutex->lmax_spent_time= ltime_diff; - } - } + if (timed_mutexes == 1 && timer_started==1) { + ut_usectime(&sec, &ms); + lfinish_time= (ib_longlong)sec * 1000000 + ms; + + ltime_diff= (ulint) (lfinish_time - lstart_time); + mutex->lspent_time += ltime_diff; + + if (mutex->lmax_spent_time < ltime_diff) { + mutex->lmax_spent_time= ltime_diff; + } + } #endif /* !UNIV_HOTBACKUP */ - return; + return; } /********************************************************************** @@ -585,9 +574,9 @@ mutex_set_debug_info( sync_thread_add_level(mutex, mutex->level); mutex->file_name = file_name; - mutex->line = line; + mutex->line = line; mutex->thread_id = os_thread_get_curr_id(); -} +} /********************************************************************** Gets the debug information for a reserved mutex. */ @@ -639,7 +628,7 @@ mutex_own( return(FALSE); } - + if (!os_thread_eq(mutex->thread_id, os_thread_get_curr_id())) { return(FALSE); @@ -673,7 +662,7 @@ mutex_list_print_info(void) count++; if (mutex_get_lock_word(mutex) != 0) { - mutex_get_debug_info(mutex, &file_name, &line, + mutex_get_debug_info(mutex, &file_name, &line, &thread_id); fprintf(stderr, "Locked mutex: addr %p thread %ld file %s line %ld\n", @@ -685,7 +674,7 @@ mutex_list_print_info(void) } fprintf(stderr, "Total number of mutexes %ld\n", count); - + mutex_exit(&mutex_list_mutex); } @@ -753,7 +742,7 @@ sync_thread_t* sync_thread_level_arrays_find_slot(void) /*====================================*/ /* out: pointer to thread slot, NULL if not found */ - + { sync_thread_t* slot; os_thread_id_t id; @@ -781,7 +770,7 @@ sync_thread_t* sync_thread_level_arrays_find_free(void) /*====================================*/ /* out: pointer to thread slot */ - + { sync_thread_t* slot; ulint i; @@ -858,7 +847,7 @@ sync_thread_levels_g( ulint line; os_thread_id_t thread_id; - mutex_get_debug_info(mutex, + mutex_get_debug_info(mutex, &file_name, &line, &thread_id); fprintf(stderr, @@ -870,13 +859,13 @@ sync_thread_levels_g( #endif /* UNIV_SYNC_DEBUG */ } else { fputs("Not locked\n", stderr); - } + } } else { #ifdef UNIV_SYNC_DEBUG rw_lock_print(lock); #endif /* UNIV_SYNC_DEBUG */ } - + return(FALSE); } } @@ -997,18 +986,18 @@ sync_thread_add_level( sync_level_t* slot; sync_thread_t* thread_slot; ulint i; - + if (!sync_order_checks_on) { return; } if ((latch == (void*)&sync_thread_mutex) - || (latch == (void*)&mutex_list_mutex) + || (latch == (void*)&mutex_list_mutex) #ifdef UNIV_SYNC_DEBUG - || (latch == (void*)&rw_lock_debug_mutex) + || (latch == (void*)&rw_lock_debug_mutex) #endif /* UNIV_SYNC_DEBUG */ - || (latch == (void*)&rw_lock_list_mutex)) { + || (latch == (void*)&rw_lock_list_mutex)) { return; } @@ -1025,12 +1014,12 @@ sync_thread_add_level( if (thread_slot == NULL) { /* We have to allocate the level array for a new thread */ array = ut_malloc(sizeof(sync_level_t) * SYNC_THREAD_N_LEVELS); - + thread_slot = sync_thread_level_arrays_find_free(); - - thread_slot->id = os_thread_get_curr_id(); + + thread_slot->id = os_thread_get_curr_id(); thread_slot->levels = array; - + for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { slot = sync_thread_levels_get_nth(array, i); @@ -1040,115 +1029,149 @@ sync_thread_add_level( } array = thread_slot->levels; - + /* NOTE that there is a problem with _NODE and _LEAF levels: if the B-tree height changes, then a leaf can change to an internal node or the other way around. We do not know at present if this can cause unnecessary assertion failures below. */ - if (level == SYNC_NO_ORDER_CHECK) { + switch (level) { + case SYNC_NO_ORDER_CHECK: + case SYNC_EXTERN_STORAGE: + case SYNC_TREE_NODE_FROM_HASH: /* Do no order checking */ - - } else if (level == SYNC_MEM_POOL) { + break; + case SYNC_MEM_POOL: ut_a(sync_thread_levels_g(array, SYNC_MEM_POOL)); - } else if (level == SYNC_MEM_HASH) { + break; + case SYNC_MEM_HASH: ut_a(sync_thread_levels_g(array, SYNC_MEM_HASH)); - } else if (level == SYNC_RECV) { + break; + case SYNC_RECV: ut_a(sync_thread_levels_g(array, SYNC_RECV)); - } else if (level == SYNC_LOG) { + break; + case SYNC_LOG: ut_a(sync_thread_levels_g(array, SYNC_LOG)); - } else if (level == SYNC_THR_LOCAL) { + break; + case SYNC_THR_LOCAL: ut_a(sync_thread_levels_g(array, SYNC_THR_LOCAL)); - } else if (level == SYNC_ANY_LATCH) { + break; + case SYNC_ANY_LATCH: ut_a(sync_thread_levels_g(array, SYNC_ANY_LATCH)); - } else if (level == SYNC_TRX_SYS_HEADER) { + break; + case SYNC_TRX_SYS_HEADER: ut_a(sync_thread_levels_g(array, SYNC_TRX_SYS_HEADER)); - } else if (level == SYNC_DOUBLEWRITE) { + break; + case SYNC_DOUBLEWRITE: ut_a(sync_thread_levels_g(array, SYNC_DOUBLEWRITE)); - } else if (level == SYNC_BUF_BLOCK) { + break; + case SYNC_BUF_BLOCK: ut_a((sync_thread_levels_contain(array, SYNC_BUF_POOL) - && sync_thread_levels_g(array, SYNC_BUF_BLOCK - 1)) - || sync_thread_levels_g(array, SYNC_BUF_BLOCK)); - } else if (level == SYNC_BUF_POOL) { + && sync_thread_levels_g(array, SYNC_BUF_BLOCK - 1)) + || sync_thread_levels_g(array, SYNC_BUF_BLOCK)); + break; + case SYNC_BUF_POOL: ut_a(sync_thread_levels_g(array, SYNC_BUF_POOL)); - } else if (level == SYNC_SEARCH_SYS) { + break; + case SYNC_SEARCH_SYS: ut_a(sync_thread_levels_g(array, SYNC_SEARCH_SYS)); - } else if (level == SYNC_TRX_LOCK_HEAP) { + break; + case SYNC_TRX_LOCK_HEAP: ut_a(sync_thread_levels_g(array, SYNC_TRX_LOCK_HEAP)); - } else if (level == SYNC_REC_LOCK) { + break; + case SYNC_REC_LOCK: ut_a((sync_thread_levels_contain(array, SYNC_KERNEL) - && sync_thread_levels_g(array, SYNC_REC_LOCK - 1)) - || sync_thread_levels_g(array, SYNC_REC_LOCK)); - } else if (level == SYNC_KERNEL) { + && sync_thread_levels_g(array, SYNC_REC_LOCK - 1)) + || sync_thread_levels_g(array, SYNC_REC_LOCK)); + break; + case SYNC_KERNEL: ut_a(sync_thread_levels_g(array, SYNC_KERNEL)); - } else if (level == SYNC_IBUF_BITMAP) { + break; + case SYNC_IBUF_BITMAP: ut_a((sync_thread_levels_contain(array, SYNC_IBUF_BITMAP_MUTEX) - && sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1)) - || sync_thread_levels_g(array, SYNC_IBUF_BITMAP)); - } else if (level == SYNC_IBUF_BITMAP_MUTEX) { + && sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1)) + || sync_thread_levels_g(array, SYNC_IBUF_BITMAP)); + break; + case SYNC_IBUF_BITMAP_MUTEX: ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP_MUTEX)); - } else if (level == SYNC_FSP_PAGE) { + break; + case SYNC_FSP_PAGE: ut_a(sync_thread_levels_contain(array, SYNC_FSP)); - } else if (level == SYNC_FSP) { + break; + case SYNC_FSP: ut_a(sync_thread_levels_contain(array, SYNC_FSP) - || sync_thread_levels_g(array, SYNC_FSP)); - } else if (level == SYNC_EXTERN_STORAGE) { - ut_a(TRUE); - } else if (level == SYNC_TRX_UNDO_PAGE) { + || sync_thread_levels_g(array, SYNC_FSP)); + break; + case SYNC_TRX_UNDO_PAGE: ut_a(sync_thread_levels_contain(array, SYNC_TRX_UNDO) - || sync_thread_levels_contain(array, SYNC_RSEG) - || sync_thread_levels_contain(array, SYNC_PURGE_SYS) - || sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE)); - } else if (level == SYNC_RSEG_HEADER) { + || sync_thread_levels_contain(array, SYNC_RSEG) + || sync_thread_levels_contain(array, SYNC_PURGE_SYS) + || sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE)); + break; + case SYNC_RSEG_HEADER: ut_a(sync_thread_levels_contain(array, SYNC_RSEG)); - } else if (level == SYNC_RSEG_HEADER_NEW) { + break; + case SYNC_RSEG_HEADER_NEW: ut_a(sync_thread_levels_contain(array, SYNC_KERNEL) - && sync_thread_levels_contain(array, SYNC_FSP_PAGE)); - } else if (level == SYNC_RSEG) { + && sync_thread_levels_contain(array, SYNC_FSP_PAGE)); + break; + case SYNC_RSEG: ut_a(sync_thread_levels_g(array, SYNC_RSEG)); - } else if (level == SYNC_TRX_UNDO) { + break; + case SYNC_TRX_UNDO: ut_a(sync_thread_levels_g(array, SYNC_TRX_UNDO)); - } else if (level == SYNC_PURGE_LATCH) { + break; + case SYNC_PURGE_LATCH: ut_a(sync_thread_levels_g(array, SYNC_PURGE_LATCH)); - } else if (level == SYNC_PURGE_SYS) { + break; + case SYNC_PURGE_SYS: ut_a(sync_thread_levels_g(array, SYNC_PURGE_SYS)); - } else if (level == SYNC_TREE_NODE) { + break; + case SYNC_TREE_NODE: ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE) - || sync_thread_levels_g(array, SYNC_TREE_NODE - 1)); - } else if (level == SYNC_TREE_NODE_FROM_HASH) { - ut_a(1); - } else if (level == SYNC_TREE_NODE_NEW) { + || sync_thread_levels_g(array, SYNC_TREE_NODE - 1)); + break; + case SYNC_TREE_NODE_NEW: ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE) - || sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); - } else if (level == SYNC_INDEX_TREE) { + || sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); + break; + case SYNC_INDEX_TREE: ut_a((sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) - && sync_thread_levels_contain(array, SYNC_FSP) - && sync_thread_levels_g(array, SYNC_FSP_PAGE - 1)) - || sync_thread_levels_g(array, SYNC_TREE_NODE - 1)); - } else if (level == SYNC_IBUF_MUTEX) { + && sync_thread_levels_contain(array, SYNC_FSP) + && sync_thread_levels_g(array, SYNC_FSP_PAGE - 1)) + || sync_thread_levels_g(array, SYNC_TREE_NODE - 1)); + break; + case SYNC_IBUF_MUTEX: ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1)); - } else if (level == SYNC_IBUF_PESS_INSERT_MUTEX) { + break; + case SYNC_IBUF_PESS_INSERT_MUTEX: ut_a(sync_thread_levels_g(array, SYNC_FSP - 1) - && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); - } else if (level == SYNC_IBUF_HEADER) { + && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); + break; + case SYNC_IBUF_HEADER: ut_a(sync_thread_levels_g(array, SYNC_FSP - 1) - && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) - && !sync_thread_levels_contain(array, - SYNC_IBUF_PESS_INSERT_MUTEX)); - } else if (level == SYNC_DICT_AUTOINC_MUTEX) { + && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) + && !sync_thread_levels_contain(array, + SYNC_IBUF_PESS_INSERT_MUTEX)); + break; + case SYNC_DICT_AUTOINC_MUTEX: ut_a(sync_thread_levels_g(array, SYNC_DICT_AUTOINC_MUTEX)); - } else if (level == SYNC_DICT_OPERATION) { + break; + case SYNC_DICT_OPERATION: ut_a(sync_thread_levels_g(array, SYNC_DICT_OPERATION)); - } else if (level == SYNC_DICT_HEADER) { + break; + case SYNC_DICT_HEADER: ut_a(sync_thread_levels_g(array, SYNC_DICT_HEADER)); - } else if (level == SYNC_DICT) { + break; + case SYNC_DICT: #ifdef UNIV_DEBUG ut_a(buf_debug_prints - || sync_thread_levels_g(array, SYNC_DICT)); + || sync_thread_levels_g(array, SYNC_DICT)); #else /* UNIV_DEBUG */ ut_a(sync_thread_levels_g(array, SYNC_DICT)); #endif /* UNIV_DEBUG */ - } else { + break; + default: ut_error; } @@ -1168,7 +1191,7 @@ sync_thread_add_level( mutex_exit(&sync_thread_mutex); } - + /********************************************************************** Removes a latch from the thread level array if it is found there. */ @@ -1183,18 +1206,18 @@ sync_thread_reset_level( sync_level_t* slot; sync_thread_t* thread_slot; ulint i; - + if (!sync_order_checks_on) { return(FALSE); } if ((latch == (void*)&sync_thread_mutex) - || (latch == (void*)&mutex_list_mutex) + || (latch == (void*)&mutex_list_mutex) #ifdef UNIV_SYNC_DEBUG - || (latch == (void*)&rw_lock_debug_mutex) + || (latch == (void*)&rw_lock_debug_mutex) #endif /* UNIV_SYNC_DEBUG */ - || (latch == (void*)&rw_lock_list_mutex)) { + || (latch == (void*)&rw_lock_list_mutex)) { return(FALSE); } @@ -1212,7 +1235,7 @@ sync_thread_reset_level( } array = thread_slot->levels; - + for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { slot = sync_thread_levels_get_nth(array, i); @@ -1232,7 +1255,7 @@ sync_thread_reset_level( return(FALSE); } - + /********************************************************************** Initializes the synchronization data structures. */ @@ -1242,7 +1265,7 @@ sync_init(void) { sync_thread_t* thread_slot; ulint i; - + ut_a(sync_initialized == FALSE); sync_initialized = TRUE; @@ -1251,7 +1274,7 @@ sync_init(void) mutex */ sync_primary_wait_array = sync_array_create(OS_THREAD_MAX_N, - SYNC_ARRAY_OS_MUTEX); + SYNC_ARRAY_OS_MUTEX); /* Create the thread latch level array where the latch levels are stored for each OS thread */ @@ -1264,24 +1287,24 @@ sync_init(void) thread_slot->levels = NULL; } - /* Init the mutex list and create the mutex to protect it. */ + /* Init the mutex list and create the mutex to protect it. */ UT_LIST_INIT(mutex_list); - mutex_create(&mutex_list_mutex); - mutex_set_level(&mutex_list_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(&mutex_list_mutex); + mutex_set_level(&mutex_list_mutex, SYNC_NO_ORDER_CHECK); + + mutex_create(&sync_thread_mutex); + mutex_set_level(&sync_thread_mutex, SYNC_NO_ORDER_CHECK); - mutex_create(&sync_thread_mutex); - mutex_set_level(&sync_thread_mutex, SYNC_NO_ORDER_CHECK); - /* Init the rw-lock list and create the mutex to protect it. */ UT_LIST_INIT(rw_lock_list); - mutex_create(&rw_lock_list_mutex); - mutex_set_level(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(&rw_lock_list_mutex); + mutex_set_level(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK); #ifdef UNIV_SYNC_DEBUG - mutex_create(&rw_lock_debug_mutex); - mutex_set_level(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(&rw_lock_debug_mutex); + mutex_set_level(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK); rw_lock_debug_event = os_event_create(NULL); rw_lock_debug_waiters = FALSE; @@ -1303,12 +1326,12 @@ sync_close(void) mutex = UT_LIST_GET_FIRST(mutex_list); while (mutex) { - mutex_free(mutex); + mutex_free(mutex); mutex = UT_LIST_GET_FIRST(mutex_list); } mutex_free(&mutex_list_mutex); - mutex_free(&sync_thread_mutex); + mutex_free(&sync_thread_mutex); } /*********************************************************************** @@ -1328,12 +1351,12 @@ sync_print_wait_info( "Mutex spin waits %lu, rounds %lu, OS waits %lu\n" "RW-shared spins %lu, OS waits %lu; RW-excl spins %lu, OS waits %lu\n", (ulong) mutex_spin_wait_count, - (ulong) mutex_spin_round_count, + (ulong) mutex_spin_round_count, (ulong) mutex_os_wait_count, (ulong) rw_s_spin_wait_count, - (ulong) rw_s_os_wait_count, + (ulong) rw_s_os_wait_count, (ulong) rw_x_spin_wait_count, - (ulong) rw_x_os_wait_count); + (ulong) rw_x_os_wait_count); } /*********************************************************************** diff --git a/storage/innobase/thr/thr0loc.c b/storage/innobase/thr/thr0loc.c index 033bb22807f..2a7a6c1c21f 100644 --- a/storage/innobase/thr/thr0loc.c +++ b/storage/innobase/thr/thr0loc.c @@ -61,8 +61,8 @@ thr_local_get( os_thread_id_t id) /* in: thread id of the thread */ { thr_local_t* local; - -try_again: + +try_again: ut_ad(thr_local_hash); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&thr_local_mutex)); @@ -71,21 +71,21 @@ try_again: /* Look for the local struct in the hash table */ local = NULL; - + HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id), local, os_thread_eq(local->id, id)); if (local == NULL) { mutex_exit(&thr_local_mutex); - + thr_local_create(); - + mutex_enter(&thr_local_mutex); goto try_again; - } + } ut_ad(local->magic_n == THR_LOCAL_MAGIC_N); - + return(local); } @@ -102,11 +102,11 @@ thr_local_get_slot_no( thr_local_t* local; mutex_enter(&thr_local_mutex); - + local = thr_local_get(id); slot_no = local->slot_no; - + mutex_exit(&thr_local_mutex); return(slot_no); @@ -124,11 +124,11 @@ thr_local_set_slot_no( thr_local_t* local; mutex_enter(&thr_local_mutex); - + local = thr_local_get(id); local->slot_no = slot_no; - + mutex_exit(&thr_local_mutex); } @@ -144,9 +144,9 @@ thr_local_get_in_ibuf_field(void) thr_local_t* local; mutex_enter(&thr_local_mutex); - + local = thr_local_get(os_thread_get_curr_id()); - + mutex_exit(&thr_local_mutex); return(&(local->in_ibuf)); @@ -164,21 +164,21 @@ thr_local_create(void) if (thr_local_hash == NULL) { thr_local_init(); } - + local = mem_alloc(sizeof(thr_local_t)); local->id = os_thread_get_curr_id(); local->handle = os_thread_get_curr(); local->magic_n = THR_LOCAL_MAGIC_N; - local->in_ibuf = FALSE; - + local->in_ibuf = FALSE; + mutex_enter(&thr_local_mutex); HASH_INSERT(thr_local_t, hash, thr_local_hash, os_thread_pf(os_thread_get_curr_id()), local); - + mutex_exit(&thr_local_mutex); } @@ -191,7 +191,7 @@ thr_local_free( os_thread_id_t id) /* in: thread id */ { thr_local_t* local; - + mutex_enter(&thr_local_mutex); /* Look for the local struct in the hash table */ @@ -203,14 +203,14 @@ thr_local_free( return; } - + HASH_DELETE(thr_local_t, hash, thr_local_hash, os_thread_pf(id), local); mutex_exit(&thr_local_mutex); - + ut_a(local->magic_n == THR_LOCAL_MAGIC_N); - + mem_free(local); } diff --git a/storage/innobase/trx/trx0purge.c b/storage/innobase/trx/trx0purge.c index 3df34111281..be949079f80 100644 --- a/storage/innobase/trx/trx0purge.c +++ b/storage/innobase/trx/trx0purge.c @@ -74,7 +74,7 @@ trx_purge_arr_store_info( ulint i; arr = purge_sys->arr; - + for (i = 0;; i++) { cell = trx_undo_arr_get_nth_info(arr, i); @@ -83,7 +83,7 @@ trx_purge_arr_store_info( cell->undo_no = undo_no; cell->trx_no = trx_no; cell->in_use = TRUE; - + arr->n_used++; return(cell); @@ -101,10 +101,10 @@ trx_purge_arr_remove_info( { trx_undo_arr_t* arr; - arr = purge_sys->arr; + arr = purge_sys->arr; cell->in_use = FALSE; - + ut_ad(arr->n_used > 0); arr->n_used--; @@ -128,24 +128,24 @@ trx_purge_arr_get_biggest( ulint n_used; ulint i; ulint n; - + n = 0; n_used = arr->n_used; pair_trx_no = ut_dulint_zero; pair_undo_no = ut_dulint_zero; - + for (i = 0;; i++) { cell = trx_undo_arr_get_nth_info(arr, i); if (cell->in_use) { n++; - trx_cmp = ut_dulint_cmp(cell->trx_no, pair_trx_no); + trx_cmp = ut_dulint_cmp(cell->trx_no, pair_trx_no); if ((trx_cmp > 0) - || ((trx_cmp == 0) - && (ut_dulint_cmp(cell->undo_no, - pair_undo_no) >= 0))) { - + || ((trx_cmp == 0) + && (ut_dulint_cmp(cell->undo_no, + pair_undo_no) >= 0))) { + pair_trx_no = cell->trx_no; pair_undo_no = cell->undo_no; } @@ -173,18 +173,18 @@ trx_purge_graph_build(void) que_fork_t* fork; que_thr_t* thr; /* que_thr_t* thr2; */ - + heap = mem_heap_create(512); fork = que_fork_create(NULL, NULL, QUE_FORK_PURGE, heap); fork->trx = purge_sys->trx; - + thr = que_thr_create(fork, heap); - thr->child = row_purge_node_create(thr, heap); + thr->child = row_purge_node_create(thr, heap); /* thr2 = que_thr_create(fork, fork, heap); - thr2->child = row_purge_node_create(fork, thr2, heap); */ + thr2->child = row_purge_node_create(fork, thr2, heap); */ return(fork); } @@ -210,7 +210,7 @@ trx_purge_sys_create(void) purge_sys->purge_trx_no = ut_dulint_zero; purge_sys->purge_undo_no = ut_dulint_zero; purge_sys->next_stored = FALSE; - + rw_lock_create(&(purge_sys->latch)); rw_lock_set_level(&(purge_sys->latch), SYNC_PURGE_LATCH); @@ -230,9 +230,9 @@ trx_purge_sys_create(void) ut_a(trx_start_low(purge_sys->trx, ULINT_UNDEFINED)); purge_sys->query = trx_purge_graph_build(); - - purge_sys->view = read_view_oldest_copy_or_open_new(NULL, - purge_sys->heap); + + purge_sys->view = read_view_oldest_copy_or_open_new( + ut_dulint_create(0,0), purge_sys->heap); } /*================ UNDO LOG HISTORY LIST =============================*/ @@ -256,11 +256,11 @@ trx_purge_add_update_undo_to_history( trx_ulogf_t* undo_header; trx_upagef_t* page_header; ulint hist_size; - + undo = trx->update_undo; - + ut_ad(undo); - + rseg = undo->rseg; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(rseg->mutex))); @@ -271,7 +271,7 @@ trx_purge_add_update_undo_to_history( undo_header = undo_page + undo->hdr_offset; seg_header = undo_page + TRX_UNDO_SEG_HDR; page_header = undo_page + TRX_UNDO_PAGE_HDR; - + if (undo->state != TRX_UNDO_CACHED) { /* The undo log segment will not be reused */ @@ -302,12 +302,12 @@ trx_purge_add_update_undo_to_history( /* Write the trx number to the undo log header */ mlog_write_dulint(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr); /* Write information about delete markings to the undo log header */ - + if (!undo->del_marks) { mlog_write_ulint(undo_header + TRX_UNDO_DEL_MARKS, FALSE, MLOG_2BYTES, mtr); } - + if (rseg->last_page_no == FIL_NULL) { rseg->last_page_no = undo->hdr_page_no; @@ -339,16 +339,16 @@ trx_purge_free_segment( ulint hist_size; ibool marked = FALSE; mtr_t mtr; - + /* fputs("Freeing an update undo log segment\n", stderr); */ #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(purge_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ -loop: +loop: mtr_start(&mtr); - mutex_enter(&(rseg->mutex)); - + mutex_enter(&(rseg->mutex)); + rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr); undo_page = trx_undo_page_get(rseg->space, hdr_addr.page, &mtr); @@ -366,11 +366,11 @@ loop: MLOG_2BYTES, &mtr); marked = TRUE; } - + freed = fseg_free_step_not_header(seg_hdr + TRX_UNDO_FSEG_HEADER, &mtr); if (!freed) { - mutex_exit(&(rseg->mutex)); + mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); goto loop; @@ -379,7 +379,7 @@ loop: /* The page list may now be inconsistent, but the length field stored in the list base node tells us how big it was before we started the freeing. */ - + seg_size = flst_get_len(seg_hdr + TRX_UNDO_PAGE_LIST, &mtr); /* We may free the undo log segment header page; it must be freed @@ -402,7 +402,7 @@ loop: page can be freed in a few steps, so that the buffer pool is not flooded with bufferfixed pages: see the note in fsp0fsp.c. */ - + freed = fseg_free_step(seg_hdr + TRX_UNDO_FSEG_HEADER, &mtr); } @@ -415,10 +415,10 @@ loop: hist_size - seg_size, MLOG_4BYTES, &mtr); ut_ad(rseg->curr_size >= seg_size); - + rseg->curr_size -= seg_size; - mutex_exit(&(rseg->mutex)); + mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); } @@ -451,8 +451,8 @@ trx_purge_truncate_rseg_history( #endif /* UNIV_SYNC_DEBUG */ mtr_start(&mtr); - mutex_enter(&(rseg->mutex)); - + mutex_enter(&(rseg->mutex)); + rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr); hdr_addr = trx_purge_get_log_from_hist( @@ -460,7 +460,7 @@ trx_purge_truncate_rseg_history( loop: if (hdr_addr.page == FIL_NULL) { - mutex_exit(&(rseg->mutex)); + mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); @@ -471,8 +471,8 @@ loop: log_hdr = undo_page + hdr_addr.boffset; - cmp = ut_dulint_cmp(mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO), - limit_trx_no); + cmp = ut_dulint_cmp(mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO), + limit_trx_no); if (cmp == 0) { trx_undo_truncate_start(rseg, rseg->space, hdr_addr.page, hdr_addr.boffset, limit_undo_no); @@ -485,10 +485,10 @@ loop: mutex_exit(&kernel_mutex); flst_truncate_end(rseg_hdr + TRX_RSEG_HISTORY, - log_hdr + TRX_UNDO_HISTORY_NODE, + log_hdr + TRX_UNDO_HISTORY_NODE, n_removed_logs, &mtr); - mutex_exit(&(rseg->mutex)); + mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); return; @@ -498,32 +498,32 @@ loop: flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE, &mtr)); n_removed_logs++; - + seg_hdr = undo_page + TRX_UNDO_SEG_HDR; if ((mach_read_from_2(seg_hdr + TRX_UNDO_STATE) == TRX_UNDO_TO_PURGE) - && (mach_read_from_2(log_hdr + TRX_UNDO_NEXT_LOG) == 0)) { + && (mach_read_from_2(log_hdr + TRX_UNDO_NEXT_LOG) == 0)) { /* We can free the whole log segment */ - mutex_exit(&(rseg->mutex)); + mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); - + trx_purge_free_segment(rseg, hdr_addr, n_removed_logs); n_removed_logs = 0; } else { - mutex_exit(&(rseg->mutex)); + mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); } mtr_start(&mtr); - mutex_enter(&(rseg->mutex)); + mutex_enter(&(rseg->mutex)); rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr); hdr_addr = prev_hdr_addr; - + goto loop; } @@ -545,9 +545,9 @@ trx_purge_truncate_history(void) trx_purge_arr_get_biggest(purge_sys->arr, &limit_trx_no, &limit_undo_no); - + if (ut_dulint_cmp(limit_trx_no, ut_dulint_zero) == 0) { - + limit_trx_no = purge_sys->purge_trx_no; limit_undo_no = purge_sys->purge_undo_no; } @@ -598,13 +598,13 @@ trx_purge_truncate_if_arr_empty(void) /*************************************************************************** Updates the last not yet purged history log info in rseg when we have purged a whole undo log. Advances also purge_sys->purge_trx_no past the purged log. */ -static +static void trx_purge_rseg_get_next_history_log( /*================================*/ trx_rseg_t* rseg) /* in: rollback segment */ { - page_t* undo_page; + page_t* undo_page; trx_ulogf_t* log_hdr; trx_usegf_t* seg_hdr; fil_addr_t prev_log_addr; @@ -623,9 +623,9 @@ trx_purge_rseg_get_next_history_log( purge_sys->purge_trx_no = ut_dulint_add(rseg->last_trx_no, 1); purge_sys->purge_undo_no = ut_dulint_zero; purge_sys->next_stored = FALSE; - + mtr_start(&mtr); - + undo_page = trx_undo_page_get_s_latched(rseg->space, rseg->last_page_no, &mtr); log_hdr = undo_page + rseg->last_offset; @@ -642,12 +642,12 @@ trx_purge_rseg_get_next_history_log( /* No logs left in the history list */ rseg->last_page_no = FIL_NULL; - + mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); mutex_enter(&kernel_mutex); - + /* Add debug code to track history list corruption reported on the MySQL mailing list on Nov 9, 2004. The fut0lst.c file-based list was corrupt. The prev node pointer was @@ -655,7 +655,7 @@ trx_purge_rseg_get_next_history_log( We assume that purge truncates the history list in moderate size pieces, and if we here reach the head of the list, the list cannot be longer than 20 000 undo logs now. */ - + if (trx_sys->rseg_history_len > 20000) { ut_print_timestamp(stderr); fprintf(stderr, @@ -681,7 +681,7 @@ trx_purge_rseg_get_next_history_log( + prev_log_addr.boffset; trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO); - + del_marks = mach_read_from_2(log_hdr + TRX_UNDO_DEL_MARKS); mtr_commit(&mtr); @@ -695,13 +695,13 @@ trx_purge_rseg_get_next_history_log( mutex_exit(&(rseg->mutex)); } - + /*************************************************************************** Chooses the next undo log to purge and updates the info in purge_sys. This function is used to initialize purge_sys when the next record to purge is not known, and also to update the purge system info on the next record when purge has handled the whole undo log for a transaction. */ -static +static void trx_purge_choose_next_log(void) /*===========================*/ @@ -714,7 +714,7 @@ trx_purge_choose_next_log(void) ulint page_no = 0; /* remove warning (??? bug ???) */ ulint offset = 0; /* remove warning (??? bug ???) */ mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(purge_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -725,15 +725,15 @@ trx_purge_choose_next_log(void) min_trx_no = ut_dulint_max; min_rseg = NULL; - + while (rseg) { mutex_enter(&(rseg->mutex)); - + if (rseg->last_page_no != FIL_NULL) { if ((min_rseg == NULL) - || (ut_dulint_cmp(min_trx_no, rseg->last_trx_no) - > 0)) { + || (ut_dulint_cmp(min_trx_no, + rseg->last_trx_no) > 0)) { min_rseg = rseg; min_trx_no = rseg->last_trx_no; @@ -750,7 +750,7 @@ trx_purge_choose_next_log(void) rseg = UT_LIST_GET_NEXT(rseg_list, rseg); } - + if (min_rseg == NULL) { return; @@ -771,7 +771,7 @@ trx_purge_choose_next_log(void) rec = &trx_purge_dummy_rec; } } - + purge_sys->next_stored = TRUE; purge_sys->rseg = min_rseg; @@ -809,8 +809,8 @@ trx_purge_get_next_rec( trx_undo_rec_t* rec_copy; trx_undo_rec_t* rec2; trx_undo_rec_t* next_rec; - page_t* undo_page; - page_t* page; + page_t* undo_page; + page_t* page; ulint offset; ulint page_no; ulint space; @@ -832,14 +832,14 @@ trx_purge_get_next_rec( no need to purge this undo log */ trx_purge_rseg_get_next_history_log(purge_sys->rseg); - + /* Look for the next undo log and record to purge */ trx_purge_choose_next_log(); return(&trx_purge_dummy_rec); } - + mtr_start(&mtr); undo_page = trx_undo_page_get_s_latched(space, page_no, &mtr); @@ -850,7 +850,7 @@ trx_purge_get_next_rec( for (;;) { /* Try first to find the next record which requires a purge operation from the same page of the same undo log */ - + next_rec = trx_undo_page_get_next_rec(rec2, purge_sys->hdr_page_no, purge_sys->hdr_offset); @@ -862,34 +862,34 @@ trx_purge_get_next_rec( } rec2 = next_rec; - + type = trx_undo_rec_get_type(rec2); if (type == TRX_UNDO_DEL_MARK_REC) { break; - } + } cmpl_info = trx_undo_rec_get_cmpl_info(rec2); if (trx_undo_rec_get_extern_storage(rec2)) { break; } - + if ((type == TRX_UNDO_UPD_EXIST_REC) && !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { - break; - } + break; + } } if (rec2 == NULL) { mtr_commit(&mtr); - + trx_purge_rseg_get_next_history_log(purge_sys->rseg); - + /* Look for the next undo log and record to purge */ - trx_purge_choose_next_log(); + trx_purge_choose_next_log(); mtr_start(&mtr); @@ -898,7 +898,7 @@ trx_purge_get_next_rec( rec = undo_page + offset; } else { page = buf_frame_align(rec2); - + purge_sys->purge_undo_no = trx_undo_rec_get_undo_no(rec2); purge_sys->page_no = buf_frame_get_page_no(page); purge_sys->offset = rec2 - page; @@ -908,7 +908,7 @@ trx_purge_get_next_rec( purge_sys->n_pages_handled++; } } - + rec_copy = trx_undo_rec_copy(rec, heap); mtr_commit(&mtr); @@ -933,7 +933,7 @@ trx_purge_fetch_next_rec( mem_heap_t* heap) /* in: memory heap where copied */ { trx_undo_rec_t* undo_rec; - + mutex_enter(&(purge_sys->mutex)); if (purge_sys->state == TRX_STOP_PURGE) { @@ -949,7 +949,7 @@ trx_purge_fetch_next_rec( if (!purge_sys->next_stored) { purge_sys->state = TRX_STOP_PURGE; - + trx_purge_truncate_if_arr_empty(); if (srv_print_thread_releases) { @@ -961,31 +961,31 @@ trx_purge_fetch_next_rec( mutex_exit(&(purge_sys->mutex)); return(NULL); - } - } + } + } if (purge_sys->n_pages_handled >= purge_sys->handle_limit) { purge_sys->state = TRX_STOP_PURGE; - + trx_purge_truncate_if_arr_empty(); mutex_exit(&(purge_sys->mutex)); return(NULL); - } + } if (ut_dulint_cmp(purge_sys->purge_trx_no, purge_sys->view->low_limit_no) >= 0) { purge_sys->state = TRX_STOP_PURGE; - + trx_purge_truncate_if_arr_empty(); mutex_exit(&(purge_sys->mutex)); return(NULL); } - + /* fprintf(stderr, "Thread %lu purging trx %lu undo record %lu\n", os_thread_get_curr_id(), ut_dulint_get_low(purge_sys->purge_trx_no), @@ -999,11 +999,11 @@ trx_purge_fetch_next_rec( purge_sys->purge_undo_no); ut_ad(ut_dulint_cmp(purge_sys->purge_trx_no, - (purge_sys->view)->low_limit_no) < 0); - + (purge_sys->view)->low_limit_no) < 0); + /* The following call will advance the stored values of purge_trx_no and purge_undo_no, therefore we had to store them first */ - + undo_rec = trx_purge_get_next_rec(heap); mutex_exit(&(purge_sys->mutex)); @@ -1020,7 +1020,7 @@ trx_purge_rec_release( trx_undo_inf_t* cell) /* in: storage cell */ { trx_undo_arr_t* arr; - + mutex_enter(&(purge_sys->mutex)); arr = purge_sys->arr; @@ -1046,21 +1046,21 @@ trx_purge(void) mutex_enter(&(purge_sys->mutex)); if (purge_sys->trx->n_active_thrs > 0) { - + mutex_exit(&(purge_sys->mutex)); /* Should not happen */ ut_error; - + return(0); - } + } rw_lock_x_lock(&(purge_sys->latch)); mutex_enter(&kernel_mutex); - /* Close and free the old purge view */ + /* Close and free the old purge view */ read_view_close(purge_sys->view); purge_sys->view = NULL; @@ -1090,14 +1090,15 @@ trx_purge(void) } } - purge_sys->view = read_view_oldest_copy_or_open_new(NULL, + purge_sys->view = read_view_oldest_copy_or_open_new( + ut_dulint_create(0, 0), purge_sys->heap); - mutex_exit(&kernel_mutex); + mutex_exit(&kernel_mutex); rw_lock_x_unlock(&(purge_sys->latch)); - purge_sys->state = TRX_PURGE_ON; - + purge_sys->state = TRX_PURGE_ON; + /* Handle at most 20 undo log pages in one purge batch */ purge_sys->handle_limit = purge_sys->n_pages_handled + 20; @@ -1111,18 +1112,18 @@ trx_purge(void) thr = que_fork_start_command(purge_sys->query); ut_ad(thr); - + /* thr2 = que_fork_start_command(purge_sys->query); - + ut_ad(thr2); */ - + mutex_exit(&kernel_mutex); /* srv_que_task_enqueue(thr2); */ if (srv_print_thread_releases) { - + fputs("Starting purge\n", stderr); } diff --git a/storage/innobase/trx/trx0rec.c b/storage/innobase/trx/trx0rec.c index 3b7171e6038..d8a5cce22e9 100644 --- a/storage/innobase/trx/trx0rec.c +++ b/storage/innobase/trx/trx0rec.c @@ -64,7 +64,7 @@ trx_undof_page_add_undo_rec_log( mlog_close(mtr, log_ptr); mlog_catenate_string(mtr, undo_page + old_free + 2, len); } -} +} /*************************************************************** Parses a redo log record of adding an undo log record. */ @@ -93,16 +93,16 @@ trx_undo_parse_add_undo_rec( return(NULL); } - + if (page == NULL) { return(ptr + len); } - + first_free = mach_read_from_2(page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE); rec = page + first_free; - + mach_write_to_2(rec, first_free + 4 + len); mach_write_to_2(rec + 2 + len, first_free); @@ -112,7 +112,7 @@ trx_undo_parse_add_undo_rec( return(ptr + len); } - + /************************************************************************** Calculates the free space left for extending an undo log record. */ UNIV_INLINE @@ -137,7 +137,7 @@ trx_undo_page_report_insert( /*========================*/ /* out: offset of the inserted entry on the page if succeed, 0 if fail */ - page_t* undo_page, /* in: undo log page */ + page_t* undo_page, /* in: undo log page */ trx_t* trx, /* in: transaction */ dict_index_t* index, /* in: clustered index */ dtuple_t* clust_entry, /* in: index entry which will be @@ -150,14 +150,14 @@ trx_undo_page_report_insert( dfield_t* field; ulint flen; ulint i; - + ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_INSERT); first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE); ptr = undo_page + first_free; - + ut_ad(first_free <= UNIV_PAGE_SIZE); if (trx_undo_left(undo_page, ptr) < 30) { @@ -170,8 +170,8 @@ trx_undo_page_report_insert( /* Reserve 2 bytes for the pointer to the next undo log record */ ptr += 2; - - /* Store first some general parameters to the undo log */ + + /* Store first some general parameters to the undo log */ mach_write_to_1(ptr, TRX_UNDO_INSERT_REC); ptr++; @@ -195,7 +195,7 @@ trx_undo_page_report_insert( return(0); } - len = mach_write_compressed(ptr, flen); + len = mach_write_compressed(ptr, flen); ptr += len; if (flen != UNIV_SQL_NULL) { @@ -234,7 +234,7 @@ trx_undo_page_report_insert( log */ trx_undof_page_add_undo_rec_log(undo_page, first_free, ptr - undo_page, mtr); - return(first_free); + return(first_free); } /************************************************************************** @@ -274,11 +274,11 @@ trx_undo_rec_get_pars( *type = type_cmpl & (TRX_UNDO_CMPL_INFO_MULT - 1); *cmpl_info = type_cmpl / TRX_UNDO_CMPL_INFO_MULT; - *undo_no = mach_dulint_read_much_compressed(ptr); + *undo_no = mach_dulint_read_much_compressed(ptr); len = mach_dulint_get_much_compressed_size(*undo_no); ptr += len; - *table_id = mach_dulint_read_much_compressed(ptr); + *table_id = mach_dulint_read_much_compressed(ptr); len = mach_dulint_get_much_compressed_size(*table_id); ptr += len; @@ -297,11 +297,11 @@ trx_undo_rec_get_col_val( byte** field, /* out: pointer to stored field */ ulint* len) /* out: length of the field, or UNIV_SQL_NULL */ { - *len = mach_read_compressed(ptr); + *len = mach_read_compressed(ptr); ptr += mach_get_compressed_size(*len); *field = ptr; - + if (*len != UNIV_SQL_NULL) { if (*len >= UNIV_EXTERN_STORAGE_FIELD) { ptr += (*len - UNIV_EXTERN_STORAGE_FIELD); @@ -337,10 +337,10 @@ trx_undo_rec_get_row_ref( ulint len; ulint ref_len; ulint i; - + ut_ad(index && ptr && ref && heap); ut_a(index->type & DICT_CLUSTERED); - + ref_len = dict_index_get_n_unique(index); *ref = dtuple_create(heap, ref_len); @@ -356,7 +356,7 @@ trx_undo_rec_get_row_ref( } return(ptr); -} +} /*********************************************************************** Skips a row reference from an undo log record. */ @@ -374,10 +374,10 @@ trx_undo_rec_skip_row_ref( ulint len; ulint ref_len; ulint i; - + ut_ad(index && ptr); ut_a(index->type & DICT_CLUSTERED); - + ref_len = dict_index_get_n_unique(index); for (i = 0; i < ref_len; i++) { @@ -385,7 +385,7 @@ trx_undo_rec_skip_row_ref( } return(ptr); -} +} /************************************************************************** Reports in the undo log of an update or delete marking of a clustered index @@ -397,7 +397,7 @@ trx_undo_page_report_modify( /* out: byte offset of the inserted undo log entry on the page if succeed, 0 if fail */ - page_t* undo_page, /* in: undo log page */ + page_t* undo_page, /* in: undo log page */ trx_t* trx, /* in: transaction */ dict_index_t* index, /* in: clustered index where update or delete marking is done */ @@ -417,7 +417,7 @@ trx_undo_page_report_modify( ulint first_free; byte* ptr; ulint len; - byte* field; + byte* field; ulint flen; ulint pos; dulint roll_ptr; @@ -428,17 +428,17 @@ trx_undo_page_report_modify( ulint type_cmpl; byte* type_cmpl_ptr; ulint i; - + ut_a(index->type & DICT_CLUSTERED); ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE); table = index->table; - + first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE); ptr = undo_page + first_free; - + ut_ad(first_free <= UNIV_PAGE_SIZE); if (trx_undo_left(undo_page, ptr) < 50) { @@ -455,7 +455,7 @@ trx_undo_page_report_modify( /* Store first some general parameters to the undo log */ if (update) { - if (rec_get_deleted_flag(rec, table->comp)) { + if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) { type_cmpl = TRX_UNDO_UPD_DEL_REC; } else { type_cmpl = TRX_UNDO_UPD_EXIST_REC; @@ -467,7 +467,7 @@ trx_undo_page_report_modify( type_cmpl = type_cmpl | (cmpl_info * TRX_UNDO_CMPL_INFO_MULT); mach_write_to_1(ptr, type_cmpl); - + type_cmpl_ptr = ptr; ptr++; @@ -480,7 +480,7 @@ trx_undo_page_report_modify( /*----------------------------------------*/ /* Store the state of the info bits */ - bits = rec_get_info_bits(rec, table->comp); + bits = rec_get_info_bits(rec, dict_table_is_comp(table)); mach_write_to_1(ptr, bits); ptr += 1; @@ -513,7 +513,7 @@ trx_undo_page_report_modify( return(0); } - len = mach_write_compressed(ptr, flen); + len = mach_write_compressed(ptr, flen); ptr += len; if (flen != UNIV_SQL_NULL) { @@ -531,66 +531,67 @@ trx_undo_page_report_modify( /* Save to the undo log the old values of the columns to be updated. */ if (update) { - if (trx_undo_left(undo_page, ptr) < 5) { + if (trx_undo_left(undo_page, ptr) < 5) { - return(0); - } + return(0); + } - len = mach_write_compressed(ptr, upd_get_n_fields(update)); - ptr += len; + len = mach_write_compressed(ptr, upd_get_n_fields(update)); + ptr += len; - for (i = 0; i < upd_get_n_fields(update); i++) { + for (i = 0; i < upd_get_n_fields(update); i++) { - upd_field = upd_get_nth_field(update, i); - pos = upd_field->field_no; + upd_field = upd_get_nth_field(update, i); + pos = upd_field->field_no; - /* Write field number to undo log */ - if (trx_undo_left(undo_page, ptr) < 5) { + /* Write field number to undo log */ + if (trx_undo_left(undo_page, ptr) < 5) { - return(0); - } + return(0); + } - len = mach_write_compressed(ptr, pos); - ptr += len; + len = mach_write_compressed(ptr, pos); + ptr += len; - /* Save the old value of field */ - field = rec_get_nth_field(rec, offsets, pos, &flen); + /* Save the old value of field */ + field = rec_get_nth_field(rec, offsets, pos, &flen); - if (trx_undo_left(undo_page, ptr) < 5) { + if (trx_undo_left(undo_page, ptr) < 5) { - return(0); - } + return(0); + } - if (rec_offs_nth_extern(offsets, pos)) { - /* If a field has external storage, we add to - flen the flag */ + if (rec_offs_nth_extern(offsets, pos)) { + /* If a field has external storage, we add + to flen the flag */ - len = mach_write_compressed(ptr, + len = mach_write_compressed(ptr, UNIV_EXTERN_STORAGE_FIELD + flen); - /* Notify purge that it eventually has to free the old - externally stored field */ - - trx->update_undo->del_marks = TRUE; + /* Notify purge that it eventually has to + free the old externally stored field */ - *type_cmpl_ptr = *type_cmpl_ptr | TRX_UNDO_UPD_EXTERN; - } else { - len = mach_write_compressed(ptr, flen); - } + trx->update_undo->del_marks = TRUE; - ptr += len; + *type_cmpl_ptr = *type_cmpl_ptr + | TRX_UNDO_UPD_EXTERN; + } else { + len = mach_write_compressed(ptr, flen); + } - if (flen != UNIV_SQL_NULL) { - if (trx_undo_left(undo_page, ptr) < flen) { + ptr += len; - return(0); - } + if (flen != UNIV_SQL_NULL) { + if (trx_undo_left(undo_page, ptr) < flen) { - ut_memcpy(ptr, field, flen); - ptr += flen; + return(0); + } + + ut_memcpy(ptr, field, flen); + ptr += flen; + } } - } - } + } /*----------------------------------------*/ /* In the case of a delete marking, and also in the case of an update @@ -604,64 +605,68 @@ trx_undo_page_report_modify( we can construct the column prefix fields in the index from the stored data. */ - if (!update || !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { + if (!update || !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { - trx->update_undo->del_marks = TRUE; + trx->update_undo->del_marks = TRUE; - if (trx_undo_left(undo_page, ptr) < 5) { + if (trx_undo_left(undo_page, ptr) < 5) { - return(0); - } - - old_ptr = ptr; + return(0); + } - /* Reserve 2 bytes to write the number of bytes the stored fields - take in this undo record */ + old_ptr = ptr; - ptr += 2; + /* Reserve 2 bytes to write the number of bytes the stored + fields take in this undo record */ - for (col_no = 0; col_no < dict_table_get_n_cols(table); col_no++) { + ptr += 2; - col = dict_table_get_nth_col(table, col_no); + for (col_no = 0; col_no < dict_table_get_n_cols(table); + col_no++) { - if (col->ord_part > 0) { - - pos = dict_index_get_nth_col_pos(index, col_no); + col = dict_table_get_nth_col(table, col_no); - /* Write field number to undo log */ - if (trx_undo_left(undo_page, ptr) < 5) { - - return(0); - } + if (col->ord_part > 0) { - len = mach_write_compressed(ptr, pos); - ptr += len; - - /* Save the old value of field */ - field = rec_get_nth_field(rec, offsets, pos, &flen); - - if (trx_undo_left(undo_page, ptr) < 5) { - - return(0); - } + pos = dict_index_get_nth_col_pos(index, + col_no); - len = mach_write_compressed(ptr, flen); - ptr += len; + /* Write field number to undo log */ + if (trx_undo_left(undo_page, ptr) < 5) { - if (flen != UNIV_SQL_NULL) { - if (trx_undo_left(undo_page, ptr) < flen) { - return(0); } - ut_memcpy(ptr, field, flen); - ptr += flen; + len = mach_write_compressed(ptr, pos); + ptr += len; + + /* Save the old value of field */ + field = rec_get_nth_field(rec, offsets, pos, + &flen); + + if (trx_undo_left(undo_page, ptr) < 5) { + + return(0); + } + + len = mach_write_compressed(ptr, flen); + ptr += len; + + if (flen != UNIV_SQL_NULL) { + if (trx_undo_left(undo_page, ptr) + < flen) { + + return(0); + } + + ut_memcpy(ptr, field, flen); + ptr += flen; + } } } - } - mach_write_to_2(old_ptr, ptr - old_ptr); - } + mach_write_to_2(old_ptr, ptr - old_ptr); + } /*----------------------------------------*/ /* Write pointers to the previous and the next undo log records */ @@ -669,7 +674,7 @@ trx_undo_page_report_modify( return(0); } - + mach_write_to_2(ptr, first_free); ptr += 2; mach_write_to_2(undo_page + first_free, ptr - undo_page); @@ -681,7 +686,7 @@ trx_undo_page_report_modify( trx_undof_page_add_undo_rec_log(undo_page, first_free, ptr - undo_page, mtr); - return(first_free); + return(first_free); } /************************************************************************** @@ -708,11 +713,11 @@ trx_undo_update_rec_get_sys_cols( /* Read the values of the system columns */ - *trx_id = mach_dulint_read_compressed(ptr); + *trx_id = mach_dulint_read_compressed(ptr); len = mach_dulint_get_compressed_size(*trx_id); ptr += len; - *roll_ptr = mach_dulint_read_compressed(ptr); + *roll_ptr = mach_dulint_read_compressed(ptr); len = mach_dulint_get_compressed_size(*roll_ptr); ptr += len; @@ -730,7 +735,7 @@ trx_undo_update_rec_get_n_upd_fields( byte* ptr, /* in: pointer to remaining part of undo log record */ ulint* n) /* out: number of fields */ { - *n = mach_read_compressed(ptr); + *n = mach_read_compressed(ptr); ptr += mach_get_compressed_size(*n); return(ptr); @@ -747,7 +752,7 @@ trx_undo_update_rec_get_field_no( byte* ptr, /* in: pointer to remaining part of undo log record */ ulint* field_no)/* out: field number */ { - *field_no = mach_read_compressed(ptr); + *field_no = mach_read_compressed(ptr); ptr += mach_get_compressed_size(*field_no); return(ptr); @@ -790,7 +795,7 @@ trx_undo_update_rec_get_update( ulint len; ulint field_no; ulint i; - + ut_a(index->type & DICT_CLUSTERED); if (type != TRX_UNDO_DEL_MARK_REC) { @@ -822,7 +827,7 @@ trx_undo_update_rec_get_update( dict_index_get_sys_col_pos(index, DATA_ROLL_PTR), index, trx); dfield_set_data(&(upd_field->new_val), buf, DATA_ROLL_PTR_LEN); - + /* Store then the updated ordinary columns to the update vector */ for (i = 0; i < n_fields; i++) { @@ -854,10 +859,10 @@ trx_undo_update_rec_get_update( if (len != UNIV_SQL_NULL && len >= UNIV_EXTERN_STORAGE_FIELD) { upd_field->extern_storage = TRUE; - + len -= UNIV_EXTERN_STORAGE_FIELD; } - + dfield_set_data(&(upd_field->new_val), field, len); } @@ -865,7 +870,7 @@ trx_undo_update_rec_get_update( return(ptr); } - + /*********************************************************************** Builds a partial row from an update undo log record. It contains the columns which occur as ordering in any index of the table. */ @@ -896,9 +901,9 @@ trx_undo_rec_get_partial_row( ulint total_len; byte* start_ptr; ulint i; - + ut_ad(index && ptr && row && heap); - + row_len = dict_table_get_n_cols(index->table); *row = dtuple_create(heap, row_len); @@ -909,18 +914,18 @@ trx_undo_rec_get_partial_row( total_len = mach_read_from_2(ptr); ptr += 2; - + for (i = 0;; i++) { if (ptr == start_ptr + total_len) { break; } - + ptr = trx_undo_update_rec_get_field_no(ptr, &field_no); col_no = dict_index_get_nth_col_no(index, field_no); - + ptr = trx_undo_rec_get_col_val(ptr, &field, &len); dfield = dtuple_get_nth_field(*row, col_no); @@ -929,7 +934,7 @@ trx_undo_rec_get_partial_row( } return(ptr); -} +} /*************************************************************************** Erases the unused undo log page end. */ @@ -949,7 +954,7 @@ trx_undo_erase_page_end( mlog_write_initial_log_record(undo_page, MLOG_UNDO_ERASE_END, mtr); } - + /*************************************************************** Parses a redo log record of erasing of an undo page end. */ @@ -1026,14 +1031,14 @@ trx_undo_report_row_operation( return(DB_SUCCESS); } - + ut_ad(thr); ut_ad((op_type != TRX_UNDO_INSERT_OP) - || (clust_entry && !update && !rec)); - + || (clust_entry && !update && !rec)); + trx = thr_get_trx(thr); rseg = trx->rseg; - + mutex_enter(&(trx->undo_mutex)); /* If the undo log is not assigned yet, assign one */ @@ -1068,7 +1073,7 @@ trx_undo_report_row_operation( } page_no = undo->last_page_no; - + mtr_start(&mtr); for (;;) { @@ -1102,7 +1107,7 @@ trx_undo_report_row_operation( trx_undo_erase_page_end(undo_page, &mtr); } - + mtr_commit(&mtr); if (offset != 0) { @@ -1112,7 +1117,7 @@ trx_undo_report_row_operation( } ut_ad(page_no == undo->last_page_no); - + /* We have to extend the undo log by one page */ mtr_start(&mtr); @@ -1122,11 +1127,11 @@ trx_undo_report_row_operation( counterpart of the tree latch, which is the rseg mutex. */ mutex_enter(&(rseg->mutex)); - + page_no = trx_undo_add_page(trx, undo, &mtr); mutex_exit(&(rseg->mutex)); - + if (page_no == FIL_NULL) { /* Did not succeed: out of space */ @@ -1146,7 +1151,7 @@ trx_undo_report_row_operation( undo->guess_page = undo_page; UT_DULINT_INC(trx->undo_no); - + mutex_exit(&(trx->undo_mutex)); *roll_ptr = trx_undo_build_roll_ptr(is_insert, rseg->id, page_no, @@ -1178,15 +1183,15 @@ trx_undo_get_undo_rec_low( trx_rseg_t* rseg; ibool is_insert; mtr_t mtr; - + trx_undo_decode_roll_ptr(roll_ptr, &is_insert, &rseg_id, &page_no, &offset); rseg = trx_rseg_get_on_id(rseg_id); mtr_start(&mtr); - + undo_page = trx_undo_page_get_s_latched(rseg->space, page_no, &mtr); - + undo_rec = trx_undo_rec_copy(undo_page + offset, heap); mtr_commit(&mtr); @@ -1219,14 +1224,14 @@ trx_undo_get_undo_rec( if (!trx_purge_update_undo_must_exist(trx_id)) { - /* It may be that the necessary undo log has already been + /* It may be that the necessary undo log has already been deleted */ return(DB_MISSING_HISTORY); } *undo_rec = trx_undo_get_undo_rec_low(roll_ptr, heap); - + return(DB_SUCCESS); } @@ -1246,7 +1251,7 @@ trx_undo_prev_version_build( rec_t* index_rec,/* in: clustered index record in the index tree */ mtr_t* index_mtr __attribute__((unused)), - /* in: mtr which contains the latch to + /* in: mtr which contains the latch to index_rec page and purge_view */ rec_t* rec, /* in: version of a clustered index record */ dict_index_t* index, /* in: clustered index */ @@ -1276,10 +1281,10 @@ trx_undo_prev_version_build( #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED)); #endif /* UNIV_SYNC_DEBUG */ - ut_ad(mtr_memo_contains(index_mtr, buf_block_align(index_rec), - MTR_MEMO_PAGE_S_FIX) || - mtr_memo_contains(index_mtr, buf_block_align(index_rec), - MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr_memo_contains(index_mtr, buf_block_align(index_rec), + MTR_MEMO_PAGE_S_FIX) || + mtr_memo_contains(index_mtr, buf_block_align(index_rec), + MTR_MEMO_PAGE_X_FIX)); ut_ad(rec_offs_validate(rec, index, offsets)); if (!(index->type & DICT_CLUSTERED)) { @@ -1293,12 +1298,12 @@ trx_undo_prev_version_build( "InnoDB: record version ", stderr); rec_print_new(stderr, rec, offsets); putc('\n', stderr); - return(DB_ERROR); - } + return(DB_ERROR); + } roll_ptr = row_get_rec_roll_ptr(rec, index, offsets); old_roll_ptr = roll_ptr; - + *old_vers = NULL; if (trx_undo_roll_ptr_is_insert(roll_ptr)) { @@ -1308,8 +1313,8 @@ trx_undo_prev_version_build( return(DB_SUCCESS); } - rec_trx_id = row_get_rec_trx_id(rec, index, offsets); - + rec_trx_id = row_get_rec_trx_id(rec, index, offsets); + err = trx_undo_get_undo_rec(roll_ptr, rec_trx_id, &undo_rec, heap); if (err != DB_SUCCESS) { @@ -1364,15 +1369,15 @@ trx_undo_prev_version_build( fprintf(stderr, "\n" "InnoDB: Record trx id %lu %lu, update rec trx id %lu %lu\n" "InnoDB: Roll ptr in rec %lu %lu, in update rec %lu %lu\n", - (ulong) ut_dulint_get_high(rec_trx_id), - (ulong) ut_dulint_get_low(rec_trx_id), - (ulong) ut_dulint_get_high(trx_id), - (ulong) ut_dulint_get_low(trx_id), - (ulong) ut_dulint_get_high(old_roll_ptr), - (ulong) ut_dulint_get_low(old_roll_ptr), - (ulong) ut_dulint_get_high(roll_ptr), - (ulong) ut_dulint_get_low(roll_ptr)); - + (ulong) ut_dulint_get_high(rec_trx_id), + (ulong) ut_dulint_get_low(rec_trx_id), + (ulong) ut_dulint_get_high(trx_id), + (ulong) ut_dulint_get_low(trx_id), + (ulong) ut_dulint_get_high(old_roll_ptr), + (ulong) ut_dulint_get_low(old_roll_ptr), + (ulong) ut_dulint_get_high(roll_ptr), + (ulong) ut_dulint_get_low(roll_ptr)); + trx_purge_sys_print(); return(DB_ERROR); } @@ -1392,7 +1397,7 @@ trx_undo_prev_version_build( n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets, update); entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, - heap); + heap); row_upd_index_replace_new_col_vals(entry, index, update, heap); buf = mem_heap_alloc(heap, diff --git a/storage/innobase/trx/trx0roll.c b/storage/innobase/trx/trx0roll.c index fdfb7428129..fd733ef5fb8 100644 --- a/storage/innobase/trx/trx0roll.c +++ b/storage/innobase/trx/trx0roll.c @@ -77,7 +77,7 @@ trx_general_rollback_for_mysql( trx->error_state = DB_SUCCESS; thr = pars_complete_graph_for_exec(roll_node, trx, heap); - + ut_a(thr == que_fork_start_command(que_node_get_parent(thr))); que_run_threads(thr); @@ -94,9 +94,9 @@ trx_general_rollback_for_mysql( mutex_exit(&kernel_mutex); - mem_heap_free(heap); + mem_heap_free(heap); - ut_a(trx->error_state == DB_SUCCESS); + ut_a(trx->error_state == DB_SUCCESS); /* Tell Innobase server that there might be work for utility threads: */ @@ -109,6 +109,7 @@ trx_general_rollback_for_mysql( InnoDB Hot Backup builds. Besides, this function should never be called in InnoDB Hot Backup. */ ut_error; + return(DB_FAIL); #endif /* UNIV_HOTBACKUP */ } @@ -129,13 +130,13 @@ trx_rollback_for_mysql( } trx->op_info = "rollback"; - + err = trx_general_rollback_for_mysql(trx, FALSE, NULL); trx->op_info = ""; return(err); -} +} /*********************************************************************** Rollback the latest SQL statement for MySQL. */ @@ -154,14 +155,14 @@ trx_rollback_last_sql_stat_for_mysql( } trx->op_info = "rollback of SQL statement"; - + err = trx_general_rollback_for_mysql(trx, TRUE, &(trx->last_sql_stat_start)); /* The following call should not be needed, but we play safe: */ trx_mark_sql_stat_end(trx); trx->op_info = ""; - + return(err); } @@ -179,13 +180,13 @@ trx_roll_savepoints_free( trx_named_savept_t* next_savep; if (savep == NULL) { - savep = UT_LIST_GET_FIRST(trx->trx_savepoints); + savep = UT_LIST_GET_FIRST(trx->trx_savepoints); } else { - savep = UT_LIST_GET_NEXT(trx_savepoints, savep); + savep = UT_LIST_GET_NEXT(trx_savepoints, savep); } - + while (savep != NULL) { - next_savep = UT_LIST_GET_NEXT(trx_savepoints, savep); + next_savep = UT_LIST_GET_NEXT(trx_savepoints, savep); UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep); mem_free(savep->name); @@ -199,7 +200,7 @@ trx_roll_savepoints_free( Rolls back a transaction back to a named savepoint. Modifications after the savepoint are undone but InnoDB does NOT release the corresponding locks which are stored in memory. If a lock is 'implicit', that is, a new inserted -row holds a lock where the lock information is carried by the trx id stored in +row holds a lock where the lock information is carried by the trx id stored in the row, these locks are naturally released in the rollback. Savepoints which were set after this savepoint are deleted. */ @@ -225,16 +226,16 @@ trx_rollback_to_savepoint_for_mysql( savep = UT_LIST_GET_FIRST(trx->trx_savepoints); while (savep != NULL) { - if (0 == ut_strcmp(savep->name, savepoint_name)) { - /* Found */ + if (0 == ut_strcmp(savep->name, savepoint_name)) { + /* Found */ break; } - savep = UT_LIST_GET_NEXT(trx_savepoints, savep); + savep = UT_LIST_GET_NEXT(trx_savepoints, savep); } - if (savep == NULL) { + if (savep == NULL) { - return(DB_NO_SAVEPOINT); + return(DB_NO_SAVEPOINT); } if (trx->conc_state == TRX_NOT_STARTED) { @@ -242,7 +243,7 @@ trx_rollback_to_savepoint_for_mysql( fputs(" InnoDB: Error: transaction has a savepoint ", stderr); ut_print_name(stderr, trx, savep->name); fputs(" though it is not started\n", stderr); - return(DB_ERROR); + return(DB_ERROR); } /* We can now free all savepoints strictly later than this one */ @@ -252,7 +253,7 @@ trx_rollback_to_savepoint_for_mysql( *mysql_binlog_cache_pos = savep->mysql_binlog_cache_pos; trx->op_info = "rollback to a savepoint"; - + err = trx_general_rollback_for_mysql(trx, TRUE, &(savep->savept)); /* Store the current undo_no of the transaction so that we know where @@ -292,18 +293,18 @@ trx_savepoint_for_mysql( savep = UT_LIST_GET_FIRST(trx->trx_savepoints); while (savep != NULL) { - if (0 == ut_strcmp(savep->name, savepoint_name)) { - /* Found */ + if (0 == ut_strcmp(savep->name, savepoint_name)) { + /* Found */ break; } - savep = UT_LIST_GET_NEXT(trx_savepoints, savep); + savep = UT_LIST_GET_NEXT(trx_savepoints, savep); } if (savep) { - /* There is a savepoint with the same name: free that */ + /* There is a savepoint with the same name: free that */ UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep); - + mem_free(savep->name); mem_free(savep); } @@ -342,22 +343,22 @@ trx_release_savepoint_for_mysql( savep = UT_LIST_GET_FIRST(trx->trx_savepoints); while (savep != NULL) { - if (0 == ut_strcmp(savep->name, savepoint_name)) { - /* Found */ + if (0 == ut_strcmp(savep->name, savepoint_name)) { + /* Found */ break; } - savep = UT_LIST_GET_NEXT(trx_savepoints, savep); + savep = UT_LIST_GET_NEXT(trx_savepoints, savep); } - if (savep == NULL) { + if (savep == NULL) { - return(DB_NO_SAVEPOINT); + return(DB_NO_SAVEPOINT); } /* We can now free all savepoints strictly later than this one */ trx_roll_savepoints_free(trx, savep); - + /* Now we can free this savepoint too */ UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep); @@ -387,7 +388,7 @@ trx_savept_take( /*********************************************************************** Rollback or clean up transactions which have no user session. If the transaction already was committed, then we clean up a possible insert -undo log. If the transaction was not yet committed, then we roll it back. +undo log. If the transaction was not yet committed, then we roll it back. Note: this is done in a background thread. */ #ifndef __WIN__ @@ -397,10 +398,10 @@ ulint #endif trx_rollback_or_clean_all_without_sess( /*===================================*/ - /* out: a dummy parameter */ - void* arg __attribute__((unused))) - /* in: a dummy parameter required by - os_thread_create */ + /* out: a dummy parameter */ + void* arg __attribute__((unused))) + /* in: a dummy parameter required by + os_thread_create */ { mem_heap_t* heap; que_fork_t* fork; @@ -413,20 +414,20 @@ trx_rollback_or_clean_all_without_sess( int err; mutex_enter(&kernel_mutex); - + /* Open a dummy session */ if (!trx_dummy_sess) { trx_dummy_sess = sess_open(); } - + mutex_exit(&kernel_mutex); if (UT_LIST_GET_FIRST(trx_sys->trx_list)) { fprintf(stderr, "InnoDB: Starting in background the rollback of uncommitted transactions\n"); - } else { + } else { goto leave_function; } loop: @@ -447,7 +448,7 @@ loop: break; } } - + mutex_exit(&kernel_mutex); if (trx == NULL) { @@ -455,20 +456,20 @@ loop: fprintf(stderr, " InnoDB: Rollback of non-prepared transactions completed\n"); - mem_heap_free(heap); + mem_heap_free(heap); goto leave_function; } trx->sess = trx_dummy_sess; - if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) { + if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) { fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n", (ulong) ut_dulint_get_high(trx->id), (ulong) ut_dulint_get_low(trx->id)); trx_cleanup_at_db_startup(trx); - + mem_heap_free(heap); goto loop; @@ -484,12 +485,12 @@ loop: thr->child = roll_node; roll_node->common.parent = thr; - mutex_enter(&kernel_mutex); + mutex_enter(&kernel_mutex); trx->graph = fork; ut_a(thr == que_fork_start_command(fork)); - + trx_roll_crash_recv_trx = trx; trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no); trx_roll_progress_printed_pct = 0; @@ -545,7 +546,7 @@ loop: table = dict_table_get_on_id_low(trx->table_id, trx); - if (table) { + if (table) { fputs("InnoDB: Table found: dropping table ", stderr); ut_print_name(stderr, trx, table->name); fputs(" in recovery\n", stderr); @@ -578,12 +579,12 @@ leave_function: /* The following is dummy code to keep the compiler happy: */ #ifndef __WIN__ - return(NULL); + return(NULL); #else - return(0); + return(0); #endif } - + /*********************************************************************** Creates an undo number array. */ @@ -594,7 +595,7 @@ trx_undo_arr_create(void) trx_undo_arr_t* arr; mem_heap_t* heap; ulint i; - + heap = mem_heap_create(1024); arr = mem_heap_alloc(heap, sizeof(trx_undo_arr_t)); @@ -649,7 +650,7 @@ trx_undo_arr_store_info( arr = trx->undo_no_arr; n_used = arr->n_used; stored_here = NULL; - + for (i = 0;; i++) { cell = trx_undo_arr_get_nth_info(arr, i); @@ -679,7 +680,7 @@ trx_undo_arr_store_info( return(FALSE); } } - + if (n == n_used && stored_here) { ut_ad(arr->n_used == 1 + n_used); @@ -710,10 +711,10 @@ trx_undo_arr_remove_info( cell = trx_undo_arr_get_nth_info(arr, i); if (cell->in_use - && 0 == ut_dulint_cmp(cell->undo_no, undo_no)) { + && 0 == ut_dulint_cmp(cell->undo_no, undo_no)) { cell->in_use = FALSE; - + ut_ad(arr->n_used > 0); arr->n_used--; @@ -738,11 +739,11 @@ trx_undo_arr_get_biggest( dulint biggest; ulint n; ulint i; - + n = 0; n_used = arr->n_used; biggest = ut_dulint_zero; - + for (i = 0;; i++) { cell = trx_undo_arr_get_nth_info(arr, i); @@ -753,7 +754,7 @@ trx_undo_arr_get_biggest( biggest = cell->undo_no; } } - + if (n == n_used) { return(biggest); } @@ -771,14 +772,14 @@ trx_roll_try_truncate( trx_undo_arr_t* arr; dulint limit; dulint biggest; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(trx->undo_mutex))); ut_ad(mutex_own(&((trx->rseg)->mutex))); #endif /* UNIV_SYNC_DEBUG */ trx->pages_undone = 0; - + arr = trx->undo_no_arr; limit = trx->undo_no; @@ -786,10 +787,10 @@ trx_roll_try_truncate( if (arr->n_used > 0) { biggest = trx_undo_arr_get_biggest(arr); - if (ut_dulint_cmp(biggest, limit) >= 0) { + if (ut_dulint_cmp(biggest, limit) >= 0) { - limit = ut_dulint_add(biggest, 1); - } + limit = ut_dulint_add(biggest, 1); + } } if (trx->insert_undo) { @@ -813,7 +814,7 @@ trx_roll_pop_top_rec( trx_undo_t* undo, /* in: undo log */ mtr_t* mtr) /* in: mtr */ { - page_t* undo_page; + page_t* undo_page; ulint offset; trx_undo_rec_t* prev_rec; page_t* prev_rec_page; @@ -838,12 +839,12 @@ trx_roll_pop_top_rec( undo->empty = TRUE; } else { prev_rec_page = buf_frame_align(prev_rec); - + if (prev_rec_page != undo_page) { trx->pages_undone++; } - + undo->top_page_no = buf_frame_get_page_no(prev_rec_page); undo->top_offset = prev_rec - prev_rec_page; undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec); @@ -880,7 +881,7 @@ trx_roll_pop_top_rec_of_trx( trx_rseg_t* rseg; ulint progress_pct; mtr_t mtr; - + rseg = trx->rseg; try_again: mutex_enter(&(trx->undo_mutex)); @@ -910,9 +911,9 @@ try_again: if (!undo || undo->empty || (ut_dulint_cmp(limit, undo->top_undo_no) > 0)) { - if ((trx->undo_no_arr)->n_used == 0) { + if ((trx->undo_no_arr)->n_used == 0) { /* Rollback is ending */ - + mutex_enter(&(rseg->mutex)); trx_roll_try_truncate(trx); @@ -930,7 +931,7 @@ try_again: } else { is_insert = FALSE; } - + *roll_ptr = trx_undo_build_roll_ptr(is_insert, (undo->rseg)->id, undo->top_page_no, undo->top_offset); mtr_start(&mtr); @@ -946,7 +947,7 @@ try_again: if (trx == trx_roll_crash_recv_trx && trx_roll_max_undo_no > 1000) { - progress_pct = 100 - (ulint) + progress_pct = 100 - (ulint) ((ut_conv_dulint_to_longlong(undo_no) * 100) / trx_roll_max_undo_no); if (progress_pct != trx_roll_progress_printed_pct) { @@ -970,16 +971,16 @@ try_again: mutex_exit(&(trx->undo_mutex)); mtr_commit(&mtr); - + goto try_again; } undo_rec_copy = trx_undo_rec_copy(undo_rec, heap); - + mutex_exit(&(trx->undo_mutex)); mtr_commit(&mtr); - + return(undo_rec_copy); } @@ -996,11 +997,11 @@ trx_undo_rec_reserve( dulint undo_no)/* in: undo number of the record */ { ibool ret; - + mutex_enter(&(trx->undo_mutex)); ret = trx_undo_arr_store_info(trx, undo_no); - + mutex_exit(&(trx->undo_mutex)); return(ret); @@ -1016,7 +1017,7 @@ trx_undo_rec_release( dulint undo_no)/* in: undo number */ { trx_undo_arr_t* arr; - + mutex_enter(&(trx->undo_mutex)); arr = trx->undo_no_arr; @@ -1027,7 +1028,7 @@ trx_undo_rec_release( } /************************************************************************* -Starts a rollback operation. */ +Starts a rollback operation. */ void trx_rollback( @@ -1049,7 +1050,7 @@ trx_rollback( ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad((trx->undo_no_arr == NULL) || ((trx->undo_no_arr)->n_used == 0)); - + /* Initialize the rollback field in the transaction */ if (sig->type == TRX_SIG_TOTAL_ROLLBACK) { @@ -1057,7 +1058,7 @@ trx_rollback( trx->roll_limit = ut_dulint_zero; } else if (sig->type == TRX_SIG_ROLLBACK_TO_SAVEPT) { - + trx->roll_limit = (sig->savept).least_undo_no; } else if (sig->type == TRX_SIG_ERROR_OCCURRED) { @@ -1074,7 +1075,7 @@ trx_rollback( if (trx->undo_no_arr == NULL) { trx->undo_no_arr = trx_undo_arr_create(); } - + /* Build a 'query' graph which will perform the undo operations */ roll_graph = trx_roll_graph_build(trx); @@ -1089,7 +1090,7 @@ trx_rollback( /* thr2 = que_fork_start_command(roll_graph); ut_ad(thr2); */ - + if (next_thr && (*next_thr == NULL)) { *next_thr = thr; /* srv_que_task_enqueue_low(thr2); */ @@ -1127,7 +1128,7 @@ trx_roll_graph_build( thr = que_thr_create(fork, heap); /* thr2 = que_thr_create(fork, heap); */ - thr->child = row_undo_node_create(trx, thr, heap); + thr->child = row_undo_node_create(trx, thr, heap); /* thr2->child = row_undo_node_create(trx, thr2, heap); */ return(fork); @@ -1206,13 +1207,13 @@ trx_finish_rollback_off_kernel( que_thr_t** next_thr)/* in/out: next query thread to run; if the value which is passed in is a pointer to a NULL pointer, then the - calling function can start running + calling function can start running a new query thread; if this parameter is NULL, it is ignored */ { trx_sig_t* sig; trx_sig_t* next_sig; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ @@ -1238,7 +1239,7 @@ trx_finish_rollback_off_kernel( } #ifdef UNIV_DEBUG - if (lock_print_waits) { + if (lock_print_waits) { fprintf(stderr, "Trx %lu rollback finished\n", (ulong) ut_dulint_get_low(trx->id)); } @@ -1250,7 +1251,7 @@ trx_finish_rollback_off_kernel( send reply messages to them */ trx->que_state = TRX_QUE_RUNNING; - + while (sig != NULL) { next_sig = UT_LIST_GET_NEXT(signals, sig); @@ -1281,7 +1282,7 @@ roll_node_create( node->state = ROLL_NODE_SEND; node->partial = FALSE; - + return(node); } @@ -1298,7 +1299,7 @@ trx_rollback_step( ibool success; ulint sig_no; trx_savept_t* savept; - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_ROLLBACK); @@ -1327,7 +1328,7 @@ trx_rollback_step( thr, savept, NULL); thr->state = QUE_THR_SIG_REPLY_WAIT; - + mutex_exit(&kernel_mutex); if (!success) { @@ -1339,8 +1340,8 @@ trx_rollback_step( } ut_ad(node->state == ROLL_NODE_WAIT); - + thr->run_node = que_node_get_parent(node); - + return(thr); } diff --git a/storage/innobase/trx/trx0rseg.c b/storage/innobase/trx/trx0rseg.c index a01d4bb835d..f396666e7c9 100644 --- a/storage/innobase/trx/trx0rseg.c +++ b/storage/innobase/trx/trx0rseg.c @@ -58,7 +58,7 @@ trx_rseg_header_create( trx_sysf_t* sys_header; ulint i; page_t* page; - + ut_ad(mtr); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); @@ -91,10 +91,10 @@ trx_rseg_header_create( /* Get the rollback segment file page */ rsegf = trx_rsegf_get_new(space, page_no, mtr); - + /* Initialize max size field */ mlog_write_ulint(rsegf + TRX_RSEG_MAX_SIZE, max_size, MLOG_4BYTES, mtr); - + /* Initialize the history list */ mlog_write_ulint(rsegf + TRX_RSEG_HISTORY_SIZE, 0, MLOG_4BYTES, mtr); @@ -109,7 +109,7 @@ trx_rseg_header_create( /* Add the rollback segment info to the free slot in the trx system header */ - trx_sysf_rseg_set_space(sys_header, *slot_no, space, mtr); + trx_sysf_rseg_set_space(sys_header, *slot_no, space, mtr); trx_sysf_rseg_set_page_no(sys_header, *slot_no, page_no, mtr); return(page_no); @@ -146,7 +146,7 @@ trx_rseg_mem_create( rseg->id = id; rseg->space = space; rseg->page_no = page_no; - + mutex_create(&(rseg->mutex)); mutex_set_level(&(rseg->mutex), SYNC_RSEG); @@ -154,7 +154,7 @@ trx_rseg_mem_create( trx_sys_set_nth_rseg(trx_sys, id, rseg); - rseg_header = trx_rsegf_get_new(space, page_no, mtr); + rseg_header = trx_rsegf_get_new(space, page_no, mtr); rseg->max_size = mtr_read_ulint(rseg_header + TRX_RSEG_MAX_SIZE, MLOG_4BYTES, mtr); @@ -172,15 +172,14 @@ trx_rseg_mem_create( trx_sys->rseg_history_len += len; node_addr = trx_purge_get_log_from_hist( - flst_get_last(rseg_header + TRX_RSEG_HISTORY, + flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr)); rseg->last_page_no = node_addr.page; rseg->last_offset = node_addr.boffset; undo_log_hdr = trx_undo_page_get(rseg->space, node_addr.page, - mtr) - + node_addr.boffset; - + mtr) + node_addr.boffset; + rseg->last_trx_no = mtr_read_dulint( undo_log_hdr + TRX_UNDO_TRX_NO, mtr); rseg->last_del_marks = mtr_read_ulint( @@ -242,7 +241,7 @@ trx_rseg_create( ulint page_no; trx_rseg_t* rseg; - mtr_x_lock(fil_space_get_latch(space), mtr); + mtr_x_lock(fil_space_get_latch(space), mtr); mutex_enter(&kernel_mutex); page_no = trx_rseg_header_create(space, max_size, id, mtr); diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index 23f1dc40d00..bd1bceef7da 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -23,7 +23,7 @@ Created 3/26/1996 Heikki Tuuri #include "os0file.h" /* The transaction system */ -trx_sys_t* trx_sys = NULL; +trx_sys_t* trx_sys = NULL; trx_doublewrite_t* trx_doublewrite = NULL; /* The following is set to TRUE when we are upgrading from the old format data @@ -42,7 +42,7 @@ file name and position here. We have successfully got the updates to InnoDB up to this position. If .._pos is -1, it means no crash recovery was needed, or there was no master log position info inside InnoDB. */ -char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN]; +char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN]; ib_longlong trx_sys_mysql_master_log_pos = -1; /* If this MySQL server uses binary logging, after InnoDB has been inited @@ -50,7 +50,7 @@ and if it has done a crash recovery, we store the binlog file name and position here. If .._pos is -1, it means there was no binlog position info inside InnoDB. */ -char trx_sys_mysql_bin_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN]; +char trx_sys_mysql_bin_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN]; ib_longlong trx_sys_mysql_bin_log_pos = -1; @@ -70,14 +70,14 @@ trx_doublewrite_page_inside( } if (page_no >= trx_doublewrite->block1 - && page_no < trx_doublewrite->block1 - + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { + && page_no < trx_doublewrite->block1 + + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { return(TRUE); } if (page_no >= trx_doublewrite->block2 - && page_no < trx_doublewrite->block2 - + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { + && page_no < trx_doublewrite->block2 + + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { return(TRUE); } @@ -112,11 +112,11 @@ trx_doublewrite_init( trx_doublewrite->block2 = mach_read_from_4( doublewrite + TRX_SYS_DOUBLEWRITE_BLOCK2); - trx_doublewrite->write_buf_unaligned = + trx_doublewrite->write_buf_unaligned = ut_malloc( (1 + 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) * UNIV_PAGE_SIZE); - + trx_doublewrite->write_buf = ut_align( trx_doublewrite->write_buf_unaligned, UNIV_PAGE_SIZE); @@ -154,7 +154,7 @@ trx_sys_mark_upgraded_to_multiple_tablespaces(void) TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N, MLOG_4BYTES, &mtr); mtr_commit(&mtr); - + /* Flush the modified pages to disk and make a checkpoint */ log_make_checkpoint_at(ut_dulint_max, TRUE); @@ -185,7 +185,7 @@ trx_sys_create_doublewrite_buf(void) return; } -start_again: +start_again: mtr_start(&mtr); page = buf_page_get(TRX_SYS_SPACE, TRX_SYS_PAGE_NO, RW_X_LATCH, &mtr); @@ -194,7 +194,7 @@ start_again: #endif /* UNIV_SYNC_DEBUG */ doublewrite = page + TRX_SYS_DOUBLEWRITE; - + if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC) == TRX_SYS_DOUBLEWRITE_MAGIC_N) { /* The doublewrite buffer has already been created: @@ -218,7 +218,7 @@ start_again: exit(1); } - + page2 = fseg_create(TRX_SYS_SPACE, TRX_SYS_PAGE_NO, TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG, &mtr); @@ -237,7 +237,7 @@ start_again: /* We exit without committing the mtr to prevent its modifications to the database getting to disk */ - + exit(1); } @@ -248,7 +248,7 @@ start_again: for (i = 0; i < 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE + FSP_EXTENT_SIZE / 2; i++) { page_no = fseg_alloc_free_page(fseg_header, - prev_page_no + 1, + prev_page_no + 1, FSP_UP, &mtr); if (page_no == FIL_NULL) { fprintf(stderr, @@ -267,7 +267,7 @@ start_again: space id and page number in them are the same as the page position in the tablespace, then the page has not been written to in doublewrite. */ - + new_page = buf_page_get(TRX_SYS_SPACE, page_no, RW_X_LATCH, &mtr); #ifdef UNIV_SYNC_DEBUG @@ -316,7 +316,7 @@ start_again: TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N, MLOG_4BYTES, &mtr); mtr_commit(&mtr); - + /* Flush the modified pages to disk and make a checkpoint */ log_make_checkpoint_at(ut_dulint_max, TRUE); @@ -352,11 +352,11 @@ trx_sys_doublewrite_init_or_restore_pages( ulint space_id; ulint page_no; ulint i; - + /* We do the file i/o past the buffer pool */ unaligned_read_buf = ut_malloc(2 * UNIV_PAGE_SIZE); - read_buf = ut_align(unaligned_read_buf, UNIV_PAGE_SIZE); + read_buf = ut_align(unaligned_read_buf, UNIV_PAGE_SIZE); /* Read the trx sys header to check if we are using the doublewrite buffer */ @@ -368,7 +368,7 @@ trx_sys_doublewrite_init_or_restore_pages( if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC) == TRX_SYS_DOUBLEWRITE_MAGIC_N) { /* The doublewrite buffer has been created */ - + trx_doublewrite_init(doublewrite); block1 = trx_doublewrite->block1; @@ -380,9 +380,9 @@ trx_sys_doublewrite_init_or_restore_pages( } if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED) - != TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N) { - - /* We are upgrading from a version < 4.1.x to a version where + != TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N) { + + /* We are upgrading from a version < 4.1.x to a version where multiple tablespaces are supported. We must reset the space id field in the pages in the doublewrite buffer because starting from this version the space id is stored to @@ -409,14 +409,14 @@ trx_sys_doublewrite_init_or_restore_pages( intended position */ page = buf; - + for (i = 0; i < TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 2; i++) { - + page_no = mach_read_from_4(page + FIL_PAGE_OFFSET); if (trx_doublewrite_must_reset_space_ids) { - space_id = 0; + space_id = 0; mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0); /* We do not need to calculate new checksums for the @@ -424,18 +424,18 @@ trx_sys_doublewrite_init_or_restore_pages( them. Write the page back to where we read it from. */ if (i < TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { - source_page_no = block1 + i; + source_page_no = block1 + i; } else { source_page_no = block2 + i - TRX_SYS_DOUBLEWRITE_BLOCK_SIZE; } fil_io(OS_FILE_WRITE, TRUE, 0, source_page_no, 0, - UNIV_PAGE_SIZE, page, NULL); + UNIV_PAGE_SIZE, page, NULL); /* printf("Resetting space id in page %lu\n", source_page_no); */ } else { - space_id = mach_read_from_4( + space_id = mach_read_from_4( page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); } @@ -449,36 +449,36 @@ trx_sys_doublewrite_init_or_restore_pages( } else if (!fil_check_adress_in_tablespace(space_id, page_no)) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Warning: a page in the doublewrite buffer is not within space\n" "InnoDB: bounds; space id %lu page number %lu, page %lu in doublewrite buf.\n", (ulong) space_id, (ulong) page_no, (ulong) i); - + } else if (space_id == TRX_SYS_SPACE - && ( (page_no >= block1 - && page_no - < block1 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) - || (page_no >= block2 - && page_no - < block2 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) { + && ((page_no >= block1 + && page_no + < block1 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) + || (page_no >= block2 + && page_no + < block2 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) { /* It is an unwritten doublewrite buffer page: do nothing */ } else { /* Read in the actual page from the data files */ - + fil_io(OS_FILE_READ, TRUE, space_id, page_no, 0, UNIV_PAGE_SIZE, read_buf, NULL); /* Check if the page is corrupt */ if (buf_page_is_corrupted(read_buf)) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Warning: database page corruption or a failed\n" "InnoDB: file read of page %lu.\n", (ulong) page_no); - fprintf(stderr, + fprintf(stderr, "InnoDB: Trying to recover it from the doublewrite buffer.\n"); - + if (buf_page_is_corrupted(page)) { fprintf(stderr, "InnoDB: Dump of the page:\n"); @@ -487,7 +487,7 @@ trx_sys_doublewrite_init_or_restore_pages( "InnoDB: Dump of corresponding page in doublewrite buffer:\n"); buf_page_print(page); - fprintf(stderr, + fprintf(stderr, "InnoDB: Also the page in the doublewrite buffer is corrupt.\n" "InnoDB: Cannot continue operation.\n" "InnoDB: You can try to recover the database with the my.cnf\n" @@ -503,7 +503,7 @@ trx_sys_doublewrite_init_or_restore_pages( fil_io(OS_FILE_WRITE, TRUE, space_id, page_no, 0, UNIV_PAGE_SIZE, page, NULL); - fprintf(stderr, + fprintf(stderr, "InnoDB: Recovered the page from the doublewrite buffer.\n"); } } @@ -512,7 +512,7 @@ trx_sys_doublewrite_init_or_restore_pages( } fil_flush_file_spaces(FIL_TABLESPACE); - + leave_func: ut_free(unaligned_read_buf); } @@ -600,7 +600,7 @@ trx_sys_update_mysql_binlog_offset( + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD) != TRX_SYS_MYSQL_LOG_MAGIC_N) { - mlog_write_ulint(sys_header + field + mlog_write_ulint(sys_header + field + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD, TRX_SYS_MYSQL_LOG_MAGIC_N, MLOG_4BYTES, mtr); @@ -616,7 +616,7 @@ trx_sys_update_mysql_binlog_offset( if (mach_read_from_4(sys_header + field + TRX_SYS_MYSQL_LOG_OFFSET_HIGH) > 0 || (offset >> 32) > 0) { - + mlog_write_ulint(sys_header + field + TRX_SYS_MYSQL_LOG_OFFSET_HIGH, (ulint)(offset >> 32), @@ -642,7 +642,7 @@ trx_sys_print_mysql_binlog_offset_from_page( trx_sysf_t* sys_header; sys_header = page + TRX_SYS; - + if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD) == TRX_SYS_MYSQL_LOG_MAGIC_N) { @@ -683,22 +683,22 @@ trx_sys_print_mysql_binlog_offset(void) return; } - trx_sys_mysql_bin_log_pos_high = mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO - + TRX_SYS_MYSQL_LOG_OFFSET_HIGH); - trx_sys_mysql_bin_log_pos_low = mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO - + TRX_SYS_MYSQL_LOG_OFFSET_LOW); + trx_sys_mysql_bin_log_pos_high = mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO + + TRX_SYS_MYSQL_LOG_OFFSET_HIGH); + trx_sys_mysql_bin_log_pos_low = mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO + + TRX_SYS_MYSQL_LOG_OFFSET_LOW); + + trx_sys_mysql_bin_log_pos = (((ib_longlong)trx_sys_mysql_bin_log_pos_high) << 32) + + (ib_longlong)trx_sys_mysql_bin_log_pos_low; - trx_sys_mysql_bin_log_pos = (((ib_longlong)trx_sys_mysql_bin_log_pos_high) << 32) + - (ib_longlong)trx_sys_mysql_bin_log_pos_low; + ut_memcpy(trx_sys_mysql_bin_log_name, sys_header + TRX_SYS_MYSQL_LOG_INFO + + TRX_SYS_MYSQL_LOG_NAME, TRX_SYS_MYSQL_LOG_NAME_LEN); - ut_memcpy(trx_sys_mysql_bin_log_name, sys_header + TRX_SYS_MYSQL_LOG_INFO + - TRX_SYS_MYSQL_LOG_NAME, TRX_SYS_MYSQL_LOG_NAME_LEN); + fprintf(stderr, + "InnoDB: Last MySQL binlog file position %lu %lu, file name %s\n", + trx_sys_mysql_bin_log_pos_high, trx_sys_mysql_bin_log_pos_low, + trx_sys_mysql_bin_log_name); - fprintf(stderr, - "InnoDB: Last MySQL binlog file position %lu %lu, file name %s\n", - trx_sys_mysql_bin_log_pos_high, trx_sys_mysql_bin_log_pos_low, - trx_sys_mysql_bin_log_name); - mtr_commit(&mtr); } @@ -712,7 +712,7 @@ trx_sys_print_mysql_master_log_pos(void) { trx_sysf_t* sys_header; mtr_t mtr; - + mtr_start(&mtr); sys_header = trx_sysf_get(&mtr); @@ -743,7 +743,7 @@ trx_sys_print_mysql_master_log_pos(void) + TRX_SYS_MYSQL_LOG_NAME, TRX_SYS_MYSQL_LOG_NAME_LEN); - trx_sys_mysql_master_log_pos = + trx_sys_mysql_master_log_pos = (((ib_longlong)mach_read_from_4( sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) @@ -766,7 +766,7 @@ trx_sysf_rseg_find_free( trx_sysf_t* sys_header; ulint page_no; ulint i; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(kernel_mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -785,7 +785,7 @@ trx_sysf_rseg_find_free( return(ULINT_UNDEFINED); } - + /********************************************************************* Creates the file page for the transaction system. This function is called only at the database creation, before trx_sys_init. */ @@ -800,7 +800,7 @@ trx_sysf_create( page_t* page; ulint page_no; ulint i; - + ut_ad(mtr); /* Note that below we first reserve the file space x-latch, and @@ -812,13 +812,16 @@ trx_sysf_create( /* Create the trx sys file block in a new allocated file segment */ page = fseg_create(TRX_SYS_SPACE, 0, TRX_SYS + TRX_SYS_FSEG_HEADER, - mtr); + mtr); ut_a(buf_frame_get_page_no(page) == TRX_SYS_PAGE_NO); #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_TRX_SYS_HEADER); #endif /* UNIV_SYNC_DEBUG */ + mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_TRX_SYS, + MLOG_2BYTES, mtr); + sys_header = trx_sysf_get(mtr); /* Start counting transaction ids from number 1 up */ @@ -828,9 +831,12 @@ trx_sysf_create( /* Reset the rollback segment slots */ for (i = 0; i < TRX_SYS_N_RSEGS; i++) { + trx_sysf_rseg_set_space(sys_header, i, ULINT_UNDEFINED, mtr); trx_sysf_rseg_set_page_no(sys_header, i, FIL_NULL, mtr); } + /* The remaining area (up to the page trailer) is uninitialized. */ + /* Create the first rollback segment in the SYSTEM tablespace */ page_no = trx_rseg_header_create(TRX_SYS_SPACE, ULINT_MAX, &slot_no, mtr); @@ -855,17 +861,17 @@ trx_sys_init_at_db_start(void) mtr_t mtr; mtr_start(&mtr); - + ut_ad(trx_sys == NULL); mutex_enter(&kernel_mutex); trx_sys = mem_alloc(sizeof(trx_sys_t)); - + sys_header = trx_sysf_get(&mtr); trx_rseg_list_and_array_init(sys_header, &mtr); - + trx_sys->latest_rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list); /* VERY important: after the database is started, max_trx_id value is @@ -876,13 +882,13 @@ trx_sys_init_at_db_start(void) the database is repeatedly started! */ trx_sys->max_trx_id = ut_dulint_add( - ut_dulint_align_up( + ut_dulint_align_up( mtr_read_dulint(sys_header + TRX_SYS_TRX_ID_STORE, &mtr), TRX_SYS_TRX_ID_WRITE_MARGIN), 2 * TRX_SYS_TRX_ID_WRITE_MARGIN); - UT_LIST_INIT(trx_sys->mysql_trx_list); + UT_LIST_INIT(trx_sys->mysql_trx_list); trx_lists_init_at_db_start(); if (UT_LIST_GET_LEN(trx_sys->trx_list) > 0) { @@ -891,8 +897,8 @@ trx_sys_init_at_db_start(void) for (;;) { if ( trx->conc_state != TRX_PREPARED) { - rows_to_undo += - ut_conv_dulint_to_longlong(trx->undo_no); + rows_to_undo += + ut_conv_dulint_to_longlong(trx->undo_no); } trx = UT_LIST_GET_NEXT(trx_list, trx); @@ -901,7 +907,7 @@ trx_sys_init_at_db_start(void) break; } } - + if (rows_to_undo > 1000000000) { unit = "M"; rows_to_undo = rows_to_undo / 1000000; @@ -913,7 +919,7 @@ trx_sys_init_at_db_start(void) (ulong) UT_LIST_GET_LEN(trx_sys->trx_list), (ulong) rows_to_undo, unit); - fprintf(stderr, "InnoDB: Trx id counter is %lu %lu\n", + fprintf(stderr, "InnoDB: Trx id counter is %lu %lu\n", (ulong) ut_dulint_get_high(trx_sys->max_trx_id), (ulong) ut_dulint_get_low(trx_sys->max_trx_id)); } diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index 090057f5d46..90d6d92c09e 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -32,7 +32,7 @@ copy MUST be equal to the one in mysql/sql/ha_innodb.cc ! */ void innobase_mysql_print_thd( FILE* f, void* thd, - uint max_query_len); + ulint max_query_len); /* Dummy session used currently in MySQL interface */ sess_t* trx_dummy_sess = NULL; @@ -47,9 +47,9 @@ Starts the transaction if it is not yet started. */ void trx_start_if_not_started_noninline( /*===============================*/ - trx_t* trx) /* in: transaction */ + trx_t* trx) /* in: transaction */ { - trx_start_if_not_started(trx); + trx_start_if_not_started(trx); } /***************************************************************** @@ -84,10 +84,10 @@ Retrieves the error_info field from a trx. */ void* trx_get_error_info( /*===============*/ - /* out: the error info */ - trx_t* trx) /* in: trx object */ + /* out: the error info */ + trx_t* trx) /* in: trx object */ { - return(trx->error_info); + return(trx->error_info); } /******************************************************************** @@ -110,7 +110,7 @@ trx_create( trx->magic_n = TRX_MAGIC_N; trx->op_info = ""; - + trx->type = TRX_USER; trx->conc_state = TRX_NOT_STARTED; trx->start_time = time(NULL); @@ -143,7 +143,7 @@ trx_create( trx->repl_wait_binlog_name = NULL; trx->repl_wait_binlog_pos = 0; - + mutex_create(&(trx->undo_mutex)); mutex_set_level(&(trx->undo_mutex), SYNC_TRX_UNDO); @@ -154,7 +154,7 @@ trx_create( trx->insert_undo = NULL; trx->update_undo = NULL; trx->undo_no_arr = NULL; - + trx->error_state = DB_SUCCESS; trx->detailed_error[0] = '\0'; @@ -186,7 +186,7 @@ trx_create( trx->n_tickets_to_enter_innodb = 0; trx->auto_inc_lock = NULL; - + trx->global_read_view_heap = mem_heap_create(256); trx->global_read_view = NULL; trx->read_view = NULL; @@ -211,25 +211,25 @@ trx_allocate_for_mysql(void) trx_t* trx; mutex_enter(&kernel_mutex); - + /* Open a dummy session */ if (!trx_dummy_sess) { trx_dummy_sess = sess_open(); } - + trx = trx_create(trx_dummy_sess); trx_n_mysql_transactions++; - + UT_LIST_ADD_FIRST(mysql_trx_list, trx_sys->mysql_trx_list, trx); - + mutex_exit(&kernel_mutex); trx->mysql_thread_id = os_thread_get_curr_id(); trx->mysql_process_no = os_proc_get_number(); - + return(trx); } @@ -244,17 +244,17 @@ trx_allocate_for_background(void) trx_t* trx; mutex_enter(&kernel_mutex); - + /* Open a dummy session */ if (!trx_dummy_sess) { trx_dummy_sess = sess_open(); } - + trx = trx_create(trx_dummy_sess); mutex_exit(&kernel_mutex); - + return(trx); } @@ -264,13 +264,13 @@ Releases the search latch if trx has reserved it. */ void trx_search_latch_release_if_reserved( /*=================================*/ - trx_t* trx) /* in: transaction */ + trx_t* trx) /* in: transaction */ { - if (trx->has_search_latch) { - rw_lock_s_unlock(&btr_search_latch); + if (trx->has_search_latch) { + rw_lock_s_unlock(&btr_search_latch); - trx->has_search_latch = FALSE; - } + trx->has_search_latch = FALSE; + } } /************************************************************************ @@ -286,7 +286,7 @@ trx_free( #endif /* UNIV_SYNC_DEBUG */ if (trx->declared_to_be_inside_innodb) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fputs( " InnoDB: Error: Freeing a trx which is declared to be processing\n" "InnoDB: inside InnoDB.\n", stderr); @@ -295,7 +295,7 @@ trx_free( } if (trx->n_mysql_tables_in_use != 0 - || trx->mysql_n_tables_locked != 0) { + || trx->mysql_n_tables_locked != 0) { ut_print_timestamp(stderr); fprintf(stderr, @@ -307,7 +307,7 @@ trx_free( trx_print(stderr, trx, 600); - ut_print_buf(stderr, (byte*)trx, sizeof(trx_t)); + ut_print_buf(stderr, trx, sizeof(trx_t)); } ut_a(trx->magic_n == TRX_MAGIC_N); @@ -315,12 +315,12 @@ trx_free( trx->magic_n = 11112222; ut_a(trx->conc_state == TRX_NOT_STARTED); - + mutex_free(&(trx->undo_mutex)); - ut_a(trx->insert_undo == NULL); - ut_a(trx->update_undo == NULL); - + ut_a(trx->insert_undo == NULL); + ut_a(trx->update_undo == NULL); + if (trx->undo_no_arr) { trx_undo_arr_free(trx->undo_no_arr); } @@ -354,7 +354,7 @@ trx_free( trx->global_read_view = NULL; ut_a(trx->read_view == NULL); - + mem_free(trx); } @@ -369,7 +369,7 @@ trx_free_for_mysql( thr_local_free(trx->mysql_thread_id); mutex_enter(&kernel_mutex); - + UT_LIST_REMOVE(mysql_trx_list, trx_sys->mysql_trx_list, trx); trx_free(trx); @@ -377,7 +377,7 @@ trx_free_for_mysql( ut_a(trx_n_mysql_transactions > 0); trx_n_mysql_transactions--; - + mutex_exit(&kernel_mutex); } @@ -390,9 +390,9 @@ trx_free_for_background( trx_t* trx) /* in, own: trx object */ { mutex_enter(&kernel_mutex); - + trx_free(trx); - + mutex_exit(&kernel_mutex); } @@ -435,7 +435,7 @@ trx_list_insert_ordered( } } else { UT_LIST_ADD_LAST(trx_list, trx_sys->trx_list, trx); - } + } } /******************************************************************** @@ -457,7 +457,7 @@ trx_lists_init_at_db_start(void) /* Look from the rollback segments if there exist undo logs for transactions */ - + rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list); while (rseg != NULL) { @@ -465,7 +465,7 @@ trx_lists_init_at_db_start(void) while (undo != NULL) { - trx = trx_create(NULL); + trx = trx_create(NULL); trx->id = undo->trx_id; trx->xid = undo->xid; @@ -480,7 +480,7 @@ trx_lists_init_at_db_start(void) if (undo->state == TRX_UNDO_PREPARED) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Transaction %lu %lu was in the XA prepared state.\n", ut_dulint_get_high(trx->id), ut_dulint_get_low(trx->id)); @@ -489,7 +489,7 @@ trx_lists_init_at_db_start(void) trx->conc_state = TRX_PREPARED; } else { - fprintf(stderr, + fprintf(stderr, "InnoDB: Since innodb_force_recovery > 0, we will rollback it anyway.\n"); trx->conc_state = TRX_ACTIVE; @@ -537,7 +537,7 @@ trx_lists_init_at_db_start(void) trx = trx_get_on_id(undo->trx_id); if (NULL == trx) { - trx = trx_create(NULL); + trx = trx_create(NULL); trx->id = undo->trx_id; trx->xid = undo->xid; @@ -549,23 +549,25 @@ trx_lists_init_at_db_start(void) commit or abort decision from MySQL */ if (undo->state == TRX_UNDO_PREPARED) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Transaction %lu %lu was in the XA prepared state.\n", - ut_dulint_get_high(trx->id), - ut_dulint_get_low(trx->id)); + ut_dulint_get_high(trx->id), + ut_dulint_get_low(trx->id)); - if (srv_force_recovery == 0) { + if (srv_force_recovery == 0) { - trx->conc_state = TRX_PREPARED; - } else { - fprintf(stderr, + trx->conc_state = + TRX_PREPARED; + } else { + fprintf(stderr, "InnoDB: Since innodb_force_recovery > 0, we will rollback it anyway.\n"); - trx->conc_state = TRX_ACTIVE; - } + trx->conc_state = + TRX_ACTIVE; + } } else { trx->conc_state = - TRX_COMMITTED_IN_MEMORY; + TRX_COMMITTED_IN_MEMORY; } /* We give a dummy value for the trx @@ -595,13 +597,13 @@ trx_lists_init_at_db_start(void) trx->update_undo = undo; if ((!undo->empty) - && (ut_dulint_cmp(undo->top_undo_no, trx->undo_no) - >= 0)) { + && (ut_dulint_cmp(undo->top_undo_no, + trx->undo_no) >= 0)) { trx->undo_no = ut_dulint_add(undo->top_undo_no, - 1); + 1); } - + undo = UT_LIST_GET_NEXT(undo_list, undo); } @@ -635,10 +637,10 @@ loop: /* If it is the SYSTEM rollback segment, and there exist others, skip it */ - if ((rseg->id == TRX_SYS_SYSTEM_RSEG_ID) + if ((rseg->id == TRX_SYS_SYSTEM_RSEG_ID) && (UT_LIST_GET_LEN(trx_sys->rseg_list) > 1)) { goto loop; - } + } trx_sys->latest_rseg = rseg; @@ -652,7 +654,7 @@ ibool trx_start_low( /*==========*/ /* out: TRUE */ - trx_t* trx, /* in: transaction */ + trx_t* trx, /* in: transaction */ ulint rseg_id)/* in: rollback segment id; if ULINT_UNDEFINED is passed, the system chooses the rollback segment automatically in a round-robin fashion */ @@ -673,7 +675,7 @@ trx_start_low( } ut_ad(trx->conc_state != TRX_ACTIVE); - + if (rseg_id == ULINT_UNDEFINED) { rseg_id = trx_assign_rseg(); @@ -705,13 +707,13 @@ ibool trx_start( /*======*/ /* out: TRUE */ - trx_t* trx, /* in: transaction */ + trx_t* trx, /* in: transaction */ ulint rseg_id)/* in: rollback segment id; if ULINT_UNDEFINED is passed, the system chooses the rollback segment automatically in a round-robin fashion */ { ibool ret; - + mutex_enter(&kernel_mutex); ret = trx_start_low(trx, rseg_id); @@ -735,7 +737,7 @@ trx_commit_off_kernel( trx_undo_t* undo; ibool must_flush_log = FALSE; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ @@ -743,13 +745,13 @@ trx_commit_off_kernel( trx->must_flush_log_later = FALSE; rseg = trx->rseg; - + if (trx->insert_undo != NULL || trx->update_undo != NULL) { mutex_exit(&kernel_mutex); mtr_start(&mtr); - + must_flush_log = TRUE; /* Change the undo log segment states from TRX_UNDO_ACTIVE @@ -759,7 +761,7 @@ trx_commit_off_kernel( number lsn obtained below. */ mutex_enter(&(rseg->mutex)); - + if (trx->insert_undo != NULL) { trx_undo_set_state_at_finish(trx, trx->insert_undo, &mtr); @@ -770,13 +772,13 @@ trx_commit_off_kernel( if (undo) { mutex_enter(&kernel_mutex); trx->no = trx_sys_get_new_trx_no(); - + mutex_exit(&kernel_mutex); /* It is not necessary to obtain trx->undo_mutex here because only a single OS thread is allowed to do the transaction commit for this transaction. */ - + update_hdr_page = trx_undo_set_state_at_finish(trx, undo, &mtr); @@ -794,7 +796,8 @@ trx_commit_off_kernel( in trx sys header if MySQL binlogging is on or the database server is a MySQL replication slave */ - if (trx->mysql_log_file_name) { + if (trx->mysql_log_file_name + && trx->mysql_log_file_name[0] != '\0') { trx_sys_update_mysql_binlog_offset( trx->mysql_log_file_name, trx->mysql_log_offset, @@ -803,13 +806,13 @@ trx_commit_off_kernel( } if (trx->mysql_master_log_file_name[0] != '\0') { - /* This database server is a MySQL replication slave */ + /* This database server is a MySQL replication slave */ trx_sys_update_mysql_binlog_offset( trx->mysql_master_log_file_name, trx->mysql_master_log_pos, TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr); } - + /* The following call commits the mini-transaction, making the whole transaction committed in the file-based world, at this log sequence number. The transaction becomes 'durable' when @@ -828,9 +831,9 @@ trx_commit_off_kernel( number and a bigger commit lsn than T1. */ /*--------------*/ - mtr_commit(&mtr); - /*--------------*/ - lsn = mtr.end_lsn; + mtr_commit(&mtr); + /*--------------*/ + lsn = mtr.end_lsn; mutex_enter(&kernel_mutex); } @@ -840,7 +843,7 @@ trx_commit_off_kernel( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - + /* The following assignment makes the transaction committed in memory and makes its changes to data visible to other transactions. NOTE that there is a small discrepancy from the strict formal @@ -872,7 +875,7 @@ trx_commit_off_kernel( if (must_flush_log) { mutex_exit(&kernel_mutex); - + if (trx->insert_undo != NULL) { trx_undo_insert_cleanup(trx); @@ -884,58 +887,58 @@ trx_commit_off_kernel( /*-------------------------------------*/ - /* Depending on the my.cnf options, we may now write the log - buffer to the log files, making the transaction durable if - the OS does not crash. We may also flush the log files to - disk, making the transaction durable also at an OS crash or a - power outage. - - The idea in InnoDB's group commit is that a group of - transactions gather behind a trx doing a physical disk write - to log files, and when that physical write has been completed, - one of those transactions does a write which commits the whole - group. Note that this group commit will only bring benefit if - there are > 2 users in the database. Then at least 2 users can - gather behind one doing the physical log write to disk. - - If we are calling trx_commit() under MySQL's binlog mutex, we - will delay possible log write and flush to a separate function - trx_commit_complete_for_mysql(), which is only called when the - thread has released the binlog mutex. This is to make the - group commit algorithm to work. Otherwise, the MySQL binlog - mutex would serialize all commits and prevent a group of - transactions from gathering. */ - - if (trx->flush_log_later) { - /* Do nothing yet */ + /* Depending on the my.cnf options, we may now write the log + buffer to the log files, making the transaction durable if + the OS does not crash. We may also flush the log files to + disk, making the transaction durable also at an OS crash or a + power outage. + + The idea in InnoDB's group commit is that a group of + transactions gather behind a trx doing a physical disk write + to log files, and when that physical write has been completed, + one of those transactions does a write which commits the whole + group. Note that this group commit will only bring benefit if + there are > 2 users in the database. Then at least 2 users can + gather behind one doing the physical log write to disk. + + If we are calling trx_commit() under MySQL's binlog mutex, we + will delay possible log write and flush to a separate function + trx_commit_complete_for_mysql(), which is only called when the + thread has released the binlog mutex. This is to make the + group commit algorithm to work. Otherwise, the MySQL binlog + mutex would serialize all commits and prevent a group of + transactions from gathering. */ + + if (trx->flush_log_later) { + /* Do nothing yet */ trx->must_flush_log_later = TRUE; - } else if (srv_flush_log_at_trx_commit == 0) { - /* Do nothing */ - } else if (srv_flush_log_at_trx_commit == 1) { - if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) { - /* Write the log but do not flush it to disk */ + } else if (srv_flush_log_at_trx_commit == 0) { + /* Do nothing */ + } else if (srv_flush_log_at_trx_commit == 1) { + if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) { + /* Write the log but do not flush it to disk */ - log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, + log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE); - } else { - /* Write the log to the log files AND flush - them to disk */ + } else { + /* Write the log to the log files AND flush + them to disk */ - log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE); - } - } else if (srv_flush_log_at_trx_commit == 2) { + log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE); + } + } else if (srv_flush_log_at_trx_commit == 2) { - /* Write the log but do not flush it to disk */ + /* Write the log but do not flush it to disk */ - log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE); - } else { - ut_error; - } + log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE); + } else { + ut_error; + } trx->commit_lsn = lsn; - + /*-------------------------------------*/ - + mutex_enter(&kernel_mutex); } @@ -992,17 +995,17 @@ trx_assign_read_view( if (trx->read_view) { return(trx->read_view); } - + mutex_enter(&kernel_mutex); if (!trx->read_view) { - trx->read_view = read_view_open_now(trx, + trx->read_view = read_view_open_now(trx->id, trx->global_read_view_heap); trx->global_read_view = trx->read_view; } mutex_exit(&kernel_mutex); - + return(trx->read_view); } @@ -1021,7 +1024,7 @@ trx_handle_commit_sig_off_kernel( { trx_sig_t* sig; trx_sig_t* next_sig; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ @@ -1068,14 +1071,14 @@ trx_end_lock_wait( ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT); - + thr = UT_LIST_GET_FIRST(trx->wait_thrs); while (thr != NULL) { que_thr_end_wait_no_next_thr(thr); UT_LIST_REMOVE(trx_thrs, trx->wait_thrs, thr); - + thr = UT_LIST_GET_FIRST(trx->wait_thrs); } @@ -1097,14 +1100,14 @@ trx_lock_wait_to_suspended( ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT); - + thr = UT_LIST_GET_FIRST(trx->wait_thrs); while (thr != NULL) { thr->state = QUE_THR_SUSPENDED; - + UT_LIST_REMOVE(trx_thrs, trx->wait_thrs, thr); - + thr = UT_LIST_GET_FIRST(trx->wait_thrs); } @@ -1126,20 +1129,20 @@ trx_sig_reply_wait_to_suspended( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - + sig = UT_LIST_GET_FIRST(trx->reply_signals); while (sig != NULL) { thr = sig->receiver; ut_ad(thr->state == QUE_THR_SIG_REPLY_WAIT); - + thr->state = QUE_THR_SUSPENDED; sig->receiver = NULL; - + UT_LIST_REMOVE(reply_signals, trx->reply_signals, sig); - + sig = UT_LIST_GET_FIRST(trx->reply_signals); } } @@ -1166,7 +1169,7 @@ trx_sig_is_compatible( return(TRUE); } - + if (sender == TRX_SIG_SELF) { if (type == TRX_SIG_ERROR_OCCURRED) { @@ -1195,7 +1198,7 @@ trx_sig_is_compatible( sig = UT_LIST_GET_NEXT(signals, sig); } - return(TRUE); + return(TRUE); } else if (type == TRX_SIG_TOTAL_ROLLBACK) { while (sig != NULL) { @@ -1212,7 +1215,7 @@ trx_sig_is_compatible( } else if (type == TRX_SIG_BREAK_EXECUTION) { - return(TRUE); + return(TRUE); } else { ut_error; @@ -1235,7 +1238,7 @@ trx_sig_send( que_thr_t* receiver_thr, /* in: query thread which wants the reply, or NULL; if type is TRX_SIG_END_WAIT, this must be NULL */ - trx_savept_t* savept, /* in: possible rollback savepoint, or + trx_savept_t* savept, /* in: possible rollback savepoint, or NULL */ que_thr_t** next_thr) /* in/out: next query thread to run; if the value which is passed in is @@ -1257,7 +1260,7 @@ trx_sig_send( the queue: do nothing */ ut_error; - + return(FALSE); } @@ -1267,11 +1270,11 @@ trx_sig_send( /* The signal list is empty: the 'sig' slot must be unused (we improve performance a bit by avoiding mem_alloc) */ - sig = &(trx->sig); - } else { + sig = &(trx->sig); + } else { /* It might be that the 'sig' slot is unused also in this case, but we choose the easy way of using mem_alloc */ - + sig = mem_alloc(sizeof(trx_sig_t)); } @@ -1294,7 +1297,7 @@ trx_sig_send( } if (trx->sess->state == SESS_ERROR) { - + trx_sig_reply_wait_to_suspended(trx); } @@ -1311,7 +1314,7 @@ trx_sig_send( handling of the signal */ if (UT_LIST_GET_FIRST(trx->signals) == sig) { - + trx_sig_start_handle(trx, next_thr); } @@ -1339,7 +1342,7 @@ trx_end_signal_handling( trx->graph = trx->graph_before_signal_handling; if (trx->graph && (trx->sess->state == SESS_ERROR)) { - + que_fork_error_handle(trx, trx->graph); } } @@ -1372,7 +1375,7 @@ loop: if (trx->handling_signals && (UT_LIST_GET_LEN(trx->signals) == 0)) { trx_end_signal_handling(trx); - + return; } @@ -1385,7 +1388,7 @@ loop: to the suspended state */ if (trx->que_state == TRX_QUE_LOCK_WAIT) { - + trx_lock_wait_to_suspended(trx); } @@ -1398,7 +1401,7 @@ loop: if (trx->sess->state == SESS_ERROR) { trx_sig_reply_wait_to_suspended(trx); } - + /* If there are no running query threads, we can start processing of a signal, otherwise we have to wait until all query threads of this transaction are aware of the arrival of the signal. */ @@ -1422,7 +1425,7 @@ loop: trx_handle_commit_sig_off_kernel(trx, next_thr); } else if ((type == TRX_SIG_TOTAL_ROLLBACK) - || (type == TRX_SIG_ROLLBACK_TO_SAVEPT)) { + || (type == TRX_SIG_ROLLBACK_TO_SAVEPT)) { trx_rollback(trx, sig, next_thr); @@ -1449,7 +1452,7 @@ loop: } goto loop; -} +} /******************************************************************** Send the reply message when a signal in the queue of the trx has been @@ -1480,7 +1483,7 @@ trx_sig_reply( UT_LIST_REMOVE(reply_signals, receiver_trx->reply_signals, sig); ut_ad(receiver_trx->sess->state != SESS_ERROR); - + que_thr_end_wait(sig->receiver, next_thr); sig->receiver = NULL; @@ -1526,7 +1529,7 @@ commit_node_create( node = mem_heap_alloc(heap, sizeof(commit_node_t)); node->common.type = QUE_NODE_COMMIT; node->state = COMMIT_NODE_SEND; - + return(node); } @@ -1542,7 +1545,7 @@ trx_commit_step( commit_node_t* node; que_thr_t* next_thr; ibool success; - + node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_COMMIT); @@ -1557,14 +1560,14 @@ trx_commit_step( node->state = COMMIT_NODE_WAIT; next_thr = NULL; - + thr->state = QUE_THR_SIG_REPLY_WAIT; /* Send the commit signal to the transaction */ - + success = trx_sig_send(thr_get_trx(thr), TRX_SIG_COMMIT, TRX_SIG_SELF, thr, NULL, &next_thr); - + mutex_exit(&kernel_mutex); if (!success) { @@ -1576,9 +1579,9 @@ trx_commit_step( } ut_ad(node->state == COMMIT_NODE_WAIT); - + node->state = COMMIT_NODE_SEND; - + thr->run_node = que_node_get_parent(node); return(thr); @@ -1600,7 +1603,7 @@ trx_commit_for_mysql( ut_a(trx); trx->op_info = "committing"; - + trx_start_if_not_started(trx); mutex_enter(&kernel_mutex); @@ -1610,7 +1613,7 @@ trx_commit_for_mysql( mutex_exit(&kernel_mutex); trx->op_info = ""; - + return(0); } @@ -1624,41 +1627,41 @@ trx_commit_complete_for_mysql( /* out: 0 or error number */ trx_t* trx) /* in: trx handle */ { - dulint lsn = trx->commit_lsn; + dulint lsn = trx->commit_lsn; + + ut_a(trx); - ut_a(trx); - trx->op_info = "flushing log"; if (!trx->must_flush_log_later) { - /* Do nothing */ - } else if (srv_flush_log_at_trx_commit == 0) { - /* Do nothing */ - } else if (srv_flush_log_at_trx_commit == 1) { - if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) { - /* Write the log but do not flush it to disk */ - - log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE); - } else { - /* Write the log to the log files AND flush them to - disk */ - - log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE); - } - } else if (srv_flush_log_at_trx_commit == 2) { - - /* Write the log but do not flush it to disk */ - - log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE); - } else { - ut_error; - } - + /* Do nothing */ + } else if (srv_flush_log_at_trx_commit == 0) { + /* Do nothing */ + } else if (srv_flush_log_at_trx_commit == 1) { + if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) { + /* Write the log but do not flush it to disk */ + + log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE); + } else { + /* Write the log to the log files AND flush them to + disk */ + + log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE); + } + } else if (srv_flush_log_at_trx_commit == 2) { + + /* Write the log but do not flush it to disk */ + + log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE); + } else { + ut_error; + } + trx->must_flush_log_later = FALSE; trx->op_info = ""; - return(0); + return(0); } /************************************************************************** @@ -1689,7 +1692,7 @@ trx_print( /*======*/ FILE* f, /* in: output stream */ trx_t* trx, /* in: transaction */ - uint max_query_len) /* in: max query length to print, or 0 to + ulint max_query_len) /* in: max query length to print, or 0 to use the default max length */ { ibool newline; @@ -1698,48 +1701,48 @@ trx_print( (ulong) ut_dulint_get_high(trx->id), (ulong) ut_dulint_get_low(trx->id)); - switch (trx->conc_state) { + switch (trx->conc_state) { case TRX_NOT_STARTED: fputs(", not started", f); break; case TRX_ACTIVE: fprintf(f, ", ACTIVE %lu sec", (ulong)difftime(time(NULL), trx->start_time)); - break; + break; case TRX_PREPARED: fprintf(f, ", ACTIVE (PREPARED) %lu sec", (ulong)difftime(time(NULL), trx->start_time)); - break; + break; case TRX_COMMITTED_IN_MEMORY: fputs(", COMMITTED IN MEMORY", f); break; default: fprintf(f, " state %lu", (ulong) trx->conc_state); - } + } #ifdef UNIV_LINUX fprintf(f, ", process no %lu", trx->mysql_process_no); #endif fprintf(f, ", OS thread id %lu", - (ulong) os_thread_pf(trx->mysql_thread_id)); + (ulong) os_thread_pf(trx->mysql_thread_id)); if (*trx->op_info) { putc(' ', f); fputs(trx->op_info, f); } - - if (trx->type != TRX_USER) { + + if (trx->type != TRX_USER) { fputs(" purge trx", f); - } + } if (trx->declared_to_be_inside_innodb) { fprintf(f, ", thread declared inside InnoDB %lu", - (ulong) trx->n_tickets_to_enter_innodb); + (ulong) trx->n_tickets_to_enter_innodb); } putc('\n', f); - - if (trx->n_mysql_tables_in_use > 0 || trx->mysql_n_tables_locked > 0) { + + if (trx->n_mysql_tables_in_use > 0 || trx->mysql_n_tables_locked > 0) { fprintf(f, "mysql tables in use %lu, locked %lu\n", (ulong) trx->n_mysql_tables_in_use, (ulong) trx->mysql_n_tables_locked); @@ -1747,7 +1750,7 @@ trx_print( newline = TRUE; - switch (trx->que_state) { + switch (trx->que_state) { case TRX_QUE_RUNNING: newline = FALSE; break; case TRX_QUE_LOCK_WAIT: @@ -1758,35 +1761,35 @@ trx_print( fputs("COMMITTING ", f); break; default: fprintf(f, "que state %lu ", (ulong) trx->que_state); - } + } - if (0 < UT_LIST_GET_LEN(trx->trx_locks) || - mem_heap_get_size(trx->lock_heap) > 400) { + if (0 < UT_LIST_GET_LEN(trx->trx_locks) || + mem_heap_get_size(trx->lock_heap) > 400) { newline = TRUE; fprintf(f, "%lu lock struct(s), heap size %lu", - (ulong) UT_LIST_GET_LEN(trx->trx_locks), - (ulong) mem_heap_get_size(trx->lock_heap)); + (ulong) UT_LIST_GET_LEN(trx->trx_locks), + (ulong) mem_heap_get_size(trx->lock_heap)); } - if (trx->has_search_latch) { + if (trx->has_search_latch) { newline = TRUE; fputs(", holds adaptive hash latch", f); - } + } if (ut_dulint_cmp(trx->undo_no, ut_dulint_zero) != 0) { newline = TRUE; fprintf(f, ", undo log entries %lu", (ulong) ut_dulint_get_low(trx->undo_no)); } - + if (newline) { putc('\n', f); } - if (trx->mysql_thd != NULL) { + if (trx->mysql_thd != NULL) { innobase_mysql_print_thd(f, trx->mysql_thd, max_query_len); - } + } } /******************************************************************** @@ -1802,19 +1805,19 @@ trx_prepare_off_kernel( ibool must_flush_log = FALSE; dulint lsn; mtr_t mtr; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ rseg = trx->rseg; - + if (trx->insert_undo != NULL || trx->update_undo != NULL) { mutex_exit(&kernel_mutex); mtr_start(&mtr); - + must_flush_log = TRUE; /* Change the undo log segment states from TRX_UNDO_ACTIVE @@ -1823,7 +1826,7 @@ trx_prepare_off_kernel( file-based world, at the serialization point of lsn. */ mutex_enter(&(rseg->mutex)); - + if (trx->insert_undo != NULL) { /* It is not necessary to obtain trx->undo_mutex here @@ -1831,7 +1834,7 @@ trx_prepare_off_kernel( transaction prepare for this transaction. */ trx_undo_set_state_at_prepare(trx, trx->insert_undo, - &mtr); + &mtr); } if (trx->update_undo) { @@ -1846,7 +1849,7 @@ trx_prepare_off_kernel( transaction prepared in the file-based world */ /*--------------*/ - lsn = mtr.end_lsn; + lsn = mtr.end_lsn; mutex_enter(&kernel_mutex); } @@ -1860,47 +1863,47 @@ trx_prepare_off_kernel( /*--------------------------------------*/ if (must_flush_log) { - /* Depending on the my.cnf options, we may now write the log - buffer to the log files, making the prepared state of the + /* Depending on the my.cnf options, we may now write the log + buffer to the log files, making the prepared state of the transaction durable if the OS does not crash. We may also flush the log files to disk, making the prepared state of the transaction durable also at an OS crash or a power outage. - The idea in InnoDB's group prepare is that a group of - transactions gather behind a trx doing a physical disk write - to log files, and when that physical write has been completed, - one of those transactions does a write which prepares the whole - group. Note that this group prepare will only bring benefit if - there are > 2 users in the database. Then at least 2 users can - gather behind one doing the physical log write to disk. + The idea in InnoDB's group prepare is that a group of + transactions gather behind a trx doing a physical disk write + to log files, and when that physical write has been completed, + one of those transactions does a write which prepares the whole + group. Note that this group prepare will only bring benefit if + there are > 2 users in the database. Then at least 2 users can + gather behind one doing the physical log write to disk. TODO: find out if MySQL holds some mutex when calling this. That would spoil our group prepare algorithm. */ mutex_exit(&kernel_mutex); - if (srv_flush_log_at_trx_commit == 0) { - /* Do nothing */ - } else if (srv_flush_log_at_trx_commit == 1) { - if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) { - /* Write the log but do not flush it to disk */ + if (srv_flush_log_at_trx_commit == 0) { + /* Do nothing */ + } else if (srv_flush_log_at_trx_commit == 1) { + if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) { + /* Write the log but do not flush it to disk */ - log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, + log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE); - } else { - /* Write the log to the log files AND flush - them to disk */ + } else { + /* Write the log to the log files AND flush + them to disk */ - log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE); - } - } else if (srv_flush_log_at_trx_commit == 2) { + log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE); + } + } else if (srv_flush_log_at_trx_commit == 2) { - /* Write the log but do not flush it to disk */ + /* Write the log but do not flush it to disk */ - log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE); - } else { - ut_error; - } + log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE); + } else { + ut_error; + } mutex_enter(&kernel_mutex); } @@ -1922,7 +1925,7 @@ trx_prepare_for_mysql( ut_a(trx); trx->op_info = "preparing"; - + trx_start_if_not_started(trx); mutex_enter(&kernel_mutex); @@ -1932,7 +1935,7 @@ trx_prepare_for_mysql( mutex_exit(&kernel_mutex); trx->op_info = ""; - + return(0); } @@ -1943,13 +1946,13 @@ their transaction objects for a recovery. */ int trx_recover_for_mysql( /*==================*/ - /* out: number of prepared transactions + /* out: number of prepared transactions stored in xid_list */ - XID* xid_list, /* in/out: prepared transactions */ + XID* xid_list, /* in/out: prepared transactions */ ulint len) /* in: number of slots in xid_list */ { trx_t* trx; - int count = 0; + ulint count = 0; ut_ad(xid_list); ut_ad(len); @@ -1983,8 +1986,8 @@ trx_recover_for_mysql( (ulong)ut_conv_dulint_to_longlong(trx->undo_no)); count++; - - if ((uint)count == len ) { + + if (count == len) { break; } } @@ -1997,11 +2000,11 @@ trx_recover_for_mysql( if (count > 0){ ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: %d transactions in prepared state after recovery\n", - count); +" InnoDB: %lu transactions in prepared state after recovery\n", + (ulong) count); } - return (count); + return (count); } /*********************************************************************** @@ -2020,7 +2023,7 @@ trx_get_trx_by_xid( return (NULL); } - + mutex_enter(&kernel_mutex); trx = UT_LIST_GET_FIRST(trx_sys->trx_list); @@ -2032,9 +2035,9 @@ trx_get_trx_by_xid( the same */ if (xid->gtrid_length == trx->xid.gtrid_length && - xid->bqual_length == trx->xid.bqual_length && - memcmp(xid->data, trx->xid.data, - xid->gtrid_length + + xid->bqual_length == trx->xid.bqual_length && + memcmp(xid->data, trx->xid.data, + xid->gtrid_length + xid->bqual_length) == 0) { break; } diff --git a/storage/innobase/trx/trx0undo.c b/storage/innobase/trx/trx0undo.c index 7441dd3f152..bba1a4d6996 100644 --- a/storage/innobase/trx/trx0undo.c +++ b/storage/innobase/trx/trx0undo.c @@ -81,7 +81,7 @@ Initializes the fields in an undo log segment page. */ static void trx_undo_page_init( -/*================*/ +/*===============*/ page_t* undo_page, /* in: undo log segment page */ ulint type, /* in: undo log segment type */ mtr_t* mtr); /* in: mtr */ @@ -97,8 +97,8 @@ trx_undo_mem_create( ulint type, /* in: type of the log: TRX_UNDO_INSERT or TRX_UNDO_UPDATE */ dulint trx_id, /* in: id of the trx for which the undo log - is created */ - XID* xid, /* in: X/Open XA transaction identification*/ + is created */ + XID* xid, /* in: X/Open XA transaction identification*/ ulint page_no,/* in: undo log header page number */ ulint offset);/* in: undo log header byte offset on page */ /******************************************************************* @@ -143,7 +143,7 @@ trx_undo_get_prev_rec_from_prev_page( page_t* undo_page; undo_page = buf_frame_align(rec); - + prev_page_no = flst_get_prev_addr(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr) .page; @@ -174,7 +174,7 @@ trx_undo_get_prev_rec( mtr_t* mtr) /* in: mtr */ { trx_undo_rec_t* prev_rec; - + prev_rec = trx_undo_page_get_prev_rec(rec, page_no, offset); if (prev_rec) { @@ -205,10 +205,10 @@ trx_undo_get_next_rec_from_next_page( { trx_ulogf_t* log_hdr; ulint next_page_no; - page_t* next_page; + page_t* next_page; ulint space; ulint next; - + if (page_no == buf_frame_get_page_no(undo_page)) { log_hdr = undo_page + offset; @@ -255,7 +255,7 @@ trx_undo_get_next_rec( mtr_t* mtr) /* in: mtr */ { trx_undo_rec_t* next_rec; - + next_rec = trx_undo_page_get_next_rec(rec, page_no, offset); if (next_rec) { @@ -275,7 +275,7 @@ trx_undo_get_first_rec( /*===================*/ /* out: undo log record, the page latched, NULL if none */ - ulint space, /* in: undo log header space */ + ulint space, /* in: undo log header space */ ulint page_no,/* in: undo log header page number */ ulint offset, /* in: undo log header offset on page */ ulint mode, /* in: latching mode: RW_S_LATCH or RW_X_LATCH */ @@ -283,7 +283,7 @@ trx_undo_get_first_rec( { page_t* undo_page; trx_undo_rec_t* rec; - + if (mode == RW_S_LATCH) { undo_page = trx_undo_page_get_s_latched(space, page_no, mtr); } else { @@ -307,7 +307,7 @@ Writes the mtr log entry of an undo log page initialization. */ UNIV_INLINE void trx_undo_page_init_log( -/*====================*/ +/*===================*/ page_t* undo_page, /* in: undo log page */ ulint type, /* in: undo log type */ mtr_t* mtr) /* in: mtr */ @@ -315,14 +315,14 @@ trx_undo_page_init_log( mlog_write_initial_log_record(undo_page, MLOG_UNDO_INIT, mtr); mlog_catenate_ulint_compressed(mtr, type); -} +} /*************************************************************** Parses the redo log entry of an undo log page initialization. */ byte* trx_undo_parse_page_init( -/*======================*/ +/*=====================*/ /* out: end of log record or NULL */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ @@ -330,7 +330,7 @@ trx_undo_parse_page_init( mtr_t* mtr) /* in: mtr or NULL */ { ulint type; - + ptr = mach_parse_compressed(ptr, end_ptr, &type); if (ptr == NULL) { @@ -343,22 +343,22 @@ trx_undo_parse_page_init( } return(ptr); -} +} /************************************************************************ Initializes the fields in an undo log segment page. */ static void trx_undo_page_init( -/*================*/ +/*===============*/ page_t* undo_page, /* in: undo log segment page */ ulint type, /* in: undo log segment type */ mtr_t* mtr) /* in: mtr */ -{ +{ trx_upagef_t* page_hdr; - + page_hdr = undo_page + TRX_UNDO_PAGE_HDR; - + mach_write_to_2(page_hdr + TRX_UNDO_PAGE_TYPE, type); mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, @@ -367,7 +367,7 @@ trx_undo_page_init( TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE); fil_page_set_type(undo_page, FIL_PAGE_UNDO_LOG); - + trx_undo_page_init_log(undo_page, type, mtr); } @@ -389,12 +389,12 @@ trx_undo_seg_create( { ulint slot_no; ulint space; - page_t* undo_page; + page_t* undo_page; trx_upagef_t* page_hdr; trx_usegf_t* seg_hdr; ulint n_reserved; ibool success; - + ut_ad(mtr && id && rseg_hdr); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(rseg->mutex))); @@ -406,8 +406,8 @@ trx_undo_seg_create( slot_no = trx_rsegf_undo_find_free(rseg_hdr, mtr); if (slot_no == ULINT_UNDEFINED) { - ut_print_timestamp(stderr); - fprintf(stderr, + ut_print_timestamp(stderr); + fprintf(stderr, "InnoDB: Warning: cannot find a free slot for an undo log. Do you have too\n" "InnoDB: many active transactions running concurrently?\n"); @@ -428,7 +428,7 @@ trx_undo_seg_create( TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER, TRUE, mtr); fil_space_release_free_extents(space, n_reserved); - + if (undo_page == NULL) { /* No space left */ @@ -447,7 +447,7 @@ trx_undo_seg_create( mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_FREE, TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE, MLOG_2BYTES, mtr); - + mlog_write_ulint(seg_hdr + TRX_UNDO_LAST_LOG, 0, MLOG_2BYTES, mtr); flst_init(seg_hdr + TRX_UNDO_PAGE_LIST, mtr); @@ -458,7 +458,7 @@ trx_undo_seg_create( trx_rsegf_set_nth_undo(rseg_hdr, slot_no, buf_frame_get_page_no(undo_page), mtr); *id = slot_no; - + return(undo_page); } @@ -475,7 +475,7 @@ trx_undo_header_create_log( mlog_write_initial_log_record(undo_page, MLOG_UNDO_HDR_CREATE, mtr); mlog_catenate_dulint_compressed(mtr, trx_id); -} +} /******************************************************************* Creates a new undo log header in file. NOTE that this function has its own @@ -500,24 +500,24 @@ trx_undo_header_create( ulint prev_log; ulint free; ulint new_free; - + ut_ad(mtr && undo_page); - + page_hdr = undo_page + TRX_UNDO_PAGE_HDR; seg_hdr = undo_page + TRX_UNDO_SEG_HDR; free = mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE); log_hdr = undo_page + free; - + new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE; ut_a(free + TRX_UNDO_LOG_XA_HDR_SIZE < UNIV_PAGE_SIZE - 100); - + mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, new_free); mach_write_to_2(page_hdr + TRX_UNDO_PAGE_FREE, new_free); - + mach_write_to_2(seg_hdr + TRX_UNDO_STATE, TRX_UNDO_ACTIVE); prev_log = mach_read_from_2(seg_hdr + TRX_UNDO_LAST_LOG); @@ -531,7 +531,7 @@ trx_undo_header_create( mach_write_to_2(seg_hdr + TRX_UNDO_LAST_LOG, free); log_hdr = undo_page + free; - + mach_write_to_2(log_hdr + TRX_UNDO_DEL_MARKS, TRUE); mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id); @@ -545,7 +545,7 @@ trx_undo_header_create( /* Write the log record about the header creation */ trx_undo_header_create_log(undo_page, trx_id, mtr); - + return(free); } @@ -582,7 +582,7 @@ trx_undo_read_xid( XID* xid) /* out: X/Open XA Transaction Identification */ { xid->formatID = (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_FORMAT); - + xid->gtrid_length = (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_TRID_LEN); xid->bqual_length = @@ -642,7 +642,7 @@ trx_undo_insert_header_reuse_log( mlog_write_initial_log_record(undo_page, MLOG_UNDO_HDR_REUSE, mtr); mlog_catenate_dulint_compressed(mtr, trx_id); -} +} /*************************************************************** Parses the redo log entry of an undo log page header create or reuse. */ @@ -658,7 +658,7 @@ trx_undo_parse_page_header( mtr_t* mtr) /* in: mtr or NULL */ { dulint trx_id; - + ptr = mach_dulint_parse_compressed(ptr, end_ptr, &trx_id); if (ptr == NULL) { @@ -676,7 +676,7 @@ trx_undo_parse_page_header( } return(ptr); -} +} /******************************************************************* Initializes a cached insert undo log header page for new use. NOTE that this @@ -697,9 +697,9 @@ trx_undo_insert_header_reuse( trx_ulogf_t* log_hdr; ulint free; ulint new_free; - + ut_ad(mtr && undo_page); - + page_hdr = undo_page + TRX_UNDO_PAGE_HDR; seg_hdr = undo_page + TRX_UNDO_SEG_HDR; @@ -708,7 +708,7 @@ trx_undo_insert_header_reuse( ut_a(free + TRX_UNDO_LOG_XA_HDR_SIZE < UNIV_PAGE_SIZE - 100); log_hdr = undo_page + free; - + new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE; /* Insert undo data is not needed after commit: we may free all @@ -719,13 +719,13 @@ trx_undo_insert_header_reuse( == TRX_UNDO_INSERT); mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, new_free); - + mach_write_to_2(page_hdr + TRX_UNDO_PAGE_FREE, new_free); - + mach_write_to_2(seg_hdr + TRX_UNDO_STATE, TRX_UNDO_ACTIVE); log_hdr = undo_page + free; - + mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id); mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free); @@ -734,9 +734,9 @@ trx_undo_insert_header_reuse( /* Write the log record MLOG_UNDO_HDR_REUSE */ trx_undo_insert_header_reuse_log(undo_page, trx_id, mtr); - + return(free); -} +} /************************************************************************** Writes the redo log entry of an update undo log header discard. */ @@ -748,7 +748,7 @@ trx_undo_discard_latest_log( mtr_t* mtr) /* in: mtr */ { mlog_write_initial_log_record(undo_page, MLOG_UNDO_HDR_DISCARD, mtr); -} +} /*************************************************************** Parses the redo log entry of an undo log page header discard. */ @@ -769,7 +769,7 @@ trx_undo_parse_discard_latest( } return(ptr); -} +} /************************************************************************** If an update undo log can be discarded immediately, this function frees the @@ -795,7 +795,7 @@ trx_undo_discard_latest_update_undo( log_hdr = undo_page + free; prev_hdr_offset = mach_read_from_2(log_hdr + TRX_UNDO_PREV_LOG); - + if (prev_hdr_offset != 0) { prev_log_hdr = undo_page + prev_hdr_offset; @@ -832,7 +832,7 @@ trx_undo_add_page( ulint page_no; ulint n_reserved; ibool success; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(trx->undo_mutex))); ut_ad(!mutex_own(&kernel_mutex)); @@ -861,11 +861,11 @@ trx_undo_add_page( TRUE, mtr); fil_space_release_free_extents(undo->space, n_reserved); - + if (page_no == FIL_NULL) { /* No space left */ - + return(FIL_NULL); } @@ -874,9 +874,9 @@ trx_undo_add_page( new_page = trx_undo_page_get(undo->space, page_no, mtr); trx_undo_page_init(new_page, undo->type, mtr); - + flst_add_last(header_page + TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST, - new_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr); + new_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr); undo->size++; rseg->curr_size++; @@ -912,13 +912,13 @@ trx_undo_free_page( ut_ad(!mutex_own(&kernel_mutex)); ut_ad(mutex_own(&(rseg->mutex))); #endif /* UNIV_SYNC_DEBUG */ - + undo_page = trx_undo_page_get(space, page_no, mtr); header_page = trx_undo_page_get(space, hdr_page_no, mtr); flst_remove(header_page + TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST, - undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr); + undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr); fseg_free_page(header_page + TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER, space, page_no, mtr); @@ -964,7 +964,7 @@ trx_undo_free_page_in_rollback( last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space, undo->hdr_page_no, page_no, mtr); - + undo->last_page_no = last_page_no; undo->size--; } @@ -984,7 +984,7 @@ trx_undo_empty_header_page( page_t* header_page; trx_ulogf_t* log_hdr; ulint end; - + header_page = trx_undo_page_get(space, hdr_page_no, mtr); log_hdr = header_page + hdr_offset; @@ -1018,13 +1018,13 @@ trx_undo_truncate_end( ut_ad(mutex_own(&(trx->rseg->mutex))); #endif /* UNIV_SYNC_DEBUG */ - rseg = trx->rseg; + rseg = trx->rseg; - for (;;) { + for (;;) { mtr_start(&mtr); trunc_here = NULL; - + last_page_no = undo->last_page_no; undo_page = trx_undo_page_get(undo->space, last_page_no, &mtr); @@ -1037,17 +1037,17 @@ trx_undo_truncate_end( goto function_exit; } - + trx_undo_free_page_in_rollback(trx, undo, last_page_no, &mtr); break; } if (ut_dulint_cmp(trx_undo_rec_get_undo_no(rec), limit) - >= 0) { - /* Truncate at least this record off, maybe - more */ - trunc_here = rec; + >= 0) { + /* Truncate at least this record off, maybe + more */ + trunc_here = rec; } else { goto function_exit; } @@ -1087,7 +1087,7 @@ trx_undo_truncate_start( header page is not freed, but emptied, if all the records there are < limit */ { - page_t* undo_page; + page_t* undo_page; trx_undo_rec_t* rec; trx_undo_rec_t* last_rec; ulint page_no; @@ -1154,8 +1154,8 @@ trx_undo_seg_free( trx_usegf_t* seg_header; ibool finished; mtr_t mtr; - - finished = FALSE; + + finished = FALSE; rseg = undo->rseg; while (!finished) { @@ -1167,8 +1167,7 @@ trx_undo_seg_free( mutex_enter(&(rseg->mutex)); seg_header = trx_undo_page_get(undo->space, undo->hdr_page_no, - &mtr) - + TRX_UNDO_SEG_HDR; + &mtr) + TRX_UNDO_SEG_HDR; file_seg = seg_header + TRX_UNDO_FSEG_HEADER; @@ -1198,7 +1197,7 @@ trx_undo_t* trx_undo_mem_create_at_db_start( /*============================*/ /* out, own: the undo log memory object */ - trx_rseg_t* rseg, /* in: rollback segment memory object */ + trx_rseg_t* rseg, /* in: rollback segment memory object */ ulint id, /* in: slot index within rseg */ ulint page_no,/* in: undo log segment page number */ mtr_t* mtr) /* in: mtr */ @@ -1232,15 +1231,15 @@ trx_undo_mem_create_at_db_start( mtr); seg_header = undo_page + TRX_UNDO_SEG_HDR; - state = mach_read_from_2(seg_header + TRX_UNDO_STATE); + state = mach_read_from_2(seg_header + TRX_UNDO_STATE); offset = mach_read_from_2(seg_header + TRX_UNDO_LAST_LOG); - + undo_header = undo_page + offset; trx_id = mtr_read_dulint(undo_header + TRX_UNDO_TRX_ID, mtr); - xid_exists = mtr_read_ulint(undo_header + TRX_UNDO_XID_EXISTS, + xid_exists = mtr_read_ulint(undo_header + TRX_UNDO_XID_EXISTS, MLOG_1BYTE, mtr); /* Read X/Open XA transaction identification if it exists, or @@ -1251,15 +1250,15 @@ trx_undo_mem_create_at_db_start( if (xid_exists == TRUE) { trx_undo_read_xid(undo_header, &xid); - } + } mutex_enter(&(rseg->mutex)); - undo = trx_undo_mem_create(rseg, id, type, trx_id, &xid, + undo = trx_undo_mem_create(rseg, id, type, trx_id, &xid, page_no, offset); mutex_exit(&(rseg->mutex)); - undo->dict_operation = mtr_read_ulint( + undo->dict_operation = mtr_read_ulint( undo_header + TRX_UNDO_DICT_TRANS, MLOG_1BYTE, mtr); @@ -1289,7 +1288,7 @@ trx_undo_mem_create_at_db_start( undo->top_offset = rec - last_page; undo->top_undo_no = trx_undo_rec_get_undo_no(rec); } -add_to_list: +add_to_list: if (type == TRX_UNDO_INSERT) { if (state != TRX_UNDO_CACHED) { UT_LIST_ADD_LAST(undo_list, rseg->insert_undo_list, @@ -1322,7 +1321,7 @@ trx_undo_lists_init( /*================*/ /* out: the combined size of undo log segments in pages */ - trx_rseg_t* rseg) /* in: rollback segment memory object */ + trx_rseg_t* rseg) /* in: rollback segment memory object */ { ulint page_no; trx_undo_t* undo; @@ -1330,16 +1329,16 @@ trx_undo_lists_init( trx_rsegf_t* rseg_header; ulint i; mtr_t mtr; - + UT_LIST_INIT(rseg->update_undo_list); UT_LIST_INIT(rseg->update_undo_cached); UT_LIST_INIT(rseg->insert_undo_list); UT_LIST_INIT(rseg->insert_undo_cached); mtr_start(&mtr); - + rseg_header = trx_rsegf_get_new(rseg->space, rseg->page_no, &mtr); - + for (i = 0; i < TRX_RSEG_N_SLOTS; i++) { page_no = trx_rsegf_get_nth_undo(rseg_header, i, &mtr); @@ -1349,7 +1348,7 @@ trx_undo_lists_init( high */ if (page_no != FIL_NULL - && srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) { + && srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) { undo = trx_undo_mem_create_at_db_start(rseg, i, page_no, &mtr); @@ -1367,7 +1366,7 @@ trx_undo_lists_init( mtr_commit(&mtr); return(size); -} +} /************************************************************************ Creates and initializes an undo log memory object. */ @@ -1420,7 +1419,7 @@ trx_undo_mem_create( undo->empty = TRUE; undo->top_page_no = page_no; undo->guess_page = NULL; - + return(undo); } @@ -1439,12 +1438,12 @@ trx_undo_mem_init_for_reuse( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&((undo->rseg)->mutex))); #endif /* UNIV_SYNC_DEBUG */ - - if (undo->id >= TRX_RSEG_N_SLOTS) { + + if (undo->id >= TRX_RSEG_N_SLOTS) { fprintf(stderr, "InnoDB: Error: undo->id is %lu\n", (ulong) undo->id); - mem_analyze_corruption((byte*)undo); + mem_analyze_corruption(undo); ut_error; } @@ -1489,7 +1488,7 @@ trx_undo_create( ulint type, /* in: type of the log: TRX_UNDO_INSERT or TRX_UNDO_UPDATE */ dulint trx_id, /* in: id of the trx for which the undo log - is created */ + is created */ XID* xid, /* in: X/Open transaction identification*/ mtr_t* mtr) /* in: mtr */ { @@ -1499,7 +1498,7 @@ trx_undo_create( ulint id; trx_undo_t* undo; page_t* undo_page; - + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(rseg->mutex))); #endif /* UNIV_SYNC_DEBUG */ @@ -1514,7 +1513,7 @@ trx_undo_create( rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, mtr); undo_page = trx_undo_seg_create(rseg, rseg_header, type, &id, mtr); - + if (undo_page == NULL) { /* Did not succeed */ @@ -1524,7 +1523,7 @@ trx_undo_create( } page_no = buf_frame_get_page_no(undo_page); - + offset = trx_undo_header_create(undo_page, trx_id, mtr); if (trx->support_xa) { @@ -1552,7 +1551,7 @@ trx_undo_reuse_cached( ulint type, /* in: type of the log: TRX_UNDO_INSERT or TRX_UNDO_UPDATE */ dulint trx_id, /* in: id of the trx for which the undo log - is used */ + is used */ XID* xid, /* in: X/Open XA transaction identification */ mtr_t* mtr) /* in: mtr */ { @@ -1590,7 +1589,7 @@ trx_undo_reuse_cached( if (undo->id >= TRX_RSEG_N_SLOTS) { fprintf(stderr, "InnoDB: Error: undo->id is %lu\n", (ulong) undo->id); - mem_analyze_corruption((byte*)undo); + mem_analyze_corruption(undo); ut_error; } @@ -1598,7 +1597,7 @@ trx_undo_reuse_cached( if (type == TRX_UNDO_INSERT) { offset = trx_undo_insert_header_reuse(undo_page, trx_id, mtr); - + if (trx->support_xa) { trx_undo_header_add_space_for_xid(undo_page, undo_page + offset, mtr); @@ -1615,7 +1614,7 @@ trx_undo_reuse_cached( undo_page + offset, mtr); } } - + trx_undo_mem_init_for_reuse(undo, trx_id, xid, offset); return(undo); @@ -1635,15 +1634,15 @@ trx_undo_mark_as_dict_operation( page_t* hdr_page; ut_a(trx->dict_operation); - + hdr_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr); - mlog_write_ulint(hdr_page + undo->hdr_offset + + mlog_write_ulint(hdr_page + undo->hdr_offset + TRX_UNDO_DICT_TRANS, trx->dict_operation, MLOG_1BYTE, mtr); mlog_write_dulint(hdr_page + undo->hdr_offset + TRX_UNDO_TABLE_ID, - trx->table_id, mtr); + trx->table_id, mtr); undo->dict_operation = trx->dict_operation; undo->table_id = trx->table_id; @@ -1732,13 +1731,13 @@ trx_undo_set_state_at_finish( trx_upagef_t* page_hdr; page_t* undo_page; ulint state; - + ut_ad(trx && undo && mtr); if (undo->id >= TRX_RSEG_N_SLOTS) { fprintf(stderr, "InnoDB: Error: undo->id is %lu\n", (ulong) undo->id); - mem_analyze_corruption((byte*)undo); + mem_analyze_corruption(undo); ut_error; } @@ -1759,7 +1758,7 @@ trx_undo_set_state_at_finish( } undo->state = state; - + mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, state, MLOG_2BYTES, mtr); return(undo_page); @@ -1782,13 +1781,13 @@ trx_undo_set_state_at_prepare( trx_ulogf_t* undo_header; page_t* undo_page; ulint offset; - + ut_ad(trx && undo && mtr); if (undo->id >= TRX_RSEG_N_SLOTS) { fprintf(stderr, "InnoDB: Error: undo->id is %lu\n", (ulong) undo->id); - mem_analyze_corruption((byte*)undo); + mem_analyze_corruption(undo); ut_error; } @@ -1801,17 +1800,17 @@ trx_undo_set_state_at_prepare( undo->state = TRX_UNDO_PREPARED; undo->xid = trx->xid; /*------------------------------*/ - - mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, undo->state, + + mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, undo->state, MLOG_2BYTES, mtr); offset = mach_read_from_2(seg_hdr + TRX_UNDO_LAST_LOG); - undo_header = undo_page + offset; + undo_header = undo_page + offset; mlog_write_ulint(undo_header + TRX_UNDO_XID_EXISTS, TRUE, MLOG_1BYTE, mtr); - trx_undo_write_xid(undo_header, &undo->xid, mtr); + trx_undo_write_xid(undo_header, &undo->xid, mtr); return(undo_page); } @@ -1831,7 +1830,7 @@ trx_undo_update_cleanup( { trx_rseg_t* rseg; trx_undo_t* undo; - + undo = trx->update_undo; rseg = trx->rseg; @@ -1866,7 +1865,7 @@ trx_undo_insert_cleanup( { trx_undo_t* undo; trx_rseg_t* rseg; - + undo = trx->insert_undo; ut_ad(undo); @@ -1892,11 +1891,11 @@ trx_undo_insert_cleanup( mutex_enter(&(rseg->mutex)); ut_ad(rseg->curr_size > undo->size); - + rseg->curr_size -= undo->size; trx_undo_mem_free(undo); } - + mutex_exit(&(rseg->mutex)); } diff --git a/storage/innobase/usr/usr0sess.c b/storage/innobase/usr/usr0sess.c index 359c1552421..ca97ea23e95 100644 --- a/storage/innobase/usr/usr0sess.c +++ b/storage/innobase/usr/usr0sess.c @@ -29,7 +29,7 @@ sess_t* sess_open(void) /*===========*/ /* out, own: session object */ -{ +{ sess_t* sess; #ifdef UNIV_SYNC_DEBUG @@ -48,13 +48,12 @@ sess_open(void) /************************************************************************* Closes a session, freeing the memory occupied by it. */ - static void sess_close( /*=======*/ sess_t* sess) /* in, own: session object */ -{ +{ #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ diff --git a/storage/innobase/ut/ut0byte.c b/storage/innobase/ut/ut0byte.c index cc83aacc90b..18f57181827 100644 --- a/storage/innobase/ut/ut0byte.c +++ b/storage/innobase/ut/ut0byte.c @@ -15,10 +15,10 @@ Created 5/11/1994 Heikki Tuuri #include "ut0sort.h" /* Zero value for a dulint */ -dulint ut_dulint_zero = {0, 0}; +dulint ut_dulint_zero = {0, 0}; /* Maximum value for a dulint */ -dulint ut_dulint_max = {0xFFFFFFFFUL, 0xFFFFFFFFUL}; +dulint ut_dulint_max = {0xFFFFFFFFUL, 0xFFFFFFFFUL}; /**************************************************************** Sort function for dulint arrays. */ diff --git a/storage/innobase/ut/ut0dbg.c b/storage/innobase/ut/ut0dbg.c index e810d8dead7..2157a71116a 100644 --- a/storage/innobase/ut/ut0dbg.c +++ b/storage/innobase/ut/ut0dbg.c @@ -17,8 +17,8 @@ ulint ut_dbg_zero = 0; /* If this is set to TRUE all threads will stop into the next assertion and assert */ ibool ut_dbg_stop_threads = FALSE; -#ifdef __NETWARE__ -ibool panic_shutdown = FALSE; /* This is set to TRUE when on NetWare there +#ifdef __NETWARE__ +ibool panic_shutdown = FALSE; /* This is set to TRUE when on NetWare there happens an InnoDB assertion failure or other fatal error condition that requires an immediate shutdown. */ diff --git a/storage/innobase/ut/ut0mem.c b/storage/innobase/ut/ut0mem.c index 47b1e24e5e1..345c14e00f9 100644 --- a/storage/innobase/ut/ut0mem.c +++ b/storage/innobase/ut/ut0mem.c @@ -23,7 +23,7 @@ typedef struct ut_mem_block_struct ut_mem_block_t; ulint ut_total_allocated_memory = 0; struct ut_mem_block_struct{ - UT_LIST_NODE_T(ut_mem_block_t) mem_block_list; + UT_LIST_NODE_T(ut_mem_block_t) mem_block_list; /* mem block list node */ ulint size; /* size of allocated memory */ ulint magic_n; @@ -35,7 +35,7 @@ struct ut_mem_block_struct{ with malloc */ UT_LIST_BASE_NODE_T(ut_mem_block_t) ut_mem_block_list; -os_fast_mutex_t ut_list_mutex; /* this protects the list */ +os_fast_mutex_t ut_list_mutex; /* this protects the list */ ibool ut_mem_block_list_inited = FALSE; @@ -48,8 +48,8 @@ void ut_mem_block_list_init(void) /*========================*/ { - os_fast_mutex_init(&ut_list_mutex); - UT_LIST_INIT(ut_mem_block_list); + os_fast_mutex_init(&ut_list_mutex); + UT_LIST_INIT(ut_mem_block_list); ut_mem_block_list_inited = TRUE; } @@ -60,12 +60,13 @@ defined and set_to_zero is TRUE. */ void* ut_malloc_low( /*==========*/ - /* out, own: allocated memory */ - ulint n, /* in: number of bytes to allocate */ - ibool set_to_zero, /* in: TRUE if allocated memory should be set - to zero if UNIV_SET_MEM_TO_ZERO is defined */ - ibool assert_on_error) /* in: if TRUE, we crash mysqld if the memory - cannot be allocated */ + /* out, own: allocated memory */ + ulint n, /* in: number of bytes to allocate */ + ibool set_to_zero, /* in: TRUE if allocated memory should be + set to zero if UNIV_SET_MEM_TO_ZERO is + defined */ + ibool assert_on_error)/* in: if TRUE, we crash mysqld if the + memory cannot be allocated */ { ulint retry_count = 0; void* ret; @@ -73,7 +74,7 @@ ut_malloc_low( ut_ad((sizeof(ut_mem_block_t) % 8) == 0); /* check alignment ok */ if (!ut_mem_block_list_inited) { - ut_mem_block_list_init(); + ut_mem_block_list_init(); } retry: os_fast_mutex_lock(&ut_list_mutex); @@ -95,7 +96,7 @@ retry: "InnoDB: Note that in most 32-bit computers the process\n" "InnoDB: memory space is limited to 2 GB or 4 GB.\n" "InnoDB: We keep retrying the allocation for 60 seconds...\n", - (ulong) n, (ulong) ut_total_allocated_memory, + (ulong) n, (ulong) ut_total_allocated_memory, #ifdef __WIN__ (ulong) GetLastError() #else @@ -110,7 +111,7 @@ retry: just a temporary shortage of memory */ os_thread_sleep(1000000); - + retry_count++; goto retry; @@ -123,13 +124,13 @@ retry: fflush(stderr); - os_fast_mutex_unlock(&ut_list_mutex); + os_fast_mutex_unlock(&ut_list_mutex); /* Make an intentional seg fault so that we get a stack trace */ - /* Intentional segfault on NetWare causes an abend. Avoid this + /* Intentional segfault on NetWare causes an abend. Avoid this by graceful exit handling in ut_a(). */ -#if (!defined __NETWARE__) +#if (!defined __NETWARE__) if (assert_on_error) { ut_print_timestamp(stderr); @@ -144,11 +145,11 @@ retry: #else ut_a(0); #endif - } + } if (set_to_zero) { #ifdef UNIV_SET_MEM_TO_ZERO - memset(ret, '\0', n + sizeof(ut_mem_block_t)); + memset(ret, '\0', n + sizeof(ut_mem_block_t)); #endif } @@ -156,9 +157,9 @@ retry: ((ut_mem_block_t*)ret)->magic_n = UT_MEM_MAGIC_N; ut_total_allocated_memory += n + sizeof(ut_mem_block_t); - + UT_LIST_ADD_FIRST(mem_block_list, ut_mem_block_list, - ((ut_mem_block_t*)ret)); + ((ut_mem_block_t*)ret)); os_fast_mutex_unlock(&ut_list_mutex); return((void*)((byte*)ret + sizeof(ut_mem_block_t))); @@ -171,10 +172,10 @@ defined. */ void* ut_malloc( /*======*/ - /* out, own: allocated memory */ - ulint n) /* in: number of bytes to allocate */ + /* out, own: allocated memory */ + ulint n) /* in: number of bytes to allocate */ { - return(ut_malloc_low(n, TRUE, TRUE)); + return(ut_malloc_low(n, TRUE, TRUE)); } /************************************************************************** @@ -202,8 +203,8 @@ ut_test_malloc( "InnoDB: ulimits of your operating system.\n" "InnoDB: On FreeBSD check you have compiled the OS with\n" "InnoDB: a big enough maximum process size.\n", - (ulong) n, - (ulong) ut_total_allocated_memory, + (ulong) n, + (ulong) ut_total_allocated_memory, (int) errno); return(FALSE); } @@ -211,7 +212,7 @@ ut_test_malloc( free(ret); return(TRUE); -} +} /************************************************************************** Frees a memory block allocated with ut_malloc. */ @@ -221,7 +222,7 @@ ut_free( /*====*/ void* ptr) /* in, own: memory block */ { - ut_mem_block_t* block; + ut_mem_block_t* block; block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t)); @@ -231,10 +232,10 @@ ut_free( ut_a(ut_total_allocated_memory >= block->size); ut_total_allocated_memory -= block->size; - + UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block); free(block); - + os_fast_mutex_unlock(&ut_list_mutex); } @@ -248,10 +249,10 @@ man realloc in Linux, 2004: realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated mem - ory will be uninitialized. If ptr is NULL, the call is + ory will be uninitialized. If ptr is NULL, the call is equivalent to malloc(size); if size is equal to zero, the - call is equivalent to free(ptr). Unless ptr is NULL, it - must have been returned by an earlier call to malloc(), + call is equivalent to free(ptr). Unless ptr is NULL, it + must have been returned by an earlier call to malloc(), calloc() or realloc(). RETURN VALUE @@ -259,8 +260,8 @@ RETURN VALUE which is suitably aligned for any kind of variable and may be different from ptr, or NULL if the request fails. If size was equal to 0, either NULL or a pointer suitable to - be passed to free() is returned. If realloc() fails the - original block is left untouched - it is not freed or + be passed to free() is returned. If realloc() fails the + original block is left untouched - it is not freed or moved. */ void* @@ -270,7 +271,7 @@ ut_realloc( void* ptr, /* in: pointer to old block or NULL */ ulint size) /* in: desired size */ { - ut_mem_block_t* block; + ut_mem_block_t* block; ulint old_size; ulint min_size; void* new_ptr; @@ -297,20 +298,20 @@ ut_realloc( } else { min_size = old_size; } - + new_ptr = ut_malloc(size); if (new_ptr == NULL) { return(NULL); - } + } /* Copy the old data from ptr */ ut_memcpy(new_ptr, ptr, min_size); ut_free(ptr); - return(new_ptr); + return(new_ptr); } /************************************************************************** @@ -320,9 +321,9 @@ void ut_free_all_mem(void) /*=================*/ { - ut_mem_block_t* block; + ut_mem_block_t* block; - os_fast_mutex_free(&ut_list_mutex); + os_fast_mutex_free(&ut_list_mutex); while ((block = UT_LIST_GET_FIRST(ut_mem_block_list))) { @@ -330,11 +331,11 @@ ut_free_all_mem(void) ut_a(ut_total_allocated_memory >= block->size); ut_total_allocated_memory -= block->size; - - UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block); - free(block); + + UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block); + free(block); } - + if (ut_total_allocated_memory != 0) { fprintf(stderr, "InnoDB: Warning: after shutdown total allocated memory is %lu\n", @@ -359,7 +360,7 @@ ut_strlcpy( if (size != 0) { ulint n = ut_min(src_size, size - 1); - + memcpy(dst, src, n); dst[n] = '\0'; } @@ -391,7 +392,7 @@ ut_strlcpy_rev( } /************************************************************************** -Make a quoted copy of a NUL-terminated string. Leading and trailing +Make a quoted copy of a NUL-terminated string. Leading and trailing quotes will not be included; only embedded quotes will be escaped. See also ut_strlenq() and ut_memcpyq(). */ diff --git a/storage/innobase/ut/ut0rnd.c b/storage/innobase/ut/ut0rnd.c index 85d2e6094c3..016809e0474 100644 --- a/storage/innobase/ut/ut0rnd.c +++ b/storage/innobase/ut/ut0rnd.c @@ -32,9 +32,9 @@ ut_find_prime( { ulint pow2; ulint i; - + n += 100; - + pow2 = 1; while (pow2 * 2 < n) { pow2 = 2 * pow2; @@ -43,23 +43,23 @@ ut_find_prime( if ((double)n < 1.05 * (double)pow2) { n = (ulint) ((double)n * UT_RANDOM_1); } - + pow2 = 2 * pow2; - + if ((double)n > 0.95 * (double)pow2) { n = (ulint) ((double)n * UT_RANDOM_2); } - + if (n > pow2 - 20) { n += 30; } /* Now we have n far enough from powers of 2. To make - n more random (especially, if it was not near - a power of 2), we then multiply it by a random number. */ + n more random (especially, if it was not near + a power of 2), we then multiply it by a random number. */ n = (ulint) ((double)n * UT_RANDOM_3); - + for (;; n++) { i = 2; while (i * i <= n) { @@ -68,11 +68,11 @@ ut_find_prime( } i++; } - + /* Found a prime */ break; -next_n: ; +next_n: ; } - + return(n); } diff --git a/storage/innobase/ut/ut0ut.c b/storage/innobase/ut/ut0ut.c index 1be5939303a..48435fe6155 100644 --- a/storage/innobase/ut/ut0ut.c +++ b/storage/innobase/ut/ut0ut.c @@ -117,11 +117,11 @@ ut_print_timestamp( FILE* file) /* in: file where to print */ { #ifdef __WIN__ - SYSTEMTIME cal_tm; + SYSTEMTIME cal_tm; - GetLocalTime(&cal_tm); + GetLocalTime(&cal_tm); - fprintf(file,"%02d%02d%02d %2d:%02d:%02d", + fprintf(file,"%02d%02d%02d %2d:%02d:%02d", (int)cal_tm.wYear % 100, (int)cal_tm.wMonth, (int)cal_tm.wDay, @@ -130,18 +130,18 @@ ut_print_timestamp( (int)cal_tm.wSecond); #else struct tm cal_tm; - struct tm* cal_tm_ptr; - time_t tm; + struct tm* cal_tm_ptr; + time_t tm; - time(&tm); + time(&tm); #ifdef HAVE_LOCALTIME_R - localtime_r(&tm, &cal_tm); - cal_tm_ptr = &cal_tm; + localtime_r(&tm, &cal_tm); + cal_tm_ptr = &cal_tm; #else - cal_tm_ptr = localtime(&tm); + cal_tm_ptr = localtime(&tm); #endif - fprintf(file,"%02d%02d%02d %2d:%02d:%02d", + fprintf(file,"%02d%02d%02d %2d:%02d:%02d", cal_tm_ptr->tm_year % 100, cal_tm_ptr->tm_mon + 1, cal_tm_ptr->tm_mday, @@ -160,11 +160,11 @@ ut_sprintf_timestamp( char* buf) /* in: buffer where to sprintf */ { #ifdef __WIN__ - SYSTEMTIME cal_tm; + SYSTEMTIME cal_tm; - GetLocalTime(&cal_tm); + GetLocalTime(&cal_tm); - sprintf(buf, "%02d%02d%02d %2d:%02d:%02d", + sprintf(buf, "%02d%02d%02d %2d:%02d:%02d", (int)cal_tm.wYear % 100, (int)cal_tm.wMonth, (int)cal_tm.wDay, @@ -173,18 +173,18 @@ ut_sprintf_timestamp( (int)cal_tm.wSecond); #else struct tm cal_tm; - struct tm* cal_tm_ptr; - time_t tm; + struct tm* cal_tm_ptr; + time_t tm; - time(&tm); + time(&tm); #ifdef HAVE_LOCALTIME_R - localtime_r(&tm, &cal_tm); - cal_tm_ptr = &cal_tm; + localtime_r(&tm, &cal_tm); + cal_tm_ptr = &cal_tm; #else - cal_tm_ptr = localtime(&tm); + cal_tm_ptr = localtime(&tm); #endif - sprintf(buf, "%02d%02d%02d %2d:%02d:%02d", + sprintf(buf, "%02d%02d%02d %2d:%02d:%02d", cal_tm_ptr->tm_year % 100, cal_tm_ptr->tm_mon + 1, cal_tm_ptr->tm_mday, @@ -204,11 +204,11 @@ ut_sprintf_timestamp_without_extra_chars( char* buf) /* in: buffer where to sprintf */ { #ifdef __WIN__ - SYSTEMTIME cal_tm; + SYSTEMTIME cal_tm; - GetLocalTime(&cal_tm); + GetLocalTime(&cal_tm); - sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d", + sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d", (int)cal_tm.wYear % 100, (int)cal_tm.wMonth, (int)cal_tm.wDay, @@ -217,18 +217,18 @@ ut_sprintf_timestamp_without_extra_chars( (int)cal_tm.wSecond); #else struct tm cal_tm; - struct tm* cal_tm_ptr; - time_t tm; + struct tm* cal_tm_ptr; + time_t tm; - time(&tm); + time(&tm); #ifdef HAVE_LOCALTIME_R - localtime_r(&tm, &cal_tm); - cal_tm_ptr = &cal_tm; + localtime_r(&tm, &cal_tm); + cal_tm_ptr = &cal_tm; #else - cal_tm_ptr = localtime(&tm); + cal_tm_ptr = localtime(&tm); #endif - sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d", + sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d", cal_tm_ptr->tm_year % 100, cal_tm_ptr->tm_mon + 1, cal_tm_ptr->tm_mday, @@ -249,29 +249,29 @@ ut_get_year_month_day( ulint* day) /* out: day */ { #ifdef __WIN__ - SYSTEMTIME cal_tm; + SYSTEMTIME cal_tm; - GetLocalTime(&cal_tm); + GetLocalTime(&cal_tm); - *year = (ulint)cal_tm.wYear; - *month = (ulint)cal_tm.wMonth; - *day = (ulint)cal_tm.wDay; + *year = (ulint)cal_tm.wYear; + *month = (ulint)cal_tm.wMonth; + *day = (ulint)cal_tm.wDay; #else struct tm cal_tm; - struct tm* cal_tm_ptr; - time_t tm; + struct tm* cal_tm_ptr; + time_t tm; - time(&tm); + time(&tm); #ifdef HAVE_LOCALTIME_R - localtime_r(&tm, &cal_tm); - cal_tm_ptr = &cal_tm; + localtime_r(&tm, &cal_tm); + cal_tm_ptr = &cal_tm; #else - cal_tm_ptr = localtime(&tm); + cal_tm_ptr = localtime(&tm); #endif - *year = (ulint)cal_tm_ptr->tm_year + 1900; - *month = (ulint)cal_tm_ptr->tm_mon + 1; - *day = (ulint)cal_tm_ptr->tm_mday; + *year = (ulint)cal_tm_ptr->tm_year + 1900; + *month = (ulint)cal_tm_ptr->tm_mon + 1; + *day = (ulint)cal_tm_ptr->tm_mday; #endif } @@ -296,9 +296,9 @@ ut_delay( if (ut_always_false) { ut_always_false = (ibool) j; } - + return(j); -} +} /***************************************************************** Prints the contents of a memory buffer in hex and ascii. */ @@ -307,7 +307,7 @@ void ut_print_buf( /*=========*/ FILE* file, /* in: file where to print */ - const byte* buf, /* in: memory buffer */ + const void* buf, /* in: memory buffer */ ulint len) /* in: length of the buffer */ { const byte* data; @@ -315,13 +315,13 @@ ut_print_buf( fprintf(file, " len %lu; hex ", len); - for (data = buf, i = 0; i < len; i++) { + for (data = (const byte*)buf, i = 0; i < len; i++) { fprintf(file, "%02lx", (ulong)*data++); } fputs("; asc ", file); - data = buf; + data = (const byte*)buf; for (i = 0; i < len; i++) { int c = (int) *data++; @@ -408,7 +408,7 @@ Outputs a fixed-length string, quoted as an SQL identifier. */ void ut_print_namel( -/*==========*/ +/*===========*/ FILE* f, /* in: output stream */ trx_t* trx, /* in: transaction (NULL=no quotes) */ const char* name, /* in: name to print */ |