1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

Merge 10.6 into 10.7

This commit is contained in:
Marko Mäkelä
2021-11-19 17:45:52 +02:00
134 changed files with 3675 additions and 3662 deletions

View File

@@ -182,16 +182,20 @@ IF(WIN32)
SET(SIGNTOOL_PARAMETERS SET(SIGNTOOL_PARAMETERS
/a /t http://timestamp.globalsign.com/?signature=sha2 /a /t http://timestamp.globalsign.com/?signature=sha2
CACHE STRING "parameters for signtool (list)") CACHE STRING "parameters for signtool (list)")
FIND_PROGRAM(SIGNTOOL_EXECUTABLE signtool
PATHS "$ENV{ProgramFiles}/Microsoft SDKs/Windows/v7.0A/bin"
"$ENV{ProgramFiles}/Windows Kits/8.0/bin/x86"
"$ENV{ProgramFiles}/Windows Kits/8.1/bin/x86"
)
IF(NOT SIGNTOOL_EXECUTABLE) IF(NOT SIGNTOOL_EXECUTABLE)
MESSAGE(FATAL_ERROR FILE(GLOB path_list
"signtool is not found. Signing executables not possible") "$ENV{ProgramFiles} (x86)/Windows Kits/*/bin/*/x64"
"$ENV{ProgramFiles} (x86)/Windows Kits/*/App Certification Kit"
)
FIND_PROGRAM(SIGNTOOL_EXECUTABLE signtool
PATHS ${path_list}
)
IF(NOT SIGNTOOL_EXECUTABLE)
MESSAGE(FATAL_ERROR
"signtool is not found. Signing executables not possible")
ENDIF()
MARK_AS_ADVANCED(SIGNTOOL_EXECUTABLE SIGNTOOL_PARAMETERS)
ENDIF() ENDIF()
MARK_AS_ADVANCED(SIGNTOOL_EXECUTABLE SIGNTOOL_PARAMETERS)
ENDIF() ENDIF()
ENDIF() ENDIF()

View File

@@ -2086,6 +2086,56 @@ a b a b
1 3 1 3 1 3 1 3
drop procedure sp; drop procedure sp;
drop table t1; drop table t1;
#
# MDEV-26825: query with two usage of CTE that refers to another CTE
# with stored function using a base table.
#
create table t1 (id int primary key);
insert into t1 values
(1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
create function f(in_id int) returns integer
return (select id from t1 where t1.id = in_id);
with c1 as (select id from t1 where f(id)=id group by id),
c2 as (select id from c1 as pt group by id)
select id from c2 as s1 union select id from c2 as s2;
id
1
2
3
4
5
6
7
8
9
10
with c1 as (select id from t1 as r where f(id)=id group by id),
c2 as (select id from c1 as pt group by id)
select id from c2 as s1 union select id from c2 as s2;
id
1
2
3
4
5
6
7
8
9
10
create function g() returns int return (select count(*) from t1);
create procedure sp1()
with c1 as (select id from t1 a where g() > 10),
c2 as (select id from c1)
select id from c2 as s1 union select id from c2 as s2;
call sp1();
id
call sp1();
id
drop procedure sp1;
drop function g;
drop function f;
drop table t1;
# End of 10.2 tests # End of 10.2 tests
# #
# MDEV-21673: several references to CTE that uses # MDEV-21673: several references to CTE that uses

View File

@@ -1554,6 +1554,42 @@ call sp();
drop procedure sp; drop procedure sp;
drop table t1; drop table t1;
--echo #
--echo # MDEV-26825: query with two usage of CTE that refers to another CTE
--echo # with stored function using a base table.
--echo #
create table t1 (id int primary key);
insert into t1 values
(1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
create function f(in_id int) returns integer
return (select id from t1 where t1.id = in_id);
with c1 as (select id from t1 where f(id)=id group by id),
c2 as (select id from c1 as pt group by id)
select id from c2 as s1 union select id from c2 as s2;
with c1 as (select id from t1 as r where f(id)=id group by id),
c2 as (select id from c1 as pt group by id)
select id from c2 as s1 union select id from c2 as s2;
create function g() returns int return (select count(*) from t1);
create procedure sp1()
with c1 as (select id from t1 a where g() > 10),
c2 as (select id from c1)
select id from c2 as s1 union select id from c2 as s2;
call sp1();
call sp1();
drop procedure sp1;
drop function g;
drop function f;
drop table t1;
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #

View File

@@ -32,8 +32,8 @@ COUNT(*)=8
# Note: We only look for 00 because the 5c only served as an escape # Note: We only look for 00 because the 5c only served as an escape
# in parsing. # in parsing.
# #
# MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql # MYSQL_DUMP test tb --hex-blob > MYSQL_TMP_DIR/dump.sql
FOUND 10 /00/ in dump.sql FOUND 8 /\([0-9]+,0x([1-9][0-9])*00([1-9][0-9])*\)/ in dump.sql
# #
# Ensure data consistency on mysqlbinlog replay # Ensure data consistency on mysqlbinlog replay
# #

View File

@@ -114,9 +114,9 @@ SELECT COUNT(*)=8 from tb;
--echo # Note: We only look for 00 because the 5c only served as an escape --echo # Note: We only look for 00 because the 5c only served as an escape
--echo # in parsing. --echo # in parsing.
--echo # --echo #
--echo # MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql --echo # MYSQL_DUMP test tb --hex-blob > MYSQL_TMP_DIR/dump.sql
--exec $MYSQL_DUMP test tb --hex-blob | grep -A8 INSERT > $MYSQL_TMP_DIR/dump.sql --exec $MYSQL_DUMP test tb --hex-blob > $MYSQL_TMP_DIR/dump.sql
--let SEARCH_PATTERN= 00 --let SEARCH_PATTERN= \([0-9]+,0x([1-9][0-9])*00([1-9][0-9])*\)
--let SEARCH_FILE= $MYSQL_TMP_DIR/dump.sql --let SEARCH_FILE= $MYSQL_TMP_DIR/dump.sql
--source include/search_pattern_in_file.inc --source include/search_pattern_in_file.inc

View File

@@ -0,0 +1,13 @@
call mtr.add_suppression("InnoDB: .*: Page 0 at offset 0 looks corrupted");
call mtr.add_suppression("Index for table 'dst' is corrupt; try to repair it");
call mtr.add_suppression("Page for tablespace .* is index page with id .* but that index is not found from configuration file");
CREATE TABLE src (pk INT PRIMARY KEY, value INT) ENGINE=INNODB;
INSERT INTO src VALUES (1, 1), (2, 2), (3, 3);
FLUSH TABLES src FOR EXPORT;
UNLOCK TABLES;
DROP TABLE src;
CREATE TABLE dst (pk INT PRIMARY KEY, value INT) ENGINE=INNODB;
ALTER TABLE dst DISCARD TABLESPACE;
ALTER TABLE dst IMPORT TABLESPACE;
ERROR HY000: Index for table 'dst' is corrupt; try to repair it
DROP TABLE dst;

View File

@@ -67,13 +67,13 @@ test/t2
test/t3 test/t3
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0; SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
NAME NAME
innodb_system
mysql/innodb_table_stats
mysql/innodb_index_stats
mysql/transaction_registry
test/t4 test/t4
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0; SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
NAME NAME
innodb_system
mysql/innodb_index_stats
mysql/innodb_table_stats
mysql/transaction_registry
test/t1 test/t1
test/t2 test/t2
test/t3 test/t3

View File

@@ -66,7 +66,7 @@ innodb_encryption_threads 0
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0
AND NAME NOT LIKE 'innodb_undo%' AND NAME NOT LIKE 'mysql/innodb_%_stats' AND NAME NOT LIKE 'mysql/transaction_registry'; AND NAME NOT LIKE 'innodb_undo%' AND NAME NOT LIKE 'mysql/innodb_%_stats' AND NAME NOT LIKE 'mysql/transaction_registry';
NAME NAME
innodb_system
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0
AND NAME NOT LIKE 'innodb_undo%' AND NAME NOT LIKE 'mysql/innodb_%_stats' AND NAME NOT LIKE 'mysql/transaction_registry'; AND NAME NOT LIKE 'innodb_undo%' AND NAME NOT LIKE 'mysql/innodb_%_stats' AND NAME NOT LIKE 'mysql/transaction_registry';
NAME NAME
innodb_system

View File

@@ -0,0 +1,4 @@
[crc32]
innodb-checksum-algorithm=crc32
[full_crc32]
innodb-checksum-algorithm=full_crc32

View File

@@ -0,0 +1 @@
--innodb-encrypt-tables=1

View File

@@ -0,0 +1,44 @@
--source include/have_innodb.inc
--source include/have_example_key_management_plugin.inc
call mtr.add_suppression("InnoDB: .*: Page 0 at offset 0 looks corrupted");
call mtr.add_suppression("Index for table 'dst' is corrupt; try to repair it");
call mtr.add_suppression("Page for tablespace .* is index page with id .* but that index is not found from configuration file");
let MYSQLD_DATADIR = `SELECT @@datadir`;
CREATE TABLE src (pk INT PRIMARY KEY, value INT) ENGINE=INNODB;
INSERT INTO src VALUES (1, 1), (2, 2), (3, 3);
FLUSH TABLES src FOR EXPORT;
--copy_file $MYSQLD_DATADIR/test/src.ibd $MYSQLD_DATADIR/test/tmp.ibd
--copy_file $MYSQLD_DATADIR/test/src.cfg $MYSQLD_DATADIR/test/tmp.cfg
perl;
use strict;
die unless open(FILE, "+<$ENV{MYSQLD_DATADIR}/test/tmp.ibd");
binmode FILE;
die unless seek(FILE, 3 * 16384 + 26, 0);
print FILE pack("N", 0x00000000);
close(FILE);
EOF
UNLOCK TABLES;
DROP TABLE src;
CREATE TABLE dst (pk INT PRIMARY KEY, value INT) ENGINE=INNODB;
ALTER TABLE dst DISCARD TABLESPACE;
--copy_file $MYSQLD_DATADIR/test/tmp.ibd $MYSQLD_DATADIR/test/dst.ibd
--copy_file $MYSQLD_DATADIR/test/tmp.cfg $MYSQLD_DATADIR/test/dst.cfg
--error ER_NOT_KEYFILE
ALTER TABLE dst IMPORT TABLESPACE;
DROP TABLE dst;
--remove_file $MYSQLD_DATADIR/test/tmp.ibd
--remove_file $MYSQLD_DATADIR/test/tmp.cfg

View File

@@ -90,6 +90,9 @@ AND NAME NOT LIKE 'innodb_undo%' AND NAME NOT LIKE 'mysql/innodb_%_stats' AND NA
SHOW VARIABLES LIKE 'innodb_encrypt%'; SHOW VARIABLES LIKE 'innodb_encrypt%';
--let $wait_condition=SELECT COUNT(*) >= $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
--source include/wait_condition.inc
--sorted_result --sorted_result
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0
AND NAME NOT LIKE 'innodb_undo%' AND NAME NOT LIKE 'mysql/innodb_%_stats' AND NAME NOT LIKE 'mysql/transaction_registry'; AND NAME NOT LIKE 'innodb_undo%' AND NAME NOT LIKE 'mysql/innodb_%_stats' AND NAME NOT LIKE 'mysql/transaction_registry';

View File

@@ -25,6 +25,7 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB; CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail"; SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
ALTER TABLE t1 ADD COLUMN f3 INT AS (f1) VIRTUAL, ADD INDEX(f2, f3); ALTER TABLE t1 ADD COLUMN f3 INT AS (f1) VIRTUAL, ADD INDEX(f2, f3);
@@ -33,6 +34,7 @@ SET DEBUG_SYNC="now WAIT_FOR con1_go";
BEGIN; BEGIN;
SELECT * FROM t1; SELECT * FROM t1;
f1 f2 f1 f2
1 1
SET DEBUG_SYNC="now SIGNAL alter_signal"; SET DEBUG_SYNC="now SIGNAL alter_signal";
connection default; connection default;
ERROR 23000: Duplicate entry '' for key '*UNKNOWN*' ERROR 23000: Duplicate entry '' for key '*UNKNOWN*'
@@ -47,6 +49,7 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB; CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail"; SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
ALTER TABLE t1 ADD INDEX(f2); ALTER TABLE t1 ADD INDEX(f2);

View File

@@ -29,6 +29,7 @@ DROP TABLE t1;
# new_vcol_info in index when rollback of alter happens # new_vcol_info in index when rollback of alter happens
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB; CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail"; SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
SEND ALTER TABLE t1 ADD COLUMN f3 INT AS (f1) VIRTUAL, ADD INDEX(f2, f3); SEND ALTER TABLE t1 ADD COLUMN f3 INT AS (f1) VIRTUAL, ADD INDEX(f2, f3);
@@ -47,6 +48,7 @@ SHOW CREATE TABLE t1;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB; CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail"; SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
send ALTER TABLE t1 ADD INDEX(f2); send ALTER TABLE t1 ADD INDEX(f2);

View File

@@ -34,6 +34,7 @@ CREATE TABLE t1(f1 INT, f2 INT,
PRIMARY KEY(f1, f2), PRIMARY KEY(f1, f2),
UNIQUE INDEX uidx2 (f1, f2), UNIQUE INDEX uidx2 (f1, f2),
UNIQUE INDEX uidx1 (f2))ENGINE=InnoDB; UNIQUE INDEX uidx1 (f2))ENGINE=InnoDB;
INSERT INTO t1 VALUES(2, 2);
ALTER TABLE t1 DROP PRIMARY KEY; ALTER TABLE t1 DROP PRIMARY KEY;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
@@ -66,7 +67,7 @@ test.t1 check status OK
DROP TABLE t1; DROP TABLE t1;
SET SQL_MODE= strict_trans_tables; SET SQL_MODE= strict_trans_tables;
CREATE TABLE t1(a INT UNIQUE) ENGINE=InnoDB; CREATE TABLE t1(a INT UNIQUE) ENGINE=InnoDB;
INSERT INTO t1 VALUES(3); INSERT INTO t1 VALUES(1);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL dml WAIT_FOR dml_done'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL dml WAIT_FOR dml_done';
ALTER TABLE t1 MODIFY COLUMN a INT NOT NULL; ALTER TABLE t1 MODIFY COLUMN a INT NOT NULL;
connection con1; connection con1;

View File

@@ -80,6 +80,7 @@ SET DEBUG_SYNC='RESET';
# #
CREATE TABLE t1 (f VARCHAR(8) CHARACTER SET latin1 COLLATE latin1_swedish_ci) CREATE TABLE t1 (f VARCHAR(8) CHARACTER SET latin1 COLLATE latin1_swedish_ci)
ENGINE=InnoDB; ENGINE=InnoDB;
INSERT INTO t1 VALUES('ZERO');
connection con1; connection con1;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done'; SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done';
ALTER TABLE t1 MODIFY f VARCHAR(256) COLLATE latin1_german2_ci NOT NULL; ALTER TABLE t1 MODIFY f VARCHAR(256) COLLATE latin1_german2_ci NOT NULL;
@@ -96,5 +97,6 @@ ALTER TABLE t1 CHANGE f eins VARCHAR(257) COLLATE latin1_german1_ci NOT NULL,
ALGORITHM=INSTANT; ALGORITHM=INSTANT;
SELECT * FROM t1; SELECT * FROM t1;
eins eins
ZERO
one one
DROP TABLE t1; DROP TABLE t1;

View File

@@ -4,6 +4,7 @@
# #
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (c CHAR(2) NOT NULL) ENGINE=InnoDB; CREATE TABLE t1 (c CHAR(2) NOT NULL) ENGINE=InnoDB;
INSERT INTO t1 VALUES('cd');
connect con1,localhost,root,,; connect con1,localhost,root,,;
BEGIN; BEGIN;
INSERT INTO t0 VALUES(1); INSERT INTO t0 VALUES(1);
@@ -21,6 +22,7 @@ ERROR 23000: Duplicate entry 'a' for key 'PRIMARY'
SET DEBUG_SYNC='RESET'; SET DEBUG_SYNC='RESET';
SELECT * FROM t1; SELECT * FROM t1;
c c
cd
ab ab
ac ac
DROP TABLE t0,t1; DROP TABLE t0,t1;

View File

@@ -1,6 +1,7 @@
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=InnoDB; CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=InnoDB;
INSERT INTO t0 VALUES(100); INSERT INTO t0 VALUES(100);
INSERT INTO t1 VALUES(100, 100);
connect con1,localhost,root,,test; connect con1,localhost,root,,test;
BEGIN; BEGIN;
INSERT INTO t0 SET pk=1; INSERT INTO t0 SET pk=1;

View File

@@ -55,7 +55,7 @@ connect con1,localhost,root,,;
BEGIN; BEGIN;
DELETE FROM mysql.innodb_table_stats; DELETE FROM mysql.innodb_table_stats;
connect con2,localhost,root,,; connect con2,localhost,root,,;
SET DEBUG_SYNC='inplace_after_index_build SIGNAL blocked WAIT_FOR ever'; SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL blocked WAIT_FOR ever';
ALTER TABLE t1 FORCE; ALTER TABLE t1 FORCE;
connection default; connection default;
SET DEBUG_SYNC='now WAIT_FOR blocked'; SET DEBUG_SYNC='now WAIT_FOR blocked';

View File

@@ -81,6 +81,7 @@ COUNT(k1) k2 k3
drop table t1; drop table t1;
create table t1(k1 int auto_increment primary key, create table t1(k1 int auto_increment primary key,
k2 char(200),k3 char(200))engine=innodb; k2 char(200),k3 char(200))engine=innodb;
INSERT INTO t1 VALUES(1, "test", "test");
SET DEBUG_SYNC= 'row_merge_after_scan SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed'; SIGNAL opened WAIT_FOR flushed';
ALTER TABLE t1 FORCE, ADD COLUMN k4 int; ALTER TABLE t1 FORCE, ADD COLUMN k4 int;
@@ -100,6 +101,7 @@ SELECT COUNT(k1),k2,k3 FROM t1 GROUP BY k2,k3;
COUNT(k1) k2 k3 COUNT(k1) k2 k3
480 aaa bbb 480 aaa bbb
480 aaaa bbbb 480 aaaa bbbb
1 test test
disconnect con1; disconnect con1;
connection default; connection default;
show create table t1; show create table t1;
@@ -109,7 +111,7 @@ t1 CREATE TABLE `t1` (
`k2` char(200) DEFAULT NULL, `k2` char(200) DEFAULT NULL,
`k3` char(200) DEFAULT NULL, `k3` char(200) DEFAULT NULL,
PRIMARY KEY (`k1`) PRIMARY KEY (`k1`)
) ENGINE=InnoDB AUTO_INCREMENT=1023 DEFAULT CHARSET=latin1 ) ENGINE=InnoDB AUTO_INCREMENT=1024 DEFAULT CHARSET=latin1
drop table t1; drop table t1;
drop table t480; drop table t480;
# #
@@ -117,6 +119,7 @@ drop table t480;
# in online table rebuild # in online table rebuild
# #
CREATE TABLE t1 (j INT UNIQUE, i INT UNIQUE) ENGINE=InnoDB; CREATE TABLE t1 (j INT UNIQUE, i INT UNIQUE) ENGINE=InnoDB;
INSERT INTO t1 VALUES(2, 2);
connect con1,localhost,root,,test; connect con1,localhost,root,,test;
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL built WAIT_FOR log'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL built WAIT_FOR log';
ALTER TABLE t1 DROP j, FORCE; ALTER TABLE t1 DROP j, FORCE;

View File

@@ -493,6 +493,7 @@ DROP TABLE t1;
# MDEV-13205 assertion !dict_index_is_online_ddl(index) upon ALTER TABLE # MDEV-13205 assertion !dict_index_is_online_ddl(index) upon ALTER TABLE
# #
CREATE TABLE t1 (c VARCHAR(64)) ENGINE=InnoDB; CREATE TABLE t1 (c VARCHAR(64)) ENGINE=InnoDB;
INSERT INTO t1 VALUES('foo');
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL t1u_created WAIT_FOR dup_done'; SET DEBUG_SYNC = 'row_log_apply_before SIGNAL t1u_created WAIT_FOR dup_done';
ALTER TABLE t1 ADD UNIQUE(c); ALTER TABLE t1 ADD UNIQUE(c);
connection con1; connection con1;
@@ -509,6 +510,7 @@ ALTER TABLE t2 ADD FOREIGN KEY (c) REFERENCES t1 (c);
ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
DROP TABLE t2,t1; DROP TABLE t2,t1;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES(0,0);
connect con1,localhost,root,,; connect con1,localhost,root,,;
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL created WAIT_FOR inserted'; SET DEBUG_SYNC = 'row_log_apply_before SIGNAL created WAIT_FOR inserted';
ALTER TABLE t1 ADD INDEX(b); ALTER TABLE t1 ADD INDEX(b);
@@ -523,6 +525,7 @@ disconnect con1;
connection default; connection default;
SELECT * FROM t1; SELECT * FROM t1;
a b a b
0 0
CHECK TABLE t1; CHECK TABLE t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 check status OK test.t1 check status OK

View File

@@ -434,6 +434,7 @@ t1 CREATE TABLE `t1` (
SET GLOBAL innodb_monitor_disable = module_ddl; SET GLOBAL innodb_monitor_disable = module_ddl;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (a INT PRIMARY KEY, b blob) ENGINE=InnoDB; CREATE TABLE t1 (a INT PRIMARY KEY, b blob) ENGINE=InnoDB;
INSERT INTO t1 VALUES(0,NULL);
connection con1; connection con1;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL created WAIT_FOR ins'; SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL created WAIT_FOR ins';
ALTER TABLE t1 FORCE; ALTER TABLE t1 FORCE;
@@ -448,6 +449,7 @@ disconnect con1;
connection default; connection default;
SELECT * FROM t1; SELECT * FROM t1;
a b a b
0 NULL
DROP TABLE t1; DROP TABLE t1;
SET DEBUG_SYNC = 'RESET'; SET DEBUG_SYNC = 'RESET';
SET GLOBAL innodb_file_per_table = @global_innodb_file_per_table_orig; SET GLOBAL innodb_file_per_table = @global_innodb_file_per_table_orig;

View File

@@ -171,6 +171,7 @@ connect stop_purge,localhost,root;
START TRANSACTION WITH CONSISTENT SNAPSHOT; START TRANSACTION WITH CONSISTENT SNAPSHOT;
connect ddl,localhost,root,,test; connect ddl,localhost,root,,test;
DELETE FROM t1; DELETE FROM t1;
INSERT INTO t1 VALUES(1, 2);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
ALTER TABLE t1 FORCE; ALTER TABLE t1 FORCE;
connection default; connection default;
@@ -206,10 +207,11 @@ DELETE FROM t1;
connection ddl; connection ddl;
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
ALTER TABLE t1 FORCE; ALTER TABLE t1 FORCE;
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR copied';
connection stop_purge; connection stop_purge;
COMMIT; COMMIT;
connection default; connection default;
SET DEBUG_SYNC = 'now WAIT_FOR copied';
InnoDB 1 transactions not purged InnoDB 1 transactions not purged
INSERT INTO t1 SET a=1; INSERT INTO t1 SET a=1;
INSERT INTO t1 SET a=2,b=3,c=4; INSERT INTO t1 SET a=2,b=3,c=4;
@@ -229,9 +231,9 @@ DELETE FROM t1;
connection ddl; connection ddl;
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
ALTER TABLE t1 ADD COLUMN b INT NOT NULL DEFAULT 2 AFTER a, FORCE; ALTER TABLE t1 ADD COLUMN b INT NOT NULL DEFAULT 2 AFTER a, FORCE;
disconnect stop_purge;
connection default; connection default;
SET DEBUG_SYNC = 'now WAIT_FOR copied'; SET DEBUG_SYNC = 'now WAIT_FOR copied';
disconnect stop_purge;
InnoDB 1 transactions not purged InnoDB 1 transactions not purged
INSERT INTO t1 SET a=1; INSERT INTO t1 SET a=1;
INSERT INTO t1 SET a=2,c=4; INSERT INTO t1 SET a=2,c=4;
@@ -449,6 +451,7 @@ DROP TABLE t1;
CREATE TABLE t1 CREATE TABLE t1
(a INT NOT NULL, b INT, c INT, d INT, e INT, f INT, g INT, h INT, i TEXT) (a INT NOT NULL, b INT, c INT, d INT, e INT, f INT, g INT, h INT, i TEXT)
ENGINE=InnoDB; ENGINE=InnoDB;
INSERT INTO t1 VALUES(1, 2, 3, 4, 5, 6, 7, 8, "test");
ALTER TABLE t1 MODIFY a INT NULL; ALTER TABLE t1 MODIFY a INT NULL;
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL alter WAIT_FOR go'; SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL alter WAIT_FOR go';
ALTER TABLE t1 ADD PRIMARY KEY (a); ALTER TABLE t1 ADD PRIMARY KEY (a);
@@ -462,6 +465,7 @@ connection default;
disconnect con1; disconnect con1;
SELECT * FROM t1; SELECT * FROM t1;
a b c d e f g h i a b c d e f g h i
1 2 3 4 5 6 7 8 test
DROP TABLE t1; DROP TABLE t1;
SET DEBUG_SYNC=RESET; SET DEBUG_SYNC=RESET;
# End of 10.4 tests # End of 10.4 tests

View File

@@ -24,6 +24,7 @@ CREATE TABLE t1(f1 INT, f2 INT,
PRIMARY KEY(f1, f2), PRIMARY KEY(f1, f2),
UNIQUE INDEX uidx2 (f1, f2), UNIQUE INDEX uidx2 (f1, f2),
UNIQUE INDEX uidx1 (f2))ENGINE=InnoDB; UNIQUE INDEX uidx1 (f2))ENGINE=InnoDB;
INSERT INTO t1 VALUES(2, 2);
ALTER TABLE t1 DROP PRIMARY KEY; ALTER TABLE t1 DROP PRIMARY KEY;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter
@@ -42,9 +43,7 @@ DROP TABLE t1;
SET SQL_MODE= strict_trans_tables; SET SQL_MODE= strict_trans_tables;
CREATE TABLE t1(a INT UNIQUE) ENGINE=InnoDB; CREATE TABLE t1(a INT UNIQUE) ENGINE=InnoDB;
# MDEV-515 takes X-lock on the table for the first insert. INSERT INTO t1 VALUES(1);
# So concurrent insert won't happen on the table
INSERT INTO t1 VALUES(3);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL dml WAIT_FOR dml_done'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL dml WAIT_FOR dml_done';
--send ALTER TABLE t1 MODIFY COLUMN a INT NOT NULL --send ALTER TABLE t1 MODIFY COLUMN a INT NOT NULL
connection con1; connection con1;

View File

@@ -75,7 +75,7 @@ SET DEBUG_SYNC='RESET';
--echo # --echo #
CREATE TABLE t1 (f VARCHAR(8) CHARACTER SET latin1 COLLATE latin1_swedish_ci) CREATE TABLE t1 (f VARCHAR(8) CHARACTER SET latin1 COLLATE latin1_swedish_ci)
ENGINE=InnoDB; ENGINE=InnoDB;
INSERT INTO t1 VALUES('ZERO');
connection con1; connection con1;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done'; SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done';
send ALTER TABLE t1 MODIFY f VARCHAR(256) COLLATE latin1_german2_ci NOT NULL; send ALTER TABLE t1 MODIFY f VARCHAR(256) COLLATE latin1_german2_ci NOT NULL;

View File

@@ -9,6 +9,7 @@
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (c CHAR(2) NOT NULL) ENGINE=InnoDB; CREATE TABLE t1 (c CHAR(2) NOT NULL) ENGINE=InnoDB;
INSERT INTO t1 VALUES('cd');
connect (con1,localhost,root,,); connect (con1,localhost,root,,);
BEGIN; BEGIN;

View File

@@ -7,6 +7,9 @@ CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=InnoDB;
# MDEV-515 takes X-lock on the table for the first insert. # MDEV-515 takes X-lock on the table for the first insert.
# So concurrent insert won't happen on the table # So concurrent insert won't happen on the table
INSERT INTO t0 VALUES(100); INSERT INTO t0 VALUES(100);
INSERT INTO t1 VALUES(100, 100);
--connect (con1,localhost,root,,test) --connect (con1,localhost,root,,test)
BEGIN; BEGIN;
INSERT INTO t0 SET pk=1; INSERT INTO t0 SET pk=1;

View File

@@ -79,7 +79,7 @@ BEGIN;
DELETE FROM mysql.innodb_table_stats; DELETE FROM mysql.innodb_table_stats;
connect (con2,localhost,root,,); connect (con2,localhost,root,,);
SET DEBUG_SYNC='inplace_after_index_build SIGNAL blocked WAIT_FOR ever'; SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL blocked WAIT_FOR ever';
send ALTER TABLE t1 FORCE; send ALTER TABLE t1 FORCE;
connection default; connection default;

View File

@@ -96,6 +96,7 @@ drop table t1;
# Log file creation failure. # Log file creation failure.
create table t1(k1 int auto_increment primary key, create table t1(k1 int auto_increment primary key,
k2 char(200),k3 char(200))engine=innodb; k2 char(200),k3 char(200))engine=innodb;
INSERT INTO t1 VALUES(1, "test", "test");
SET DEBUG_SYNC= 'row_merge_after_scan SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed'; SIGNAL opened WAIT_FOR flushed';
send ALTER TABLE t1 FORCE, ADD COLUMN k4 int; send ALTER TABLE t1 FORCE, ADD COLUMN k4 int;
@@ -122,6 +123,7 @@ drop table t480;
--echo # --echo #
CREATE TABLE t1 (j INT UNIQUE, i INT UNIQUE) ENGINE=InnoDB; CREATE TABLE t1 (j INT UNIQUE, i INT UNIQUE) ENGINE=InnoDB;
INSERT INTO t1 VALUES(2, 2);
--connect (con1,localhost,root,,test) --connect (con1,localhost,root,,test)
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL built WAIT_FOR log'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL built WAIT_FOR log';
--send --send

View File

@@ -475,6 +475,7 @@ DROP TABLE t1;
--echo # MDEV-13205 assertion !dict_index_is_online_ddl(index) upon ALTER TABLE --echo # MDEV-13205 assertion !dict_index_is_online_ddl(index) upon ALTER TABLE
--echo # --echo #
CREATE TABLE t1 (c VARCHAR(64)) ENGINE=InnoDB; CREATE TABLE t1 (c VARCHAR(64)) ENGINE=InnoDB;
INSERT INTO t1 VALUES('foo');
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL t1u_created WAIT_FOR dup_done'; SET DEBUG_SYNC = 'row_log_apply_before SIGNAL t1u_created WAIT_FOR dup_done';
send ALTER TABLE t1 ADD UNIQUE(c); send ALTER TABLE t1 ADD UNIQUE(c);
@@ -497,6 +498,7 @@ ALTER TABLE t2 ADD FOREIGN KEY (c) REFERENCES t1 (c);
DROP TABLE t2,t1; DROP TABLE t2,t1;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES(0,0);
connect (con1,localhost,root,,); connect (con1,localhost,root,,);
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL created WAIT_FOR inserted'; SET DEBUG_SYNC = 'row_log_apply_before SIGNAL created WAIT_FOR inserted';

View File

@@ -395,6 +395,7 @@ SET GLOBAL innodb_monitor_disable = module_ddl;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (a INT PRIMARY KEY, b blob) ENGINE=InnoDB; CREATE TABLE t1 (a INT PRIMARY KEY, b blob) ENGINE=InnoDB;
INSERT INTO t1 VALUES(0,NULL);
connection con1; connection con1;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL created WAIT_FOR ins'; SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL created WAIT_FOR ins';

View File

@@ -186,6 +186,7 @@ connect stop_purge,localhost,root;
START TRANSACTION WITH CONSISTENT SNAPSHOT; START TRANSACTION WITH CONSISTENT SNAPSHOT;
connect ddl,localhost,root,,test; connect ddl,localhost,root,,test;
DELETE FROM t1; DELETE FROM t1;
INSERT INTO t1 VALUES(1, 2);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
send ALTER TABLE t1 FORCE; send ALTER TABLE t1 FORCE;
connection default; connection default;
@@ -236,11 +237,11 @@ connection ddl;
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
send ALTER TABLE t1 FORCE; send ALTER TABLE t1 FORCE;
connection stop_purge;
COMMIT;
connection default; connection default;
SET DEBUG_SYNC = 'now WAIT_FOR copied'; SET DEBUG_SYNC = 'now WAIT_FOR copied';
connection stop_purge;
COMMIT;
connection default;
let $wait_all_purged = 1; let $wait_all_purged = 1;
--source include/wait_all_purged.inc --source include/wait_all_purged.inc
let $wait_all_purged = 0; let $wait_all_purged = 0;
@@ -265,10 +266,9 @@ connection ddl;
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
send ALTER TABLE t1 ADD COLUMN b INT NOT NULL DEFAULT 2 AFTER a, FORCE; send ALTER TABLE t1 ADD COLUMN b INT NOT NULL DEFAULT 2 AFTER a, FORCE;
disconnect stop_purge;
connection default; connection default;
SET DEBUG_SYNC = 'now WAIT_FOR copied'; SET DEBUG_SYNC = 'now WAIT_FOR copied';
disconnect stop_purge;
let $wait_all_purged = 1; let $wait_all_purged = 1;
--source include/wait_all_purged.inc --source include/wait_all_purged.inc
let $wait_all_purged = 0; let $wait_all_purged = 0;
@@ -519,7 +519,7 @@ DROP TABLE t1;
CREATE TABLE t1 CREATE TABLE t1
(a INT NOT NULL, b INT, c INT, d INT, e INT, f INT, g INT, h INT, i TEXT) (a INT NOT NULL, b INT, c INT, d INT, e INT, f INT, g INT, h INT, i TEXT)
ENGINE=InnoDB; ENGINE=InnoDB;
INSERT INTO t1 VALUES(1, 2, 3, 4, 5, 6, 7, 8, "test");
ALTER TABLE t1 MODIFY a INT NULL; ALTER TABLE t1 MODIFY a INT NULL;
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL alter WAIT_FOR go'; SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL alter WAIT_FOR go';

View File

@@ -31,6 +31,7 @@ SET SESSION debug_dbug=@saved_debug_dbug;
# MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX # MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX
# #
CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB; CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1, "test", "test_1");
connect con1,localhost,root,,test; connect con1,localhost,root,,test;
SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter"; SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter";
SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2'; SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2';
@@ -40,6 +41,7 @@ SET DEBUG_SYNC='now WAIT_FOR s2';
START TRANSACTION; START TRANSACTION;
SELECT * FROM t1; SELECT * FROM t1;
a b c a b c
1 test test_1
SET DEBUG_SYNC='now SIGNAL g2'; SET DEBUG_SYNC='now SIGNAL g2';
connection con1; connection con1;
ERROR HY000: Out of memory. ERROR HY000: Out of memory.

View File

@@ -60,6 +60,7 @@ SET SESSION debug_dbug=@saved_debug_dbug;
--echo # MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX --echo # MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX
--echo # --echo #
CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB; CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1, "test", "test_1");
connect(con1,localhost,root,,test); connect(con1,localhost,root,,test);
SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter"; SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter";
SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2'; SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2';

View File

@@ -18,7 +18,7 @@ INNODB_BUFFER_PAGE CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE` (
`DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0, `DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0,
`COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0, `COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0,
`PAGE_STATE` enum('NOT_USED','MEMORY','REMOVE_HASH','FILE_PAGE') NOT NULL, `PAGE_STATE` enum('NOT_USED','MEMORY','REMOVE_HASH','FILE_PAGE') NOT NULL,
`IO_FIX` enum('IO_NONE','IO_READ','IO_WRITE','IO_PIN') NOT NULL, `IO_FIX` enum('IO_NONE','IO_READ','IO_WRITE') NOT NULL,
`IS_OLD` int(1) NOT NULL DEFAULT 0, `IS_OLD` int(1) NOT NULL DEFAULT 0,
`FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT 0 `FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT 0
) ENGINE=MEMORY DEFAULT CHARSET=utf8mb3 ) ENGINE=MEMORY DEFAULT CHARSET=utf8mb3

View File

@@ -18,7 +18,7 @@ INNODB_BUFFER_PAGE_LRU CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE_LRU` (
`DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0, `DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0,
`COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0, `COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0,
`COMPRESSED` int(1) NOT NULL DEFAULT 0, `COMPRESSED` int(1) NOT NULL DEFAULT 0,
`IO_FIX` enum('IO_NONE','IO_READ','IO_WRITE','IO_PIN') NOT NULL, `IO_FIX` enum('IO_NONE','IO_READ','IO_WRITE') NOT NULL,
`IS_OLD` int(1) DEFAULT NULL, `IS_OLD` int(1) DEFAULT NULL,
`FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT 0 `FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT 0
) ENGINE=MEMORY DEFAULT CHARSET=utf8mb3 ) ENGINE=MEMORY DEFAULT CHARSET=utf8mb3

View File

@@ -0,0 +1,29 @@
include/master-slave.inc
[connection master]
connection slave;
SET @qtype= @@global.query_cache_type;
SET GLOBAL query_cache_type= ON;
SET query_cache_type= ON;
connection master;
create table t1 (i int) engine=innodb;
insert into t1 set i=1;
connection slave;
select * from t1;
i
1
connection master;
insert into t1 set i=2;
connection slave;
select * from t1;
i
1
2
select sql_no_cache * from t1;
i
1
2
connection master;
DROP TABLE t1;
connection slave;
SET GLOBAL query_cache_type= @qtype;
include/rpl_end.inc

View File

@@ -0,0 +1,27 @@
-- source include/have_binlog_format_row.inc
-- source include/have_innodb.inc
-- source include/master-slave.inc
--connection slave
SET @qtype= @@global.query_cache_type;
SET GLOBAL query_cache_type= ON;
SET query_cache_type= ON;
--connection master
create table t1 (i int) engine=innodb;
insert into t1 set i=1;
--sync_slave_with_master
select * from t1;
--connection master
insert into t1 set i=2;
--sync_slave_with_master
select * from t1;
select sql_no_cache * from t1;
--connection master
DROP TABLE t1;
--sync_slave_with_master
SET GLOBAL query_cache_type= @qtype;
--source include/rpl_end.inc

View File

@@ -2625,6 +2625,9 @@ public:
/** true when InnoDB should abort the alter when table is not empty */ /** true when InnoDB should abort the alter when table is not empty */
const bool error_if_not_empty; const bool error_if_not_empty;
/** True when DDL should avoid downgrading the MDL */
bool mdl_exclusive_after_prepare= false;
Alter_inplace_info(HA_CREATE_INFO *create_info_arg, Alter_inplace_info(HA_CREATE_INFO *create_info_arg,
Alter_info *alter_info_arg, Alter_info *alter_info_arg,
KEY *key_info_arg, uint key_count_arg, KEY *key_info_arg, uint key_count_arg,

View File

@@ -5621,14 +5621,16 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
} }
} }
#if defined(WITH_WSREP) && defined(HAVE_QUERY_CACHE) #ifdef HAVE_QUERY_CACHE
/* /*
Moved invalidation right before the call to rows_event_stmt_cleanup(), Moved invalidation right before the call to rows_event_stmt_cleanup(),
to avoid query cache being polluted with stale entries, to avoid query cache being polluted with stale entries,
*/ */
if (WSREP(thd) && wsrep_thd_is_applying(thd)) # ifdef WITH_WSREP
if (!WSREP(thd) && !wsrep_thd_is_applying(thd))
# endif /* WITH_WSREP */
query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock); query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock);
#endif /* WITH_WSREP && HAVE_QUERY_CACHE */ #endif /* HAVE_QUERY_CACHE */
} }
table= m_table= rgi->m_table_map.get_table(m_table_id); table= m_table= rgi->m_table_map.get_table(m_table_id);

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2014, 2020, MariaDB Corporation. /* Copyright (C) 2014, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@@ -18,6 +18,14 @@
#include "sql_string.h" #include "sql_string.h"
#include "my_json_writer.h" #include "my_json_writer.h"
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
bool Json_writer::named_item_expected() const
{
return named_items_expectation.size()
&& named_items_expectation.back();
}
#endif
void Json_writer::append_indent() void Json_writer::append_indent()
{ {
if (!document_start) if (!document_start)
@@ -26,9 +34,21 @@ void Json_writer::append_indent()
output.append(' '); output.append(' ');
} }
inline void Json_writer::on_start_object()
{
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
if(!fmt_helper.is_making_writer_calls())
{
VALIDITY_ASSERT(got_name == named_item_expected());
named_items_expectation.push_back(true);
}
#endif
fmt_helper.on_start_object();
}
void Json_writer::start_object() void Json_writer::start_object()
{ {
fmt_helper.on_start_object(); on_start_object();
if (!element_started) if (!element_started)
start_element(); start_element();
@@ -38,10 +58,22 @@ void Json_writer::start_object()
first_child=true; first_child=true;
element_started= false; element_started= false;
document_start= false; document_start= false;
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
got_name= false;
#endif
} }
void Json_writer::start_array() void Json_writer::start_array()
{ {
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
if(!fmt_helper.is_making_writer_calls())
{
VALIDITY_ASSERT(got_name == named_item_expected());
named_items_expectation.push_back(false);
got_name= false;
}
#endif
if (fmt_helper.on_start_array()) if (fmt_helper.on_start_array())
return; return;
@@ -58,6 +90,12 @@ void Json_writer::start_array()
void Json_writer::end_object() void Json_writer::end_object()
{ {
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
VALIDITY_ASSERT(named_item_expected());
named_items_expectation.pop_back();
VALIDITY_ASSERT(!got_name);
got_name= false;
#endif
indent_level-=INDENT_SIZE; indent_level-=INDENT_SIZE;
if (!first_child) if (!first_child)
append_indent(); append_indent();
@@ -68,6 +106,11 @@ void Json_writer::end_object()
void Json_writer::end_array() void Json_writer::end_array()
{ {
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
VALIDITY_ASSERT(!named_item_expected());
named_items_expectation.pop_back();
got_name= false;
#endif
if (fmt_helper.on_end_array()) if (fmt_helper.on_end_array())
return; return;
indent_level-=INDENT_SIZE; indent_level-=INDENT_SIZE;
@@ -80,31 +123,25 @@ void Json_writer::end_array()
Json_writer& Json_writer::add_member(const char *name) Json_writer& Json_writer::add_member(const char *name)
{ {
size_t len= strlen(name); size_t len= strlen(name);
if (fmt_helper.on_add_member(name, len)) return add_member(name, len);
return *this; // handled
// assert that we are in an object
DBUG_ASSERT(!element_started);
start_element();
output.append('"');
output.append(name, len);
output.append("\": ", 3);
return *this;
} }
Json_writer& Json_writer::add_member(const char *name, size_t len) Json_writer& Json_writer::add_member(const char *name, size_t len)
{ {
if (fmt_helper.on_add_member(name, len)) if (!fmt_helper.on_add_member(name, len))
return *this; // handled {
// assert that we are in an object
DBUG_ASSERT(!element_started);
start_element();
// assert that we are in an object output.append('"');
DBUG_ASSERT(!element_started); output.append(name, len);
start_element(); output.append(STRING_WITH_LEN("\": "));
}
output.append('"'); #if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
output.append(name, len); if (!fmt_helper.is_making_writer_calls())
output.append(STRING_WITH_LEN("\": ")); got_name= true;
#endif
return *this; return *this;
} }
@@ -200,7 +237,14 @@ void Json_writer::add_null()
void Json_writer::add_unquoted_str(const char* str) void Json_writer::add_unquoted_str(const char* str)
{ {
size_t len= strlen(str); size_t len= strlen(str);
if (fmt_helper.on_add_str(str, len)) add_unquoted_str(str, len);
}
void Json_writer::add_unquoted_str(const char* str, size_t len)
{
VALIDITY_ASSERT(fmt_helper.is_making_writer_calls() ||
got_name == named_item_expected());
if (on_add_str(str, len))
return; return;
if (!element_started) if (!element_started)
@@ -210,31 +254,19 @@ void Json_writer::add_unquoted_str(const char* str)
element_started= false; element_started= false;
} }
void Json_writer::add_unquoted_str(const char* str, size_t len) inline bool Json_writer::on_add_str(const char *str, size_t num_bytes)
{ {
if (fmt_helper.on_add_str(str, len)) #if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
return; got_name= false;
#endif
if (!element_started) bool helped= fmt_helper.on_add_str(str, num_bytes);
start_element(); return helped;
output.append(str, len);
element_started= false;
} }
void Json_writer::add_str(const char *str) void Json_writer::add_str(const char *str)
{ {
size_t len= strlen(str); size_t len= strlen(str);
if (fmt_helper.on_add_str(str, len)) add_str(str, len);
return;
if (!element_started)
start_element();
output.append('"');
output.append(str, len);
output.append('"');
element_started= false;
} }
/* /*
@@ -243,7 +275,9 @@ void Json_writer::add_str(const char *str)
void Json_writer::add_str(const char* str, size_t num_bytes) void Json_writer::add_str(const char* str, size_t num_bytes)
{ {
if (fmt_helper.on_add_str(str, num_bytes)) VALIDITY_ASSERT(fmt_helper.is_making_writer_calls() ||
got_name == named_item_expected());
if (on_add_str(str, num_bytes))
return; return;
if (!element_started) if (!element_started)

View File

@@ -17,9 +17,20 @@
#define JSON_WRITER_INCLUDED #define JSON_WRITER_INCLUDED
#include "my_base.h" #include "my_base.h"
#include "sql_select.h"
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST) || defined ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
#include <vector> #include <vector>
#endif
#ifdef JSON_WRITER_UNIT_TEST
#include "sql_string.h"
constexpr uint FAKE_SELECT_LEX_ID= UINT_MAX;
// Also, mock objects are defined in my_json_writer-t.cc
#define VALIDITY_ASSERT(x) if (!(x)) this->invalid_json= true;
#else
#include "sql_select.h"
#define VALIDITY_ASSERT(x) DBUG_ASSERT(x)
#endif
class Opt_trace_stmt; class Opt_trace_stmt;
class Opt_trace_context; class Opt_trace_context;
@@ -99,6 +110,15 @@ public:
bool on_add_str(const char *str, size_t num_bytes); bool on_add_str(const char *str, size_t num_bytes);
/*
Returns true if the helper is flushing its buffer and is probably
making calls back to its Json_writer. (The Json_writer uses this
function to avoid re-doing the processing that it has already done
before making a call to fmt_helper)
*/
bool is_making_writer_calls() const { return state == DISABLED; }
private:
void flush_on_one_line(); void flush_on_one_line();
void disable_and_flush(); void disable_and_flush();
}; };
@@ -185,6 +205,25 @@ private:
class Json_writer class Json_writer
{ {
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
/*
In debug mode, Json_writer will fail and assertion if one attempts to
produce an invalid JSON document (e.g. JSON array having named elements).
*/
std::vector<bool> named_items_expectation;
bool named_item_expected() const;
bool got_name;
#ifdef JSON_WRITER_UNIT_TEST
public:
// When compiled for unit test, creating invalid JSON will set this to true
// instead of an assertion.
bool invalid_json= false;
#endif
#endif
public: public:
/* Add a member. We must be in an object. */ /* Add a member. We must be in an object. */
Json_writer& add_member(const char *name); Json_writer& add_member(const char *name);
@@ -208,6 +247,10 @@ public:
private: private:
void add_unquoted_str(const char* val); void add_unquoted_str(const char* val);
void add_unquoted_str(const char* val, size_t len); void add_unquoted_str(const char* val, size_t len);
bool on_add_str(const char *str, size_t num_bytes);
void on_start_object();
public: public:
/* Start a child object */ /* Start a child object */
void start_object(); void start_object();
@@ -225,6 +268,9 @@ public:
size_t get_truncated_bytes() { return output.get_truncated_bytes(); } size_t get_truncated_bytes() { return output.get_truncated_bytes(); }
Json_writer() : Json_writer() :
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
got_name(false),
#endif
indent_level(0), document_start(true), element_started(false), indent_level(0), document_start(true), element_started(false),
first_child(true) first_child(true)
{ {
@@ -312,6 +358,9 @@ public:
/* A common base for Json_writer_object and Json_writer_array */ /* A common base for Json_writer_object and Json_writer_array */
class Json_writer_struct class Json_writer_struct
{ {
Json_writer_struct(const Json_writer_struct&)= delete;
Json_writer_struct& operator=(const Json_writer_struct&)= delete;
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS #ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
static thread_local std::vector<bool> named_items_expectation; static thread_local std::vector<bool> named_items_expectation;
#endif #endif
@@ -372,24 +421,18 @@ private:
my_writer->add_member(name); my_writer->add_member(name);
} }
public: public:
explicit Json_writer_object(THD *thd) explicit Json_writer_object(THD* thd, const char *str= nullptr)
: Json_writer_struct(thd, true)
{
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
DBUG_ASSERT(!named_item_expected());
#endif
if (unlikely(my_writer))
my_writer->start_object();
}
explicit Json_writer_object(THD* thd, const char *str)
: Json_writer_struct(thd, true) : Json_writer_struct(thd, true)
{ {
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS #ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
DBUG_ASSERT(named_item_expected()); DBUG_ASSERT(named_item_expected());
#endif #endif
if (unlikely(my_writer)) if (unlikely(my_writer))
my_writer->add_member(str).start_object(); {
if (str)
my_writer->add_member(str);
my_writer->start_object();
}
} }
~Json_writer_object() ~Json_writer_object()

View File

@@ -7655,7 +7655,7 @@ static int mysql_init_variables(void)
disable_log_notes= 0; disable_log_notes= 0;
mqh_used= 0; mqh_used= 0;
cleanup_done= 0; cleanup_done= 0;
test_flags= select_errors= dropping_tables= ha_open_options=0; select_errors= dropping_tables= ha_open_options=0;
THD_count::count= CONNECT::count= 0; THD_count::count= CONNECT::count= 0;
slave_open_temp_tables= 0; slave_open_temp_tables= 0;
opt_endinfo= using_udf_functions= 0; opt_endinfo= using_udf_functions= 0;

View File

@@ -370,7 +370,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
double read_time); double read_time);
static static
TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
double read_time); double read_time, bool named_trace= false);
static static
TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge, TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge,
TRP_INDEX_MERGE *imerge_trp, TRP_INDEX_MERGE *imerge_trp,
@@ -5084,7 +5084,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
static static
TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
double read_time) double read_time, bool named_trace)
{ {
SEL_TREE **ptree; SEL_TREE **ptree;
TRP_INDEX_MERGE *imerge_trp= NULL; TRP_INDEX_MERGE *imerge_trp= NULL;
@@ -5132,7 +5132,8 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
n_child_scans))) n_child_scans)))
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
Json_writer_object trace_best_disjunct(thd); const char* trace_best_disjunct_obj_name= named_trace ? "best_disjunct_quick" : nullptr;
Json_writer_object trace_best_disjunct(thd, trace_best_disjunct_obj_name);
Json_writer_array to_merge(thd, "indexes_to_merge"); Json_writer_array to_merge(thd, "indexes_to_merge");
/* /*
Collect best 'range' scan for each of disjuncts, and, while doing so, Collect best 'range' scan for each of disjuncts, and, while doing so,
@@ -5488,7 +5489,7 @@ TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge,
DBUG_ASSERT(imerge->trees_next>imerge->trees); DBUG_ASSERT(imerge->trees_next>imerge->trees);
if (imerge->trees_next-imerge->trees > 1) if (imerge->trees_next-imerge->trees > 1)
trp= get_best_disjunct_quick(param, imerge, read_time); trp= get_best_disjunct_quick(param, imerge, read_time, true);
else else
{ {
/* /*
@@ -5676,7 +5677,7 @@ void print_keyparts(THD *thd, KEY *key, uint key_parts)
DBUG_ASSERT(thd->trace_started()); DBUG_ASSERT(thd->trace_started());
KEY_PART_INFO *part= key->key_part; KEY_PART_INFO *part= key->key_part;
Json_writer_array keyparts= Json_writer_array(thd, "keyparts"); Json_writer_array keyparts(thd, "keyparts");
for(uint i= 0; i < key_parts; i++, part++) for(uint i= 0; i < key_parts; i++, part++)
keyparts.add(part->field->field_name); keyparts.add(part->field->field_name);
} }

View File

@@ -3839,9 +3839,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
Json_writer_array semijoin_plan(thd, "join_order"); Json_writer_array semijoin_plan(thd, "join_order");
for (i= first + sjm->tables; i <= tablenr; i++) for (i= first + sjm->tables; i <= tablenr; i++)
{ {
Json_writer_object trace_one_table(thd);
if (unlikely(thd->trace_started())) if (unlikely(thd->trace_started()))
{ {
Json_writer_object trace_one_table(thd);
trace_one_table.add_table_name(join->best_positions[i].table); trace_one_table.add_table_name(join->best_positions[i].table);
} }
best_access_path(join, join->best_positions[i].table, rem_tables, best_access_path(join, join->best_positions[i].table, rem_tables,
@@ -3878,9 +3878,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
Json_writer_array semijoin_plan(thd, "join_order"); Json_writer_array semijoin_plan(thd, "join_order");
for (idx= first; idx <= tablenr; idx++) for (idx= first; idx <= tablenr; idx++)
{ {
Json_writer_object trace_one_table(thd);
if (unlikely(thd->trace_started())) if (unlikely(thd->trace_started()))
{ {
Json_writer_object trace_one_table(thd);
trace_one_table.add_table_name(join->best_positions[idx].table); trace_one_table.add_table_name(join->best_positions[idx].table);
} }
if (join->best_positions[idx].use_join_buffer) if (join->best_positions[idx].use_join_buffer)
@@ -3917,9 +3917,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
Json_writer_array semijoin_plan(thd, "join_order"); Json_writer_array semijoin_plan(thd, "join_order");
for (idx= first; idx <= tablenr; idx++) for (idx= first; idx <= tablenr; idx++)
{ {
Json_writer_object trace_one_table(thd);
if (unlikely(thd->trace_started())) if (unlikely(thd->trace_started()))
{ {
Json_writer_object trace_one_table(thd);
trace_one_table.add_table_name(join->best_positions[idx].table); trace_one_table.add_table_name(join->best_positions[idx].table);
} }
if (join->best_positions[idx].use_join_buffer || (idx == first)) if (join->best_positions[idx].use_join_buffer || (idx == first))

View File

@@ -1048,6 +1048,15 @@ st_select_lex_unit *With_element::clone_parsed_spec(LEX *old_lex,
lex_start(thd); lex_start(thd);
lex->clone_spec_offset= unparsed_spec_offset; lex->clone_spec_offset= unparsed_spec_offset;
lex->with_cte_resolution= true; lex->with_cte_resolution= true;
/*
There's no need to add SPs/SFs referenced in the clone to the global
list of the SPs/SFs used in the query as they were added when the first
reference to the cloned CTE was parsed. Yet the recursive call of the
parser must to know that they were already included into the list.
*/
lex->sroutines= old_lex->sroutines;
lex->sroutines_list_own_last= old_lex->sroutines_list_own_last;
lex->sroutines_list_own_elements= old_lex->sroutines_list_own_elements;
/* /*
The specification of a CTE is to be parsed as a regular query. The specification of a CTE is to be parsed as a regular query.
@@ -1092,6 +1101,29 @@ st_select_lex_unit *With_element::clone_parsed_spec(LEX *old_lex,
if (parse_status) if (parse_status)
goto err; goto err;
/*
The unit of the specification that just has been parsed is included
as a slave of the select that contained in its from list the table
reference for which the unit has been created.
*/
lex->unit.include_down(with_table->select_lex);
lex->unit.set_slave(with_select);
lex->unit.cloned_from= spec;
/*
Now all references to the CTE defined outside of the cloned specification
has to be resolved. Additionally if old_lex->only_cte_resolution == false
for the table references that has not been resolved requests for mdl_locks
has to be set.
*/
lex->only_cte_resolution= old_lex->only_cte_resolution;
if (lex->resolve_references_to_cte(lex->query_tables,
lex->query_tables_last))
{
res= NULL;
goto err;
}
/* /*
The global chain of TABLE_LIST objects created for the specification that The global chain of TABLE_LIST objects created for the specification that
just has been parsed is added to such chain that contains the reference just has been parsed is added to such chain that contains the reference
@@ -1116,32 +1148,11 @@ st_select_lex_unit *With_element::clone_parsed_spec(LEX *old_lex,
old_lex->query_tables_last= lex->query_tables_last; old_lex->query_tables_last= lex->query_tables_last;
} }
} }
old_lex->sroutines_list_own_last= lex->sroutines_list_own_last;
old_lex->sroutines_list_own_elements= lex->sroutines_list_own_elements;
res= &lex->unit; res= &lex->unit;
res->with_element= this; res->with_element= this;
/*
The unit of the specification that just has been parsed is included
as a slave of the select that contained in its from list the table
reference for which the unit has been created.
*/
lex->unit.include_down(with_table->select_lex);
lex->unit.set_slave(with_select);
lex->unit.cloned_from= spec;
/*
Now all references to the CTE defined outside of the cloned specification
has to be resolved. Additionally if old_lex->only_cte_resolution == false
for the table references that has not been resolved requests for mdl_locks
has to be set.
*/
lex->only_cte_resolution= old_lex->only_cte_resolution;
if (lex->resolve_references_to_cte(lex->query_tables,
lex->query_tables_last))
{
res= NULL;
goto err;
}
last_clone_select= lex->all_selects_list; last_clone_select= lex->all_selects_list;
while (last_clone_select->next_select_in_list()) while (last_clone_select->next_select_in_list())
last_clone_select= last_clone_select->next_select_in_list(); last_clone_select= last_clone_select->next_select_in_list();

View File

@@ -7346,15 +7346,16 @@ static bool mysql_inplace_alter_table(THD *thd,
lock for prepare phase under LOCK TABLES in the same way as when lock for prepare phase under LOCK TABLES in the same way as when
exclusive lock is required for duration of the whole statement. exclusive lock is required for duration of the whole statement.
*/ */
if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK || if (!ha_alter_info->mdl_exclusive_after_prepare &&
((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK || (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_COPY_LOCK || inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK || inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK || inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_INSTANT) && inplace_supported == HA_ALTER_INPLACE_INSTANT) &&
(thd->locked_tables_mode == LTM_LOCK_TABLES || (thd->locked_tables_mode == LTM_LOCK_TABLES ||
thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) || thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) ||
alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE) alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE))
{ {
if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
goto cleanup; goto cleanup;

View File

@@ -95,7 +95,6 @@ SET(INNOBASE_SOURCES
include/buf0dblwr.h include/buf0dblwr.h
include/buf0dump.h include/buf0dump.h
include/buf0flu.h include/buf0flu.h
include/buf0flu.ic
include/buf0lru.h include/buf0lru.h
include/buf0rea.h include/buf0rea.h
include/buf0types.h include/buf0types.h

View File

@@ -403,7 +403,7 @@ btr_page_create(
{ {
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
byte *index_id= my_assume_aligned<2>(PAGE_HEADER + PAGE_INDEX_ID + byte *index_id= my_assume_aligned<2>(PAGE_HEADER + PAGE_INDEX_ID +
block->frame); block->page.frame);
if (UNIV_LIKELY_NULL(page_zip)) if (UNIV_LIKELY_NULL(page_zip))
{ {
@@ -417,16 +417,17 @@ btr_page_create(
{ {
static_assert(((FIL_PAGE_INDEX & 0xff00) | byte(FIL_PAGE_RTREE)) == static_assert(((FIL_PAGE_INDEX & 0xff00) | byte(FIL_PAGE_RTREE)) ==
FIL_PAGE_RTREE, "compatibility"); FIL_PAGE_RTREE, "compatibility");
mtr->write<1>(*block, FIL_PAGE_TYPE + 1 + block->frame, mtr->write<1>(*block, FIL_PAGE_TYPE + 1 + block->page.frame,
byte(FIL_PAGE_RTREE)); byte(FIL_PAGE_RTREE));
if (mach_read_from_8(block->frame + FIL_RTREE_SPLIT_SEQ_NUM)) if (mach_read_from_8(block->page.frame + FIL_RTREE_SPLIT_SEQ_NUM))
mtr->memset(block, FIL_RTREE_SPLIT_SEQ_NUM, 8, 0); mtr->memset(block, FIL_RTREE_SPLIT_SEQ_NUM, 8, 0);
} }
/* Set the level of the new index page */ /* Set the level of the new index page */
mtr->write<2,mtr_t::MAYBE_NOP>(*block, mtr->write<2,mtr_t::MAYBE_NOP>(*block,
my_assume_aligned<2>(PAGE_HEADER + my_assume_aligned<2>(PAGE_HEADER +
PAGE_LEVEL + PAGE_LEVEL +
block->frame), level); block->page.frame),
level);
mtr->write<8,mtr_t::MAYBE_NOP>(*block, index_id, index->id); mtr->write<8,mtr_t::MAYBE_NOP>(*block, index_id, index->id);
} }
} }
@@ -448,7 +449,7 @@ btr_page_alloc_for_ibuf(
fil_addr_t node_addr = flst_get_first(PAGE_HEADER fil_addr_t node_addr = flst_get_first(PAGE_HEADER
+ PAGE_BTR_IBUF_FREE_LIST + PAGE_BTR_IBUF_FREE_LIST
+ root->frame); + root->page.frame);
ut_a(node_addr.page != FIL_NULL); ut_a(node_addr.page != FIL_NULL);
new_block = buf_page_get( new_block = buf_page_get(
@@ -564,7 +565,7 @@ void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
if (block->index && !block->index->freed()) { if (block->index && !block->index->freed()) {
ut_ad(!blob); ut_ad(!blob);
ut_ad(page_is_leaf(block->frame)); ut_ad(page_is_leaf(block->page.frame));
} }
#endif #endif
const page_id_t id(block->page.id()); const page_id_t id(block->page.id());
@@ -587,7 +588,8 @@ void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
The page will be freed, so previous changes to it by this The page will be freed, so previous changes to it by this
mini-transaction should not matter. */ mini-transaction should not matter. */
page_t* root = btr_root_get(index, mtr); page_t* root = btr_root_get(index, mtr);
fseg_header_t* seg_header = &root[blob || page_is_leaf(block->frame) fseg_header_t* seg_header = &root[blob
|| page_is_leaf(block->page.frame)
? PAGE_HEADER + PAGE_BTR_SEG_LEAF ? PAGE_HEADER + PAGE_BTR_SEG_LEAF
: PAGE_HEADER + PAGE_BTR_SEG_TOP]; : PAGE_HEADER + PAGE_BTR_SEG_TOP];
fil_space_t* space= index->table->space; fil_space_t* space= index->table->space;
@@ -813,13 +815,15 @@ static void btr_free_root(buf_block_t *block, mtr_t *mtr)
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(PAGE_HEADER + PAGE_BTR_SEG_TOP + block->frame, ut_a(btr_root_fseg_validate(PAGE_HEADER + PAGE_BTR_SEG_TOP +
block->page.id().space())); block->page.frame,
block->page.id().space()));
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
/* Free the entire segment in small steps. */ /* Free the entire segment in small steps. */
ut_d(mtr->freeing_tree()); ut_d(mtr->freeing_tree());
while (!fseg_free_step(PAGE_HEADER + PAGE_BTR_SEG_TOP + block->frame, mtr)); while (!fseg_free_step(PAGE_HEADER + PAGE_BTR_SEG_TOP +
block->page.frame, mtr));
} }
MY_ATTRIBUTE((warn_unused_result)) MY_ATTRIBUTE((warn_unused_result))
@@ -841,14 +845,14 @@ buf_block_t *btr_free_root_check(const page_id_t page_id, ulint zip_size,
nullptr, BUF_GET_POSSIBLY_FREED, mtr); nullptr, BUF_GET_POSSIBLY_FREED, mtr);
if (!block); if (!block);
else if (block->page.status == buf_page_t::FREED) else if (block->page.is_freed())
block= nullptr; block= nullptr;
else if (fil_page_index_page_check(block->frame) && else if (fil_page_index_page_check(block->page.frame) &&
index_id == btr_page_get_index_id(block->frame)) index_id == btr_page_get_index_id(block->page.frame))
/* This should be a root page. It should not be possible to /* This should be a root page. It should not be possible to
reassign the same index_id for some other index in the reassign the same index_id for some other index in the
tablespace. */ tablespace. */
ut_ad(!page_has_siblings(block->frame)); ut_ad(!page_has_siblings(block->page.frame));
else else
block= nullptr; block= nullptr;
@@ -864,7 +868,7 @@ static void btr_root_page_init(buf_block_t *block, index_id_t index_id,
dict_index_t *index, mtr_t *mtr) dict_index_t *index, mtr_t *mtr)
{ {
constexpr uint16_t field= PAGE_HEADER + PAGE_INDEX_ID; constexpr uint16_t field= PAGE_HEADER + PAGE_INDEX_ID;
byte *page_index_id= my_assume_aligned<2>(field + block->frame); byte *page_index_id= my_assume_aligned<2>(field + block->page.frame);
/* Create a new index page on the allocated segment page */ /* Create a new index page on the allocated segment page */
if (UNIV_LIKELY_NULL(block->page.zip.data)) if (UNIV_LIKELY_NULL(block->page.zip.data))
@@ -880,14 +884,14 @@ static void btr_root_page_init(buf_block_t *block, index_id_t index_id,
{ {
static_assert(((FIL_PAGE_INDEX & 0xff00) | byte(FIL_PAGE_RTREE)) == static_assert(((FIL_PAGE_INDEX & 0xff00) | byte(FIL_PAGE_RTREE)) ==
FIL_PAGE_RTREE, "compatibility"); FIL_PAGE_RTREE, "compatibility");
mtr->write<1>(*block, FIL_PAGE_TYPE + 1 + block->frame, mtr->write<1>(*block, FIL_PAGE_TYPE + 1 + block->page.frame,
byte(FIL_PAGE_RTREE)); byte(FIL_PAGE_RTREE));
if (mach_read_from_8(block->frame + FIL_RTREE_SPLIT_SEQ_NUM)) if (mach_read_from_8(block->page.frame + FIL_RTREE_SPLIT_SEQ_NUM))
mtr->memset(block, FIL_RTREE_SPLIT_SEQ_NUM, 8, 0); mtr->memset(block, FIL_RTREE_SPLIT_SEQ_NUM, 8, 0);
} }
/* Set the level of the new index page */ /* Set the level of the new index page */
mtr->write<2,mtr_t::MAYBE_NOP>( mtr->write<2,mtr_t::MAYBE_NOP>(
*block, PAGE_HEADER + PAGE_LEVEL + block->frame, 0U); *block, PAGE_HEADER + PAGE_LEVEL + block->page.frame, 0U);
mtr->write<8,mtr_t::MAYBE_NOP>(*block, page_index_id, index_id); mtr->write<8,mtr_t::MAYBE_NOP>(*block, page_index_id, index_id);
} }
} }
@@ -962,7 +966,7 @@ btr_create(
} }
} }
ut_ad(!page_has_siblings(block->frame)); ut_ad(!page_has_siblings(block->page.frame));
btr_root_page_init(block, index_id, index, mtr); btr_root_page_init(block, index_id, index, mtr);
@@ -982,7 +986,7 @@ btr_create(
allowed size fit on the root page: this fact is needed to ensure allowed size fit on the root page: this fact is needed to ensure
correctness of split algorithms */ correctness of split algorithms */
ut_ad(page_get_max_insert_size(block->frame, 2) ut_ad(page_get_max_insert_size(block->page.frame, 2)
> 2 * BTR_PAGE_MAX_REC_SIZE); > 2 * BTR_PAGE_MAX_REC_SIZE);
return(block->page.id().page_no()); return(block->page.id().page_no());
@@ -1004,15 +1008,15 @@ btr_free_but_not_root(
{ {
mtr_t mtr; mtr_t mtr;
ut_ad(fil_page_index_page_check(block->frame)); ut_ad(fil_page_index_page_check(block->page.frame));
ut_ad(!page_has_siblings(block->frame)); ut_ad(!page_has_siblings(block->page.frame));
leaf_loop: leaf_loop:
mtr_start(&mtr); mtr_start(&mtr);
ut_d(mtr.freeing_tree()); ut_d(mtr.freeing_tree());
mtr_set_log_mode(&mtr, log_mode); mtr_set_log_mode(&mtr, log_mode);
mtr.set_named_space_id(block->page.id().space()); mtr.set_named_space_id(block->page.id().space());
page_t* root = block->frame; page_t* root = block->page.frame;
if (!root) { if (!root) {
mtr_commit(&mtr); mtr_commit(&mtr);
@@ -1046,7 +1050,7 @@ top_loop:
mtr_set_log_mode(&mtr, log_mode); mtr_set_log_mode(&mtr, log_mode);
mtr.set_named_space_id(block->page.id().space()); mtr.set_named_space_id(block->page.id().space());
root = block->frame; root = block->page.frame;
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
@@ -1164,7 +1168,7 @@ btr_read_autoinc(dict_index_t* index)
page_id_t(index->table->space_id, index->page), page_id_t(index->table->space_id, index->page),
index->table->space->zip_size(), index->table->space->zip_size(),
RW_S_LATCH, &mtr)) { RW_S_LATCH, &mtr)) {
autoinc = page_get_autoinc(block->frame); autoinc = page_get_autoinc(block->page.frame);
} else { } else {
autoinc = 0; autoinc = 0;
} }
@@ -1197,9 +1201,10 @@ btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no)
index->table->space->zip_size(), index->table->space->zip_size(),
RW_S_LATCH, &mtr); RW_S_LATCH, &mtr);
ib_uint64_t autoinc = block ? page_get_autoinc(block->frame) : 0; ib_uint64_t autoinc = block
? page_get_autoinc(block->page.frame) : 0;
const bool retry = block && autoinc == 0 const bool retry = block && autoinc == 0
&& !page_is_empty(block->frame); && !page_is_empty(block->page.frame);
mtr.commit(); mtr.commit();
if (retry) { if (retry) {
@@ -1259,15 +1264,16 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
ut_ad(!is_buf_block_get_page_zip(block)); ut_ad(!is_buf_block_get_page_zip(block));
btr_assert_not_corrupted(block, index); btr_assert_not_corrupted(block, index);
ut_ad(fil_page_index_page_check(block->frame)); ut_ad(fil_page_index_page_check(block->page.frame));
ut_ad(index->is_dummy || ut_ad(index->is_dummy ||
block->page.id().space() == index->table->space->id); block->page.id().space() == index->table->space->id);
ut_ad(index->is_dummy || block->page.id().page_no() != index->page || ut_ad(index->is_dummy || block->page.id().page_no() != index->page ||
!page_has_siblings(block->frame)); !page_has_siblings(block->page.frame));
buf_block_t *old= buf_block_alloc(); buf_block_t *old= buf_block_alloc();
/* Copy the old page to temporary space */ /* Copy the old page to temporary space */
memcpy_aligned<UNIV_PAGE_SIZE_MIN>(old->frame, block->frame, srv_page_size); memcpy_aligned<UNIV_PAGE_SIZE_MIN>(old->page.frame, block->page.frame,
srv_page_size);
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
@@ -1276,7 +1282,7 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
page_create(block, mtr, index->table->not_redundant()); page_create(block, mtr, index->table->not_redundant());
if (index->is_spatial()) if (index->is_spatial())
block->frame[FIL_PAGE_TYPE + 1]= byte(FIL_PAGE_RTREE); block->page.frame[FIL_PAGE_TYPE + 1]= byte(FIL_PAGE_RTREE);
static_assert(((FIL_PAGE_INDEX & 0xff00) | byte(FIL_PAGE_RTREE)) == static_assert(((FIL_PAGE_INDEX & 0xff00) | byte(FIL_PAGE_RTREE)) ==
FIL_PAGE_RTREE, "compatibility"); FIL_PAGE_RTREE, "compatibility");
@@ -1284,19 +1290,20 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
/* Copy the records from the temporary space to the recreated page; /* Copy the records from the temporary space to the recreated page;
do not copy the lock bits yet */ do not copy the lock bits yet */
page_copy_rec_list_end_no_locks(block, old, page_get_infimum_rec(old->frame), page_copy_rec_list_end_no_locks(block, old,
page_get_infimum_rec(old->page.frame),
index, mtr); index, mtr);
/* Copy the PAGE_MAX_TRX_ID or PAGE_ROOT_AUTO_INC. */ /* Copy the PAGE_MAX_TRX_ID or PAGE_ROOT_AUTO_INC. */
ut_ad(!page_get_max_trx_id(block->frame)); ut_ad(!page_get_max_trx_id(block->page.frame));
memcpy_aligned<8>(PAGE_MAX_TRX_ID + PAGE_HEADER + block->frame, memcpy_aligned<8>(PAGE_MAX_TRX_ID + PAGE_HEADER + block->page.frame,
PAGE_MAX_TRX_ID + PAGE_HEADER + old->frame, 8); PAGE_MAX_TRX_ID + PAGE_HEADER + old->page.frame, 8);
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
if (page_get_max_trx_id(block->frame)) if (page_get_max_trx_id(block->page.frame))
/* PAGE_MAX_TRX_ID must be zero on non-leaf pages other than /* PAGE_MAX_TRX_ID must be zero on non-leaf pages other than
clustered index root pages. */ clustered index root pages. */
ut_ad(dict_index_is_sec_or_ibuf(index) ut_ad(dict_index_is_sec_or_ibuf(index)
? page_is_leaf(block->frame) ? page_is_leaf(block->page.frame)
: block->page.id().page_no() == index->page); : block->page.id().page_no() == index->page);
else else
/* PAGE_MAX_TRX_ID is unused in clustered index pages (other than /* PAGE_MAX_TRX_ID is unused in clustered index pages (other than
@@ -1304,14 +1311,16 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
pages, and in temporary tables. It was always zero-initialized in pages, and in temporary tables. It was always zero-initialized in
page_create(). PAGE_MAX_TRX_ID must be nonzero on page_create(). PAGE_MAX_TRX_ID must be nonzero on
dict_index_is_sec_or_ibuf() leaf pages. */ dict_index_is_sec_or_ibuf() leaf pages. */
ut_ad(index->table->is_temporary() || !page_is_leaf(block->frame) || ut_ad(index->table->is_temporary() || !page_is_leaf(block->page.frame) ||
!dict_index_is_sec_or_ibuf(index)); !dict_index_is_sec_or_ibuf(index));
#endif #endif
const uint16_t data_size1= page_get_data_size(old->frame); const uint16_t data_size1= page_get_data_size(old->page.frame);
const uint16_t data_size2= page_get_data_size(block->frame); const uint16_t data_size2= page_get_data_size(block->page.frame);
const ulint max1= page_get_max_insert_size_after_reorganize(old->frame, 1); const ulint max1=
const ulint max2= page_get_max_insert_size_after_reorganize(block->frame, 1); page_get_max_insert_size_after_reorganize(old->page.frame, 1);
const ulint max2=
page_get_max_insert_size_after_reorganize(block->page.frame, 1);
if (UNIV_UNLIKELY(data_size1 != data_size2 || max1 != max2)) if (UNIV_UNLIKELY(data_size1 != data_size2 || max1 != max2))
ib::fatal() << "Page old data size " << data_size1 ib::fatal() << "Page old data size " << data_size1
@@ -1321,39 +1330,39 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
/* Restore the cursor position. */ /* Restore the cursor position. */
if (pos) if (pos)
cursor->rec = page_rec_get_nth(block->frame, pos); cursor->rec = page_rec_get_nth(block->page.frame, pos);
else else
ut_ad(cursor->rec == page_get_infimum_rec(block->frame)); ut_ad(cursor->rec == page_get_infimum_rec(block->page.frame));
if (block->page.id().page_no() == index->page && if (block->page.id().page_no() == index->page &&
fil_page_get_type(old->frame) == FIL_PAGE_TYPE_INSTANT) fil_page_get_type(old->page.frame) == FIL_PAGE_TYPE_INSTANT)
{ {
/* Preserve the PAGE_INSTANT information. */ /* Preserve the PAGE_INSTANT information. */
ut_ad(index->is_instant()); ut_ad(index->is_instant());
memcpy_aligned<2>(FIL_PAGE_TYPE + block->frame, memcpy_aligned<2>(FIL_PAGE_TYPE + block->page.frame,
FIL_PAGE_TYPE + old->frame, 2); FIL_PAGE_TYPE + old->page.frame, 2);
memcpy_aligned<2>(PAGE_HEADER + PAGE_INSTANT + block->frame, memcpy_aligned<2>(PAGE_HEADER + PAGE_INSTANT + block->page.frame,
PAGE_HEADER + PAGE_INSTANT + old->frame, 2); PAGE_HEADER + PAGE_INSTANT + old->page.frame, 2);
if (!index->table->instant); if (!index->table->instant);
else if (page_is_comp(block->frame)) else if (page_is_comp(block->page.frame))
{ {
memcpy(PAGE_NEW_INFIMUM + block->frame, memcpy(PAGE_NEW_INFIMUM + block->page.frame,
PAGE_NEW_INFIMUM + old->frame, 8); PAGE_NEW_INFIMUM + old->page.frame, 8);
memcpy(PAGE_NEW_SUPREMUM + block->frame, memcpy(PAGE_NEW_SUPREMUM + block->page.frame,
PAGE_NEW_SUPREMUM + old->frame, 8); PAGE_NEW_SUPREMUM + old->page.frame, 8);
} }
else else
{ {
memcpy(PAGE_OLD_INFIMUM + block->frame, memcpy(PAGE_OLD_INFIMUM + block->page.frame,
PAGE_OLD_INFIMUM + old->frame, 8); PAGE_OLD_INFIMUM + old->page.frame, 8);
memcpy(PAGE_OLD_SUPREMUM + block->frame, memcpy(PAGE_OLD_SUPREMUM + block->page.frame,
PAGE_OLD_SUPREMUM + old->frame, 8); PAGE_OLD_SUPREMUM + old->page.frame, 8);
} }
} }
ut_ad(!memcmp(old->frame, block->frame, PAGE_HEADER)); ut_ad(!memcmp(old->page.frame, block->page.frame, PAGE_HEADER));
ut_ad(!memcmp(old->frame + PAGE_MAX_TRX_ID + PAGE_HEADER, ut_ad(!memcmp(old->page.frame + PAGE_MAX_TRX_ID + PAGE_HEADER,
block->frame + PAGE_MAX_TRX_ID + PAGE_HEADER, block->page.frame + PAGE_MAX_TRX_ID + PAGE_HEADER,
PAGE_DATA - (PAGE_MAX_TRX_ID + PAGE_HEADER))); PAGE_DATA - (PAGE_MAX_TRX_ID + PAGE_HEADER)));
if (!dict_table_is_locking_disabled(index->table)) if (!dict_table_is_locking_disabled(index->table))
@@ -1367,9 +1376,9 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
ulint a, e; ulint a, e;
for (a= PAGE_HEADER, e= PAGE_MAX_TRX_ID + PAGE_HEADER; a < e; a++) for (a= PAGE_HEADER, e= PAGE_MAX_TRX_ID + PAGE_HEADER; a < e; a++)
{ {
if (old->frame[a] == block->frame[a]) if (old->page.frame[a] == block->page.frame[a])
continue; continue;
while (--e, old->frame[e] == block->frame[e]); while (--e, old->page.frame[e] == block->page.frame[e]);
e++; e++;
ut_ad(a < e); ut_ad(a < e);
/* Write log for the changed page header fields. */ /* Write log for the changed page header fields. */
@@ -1377,88 +1386,92 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
break; break;
} }
const uint16_t top= page_header_get_offs(block->frame, PAGE_HEAP_TOP); const uint16_t top= page_header_get_offs(block->page.frame, PAGE_HEAP_TOP);
if (page_is_comp(block->frame)) if (page_is_comp(block->page.frame))
{ {
/* info_bits=0, n_owned=1, heap_no=0, status */ /* info_bits=0, n_owned=1, heap_no=0, status */
ut_ad(!memcmp(PAGE_NEW_INFIMUM - REC_N_NEW_EXTRA_BYTES + block->frame, ut_ad(!memcmp(PAGE_NEW_INFIMUM - REC_N_NEW_EXTRA_BYTES +
PAGE_NEW_INFIMUM - REC_N_NEW_EXTRA_BYTES + old->frame, 3)); block->page.frame,
PAGE_NEW_INFIMUM - REC_N_NEW_EXTRA_BYTES +
old->page.frame, 3));
/* If the 'next' pointer of the infimum record has changed, log it. */ /* If the 'next' pointer of the infimum record has changed, log it. */
a= PAGE_NEW_INFIMUM - 2; a= PAGE_NEW_INFIMUM - 2;
e= a + 2; e= a + 2;
if (block->frame[a] == old->frame[a]) if (block->page.frame[a] == old->page.frame[a])
a++; a++;
if (--e, block->frame[e] != old->frame[e]) if (--e, block->page.frame[e] != old->page.frame[e])
e++; e++;
if (ulint len= e - a) if (ulint len= e - a)
mtr->memcpy(*block, a, len); mtr->memcpy(*block, a, len);
/* The infimum record itself must not change. */ /* The infimum record itself must not change. */
ut_ad(!memcmp(PAGE_NEW_INFIMUM + block->frame, ut_ad(!memcmp(PAGE_NEW_INFIMUM + block->page.frame,
PAGE_NEW_INFIMUM + old->frame, 8)); PAGE_NEW_INFIMUM + old->page.frame, 8));
/* Log any change of the n_owned of the supremum record. */ /* Log any change of the n_owned of the supremum record. */
a= PAGE_NEW_SUPREMUM - REC_N_NEW_EXTRA_BYTES; a= PAGE_NEW_SUPREMUM - REC_N_NEW_EXTRA_BYTES;
if (block->frame[a] != old->frame[a]) if (block->page.frame[a] != old->page.frame[a])
mtr->memcpy(*block, a, 1); mtr->memcpy(*block, a, 1);
/* The rest of the supremum record must not change. */ /* The rest of the supremum record must not change. */
ut_ad(!memcmp(&block->frame[a + 1], &old->frame[a + 1], ut_ad(!memcmp(&block->page.frame[a + 1], &old->page.frame[a + 1],
PAGE_NEW_SUPREMUM_END - PAGE_NEW_SUPREMUM + PAGE_NEW_SUPREMUM_END - PAGE_NEW_SUPREMUM +
REC_N_NEW_EXTRA_BYTES - 1)); REC_N_NEW_EXTRA_BYTES - 1));
/* Log the differences in the payload. */ /* Log the differences in the payload. */
for (a= PAGE_NEW_SUPREMUM_END, e= top; a < e; a++) for (a= PAGE_NEW_SUPREMUM_END, e= top; a < e; a++)
{ {
if (old->frame[a] == block->frame[a]) if (old->page.frame[a] == block->page.frame[a])
continue; continue;
while (--e, old->frame[e] == block->frame[e]); while (--e, old->page.frame[e] == block->page.frame[e]);
e++; e++;
ut_ad(a < e); ut_ad(a < e);
/* TODO: write MEMMOVE records to minimize this further! */ /* TODO: write MEMMOVE records to minimize this further! */
mtr->memcpy(*block, a, e - a); mtr->memcpy(*block, a, e - a);
break; break;
} }
} }
else else
{ {
/* info_bits=0, n_owned=1, heap_no=0, number of fields, 1-byte format */ /* info_bits=0, n_owned=1, heap_no=0, number of fields, 1-byte format */
ut_ad(!memcmp(PAGE_OLD_INFIMUM - REC_N_OLD_EXTRA_BYTES + block->frame, ut_ad(!memcmp(PAGE_OLD_INFIMUM - REC_N_OLD_EXTRA_BYTES +
PAGE_OLD_INFIMUM - REC_N_OLD_EXTRA_BYTES + old->frame, 4)); block->page.frame,
PAGE_OLD_INFIMUM - REC_N_OLD_EXTRA_BYTES +
old->page.frame, 4));
/* If the 'next' pointer of the infimum record has changed, log it. */ /* If the 'next' pointer of the infimum record has changed, log it. */
a= PAGE_OLD_INFIMUM - 2; a= PAGE_OLD_INFIMUM - 2;
e= a + 2; e= a + 2;
if (block->frame[a] == old->frame[a]) if (block->page.frame[a] == old->page.frame[a])
a++; a++;
if (--e, block->frame[e] != old->frame[e]) if (--e, block->page.frame[e] != old->page.frame[e])
e++; e++;
if (ulint len= e - a) if (ulint len= e - a)
mtr->memcpy(*block, a, len); mtr->memcpy(*block, a, len);
/* The infimum record itself must not change. */ /* The infimum record itself must not change. */
ut_ad(!memcmp(PAGE_OLD_INFIMUM + block->frame, ut_ad(!memcmp(PAGE_OLD_INFIMUM + block->page.frame,
PAGE_OLD_INFIMUM + old->frame, 8)); PAGE_OLD_INFIMUM + old->page.frame, 8));
/* Log any change of the n_owned of the supremum record. */ /* Log any change of the n_owned of the supremum record. */
a= PAGE_OLD_SUPREMUM - REC_N_OLD_EXTRA_BYTES; a= PAGE_OLD_SUPREMUM - REC_N_OLD_EXTRA_BYTES;
if (block->frame[a] != old->frame[a]) if (block->page.frame[a] != old->page.frame[a])
mtr->memcpy(*block, a, 1); mtr->memcpy(*block, a, 1);
ut_ad(!memcmp(&block->frame[a + 1], &old->frame[a + 1], ut_ad(!memcmp(&block->page.frame[a + 1], &old->page.frame[a + 1],
PAGE_OLD_SUPREMUM_END - PAGE_OLD_SUPREMUM + PAGE_OLD_SUPREMUM_END - PAGE_OLD_SUPREMUM +
REC_N_OLD_EXTRA_BYTES - 1)); REC_N_OLD_EXTRA_BYTES - 1));
/* Log the differences in the payload. */ /* Log the differences in the payload. */
for (a= PAGE_OLD_SUPREMUM_END, e= top; a < e; a++) for (a= PAGE_OLD_SUPREMUM_END, e= top; a < e; a++)
{ {
if (old->frame[a] == block->frame[a]) if (old->page.frame[a] == block->page.frame[a])
continue; continue;
while (--e, old->frame[e] == block->frame[e]); while (--e, old->page.frame[e] == block->page.frame[e]);
e++; e++;
ut_ad(a < e); ut_ad(a < e);
/* TODO: write MEMMOVE records to minimize this further! */ /* TODO: write MEMMOVE records to minimize this further! */
mtr->memcpy(*block, a, e - a); mtr->memcpy(*block, a, e - a);
break; break;
} }
} }
e= srv_page_size - PAGE_DIR; e= srv_page_size - PAGE_DIR;
a= e - PAGE_DIR_SLOT_SIZE * page_dir_get_n_slots(block->frame); a= e - PAGE_DIR_SLOT_SIZE * page_dir_get_n_slots(block->page.frame);
/* Zero out the payload area. */ /* Zero out the payload area. */
mtr->memset(*block, top, a - top, 0); mtr->memset(*block, top, a - top, 0);
@@ -1466,9 +1479,9 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
/* Log changes to the page directory. */ /* Log changes to the page directory. */
for (; a < e; a++) for (; a < e; a++)
{ {
if (old->frame[a] == block->frame[a]) if (old->page.frame[a] == block->page.frame[a])
continue; continue;
while (--e, old->frame[e] == block->frame[e]); while (--e, old->page.frame[e] == block->page.frame[e]);
e++; e++;
ut_ad(a < e); ut_ad(a < e);
/* Write log for the changed page directory slots. */ /* Write log for the changed page directory slots. */
@@ -1542,10 +1555,10 @@ btr_page_reorganize(
return false; return false;
} }
if (pos) { if (pos) {
cursor->rec = page_rec_get_nth(cursor->block->frame, pos); cursor->rec = page_rec_get_nth(cursor->block->page.frame, pos);
} else { } else {
ut_ad(cursor->rec == page_get_infimum_rec( ut_ad(cursor->rec == page_get_infimum_rec(
cursor->block->frame)); cursor->block->page.frame));
} }
return true; return true;
@@ -1570,7 +1583,8 @@ btr_page_empty(
ut_ad(!index->is_dummy); ut_ad(!index->is_dummy);
ut_ad(index->table->space->id == block->page.id().space()); ut_ad(index->table->space->id == block->page.id().space());
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index)); ut_a(!page_zip
|| page_zip_validate(page_zip, block->page.frame, index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
@@ -1583,7 +1597,7 @@ btr_page_empty(
const ib_uint64_t autoinc const ib_uint64_t autoinc
= dict_index_is_clust(index) = dict_index_is_clust(index)
&& index->page == block->page.id().page_no() && index->page == block->page.id().page_no()
? page_get_autoinc(block->frame) ? page_get_autoinc(block->page.frame)
: 0; : 0;
if (page_zip) { if (page_zip) {
@@ -1594,19 +1608,20 @@ btr_page_empty(
static_assert(((FIL_PAGE_INDEX & 0xff00) static_assert(((FIL_PAGE_INDEX & 0xff00)
| byte(FIL_PAGE_RTREE)) | byte(FIL_PAGE_RTREE))
== FIL_PAGE_RTREE, "compatibility"); == FIL_PAGE_RTREE, "compatibility");
mtr->write<1>(*block, FIL_PAGE_TYPE + 1 + block->frame, mtr->write<1>(*block, FIL_PAGE_TYPE + 1
+ block->page.frame,
byte(FIL_PAGE_RTREE)); byte(FIL_PAGE_RTREE));
if (mach_read_from_8(block->frame if (mach_read_from_8(block->page.frame
+ FIL_RTREE_SPLIT_SEQ_NUM)) { + FIL_RTREE_SPLIT_SEQ_NUM)) {
mtr->memset(block, FIL_RTREE_SPLIT_SEQ_NUM, mtr->memset(block, FIL_RTREE_SPLIT_SEQ_NUM,
8, 0); 8, 0);
} }
} }
mtr->write<2,mtr_t::MAYBE_NOP>(*block, PAGE_HEADER + PAGE_LEVEL mtr->write<2,mtr_t::MAYBE_NOP>(*block, PAGE_HEADER + PAGE_LEVEL
+ block->frame, level); + block->page.frame, level);
if (autoinc) { if (autoinc) {
mtr->write<8>(*block, PAGE_HEADER + PAGE_MAX_TRX_ID mtr->write<8>(*block, PAGE_HEADER + PAGE_MAX_TRX_ID
+ block->frame, autoinc); + block->page.frame, autoinc);
} }
} }
} }
@@ -1620,19 +1635,20 @@ void btr_set_instant(buf_block_t* root, const dict_index_t& index, mtr_t* mtr)
ut_ad(index.n_core_fields > 0); ut_ad(index.n_core_fields > 0);
ut_ad(index.n_core_fields < REC_MAX_N_FIELDS); ut_ad(index.n_core_fields < REC_MAX_N_FIELDS);
ut_ad(index.is_instant()); ut_ad(index.is_instant());
ut_ad(fil_page_get_type(root->frame) == FIL_PAGE_TYPE_INSTANT ut_ad(fil_page_get_type(root->page.frame) == FIL_PAGE_TYPE_INSTANT
|| fil_page_get_type(root->frame) == FIL_PAGE_INDEX); || fil_page_get_type(root->page.frame) == FIL_PAGE_INDEX);
ut_ad(!page_has_siblings(root->frame)); ut_ad(!page_has_siblings(root->page.frame));
ut_ad(root->page.id().page_no() == index.page); ut_ad(root->page.id().page_no() == index.page);
rec_t* infimum = page_get_infimum_rec(root->frame); rec_t* infimum = page_get_infimum_rec(root->page.frame);
rec_t* supremum = page_get_supremum_rec(root->frame); rec_t* supremum = page_get_supremum_rec(root->page.frame);
byte* page_type = root->frame + FIL_PAGE_TYPE; byte* page_type = root->page.frame + FIL_PAGE_TYPE;
uint16_t i = page_header_get_field(root->frame, PAGE_INSTANT); uint16_t i = page_header_get_field(root->page.frame, PAGE_INSTANT);
switch (mach_read_from_2(page_type)) { switch (mach_read_from_2(page_type)) {
case FIL_PAGE_TYPE_INSTANT: case FIL_PAGE_TYPE_INSTANT:
ut_ad(page_get_instant(root->frame) == index.n_core_fields); ut_ad(page_get_instant(root->page.frame)
== index.n_core_fields);
if (memcmp(infimum, "infimum", 8) if (memcmp(infimum, "infimum", 8)
|| memcmp(supremum, "supremum", 8)) { || memcmp(supremum, "supremum", 8)) {
ut_ad(index.table->instant); ut_ad(index.table->instant);
@@ -1649,21 +1665,21 @@ void btr_set_instant(buf_block_t* root, const dict_index_t& index, mtr_t* mtr)
ut_ad("wrong page type" == 0); ut_ad("wrong page type" == 0);
/* fall through */ /* fall through */
case FIL_PAGE_INDEX: case FIL_PAGE_INDEX:
ut_ad(!page_is_comp(root->frame) ut_ad(!page_is_comp(root->page.frame)
|| !page_get_instant(root->frame)); || !page_get_instant(root->page.frame));
ut_ad(!memcmp(infimum, "infimum", 8)); ut_ad(!memcmp(infimum, "infimum", 8));
ut_ad(!memcmp(supremum, "supremum", 8)); ut_ad(!memcmp(supremum, "supremum", 8));
mtr->write<2>(*root, page_type, FIL_PAGE_TYPE_INSTANT); mtr->write<2>(*root, page_type, FIL_PAGE_TYPE_INSTANT);
ut_ad(i <= PAGE_NO_DIRECTION); ut_ad(i <= PAGE_NO_DIRECTION);
i |= static_cast<uint16_t>(index.n_core_fields << 3); i |= static_cast<uint16_t>(index.n_core_fields << 3);
mtr->write<2>(*root, PAGE_HEADER + PAGE_INSTANT + root->frame, mtr->write<2>(*root, PAGE_HEADER + PAGE_INSTANT
i); + root->page.frame, i);
break; break;
} }
if (index.table->instant) { if (index.table->instant) {
mtr->memset(root, infimum - root->frame, 8, 0); mtr->memset(root, infimum - root->page.frame, 8, 0);
mtr->memset(root, supremum - root->frame, 7, 0); mtr->memset(root, supremum - root->page.frame, 7, 0);
mtr->write<1,mtr_t::MAYBE_NOP>(*root, &supremum[7], mtr->write<1,mtr_t::MAYBE_NOP>(*root, &supremum[7],
index.n_core_null_bytes); index.n_core_null_bytes);
} }
@@ -1680,13 +1696,13 @@ void btr_reset_instant(const dict_index_t &index, bool all, mtr_t *mtr)
ut_ad(index.is_primary()); ut_ad(index.is_primary());
if (buf_block_t *root = btr_root_block_get(&index, RW_SX_LATCH, mtr)) if (buf_block_t *root = btr_root_block_get(&index, RW_SX_LATCH, mtr))
{ {
byte *page_type= root->frame + FIL_PAGE_TYPE; byte *page_type= root->page.frame + FIL_PAGE_TYPE;
if (all) if (all)
{ {
ut_ad(mach_read_from_2(page_type) == FIL_PAGE_TYPE_INSTANT || ut_ad(mach_read_from_2(page_type) == FIL_PAGE_TYPE_INSTANT ||
mach_read_from_2(page_type) == FIL_PAGE_INDEX); mach_read_from_2(page_type) == FIL_PAGE_INDEX);
mtr->write<2,mtr_t::MAYBE_NOP>(*root, page_type, FIL_PAGE_INDEX); mtr->write<2,mtr_t::MAYBE_NOP>(*root, page_type, FIL_PAGE_INDEX);
byte *instant= PAGE_INSTANT + PAGE_HEADER + root->frame; byte *instant= PAGE_INSTANT + PAGE_HEADER + root->page.frame;
mtr->write<2,mtr_t::MAYBE_NOP>(*root, instant, mtr->write<2,mtr_t::MAYBE_NOP>(*root, instant,
page_ptr_get_direction(instant + 1)); page_ptr_get_direction(instant + 1));
} }
@@ -1694,7 +1710,7 @@ void btr_reset_instant(const dict_index_t &index, bool all, mtr_t *mtr)
ut_ad(mach_read_from_2(page_type) == FIL_PAGE_TYPE_INSTANT); ut_ad(mach_read_from_2(page_type) == FIL_PAGE_TYPE_INSTANT);
static const byte supremuminfimum[8 + 8] = "supremuminfimum"; static const byte supremuminfimum[8 + 8] = "supremuminfimum";
uint16_t infimum, supremum; uint16_t infimum, supremum;
if (page_is_comp(root->frame)) if (page_is_comp(root->page.frame))
{ {
infimum= PAGE_NEW_INFIMUM; infimum= PAGE_NEW_INFIMUM;
supremum= PAGE_NEW_SUPREMUM; supremum= PAGE_NEW_SUPREMUM;
@@ -1704,11 +1720,11 @@ void btr_reset_instant(const dict_index_t &index, bool all, mtr_t *mtr)
infimum= PAGE_OLD_INFIMUM; infimum= PAGE_OLD_INFIMUM;
supremum= PAGE_OLD_SUPREMUM; supremum= PAGE_OLD_SUPREMUM;
} }
ut_ad(!memcmp(&root->frame[infimum], supremuminfimum + 8, 8) == ut_ad(!memcmp(&root->page.frame[infimum], supremuminfimum + 8, 8) ==
!memcmp(&root->frame[supremum], supremuminfimum, 8)); !memcmp(&root->page.frame[supremum], supremuminfimum, 8));
mtr->memcpy<mtr_t::MAYBE_NOP>(*root, &root->frame[infimum], mtr->memcpy<mtr_t::MAYBE_NOP>(*root, &root->page.frame[infimum],
supremuminfimum + 8, 8); supremuminfimum + 8, 8);
mtr->memcpy<mtr_t::MAYBE_NOP>(*root, &root->frame[supremum], mtr->memcpy<mtr_t::MAYBE_NOP>(*root, &root->page.frame[supremum],
supremuminfimum, 8); supremuminfimum, 8);
} }
} }
@@ -1748,12 +1764,12 @@ btr_root_raise_and_insert(
root = btr_cur_get_block(cursor); root = btr_cur_get_block(cursor);
root_page_zip = buf_block_get_page_zip(root); root_page_zip = buf_block_get_page_zip(root);
ut_ad(!page_is_empty(root->frame)); ut_ad(!page_is_empty(root->page.frame));
index = btr_cur_get_index(cursor); index = btr_cur_get_index(cursor);
ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable)); ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable));
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!root_page_zip || page_zip_validate(root_page_zip, root->frame, ut_a(!root_page_zip
index)); || page_zip_validate(root_page_zip, root->page.frame, index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
const page_id_t root_id{root->page.id()}; const page_id_t root_id{root->page.id()};
@@ -1762,9 +1778,9 @@ btr_root_raise_and_insert(
ulint space = index->table->space_id; ulint space = index->table->space_id;
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
+ root->frame, space)); + root->page.frame, space));
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
+ root->frame, space)); + root->page.frame, space));
} }
ut_a(dict_index_get_page(index) == root_id.page_no()); ut_a(dict_index_get_page(index) == root_id.page_no());
@@ -1777,7 +1793,7 @@ btr_root_raise_and_insert(
moving the root records to the new page, emptying the root, putting 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. */ a node pointer to the new page, and then splitting the new page. */
level = btr_page_get_level(root->frame); level = btr_page_get_level(root->page.frame);
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr); new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr);
@@ -1792,11 +1808,12 @@ btr_root_raise_and_insert(
== page_zip_get_size(root_page_zip)); == page_zip_get_size(root_page_zip));
btr_page_create(new_block, new_page_zip, index, level, mtr); btr_page_create(new_block, new_page_zip, index, level, mtr);
if (page_has_siblings(new_block->frame)) { if (page_has_siblings(new_block->page.frame)) {
compile_time_assert(FIL_PAGE_NEXT == FIL_PAGE_PREV + 4); compile_time_assert(FIL_PAGE_NEXT == FIL_PAGE_PREV + 4);
compile_time_assert(FIL_NULL == 0xffffffff); compile_time_assert(FIL_NULL == 0xffffffff);
static_assert(FIL_PAGE_PREV % 8 == 0, "alignment"); static_assert(FIL_PAGE_PREV % 8 == 0, "alignment");
memset_aligned<8>(new_block->frame + FIL_PAGE_PREV, 0xff, 8); memset_aligned<8>(new_block->page.frame + FIL_PAGE_PREV,
0xff, 8);
mtr->memset(new_block, FIL_PAGE_PREV, 8, 0xff); mtr->memset(new_block, FIL_PAGE_PREV, 8, 0xff);
if (UNIV_LIKELY_NULL(new_page_zip)) { if (UNIV_LIKELY_NULL(new_page_zip)) {
memset_aligned<8>(new_page_zip->data + FIL_PAGE_PREV, memset_aligned<8>(new_page_zip->data + FIL_PAGE_PREV,
@@ -1811,17 +1828,17 @@ btr_root_raise_and_insert(
|| new_page_zip || new_page_zip
#endif /* UNIV_ZIP_COPY */ #endif /* UNIV_ZIP_COPY */
|| !page_copy_rec_list_end(new_block, root, || !page_copy_rec_list_end(new_block, root,
page_get_infimum_rec(root->frame), page_get_infimum_rec(root->page.frame),
index, mtr)) { index, mtr)) {
ut_a(new_page_zip); ut_a(new_page_zip);
/* Copy the page byte for byte. */ /* Copy the page byte for byte. */
page_zip_copy_recs(new_block, page_zip_copy_recs(new_block, root_page_zip,
root_page_zip, root->frame, index, mtr); root->page.frame, index, mtr);
/* Update the lock table and possible hash index. */ /* Update the lock table and possible hash index. */
lock_move_rec_list_end(new_block, root, lock_move_rec_list_end(new_block, root,
page_get_infimum_rec(root->frame)); page_get_infimum_rec(root->page.frame));
/* Move any existing predicate locks */ /* Move any existing predicate locks */
if (dict_index_is_spatial(index)) { if (dict_index_is_spatial(index)) {
@@ -1840,7 +1857,7 @@ btr_root_raise_and_insert(
longer is a leaf page. (Older versions of InnoDB did longer is a leaf page. (Older versions of InnoDB did
set PAGE_MAX_TRX_ID on all secondary index pages.) */ set PAGE_MAX_TRX_ID on all secondary index pages.) */
byte* p = my_assume_aligned<8>( byte* p = my_assume_aligned<8>(
PAGE_HEADER + PAGE_MAX_TRX_ID + root->frame); PAGE_HEADER + PAGE_MAX_TRX_ID + root->page.frame);
if (mach_read_from_8(p)) { if (mach_read_from_8(p)) {
mtr->memset(root, max_trx_id, 8, 0); mtr->memset(root, max_trx_id, 8, 0);
if (UNIV_LIKELY_NULL(root->page.zip.data)) { if (UNIV_LIKELY_NULL(root->page.zip.data)) {
@@ -1853,7 +1870,7 @@ btr_root_raise_and_insert(
root page; on other clustered index pages, we want to reserve root page; on other clustered index pages, we want to reserve
the field PAGE_MAX_TRX_ID for future use. */ the field PAGE_MAX_TRX_ID for future use. */
byte* p = my_assume_aligned<8>( byte* p = my_assume_aligned<8>(
PAGE_HEADER + PAGE_MAX_TRX_ID + new_block->frame); PAGE_HEADER + PAGE_MAX_TRX_ID + new_block->page.frame);
if (mach_read_from_8(p)) { if (mach_read_from_8(p)) {
mtr->memset(new_block, max_trx_id, 8, 0); mtr->memset(new_block, max_trx_id, 8, 0);
if (UNIV_LIKELY_NULL(new_block->page.zip.data)) { if (UNIV_LIKELY_NULL(new_block->page.zip.data)) {
@@ -1878,7 +1895,7 @@ btr_root_raise_and_insert(
*heap = mem_heap_create(1000); *heap = mem_heap_create(1000);
} }
rec = page_rec_get_next(page_get_infimum_rec(new_block->frame)); rec = page_rec_get_next(page_get_infimum_rec(new_block->page.frame));
new_page_no = new_block->page.id().page_no(); new_page_no = new_block->page.id().page_no();
/* Build the node pointer (= node key and page address) for the /* Build the node pointer (= node key and page address) for the
@@ -1903,14 +1920,14 @@ btr_root_raise_and_insert(
/* Rebuild the root page to get free space */ /* Rebuild the root page to get free space */
btr_page_empty(root, root_page_zip, index, level + 1, mtr); btr_page_empty(root, root_page_zip, index, level + 1, mtr);
/* btr_page_empty() is supposed to zero-initialize the field. */ /* btr_page_empty() is supposed to zero-initialize the field. */
ut_ad(!page_get_instant(root->frame)); ut_ad(!page_get_instant(root->page.frame));
if (index->is_instant()) { if (index->is_instant()) {
ut_ad(!root_page_zip); ut_ad(!root_page_zip);
btr_set_instant(root, *index, mtr); btr_set_instant(root, *index, mtr);
} }
ut_ad(!page_has_siblings(root->frame)); ut_ad(!page_has_siblings(root->page.frame));
page_cursor = btr_cur_get_page_cur(cursor); page_cursor = btr_cur_get_page_cur(cursor);
@@ -2395,12 +2412,12 @@ btr_attach_half_pages(
} }
/* Get the level of the split pages */ /* Get the level of the split pages */
const ulint level = btr_page_get_level(buf_block_get_frame(block)); const ulint level = btr_page_get_level(block->page.frame);
ut_ad(level == btr_page_get_level(buf_block_get_frame(new_block))); ut_ad(level == btr_page_get_level(new_block->page.frame));
/* Get the previous and next pages of page */ /* Get the previous and next pages of page */
const uint32_t prev_page_no = btr_page_get_prev(block->frame); const uint32_t prev_page_no = btr_page_get_prev(block->page.frame);
const uint32_t next_page_no = btr_page_get_next(block->frame); const uint32_t next_page_no = btr_page_get_next(block->page.frame);
/* for consistency, both blocks should be locked, before change */ /* for consistency, both blocks should be locked, before change */
if (prev_page_no != FIL_NULL && direction == FSP_DOWN) { if (prev_page_no != FIL_NULL && direction == FSP_DOWN) {
@@ -2432,9 +2449,9 @@ btr_attach_half_pages(
if (prev_block) { if (prev_block) {
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(prev_block->frame) ut_a(page_is_comp(prev_block->page.frame)
== page_is_comp(block->frame)); == page_is_comp(block->page.frame));
ut_a(btr_page_get_next(prev_block->frame) ut_a(btr_page_get_next(prev_block->page.frame)
== block->page.id().page_no()); == block->page.id().page_no());
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
btr_page_set_next(prev_block, lower_block->page.id().page_no(), btr_page_set_next(prev_block, lower_block->page.id().page_no(),
@@ -2443,9 +2460,9 @@ btr_attach_half_pages(
if (next_block) { if (next_block) {
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) ut_a(page_is_comp(next_block->page.frame)
== page_is_comp(block->frame)); == page_is_comp(block->page.frame));
ut_a(btr_page_get_prev(next_block->frame) ut_a(btr_page_get_prev(next_block->page.frame)
== block->page.id().page_no()); == block->page.id().page_no());
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
btr_page_set_prev(next_block, upper_block->page.id().page_no(), btr_page_set_prev(next_block, upper_block->page.id().page_no(),
@@ -2454,11 +2471,13 @@ btr_attach_half_pages(
if (direction == FSP_DOWN) { if (direction == FSP_DOWN) {
ut_ad(lower_block == new_block); ut_ad(lower_block == new_block);
ut_ad(btr_page_get_next(upper_block->frame) == next_page_no); ut_ad(btr_page_get_next(upper_block->page.frame)
== next_page_no);
btr_page_set_prev(lower_block, prev_page_no, mtr); btr_page_set_prev(lower_block, prev_page_no, mtr);
} else { } else {
ut_ad(upper_block == new_block); ut_ad(upper_block == new_block);
ut_ad(btr_page_get_prev(lower_block->frame) == prev_page_no); ut_ad(btr_page_get_prev(lower_block->page.frame)
== prev_page_no);
btr_page_set_next(upper_block, next_page_no, mtr); btr_page_set_next(upper_block, next_page_no, mtr);
} }
@@ -2490,10 +2509,10 @@ btr_page_tuple_smaller(
page_cur_move_to_next(&pcur); page_cur_move_to_next(&pcur);
first_rec = page_cur_get_rec(&pcur); first_rec = page_cur_get_rec(&pcur);
*offsets = rec_get_offsets( *offsets = rec_get_offsets(first_rec, cursor->index, *offsets,
first_rec, cursor->index, *offsets, page_is_leaf(block->page.frame)
page_is_leaf(block->frame) ? cursor->index->n_core_fields : 0, ? cursor->index->n_core_fields : 0,
n_uniq, heap); n_uniq, heap);
return(cmp_dtuple_rec(tuple, first_rec, *offsets) < 0); return(cmp_dtuple_rec(tuple, first_rec, *offsets) < 0);
} }
@@ -3053,7 +3072,7 @@ dberr_t btr_level_list_remove(const buf_block_t& block,
ut_ad(index.table->space->id == block.page.id().space()); ut_ad(index.table->space->id == block.page.id().space());
/* Get the previous and next page numbers of page */ /* Get the previous and next page numbers of page */
const page_t* page = block.frame; const page_t* page = block.page.frame;
const uint32_t prev_page_no = btr_page_get_prev(page); const uint32_t prev_page_no = btr_page_get_prev(page);
const uint32_t next_page_no = btr_page_get_next(page); const uint32_t next_page_no = btr_page_get_next(page);
@@ -3064,10 +3083,11 @@ dberr_t btr_level_list_remove(const buf_block_t& block,
index, prev_page_no, RW_X_LATCH, page_is_leaf(page), index, prev_page_no, RW_X_LATCH, page_is_leaf(page),
mtr); mtr);
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(prev_block->frame) == page_is_comp(page)); ut_a(page_is_comp(prev_block->page.frame)
== page_is_comp(page));
static_assert(FIL_PAGE_NEXT % 4 == 0, "alignment"); static_assert(FIL_PAGE_NEXT % 4 == 0, "alignment");
static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment"); static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
ut_a(!memcmp_aligned<4>(prev_block->frame + FIL_PAGE_NEXT, ut_a(!memcmp_aligned<4>(prev_block->page.frame + FIL_PAGE_NEXT,
page + FIL_PAGE_OFFSET, 4)); page + FIL_PAGE_OFFSET, 4));
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
@@ -3083,10 +3103,11 @@ dberr_t btr_level_list_remove(const buf_block_t& block,
return DB_ERROR; return DB_ERROR;
} }
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) == page_is_comp(page)); ut_a(page_is_comp(next_block->page.frame)
== page_is_comp(page));
static_assert(FIL_PAGE_PREV % 4 == 0, "alignment"); static_assert(FIL_PAGE_PREV % 4 == 0, "alignment");
static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment"); static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
ut_a(!memcmp_aligned<4>(next_block->frame + FIL_PAGE_PREV, ut_a(!memcmp_aligned<4>(next_block->page.frame + FIL_PAGE_PREV,
page + FIL_PAGE_OFFSET, 4)); page + FIL_PAGE_OFFSET, 4));
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
@@ -3203,7 +3224,7 @@ btr_lift_page_up(
/* Make the father empty */ /* Make the father empty */
btr_page_empty(father_block, father_page_zip, index, page_level, mtr); btr_page_empty(father_block, father_page_zip, index, page_level, mtr);
/* btr_page_empty() is supposed to zero-initialize the field. */ /* btr_page_empty() is supposed to zero-initialize the field. */
ut_ad(!page_get_instant(father_block->frame)); ut_ad(!page_get_instant(father_block->page.frame));
if (index->is_instant() if (index->is_instant()
&& father_block->page.id().page_no() == root_page_no) { && father_block->page.id().page_no() == root_page_no) {
@@ -3256,7 +3277,8 @@ btr_lift_page_up(
/* Go upward to root page, decrementing levels by one. */ /* Go upward to root page, decrementing levels by one. */
for (i = lift_father_up ? 1 : 0; i < n_blocks; i++, page_level++) { for (i = lift_father_up ? 1 : 0; i < n_blocks; i++, page_level++) {
ut_ad(btr_page_get_level(blocks[i]->frame) == page_level + 1); ut_ad(btr_page_get_level(blocks[i]->page.frame)
== page_level + 1);
btr_page_set_level(blocks[i], page_level, mtr); btr_page_set_level(blocks[i], page_level, mtr);
} }
@@ -3272,7 +3294,7 @@ btr_lift_page_up(
&& !index->table->is_temporary()) { && !index->table->is_temporary()) {
ibuf_reset_free_bits(father_block); ibuf_reset_free_bits(father_block);
} }
ut_ad(page_validate(father_block->frame, index)); ut_ad(page_validate(father_block->page.frame, index));
ut_ad(btr_check_node_ptr(index, father_block, mtr)); ut_ad(btr_check_node_ptr(index, father_block, mtr));
return(lift_father_up ? block_orig : father_block); return(lift_father_up ? block_orig : father_block);
@@ -3448,7 +3470,7 @@ retry:
offsets2 = rec_get_offsets( offsets2 = rec_get_offsets(
btr_cur_get_rec(&cursor2), index, NULL, btr_cur_get_rec(&cursor2), index, NULL,
page_is_leaf(cursor2.page_cur.block->frame) page_is_leaf(btr_cur_get_page(&cursor2))
? index->n_fields : 0, ? index->n_fields : 0,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
@@ -3627,7 +3649,7 @@ retry:
offsets2 = rec_get_offsets( offsets2 = rec_get_offsets(
btr_cur_get_rec(&cursor2), index, NULL, btr_cur_get_rec(&cursor2), index, NULL,
page_is_leaf(cursor2.page_cur.block->frame) page_is_leaf(btr_cur_get_page(&cursor2))
? index->n_fields : 0, ? index->n_fields : 0,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
@@ -3747,7 +3769,7 @@ func_exit:
ut_ad(nth_rec > 0); ut_ad(nth_rec > 0);
btr_cur_position( btr_cur_position(
index, index,
page_rec_get_nth(merge_block->frame, nth_rec), page_rec_get_nth(merge_block->page.frame, nth_rec),
merge_block, cursor); merge_block, cursor);
} }
@@ -3758,7 +3780,7 @@ func_exit:
err_exit: err_exit:
/* We play it safe and reset the free bits. */ /* We play it safe and reset the free bits. */
if (merge_block && merge_block->zip_size() if (merge_block && merge_block->zip_size()
&& page_is_leaf(merge_block->frame) && page_is_leaf(merge_block->page.frame)
&& !dict_index_is_clust(index)) { && !dict_index_is_clust(index)) {
ibuf_reset_free_bits(merge_block); ibuf_reset_free_bits(merge_block);
@@ -3787,8 +3809,9 @@ btr_discard_only_page_on_level(
ut_ad(!index->is_dummy); ut_ad(!index->is_dummy);
/* Save the PAGE_MAX_TRX_ID from the leaf page. */ /* Save the PAGE_MAX_TRX_ID from the leaf page. */
const trx_id_t max_trx_id = page_get_max_trx_id(block->frame); const trx_id_t max_trx_id = page_get_max_trx_id(block->page.frame);
const rec_t* r = page_rec_get_next(page_get_infimum_rec(block->frame)); const rec_t* r = page_rec_get_next(
page_get_infimum_rec(block->page.frame));
ut_ad(rec_is_metadata(r, *index) == index->is_instant()); ut_ad(rec_is_metadata(r, *index) == index->is_instant());
while (block->page.id().page_no() != dict_index_get_page(index)) { while (block->page.id().page_no() != dict_index_get_page(index)) {
@@ -3827,7 +3850,7 @@ btr_discard_only_page_on_level(
/* block is the root page, which must be empty, except /* block is the root page, which must be empty, except
for the node pointer to the (now discarded) block(s). */ for the node pointer to the (now discarded) block(s). */
ut_ad(!page_has_siblings(block->frame)); ut_ad(!page_has_siblings(block->page.frame));
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
if (!dict_index_is_ibuf(index)) { if (!dict_index_is_ibuf(index)) {
@@ -3861,7 +3884,7 @@ btr_discard_only_page_on_level(
btr_page_empty(block, buf_block_get_page_zip(block), index, 0, mtr); btr_page_empty(block, buf_block_get_page_zip(block), index, 0, mtr);
ut_ad(page_is_leaf(buf_block_get_frame(block))); ut_ad(page_is_leaf(buf_block_get_frame(block)));
/* btr_page_empty() is supposed to zero-initialize the field. */ /* btr_page_empty() is supposed to zero-initialize the field. */
ut_ad(!page_get_instant(block->frame)); ut_ad(!page_get_instant(block->page.frame));
if (index->is_primary()) { if (index->is_primary()) {
if (rec) { if (rec) {
@@ -3923,15 +3946,15 @@ btr_discard_page(
/* Decide the page which will inherit the locks */ /* Decide the page which will inherit the locks */
const uint32_t left_page_no = btr_page_get_prev(block->frame); const uint32_t left_page_no = btr_page_get_prev(block->page.frame);
const uint32_t right_page_no = btr_page_get_next(block->frame); const uint32_t right_page_no = btr_page_get_next(block->page.frame);
ut_d(bool parent_is_different = false); ut_d(bool parent_is_different = false);
if (left_page_no != FIL_NULL) { if (left_page_no != FIL_NULL) {
merge_block = btr_block_get(*index, left_page_no, RW_X_LATCH, merge_block = btr_block_get(*index, left_page_no, RW_X_LATCH,
true, mtr); true, mtr);
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(merge_block->frame) ut_a(btr_page_get_next(merge_block->page.frame)
== block->page.id().page_no()); == block->page.id().page_no());
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
ut_d(parent_is_different = ut_d(parent_is_different =
@@ -3944,14 +3967,14 @@ btr_discard_page(
merge_block = btr_block_get(*index, right_page_no, RW_X_LATCH, merge_block = btr_block_get(*index, right_page_no, RW_X_LATCH,
true, mtr); true, mtr);
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_prev(merge_block->frame) ut_a(btr_page_get_prev(merge_block->page.frame)
== block->page.id().page_no()); == block->page.id().page_no());
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
ut_d(parent_is_different = page_rec_is_supremum( ut_d(parent_is_different = page_rec_is_supremum(
page_rec_get_next(btr_cur_get_rec(&parent_cursor)))); page_rec_get_next(btr_cur_get_rec(&parent_cursor))));
if (!page_is_leaf(merge_block->frame)) { if (!page_is_leaf(merge_block->page.frame)) {
rec_t* node_ptr = page_rec_get_next( rec_t* node_ptr = page_rec_get_next(
page_get_infimum_rec(merge_block->frame)); page_get_infimum_rec(merge_block->page.frame));
ut_ad(page_rec_is_user_rec(node_ptr)); ut_ad(page_rec_is_user_rec(node_ptr));
/* We have to mark the leftmost node pointer as the /* We have to mark the leftmost node pointer as the
predefined minimum record. */ predefined minimum record. */
@@ -3964,9 +3987,12 @@ btr_discard_page(
return; return;
} }
ut_a(page_is_comp(merge_block->frame) == page_is_comp(block->frame)); ut_a(page_is_comp(merge_block->page.frame)
ut_ad(!memcmp_aligned<2>(&merge_block->frame[PAGE_HEADER + PAGE_LEVEL], == page_is_comp(block->page.frame));
&block->frame[PAGE_HEADER + PAGE_LEVEL], 2)); ut_ad(!memcmp_aligned<2>(&merge_block->page.frame
[PAGE_HEADER + PAGE_LEVEL],
&block->page.frame
[PAGE_HEADER + PAGE_LEVEL], 2));
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
if (dict_index_is_spatial(index)) { if (dict_index_is_spatial(index)) {
@@ -3983,8 +4009,8 @@ btr_discard_page(
page_zip_des_t* merge_page_zip page_zip_des_t* merge_page_zip
= buf_block_get_page_zip(merge_block); = buf_block_get_page_zip(merge_block);
ut_a(!merge_page_zip ut_a(!merge_page_zip
|| page_zip_validate(merge_page_zip, merge_block->frame, || page_zip_validate(merge_page_zip,
index)); merge_block->page.frame, index));
} }
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */

View File

@@ -494,8 +494,8 @@ inline void PageBulk::finishPage()
inline bool PageBulk::needs_finish() const inline bool PageBulk::needs_finish() const
{ {
ut_ad(page_align(m_cur_rec) == m_block->frame); ut_ad(page_align(m_cur_rec) == m_block->page.frame);
ut_ad(m_page == m_block->frame); ut_ad(m_page == m_block->page.frame);
if (!m_page[PAGE_HEADER + PAGE_DIRECTION_B]) if (!m_page[PAGE_HEADER + PAGE_DIRECTION_B])
return true; return true;
ulint heap_no, n_heap= page_header_get_field(m_page, PAGE_N_HEAP); ulint heap_no, n_heap= page_header_get_field(m_page, PAGE_N_HEAP);
@@ -839,7 +839,7 @@ PageBulk::release()
finish(); finish();
/* We fix the block because we will re-pin it soon. */ /* We fix the block because we will re-pin it soon. */
buf_block_buf_fix_inc(m_block); m_block->page.fix();
/* No other threads can modify this block. */ /* No other threads can modify this block. */
m_modify_clock = buf_block_get_modify_clock(m_block); m_modify_clock = buf_block_get_modify_clock(m_block);
@@ -873,11 +873,11 @@ PageBulk::latch()
ut_ad(m_block != NULL); ut_ad(m_block != NULL);
} }
buf_block_buf_fix_dec(m_block); ut_d(const auto buf_fix_count =) m_block->page.unfix();
ut_ad(m_block->page.buf_fix_count()); ut_ad(buf_fix_count);
ut_ad(m_cur_rec > m_page);
ut_ad(m_cur_rec > m_page && m_cur_rec < m_heap_top); ut_ad(m_cur_rec < m_heap_top);
return (m_err); return (m_err);
} }
@@ -1208,7 +1208,7 @@ BtrBulk::finish(dberr_t err)
last_block = btr_block_get(*m_index, last_page_no, RW_X_LATCH, last_block = btr_block_get(*m_index, last_page_no, RW_X_LATCH,
false, &mtr); false, &mtr);
first_rec = page_rec_get_next( first_rec = page_rec_get_next(
page_get_infimum_rec(last_block->frame)); page_get_infimum_rec(last_block->page.frame));
ut_ad(page_rec_is_user_rec(first_rec)); ut_ad(page_rec_is_user_rec(first_rec));
/* Copy last page to root page. */ /* Copy last page to root page. */

View File

@@ -224,6 +224,11 @@ btr_cur_latch_leaves(
spatial = dict_index_is_spatial(cursor->index) && cursor->rtr_info; spatial = dict_index_is_spatial(cursor->index) && cursor->rtr_info;
ut_ad(block->page.in_file()); ut_ad(block->page.in_file());
ut_ad(srv_read_only_mode
|| mtr->memo_contains_flagged(&cursor->index->lock,
MTR_MEMO_S_LOCK
| MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
switch (latch_mode) { switch (latch_mode) {
case BTR_SEARCH_LEAF: case BTR_SEARCH_LEAF:
@@ -241,8 +246,8 @@ btr_cur_latch_leaves(
true, mtr); true, mtr);
latch_leaves.blocks[1] = get_block; latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) ut_a(page_is_comp(get_block->page.frame)
== page_is_comp(block->frame)); == page_is_comp(block->page.frame));
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
if (spatial) { if (spatial) {
cursor->rtr_info->tree_blocks[RTR_MAX_LEVELS] cursor->rtr_info->tree_blocks[RTR_MAX_LEVELS]
@@ -257,7 +262,7 @@ btr_cur_latch_leaves(
MTR_MEMO_X_LOCK MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK)); | MTR_MEMO_SX_LOCK));
/* x-latch also siblings from left to right */ /* x-latch also siblings from left to right */
left_page_no = btr_page_get_prev(block->frame); left_page_no = btr_page_get_prev(block->page.frame);
if (left_page_no != FIL_NULL) { if (left_page_no != FIL_NULL) {
@@ -290,15 +295,8 @@ btr_cur_latch_leaves(
latch_leaves.blocks[1] = get_block; latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
/* Sanity check only after both the blocks are latched. */ ut_a(page_is_comp(get_block->page.frame)
if (latch_leaves.blocks[0] != NULL) { == page_is_comp(block->page.frame));
ut_a(page_is_comp(latch_leaves.blocks[0]->frame)
== page_is_comp(block->frame));
ut_a(btr_page_get_next(latch_leaves.blocks[0]->frame)
== block->page.id().page_no());
}
ut_a(page_is_comp(get_block->frame)
== page_is_comp(block->frame));
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
if (spatial) { if (spatial) {
@@ -306,7 +304,7 @@ btr_cur_latch_leaves(
= get_block; = get_block;
} }
right_page_no = btr_page_get_next(block->frame); right_page_no = btr_page_get_next(block->page.frame);
if (right_page_no != FIL_NULL) { if (right_page_no != FIL_NULL) {
if (spatial) { if (spatial) {
@@ -321,9 +319,9 @@ btr_cur_latch_leaves(
latch_leaves.blocks[2] = get_block; latch_leaves.blocks[2] = get_block;
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
if (get_block) { if (get_block) {
ut_a(page_is_comp(get_block->frame) ut_a(page_is_comp(get_block->page.frame)
== page_is_comp(block->frame)); == page_is_comp(block->page.frame));
ut_a(btr_page_get_prev(get_block->frame) ut_a(btr_page_get_prev(get_block->page.frame)
== block->page.id().page_no()); == block->page.id().page_no());
} }
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
@@ -338,10 +336,10 @@ btr_cur_latch_leaves(
case BTR_SEARCH_PREV: case BTR_SEARCH_PREV:
case BTR_MODIFY_PREV: case BTR_MODIFY_PREV:
mode = latch_mode == BTR_SEARCH_PREV ? RW_S_LATCH : RW_X_LATCH; mode = latch_mode == BTR_SEARCH_PREV ? RW_S_LATCH : RW_X_LATCH;
/* latch also left sibling */ /* Because we are holding index->lock, no page splits
block->lock.s_lock(); or merges may run concurrently, and we may read
left_page_no = btr_page_get_prev(block->frame); FIL_PAGE_PREV from a buffer-fixed, unlatched page. */
block->lock.s_unlock(); left_page_no = btr_page_get_prev(block->page.frame);
if (left_page_no != FIL_NULL) { if (left_page_no != FIL_NULL) {
latch_leaves.savepoints[0] = mtr_set_savepoint(mtr); latch_leaves.savepoints[0] = mtr_set_savepoint(mtr);
@@ -351,9 +349,9 @@ btr_cur_latch_leaves(
latch_leaves.blocks[0] = get_block; latch_leaves.blocks[0] = get_block;
cursor->left_block = get_block; cursor->left_block = get_block;
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) ut_a(page_is_comp(get_block->page.frame)
== page_is_comp(block->frame)); == page_is_comp(block->page.frame));
ut_a(btr_page_get_next(get_block->frame) ut_a(btr_page_get_next(get_block->page.frame)
== block->page.id().page_no()); == block->page.id().page_no());
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
} }
@@ -364,8 +362,8 @@ btr_cur_latch_leaves(
true, mtr); true, mtr);
latch_leaves.blocks[1] = get_block; latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) ut_a(page_is_comp(get_block->page.frame)
== page_is_comp(block->frame)); == page_is_comp(block->page.frame));
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
return(latch_leaves); return(latch_leaves);
case BTR_CONT_MODIFY_TREE: case BTR_CONT_MODIFY_TREE:
@@ -402,13 +400,13 @@ unreadable:
buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr); buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr);
if (!root || btr_cur_instant_root_init(index, root->frame)) { if (!root || btr_cur_instant_root_init(index, root->page.frame)) {
goto unreadable; goto unreadable;
} }
ut_ad(index->n_core_null_bytes != dict_index_t::NO_CORE_NULL_BYTES); ut_ad(index->n_core_null_bytes != dict_index_t::NO_CORE_NULL_BYTES);
if (fil_page_get_type(root->frame) == FIL_PAGE_INDEX) { if (fil_page_get_type(root->page.frame) == FIL_PAGE_INDEX) {
ut_ad(!index->is_instant()); ut_ad(!index->is_instant());
return DB_SUCCESS; return DB_SUCCESS;
} }
@@ -426,7 +424,7 @@ unreadable:
} }
ut_ad(page_cur_is_before_first(&cur.page_cur)); ut_ad(page_cur_is_before_first(&cur.page_cur));
ut_ad(page_is_leaf(cur.page_cur.block->frame)); ut_ad(page_is_leaf(cur.page_cur.block->page.frame));
page_cur_move_to_next(&cur.page_cur); page_cur_move_to_next(&cur.page_cur);
@@ -551,20 +549,22 @@ incompatible:
page_id_t(space->id, page_id_t(space->id,
mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)), mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)),
0, RW_S_LATCH, mtr); 0, RW_S_LATCH, mtr);
if (fil_page_get_type(block->frame) != FIL_PAGE_TYPE_BLOB if (fil_page_get_type(block->page.frame) != FIL_PAGE_TYPE_BLOB
|| mach_read_from_4(&block->frame[FIL_PAGE_DATA || mach_read_from_4(&block->page.frame
+ BTR_BLOB_HDR_NEXT_PAGE_NO]) [FIL_PAGE_DATA
+ BTR_BLOB_HDR_NEXT_PAGE_NO])
!= FIL_NULL != FIL_NULL
|| mach_read_from_4(&block->frame[FIL_PAGE_DATA || mach_read_from_4(&block->page.frame
+ BTR_BLOB_HDR_PART_LEN]) [FIL_PAGE_DATA
+ BTR_BLOB_HDR_PART_LEN])
!= len) { != len) {
goto incompatible; goto incompatible;
} }
/* The unused part of the BLOB page should be zero-filled. */ /* The unused part of the BLOB page should be zero-filled. */
for (const byte* b = block->frame for (const byte* b = block->page.frame
+ (FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE) + len, + (FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE) + len,
* const end = block->frame + srv_page_size * const end = block->page.frame + srv_page_size
- BTR_EXTERN_LEN; - BTR_EXTERN_LEN;
b < end; ) { b < end; ) {
if (*b++) { if (*b++) {
@@ -573,8 +573,8 @@ incompatible:
} }
if (index->table->deserialise_columns( if (index->table->deserialise_columns(
&block->frame[FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE], &block->page.frame
len)) { [FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE], len)) {
goto incompatible; goto incompatible;
} }
@@ -753,6 +753,7 @@ bool btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
@param[in,out] cursor cursor @param[in,out] cursor cursor
@param[in] mtr mini-transaction @param[in] mtr mini-transaction
@return true if success */ @return true if success */
TRANSACTIONAL_TARGET
bool bool
btr_cur_optimistic_latch_leaves( btr_cur_optimistic_latch_leaves(
buf_block_t* block, buf_block_t* block,
@@ -762,7 +763,8 @@ btr_cur_optimistic_latch_leaves(
mtr_t* mtr) mtr_t* mtr)
{ {
ut_ad(block->page.buf_fix_count()); ut_ad(block->page.buf_fix_count());
ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); ut_ad(block->page.in_file());
ut_ad(block->page.frame);
switch (*latch_mode) { switch (*latch_mode) {
default: default:
@@ -774,14 +776,16 @@ btr_cur_optimistic_latch_leaves(
modify_clock, mtr)); modify_clock, mtr));
case BTR_SEARCH_PREV: case BTR_SEARCH_PREV:
case BTR_MODIFY_PREV: case BTR_MODIFY_PREV:
block->lock.s_lock(); uint32_t curr_page_no, left_page_no;
if (block->modify_clock != modify_clock) { {
block->lock.s_unlock(); transactional_shared_lock_guard<block_lock> g{
return false; block->page.lock};
if (block->modify_clock != modify_clock) {
return false;
}
curr_page_no = block->page.id().page_no();
left_page_no = btr_page_get_prev(block->page.frame);
} }
const uint32_t curr_page_no = block->page.id().page_no();
const uint32_t left_page_no = btr_page_get_prev(block->frame);
block->lock.s_unlock();
const rw_lock_type_t mode = *latch_mode == BTR_SEARCH_PREV const rw_lock_type_t mode = *latch_mode == BTR_SEARCH_PREV
? RW_S_LATCH : RW_X_LATCH; ? RW_S_LATCH : RW_X_LATCH;
@@ -797,12 +801,10 @@ btr_cur_optimistic_latch_leaves(
if (!cursor->left_block) { if (!cursor->left_block) {
cursor->index->table->file_unreadable = true; cursor->index->table->file_unreadable = true;
} } else if (cursor->left_block->page.is_freed()
|| btr_page_get_next(
if (cursor->left_block->page.status cursor->left_block->page.frame)
== buf_page_t::FREED != curr_page_no) {
|| btr_page_get_next(cursor->left_block->frame)
!= curr_page_no) {
/* release the left block */ /* release the left block */
btr_leaf_page_release( btr_leaf_page_release(
cursor->left_block, mode, mtr); cursor->left_block, mode, mtr);
@@ -813,7 +815,8 @@ btr_cur_optimistic_latch_leaves(
} }
if (buf_page_optimistic_get(mode, block, modify_clock, mtr)) { if (buf_page_optimistic_get(mode, block, modify_clock, mtr)) {
if (btr_page_get_prev(block->frame) == left_page_no) { if (btr_page_get_prev(block->page.frame)
== left_page_no) {
/* block was already buffer-fixed while /* block was already buffer-fixed while
entering the function and entering the function and
buf_page_optimistic_get() buffer-fixes buf_page_optimistic_get() buffer-fixes
@@ -1271,7 +1274,6 @@ btr_cur_search_to_nth_level_func(
ulint n_releases = 0; ulint n_releases = 0;
bool detected_same_key_root = false; bool detected_same_key_root = false;
bool retrying_for_search_prev = false;
ulint leftmost_from_level = 0; ulint leftmost_from_level = 0;
buf_block_t** prev_tree_blocks = NULL; buf_block_t** prev_tree_blocks = NULL;
ulint* prev_tree_savepoints = NULL; ulint* prev_tree_savepoints = NULL;
@@ -1494,9 +1496,6 @@ x_latch_index:
default: default:
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
if (s_latch_by_caller) { if (s_latch_by_caller) {
ut_ad(mtr->memo_contains_flagged(
&index->lock, MTR_MEMO_S_LOCK
| MTR_MEMO_SX_LOCK));
} else if (!modify_external) { } else if (!modify_external) {
/* BTR_SEARCH_TREE is intended to be used with /* BTR_SEARCH_TREE is intended to be used with
BTR_ALREADY_S_LATCHED */ BTR_ALREADY_S_LATCHED */
@@ -1568,7 +1567,7 @@ search_loop:
if (height != 0) { if (height != 0) {
/* We are about to fetch the root or a non-leaf page. */ /* We are about to fetch the root or a non-leaf page. */
if ((latch_mode != BTR_MODIFY_TREE || height == level) if ((latch_mode != BTR_MODIFY_TREE || height == level)
&& !retrying_for_search_prev) { && !prev_tree_blocks) {
/* If doesn't have SX or X latch of index, /* If doesn't have SX or X latch of index,
each pages should be latched before reading. */ each pages should be latched before reading. */
if (height == ULINT_UNDEFINED if (height == ULINT_UNDEFINED
@@ -1698,18 +1697,18 @@ retry_page_get:
goto retry_page_get; goto retry_page_get;
} }
if (retrying_for_search_prev && height != 0) { if (height && prev_tree_blocks) {
/* also latch left sibling */ /* also latch left sibling */
uint32_t left_page_no;
buf_block_t* get_block; buf_block_t* get_block;
ut_ad(rw_latch == RW_NO_LATCH); ut_ad(rw_latch == RW_NO_LATCH);
rw_latch = upper_rw_latch; rw_latch = upper_rw_latch;
block->lock.s_lock(); /* Because we are holding index->lock, no page splits
left_page_no = btr_page_get_prev(buf_block_get_frame(block)); or merges may run concurrently, and we may read
block->lock.s_unlock(); FIL_PAGE_PREV from a buffer-fixed, unlatched page. */
uint32_t left_page_no = btr_page_get_prev(block->page.frame);
if (left_page_no != FIL_NULL) { if (left_page_no != FIL_NULL) {
ut_ad(prev_n_blocks < leftmost_from_level); ut_ad(prev_n_blocks < leftmost_from_level);
@@ -1852,7 +1851,7 @@ retry_page_get:
} }
/* release upper blocks */ /* release upper blocks */
if (retrying_for_search_prev) { if (prev_tree_blocks) {
ut_ad(!autoinc); ut_ad(!autoinc);
for (; for (;
prev_n_releases < prev_n_blocks; prev_n_releases < prev_n_blocks;
@@ -2006,14 +2005,14 @@ retry_page_get:
} }
if (rw_latch == RW_NO_LATCH && height != 0) { if (rw_latch == RW_NO_LATCH && height != 0) {
block->lock.s_lock(); block->page.lock.s_lock();
} }
lock_prdt_lock(block, &prdt, index, LOCK_S, lock_prdt_lock(block, &prdt, index, LOCK_S,
LOCK_PREDICATE, cursor->thr); LOCK_PREDICATE, cursor->thr);
if (rw_latch == RW_NO_LATCH && height != 0) { if (rw_latch == RW_NO_LATCH && height != 0) {
block->lock.s_unlock(); block->page.lock.s_unlock();
} }
} }
@@ -2087,7 +2086,7 @@ need_opposite_intention:
ut_ad(mtr->memo_contains_flagged( ut_ad(mtr->memo_contains_flagged(
&index->lock, MTR_MEMO_X_LOCK &index->lock, MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK)); | MTR_MEMO_SX_LOCK));
block->lock.s_lock(); block->page.lock.s_lock();
add_latch = true; add_latch = true;
} }
@@ -2119,7 +2118,7 @@ need_opposite_intention:
} }
if (add_latch) { if (add_latch) {
block->lock.s_unlock(); block->page.lock.s_unlock();
} }
ut_ad(!page_rec_is_supremum(node_ptr)); ut_ad(!page_rec_is_supremum(node_ptr));
@@ -2238,7 +2237,7 @@ need_opposite_intention:
BTR_MODIFY_PREV latches prev_page of the leaf page. */ BTR_MODIFY_PREV latches prev_page of the leaf page. */
if ((latch_mode == BTR_SEARCH_PREV if ((latch_mode == BTR_SEARCH_PREV
|| latch_mode == BTR_MODIFY_PREV) || latch_mode == BTR_MODIFY_PREV)
&& !retrying_for_search_prev) { && !prev_tree_blocks) {
/* block should be latched for consistent /* block should be latched for consistent
btr_page_get_prev() */ btr_page_get_prev() */
ut_ad(mtr->memo_contains_flagged( ut_ad(mtr->memo_contains_flagged(
@@ -2258,8 +2257,6 @@ need_opposite_intention:
if (height == 0 && leftmost_from_level > 0) { if (height == 0 && leftmost_from_level > 0) {
/* should retry to get also prev_page /* should retry to get also prev_page
from level==leftmost_from_level. */ from level==leftmost_from_level. */
retrying_for_search_prev = true;
prev_tree_blocks = static_cast<buf_block_t**>( prev_tree_blocks = static_cast<buf_block_t**>(
ut_malloc_nokey(sizeof(buf_block_t*) ut_malloc_nokey(sizeof(buf_block_t*)
* leftmost_from_level)); * leftmost_from_level));
@@ -2481,10 +2478,8 @@ func_exit:
mem_heap_free(heap); mem_heap_free(heap);
} }
if (retrying_for_search_prev) { ut_free(prev_tree_blocks);
ut_free(prev_tree_blocks); ut_free(prev_tree_savepoints);
ut_free(prev_tree_savepoints);
}
if (mbr_adj) { if (mbr_adj) {
/* remember that we will need to adjust parent MBR */ /* remember that we will need to adjust parent MBR */
@@ -3321,12 +3316,12 @@ Prefetch siblings of the leaf for the pessimistic operation.
static void btr_cur_prefetch_siblings(const buf_block_t *block, static void btr_cur_prefetch_siblings(const buf_block_t *block,
const dict_index_t *index) const dict_index_t *index)
{ {
ut_ad(page_is_leaf(block->frame)); ut_ad(page_is_leaf(block->page.frame));
if (index->is_ibuf()) if (index->is_ibuf())
return; return;
const page_t *page= block->frame; const page_t *page= block->page.frame;
uint32_t prev= mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_PREV)); uint32_t prev= mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_PREV));
uint32_t next= mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_NEXT)); uint32_t next= mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_NEXT));
@@ -4255,7 +4250,7 @@ btr_cur_update_in_place(
roll_ptr_t roll_ptr = 0; roll_ptr_t roll_ptr = 0;
ulint was_delete_marked; ulint was_delete_marked;
ut_ad(page_is_leaf(cursor->page_cur.block->frame)); ut_ad(page_is_leaf(cursor->page_cur.block->page.frame));
rec = btr_cur_get_rec(cursor); rec = btr_cur_get_rec(cursor);
index = cursor->index; index = cursor->index;
ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_validate(rec, index, offsets));
@@ -4425,15 +4420,15 @@ static void btr_cur_trim_alter_metadata(dtuple_t* entry,
page_id_t(index->table->space->id, page_id_t(index->table->space->id,
mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)), mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)),
0, RW_S_LATCH, &mtr); 0, RW_S_LATCH, &mtr);
ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_TYPE_BLOB); ut_ad(fil_page_get_type(block->page.frame) == FIL_PAGE_TYPE_BLOB);
ut_ad(mach_read_from_4(&block->frame[FIL_PAGE_DATA ut_ad(mach_read_from_4(&block->page.frame
+ BTR_BLOB_HDR_NEXT_PAGE_NO]) [FIL_PAGE_DATA + BTR_BLOB_HDR_NEXT_PAGE_NO])
== FIL_NULL); == FIL_NULL);
ut_ad(mach_read_from_4(&block->frame[FIL_PAGE_DATA ut_ad(mach_read_from_4(&block->page.frame
+ BTR_BLOB_HDR_PART_LEN]) [FIL_PAGE_DATA + BTR_BLOB_HDR_PART_LEN])
== mach_read_from_4(ptr + BTR_EXTERN_LEN + 4)); == mach_read_from_4(ptr + BTR_EXTERN_LEN + 4));
n_fields = mach_read_from_4( n_fields = mach_read_from_4(
&block->frame[FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE]) &block->page.frame[FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE])
+ index->first_user_field(); + index->first_user_field();
/* Rollback should not increase the number of fields. */ /* Rollback should not increase the number of fields. */
ut_ad(n_fields <= index->n_fields); ut_ad(n_fields <= index->n_fields);
@@ -4839,7 +4834,7 @@ btr_cur_pess_upd_restore_supremum(
prev_block = buf_page_get_with_no_latch(prev_id, block->zip_size(), prev_block = buf_page_get_with_no_latch(prev_id, block->zip_size(),
mtr); mtr);
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(prev_block->frame) ut_a(btr_page_get_next(prev_block->page.frame)
== block->page.id().page_no()); == block->page.id().page_no());
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
@@ -4910,7 +4905,8 @@ btr_cur_pessimistic_update(
MTR_MEMO_SX_LOCK)); MTR_MEMO_SX_LOCK));
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index)); ut_a(!page_zip
|| page_zip_validate(page_zip, block->page.frame, index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
ut_ad(!page_zip || !index->table->is_temporary()); ut_ad(!page_zip || !index->table->is_temporary());
/* The insert buffer tree should never be updated in place. */ /* The insert buffer tree should never be updated in place. */
@@ -4943,7 +4939,7 @@ btr_cur_pessimistic_update(
if (page_zip if (page_zip
&& optim_err != DB_ZIP_OVERFLOW && optim_err != DB_ZIP_OVERFLOW
&& !dict_index_is_clust(index) && !dict_index_is_clust(index)
&& page_is_leaf(block->frame)) { && page_is_leaf(block->page.frame)) {
ut_ad(!index->table->is_temporary()); ut_ad(!index->table->is_temporary());
ibuf_update_free_bits_zip(block, mtr); ibuf_update_free_bits_zip(block, mtr);
} }
@@ -4990,7 +4986,7 @@ btr_cur_pessimistic_update(
/* We have to set appropriate extern storage bits in the new /* We have to set appropriate extern storage bits in the new
record to be inserted: we have to remember which fields were such */ record to be inserted: we have to remember which fields were such */
ut_ad(!page_is_comp(block->frame) || !rec_get_node_ptr_flag(rec)); ut_ad(!page_is_comp(block->page.frame) || !rec_get_node_ptr_flag(rec));
ut_ad(rec_offs_validate(rec, index, *offsets)); ut_ad(rec_offs_validate(rec, index, *offsets));
if ((flags & BTR_NO_UNDO_LOG_FLAG) if ((flags & BTR_NO_UNDO_LOG_FLAG)
@@ -5016,7 +5012,7 @@ btr_cur_pessimistic_update(
if (page_zip_rec_needs_ext( if (page_zip_rec_needs_ext(
rec_get_converted_size(index, new_entry, n_ext), rec_get_converted_size(index, new_entry, n_ext),
page_is_comp(block->frame), page_is_comp(block->page.frame),
dict_index_get_n_fields(index), dict_index_get_n_fields(index),
block->zip_size()) block->zip_size())
|| (UNIV_UNLIKELY(update->is_alter_metadata()) || (UNIV_UNLIKELY(update->is_alter_metadata())
@@ -5032,7 +5028,7 @@ btr_cur_pessimistic_update(
BTR_KEEP_IBUF_BITMAP. */ BTR_KEEP_IBUF_BITMAP. */
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip ut_a(!page_zip
|| page_zip_validate(page_zip, block->frame, || page_zip_validate(page_zip, block->page.frame,
index)); index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
index->table->space->release_free_extents(n_reserved); index->table->space->release_free_extents(n_reserved);
@@ -5040,7 +5036,7 @@ btr_cur_pessimistic_update(
goto err_exit; goto err_exit;
} }
ut_ad(page_is_leaf(block->frame)); ut_ad(page_is_leaf(block->page.frame));
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
ut_ad(flags & BTR_KEEP_POS_FLAG); ut_ad(flags & BTR_KEEP_POS_FLAG);
} }
@@ -5076,8 +5072,9 @@ btr_cur_pessimistic_update(
} }
const ulint max_ins_size = page_zip const ulint max_ins_size = page_zip
? 0 : page_get_max_insert_size_after_reorganize(block->frame, ? 0
1); : page_get_max_insert_size_after_reorganize(block->page.frame,
1);
if (UNIV_UNLIKELY(is_metadata)) { if (UNIV_UNLIKELY(is_metadata)) {
ut_ad(new_entry->is_metadata()); ut_ad(new_entry->is_metadata());
@@ -5105,7 +5102,8 @@ btr_cur_pessimistic_update(
} }
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index)); ut_a(!page_zip
|| page_zip_validate(page_zip, block->page.frame, index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
page_cursor = btr_cur_get_page_cur(cursor); page_cursor = btr_cur_get_page_cur(cursor);
@@ -5151,7 +5149,7 @@ btr_cur_pessimistic_update(
} }
bool adjust = big_rec_vec && (flags & BTR_KEEP_POS_FLAG); bool adjust = big_rec_vec && (flags & BTR_KEEP_POS_FLAG);
ut_ad(!adjust || page_is_leaf(block->frame)); ut_ad(!adjust || page_is_leaf(block->page.frame));
if (btr_cur_compress_if_useful(cursor, adjust, mtr)) { if (btr_cur_compress_if_useful(cursor, adjust, mtr)) {
if (adjust) { if (adjust) {
@@ -5159,7 +5157,7 @@ btr_cur_pessimistic_update(
true, *offsets); true, *offsets);
} }
} else if (!dict_index_is_clust(index) } else if (!dict_index_is_clust(index)
&& page_is_leaf(block->frame)) { && page_is_leaf(block->page.frame)) {
/* Update the free bits in the insert buffer. /* Update the free bits in the insert buffer.
This is the same block which was skipped by This is the same block which was skipped by
BTR_KEEP_IBUF_BITMAP. */ BTR_KEEP_IBUF_BITMAP. */
@@ -5174,7 +5172,7 @@ btr_cur_pessimistic_update(
if (!srv_read_only_mode if (!srv_read_only_mode
&& !big_rec_vec && !big_rec_vec
&& page_is_leaf(block->frame) && page_is_leaf(block->page.frame)
&& !dict_index_is_online_ddl(index)) { && !dict_index_is_online_ddl(index)) {
mtr_memo_release(mtr, &index->lock, mtr_memo_release(mtr, &index->lock,
@@ -5199,13 +5197,13 @@ btr_cur_pessimistic_update(
BTR_KEEP_IBUF_BITMAP. */ BTR_KEEP_IBUF_BITMAP. */
if (!dict_index_is_clust(index) if (!dict_index_is_clust(index)
&& !index->table->is_temporary() && !index->table->is_temporary()
&& page_is_leaf(block->frame)) { && page_is_leaf(block->page.frame)) {
ibuf_reset_free_bits(block); ibuf_reset_free_bits(block);
} }
} }
if (big_rec_vec != NULL) { if (big_rec_vec != NULL) {
ut_ad(page_is_leaf(block->frame)); ut_ad(page_is_leaf(block->page.frame));
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
ut_ad(flags & BTR_KEEP_POS_FLAG); ut_ad(flags & BTR_KEEP_POS_FLAG);
@@ -5260,8 +5258,8 @@ btr_cur_pessimistic_update(
/* The new inserted record owns its possible externally /* The new inserted record owns its possible externally
stored fields */ stored fields */
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, block->frame, ut_a(!page_zip
index)); || page_zip_validate(page_zip, block->page.frame, index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
btr_cur_unmark_extern_fields(btr_cur_get_block(cursor), rec, btr_cur_unmark_extern_fields(btr_cur_get_block(cursor), rec,
index, *offsets, mtr); index, *offsets, mtr);
@@ -5511,7 +5509,7 @@ btr_cur_optimistic_delete_func(
} }
if (UNIV_UNLIKELY(block->page.id().page_no() == cursor->index->page if (UNIV_UNLIKELY(block->page.id().page_no() == cursor->index->page
&& page_get_n_recs(block->frame) == 1 && page_get_n_recs(block->page.frame) == 1
+ (cursor->index->is_instant() + (cursor->index->is_instant()
&& !rec_is_metadata(rec, *cursor->index)) && !rec_is_metadata(rec, *cursor->index))
&& !cursor->index->must_avoid_clear_instant_add())) { && !cursor->index->must_avoid_clear_instant_add())) {
@@ -5523,7 +5521,7 @@ btr_cur_optimistic_delete_func(
table becomes empty, clean up the whole page. */ table becomes empty, clean up the whole page. */
dict_index_t* index = cursor->index; dict_index_t* index = cursor->index;
const rec_t* first_rec = page_rec_get_next_const( const rec_t* first_rec = page_rec_get_next_const(
page_get_infimum_rec(block->frame)); page_get_infimum_rec(block->page.frame));
ut_ad(!index->is_instant() ut_ad(!index->is_instant()
|| rec_is_metadata(first_rec, *index)); || rec_is_metadata(first_rec, *index));
const bool is_metadata = rec_is_metadata(rec, *index); const bool is_metadata = rec_is_metadata(rec, *index);
@@ -5974,9 +5972,9 @@ btr_cur_add_path_info(
const buf_block_t* block = btr_cur_get_block(cursor); const buf_block_t* block = btr_cur_get_block(cursor);
slot->nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor)); slot->nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
slot->n_recs = page_get_n_recs(block->frame); slot->n_recs = page_get_n_recs(block->page.frame);
slot->page_no = block->page.id().page_no(); slot->page_no = block->page.id().page_no();
slot->page_level = btr_page_get_level(block->frame); slot->page_level = btr_page_get_level(block->page.frame);
} }
/*******************************************************************//** /*******************************************************************//**
@@ -6796,7 +6794,7 @@ struct btr_blob_log_check_t {
m_op(op) m_op(op)
{ {
ut_ad(rec_offs_validate(*m_rec, m_pcur->index(), m_offsets)); ut_ad(rec_offs_validate(*m_rec, m_pcur->index(), m_offsets));
ut_ad((*m_block)->frame == page_align(*m_rec)); ut_ad((*m_block)->page.frame == page_align(*m_rec));
ut_ad(*m_rec == btr_pcur_get_rec(m_pcur)); ut_ad(*m_rec == btr_pcur_get_rec(m_pcur));
} }
@@ -6811,7 +6809,7 @@ struct btr_blob_log_check_t {
if (UNIV_UNLIKELY(m_op == BTR_STORE_INSERT_BULK)) { if (UNIV_UNLIKELY(m_op == BTR_STORE_INSERT_BULK)) {
offs = page_offset(*m_rec); offs = page_offset(*m_rec);
page_no = (*m_block)->page.id().page_no(); page_no = (*m_block)->page.id().page_no();
buf_block_buf_fix_inc(*m_block); (*m_block)->page.fix();
ut_ad(page_no != FIL_NULL); ut_ad(page_no != FIL_NULL);
} else { } else {
btr_pcur_store_position(m_pcur, m_mtr); btr_pcur_store_position(m_pcur, m_mtr);
@@ -6833,10 +6831,10 @@ struct btr_blob_log_check_t {
m_pcur->btr_cur.page_cur.block = btr_block_get( m_pcur->btr_cur.page_cur.block = btr_block_get(
*index, page_no, RW_X_LATCH, false, m_mtr); *index, page_no, RW_X_LATCH, false, m_mtr);
m_pcur->btr_cur.page_cur.rec m_pcur->btr_cur.page_cur.rec
= m_pcur->btr_cur.page_cur.block->frame = m_pcur->btr_cur.page_cur.block->page.frame
+ offs; + offs;
buf_block_buf_fix_dec(m_pcur->btr_cur.page_cur.block); m_pcur->btr_cur.page_cur.block->page.unfix();
} else { } else {
ut_ad(m_pcur->rel_pos == BTR_PCUR_ON); ut_ad(m_pcur->rel_pos == BTR_PCUR_ON);
bool ret = btr_pcur_restore_position( bool ret = btr_pcur_restore_position(
@@ -7047,42 +7045,43 @@ btr_store_big_rec_extern_fields(
if (page_zip) { if (page_zip) {
mtr.write<4>(*prev_block, mtr.write<4>(*prev_block,
prev_block->frame prev_block->page.frame
+ FIL_PAGE_NEXT, + FIL_PAGE_NEXT,
page_no); page_no);
memcpy_aligned<4>( memcpy_aligned<4>(
buf_block_get_page_zip( buf_block_get_page_zip(
prev_block) prev_block)
->data + FIL_PAGE_NEXT, ->data + FIL_PAGE_NEXT,
prev_block->frame prev_block->page.frame
+ FIL_PAGE_NEXT, 4); + FIL_PAGE_NEXT, 4);
} else { } else {
mtr.write<4>(*prev_block, mtr.write<4>(*prev_block,
BTR_BLOB_HDR_NEXT_PAGE_NO BTR_BLOB_HDR_NEXT_PAGE_NO
+ FIL_PAGE_DATA + FIL_PAGE_DATA
+ prev_block->frame, + prev_block->page.frame,
page_no); page_no);
} }
} else if (dict_index_is_online_ddl(index)) { } else if (dict_index_is_online_ddl(index)) {
row_log_table_blob_alloc(index, page_no); row_log_table_blob_alloc(index, page_no);
} }
ut_ad(!page_has_siblings(block->frame)); ut_ad(!page_has_siblings(block->page.frame));
ut_ad(!fil_page_get_type(block->frame)); ut_ad(!fil_page_get_type(block->page.frame));
if (page_zip) { if (page_zip) {
int err; int err;
page_zip_des_t* blob_page_zip; page_zip_des_t* blob_page_zip;
mtr.write<1>(*block, mtr.write<1>(*block,
FIL_PAGE_TYPE + 1 + block->frame, FIL_PAGE_TYPE + 1
+ block->page.frame,
prev_page_no == FIL_NULL prev_page_no == FIL_NULL
? FIL_PAGE_TYPE_ZBLOB ? FIL_PAGE_TYPE_ZBLOB
: FIL_PAGE_TYPE_ZBLOB2); : FIL_PAGE_TYPE_ZBLOB2);
block->page.zip.data[FIL_PAGE_TYPE + 1] block->page.zip.data[FIL_PAGE_TYPE + 1]
= block->frame[FIL_PAGE_TYPE + 1]; = block->page.frame[FIL_PAGE_TYPE + 1];
c_stream.next_out = block->frame c_stream.next_out = block->page.frame
+ FIL_PAGE_DATA; + FIL_PAGE_DATA;
c_stream.avail_out = static_cast<uInt>( c_stream.avail_out = static_cast<uInt>(
payload_size_zip); payload_size_zip);
@@ -7104,7 +7103,7 @@ btr_store_big_rec_extern_fields(
ut_ad(blob_page_zip); ut_ad(blob_page_zip);
ut_ad(page_zip_get_size(blob_page_zip) ut_ad(page_zip_get_size(blob_page_zip)
== page_zip_get_size(page_zip)); == page_zip_get_size(page_zip));
memcpy(blob_page_zip->data, block->frame, memcpy(blob_page_zip->data, block->page.frame,
page_zip_get_size(page_zip)); page_zip_get_size(page_zip));
if (err == Z_OK && prev_page_no != FIL_NULL) { if (err == Z_OK && prev_page_no != FIL_NULL) {
@@ -7157,7 +7156,7 @@ next_zip_page:
} }
} else { } else {
mtr.write<1>(*block, FIL_PAGE_TYPE + 1 mtr.write<1>(*block, FIL_PAGE_TYPE + 1
+ block->frame, + block->page.frame,
FIL_PAGE_TYPE_BLOB); FIL_PAGE_TYPE_BLOB);
if (extern_len > payload_size) { if (extern_len > payload_size) {
@@ -7169,13 +7168,14 @@ next_zip_page:
mtr.memcpy<mtr_t::MAYBE_NOP>( mtr.memcpy<mtr_t::MAYBE_NOP>(
*block, *block,
FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE
+ block->frame, + block->page.frame,
static_cast<const byte*> static_cast<const byte*>
(big_rec_vec->fields[i].data) (big_rec_vec->fields[i].data)
+ big_rec_vec->fields[i].len + big_rec_vec->fields[i].len
- extern_len, store_len); - extern_len, store_len);
mtr.write<4>(*block, BTR_BLOB_HDR_PART_LEN mtr.write<4>(*block, BTR_BLOB_HDR_PART_LEN
+ FIL_PAGE_DATA + block->frame, + FIL_PAGE_DATA
+ block->page.frame,
store_len); store_len);
compile_time_assert(FIL_NULL == 0xffffffff); compile_time_assert(FIL_NULL == 0xffffffff);
mtr.memset(block, BTR_BLOB_HDR_NEXT_PAGE_NO mtr.memset(block, BTR_BLOB_HDR_NEXT_PAGE_NO
@@ -7259,7 +7259,7 @@ func_exit:
@param[in] read true=read, false=purge */ @param[in] read true=read, false=purge */
static void btr_check_blob_fil_page_type(const buf_block_t& block, bool read) static void btr_check_blob_fil_page_type(const buf_block_t& block, bool read)
{ {
uint16_t type= fil_page_get_type(block.frame); uint16_t type= fil_page_get_type(block.page.frame);
if (UNIV_LIKELY(type == FIL_PAGE_TYPE_BLOB)) if (UNIV_LIKELY(type == FIL_PAGE_TYPE_BLOB))
return; return;
@@ -7710,11 +7710,13 @@ inflate_error:
} }
end_of_blob: end_of_blob:
buf_page_release_zip(bpage); bpage->lock.s_unlock();
bpage->unfix();
goto func_exit; goto func_exit;
} }
buf_page_release_zip(bpage); bpage->lock.s_unlock();
bpage->unfix();
/* On other BLOB pages except the first /* On other BLOB pages except the first
the BLOB header always is at the page header: */ the BLOB header always is at the page header: */

View File

@@ -476,7 +476,7 @@ btr_defragment_n_pages(
/* It doesn't make sense to call this function with n_pages = 1. */ /* It doesn't make sense to call this function with n_pages = 1. */
ut_ad(n_pages > 1); ut_ad(n_pages > 1);
if (!page_is_leaf(block->frame)) { if (!page_is_leaf(block->page.frame)) {
return NULL; return NULL;
} }

View File

@@ -112,8 +112,9 @@ btr_pcur_store_position(
page_cursor = btr_pcur_get_page_cur(cursor); page_cursor = btr_pcur_get_page_cur(cursor);
rec = page_cur_get_rec(page_cursor); rec = page_cur_get_rec(page_cursor);
offs = rec - block->frame; offs = rec - block->page.frame;
ut_ad(block->page.id().page_no() == page_get_page_no(block->frame)); ut_ad(block->page.id().page_no()
== page_get_page_no(block->page.frame));
ut_ad(block->page.buf_fix_count()); ut_ad(block->page.buf_fix_count());
/* For spatial index, when we do positioning on parent /* For spatial index, when we do positioning on parent
buffer if necessary, it might not hold latches, but the buffer if necessary, it might not hold latches, but the
@@ -126,13 +127,13 @@ btr_pcur_store_position(
cursor->old_stored = true; cursor->old_stored = true;
if (page_is_empty(block->frame)) { if (page_is_empty(block->page.frame)) {
/* It must be an empty index tree; NOTE that in this case /* It must be an empty index tree; NOTE that in this case
we do not store the modify_clock, but always do a search we do not store the modify_clock, but always do a search
if we restore the cursor position */ if we restore the cursor position */
ut_a(!page_has_siblings(block->frame)); ut_a(!page_has_siblings(block->page.frame));
ut_ad(page_is_leaf(block->frame)); ut_ad(page_is_leaf(block->page.frame));
ut_ad(block->page.id().page_no() == index->page); ut_ad(block->page.id().page_no() == index->page);
if (page_rec_is_supremum_low(offs)) { if (page_rec_is_supremum_low(offs)) {
@@ -159,9 +160,9 @@ before_first:
#endif #endif
ut_ad(index->is_instant() ut_ad(index->is_instant()
|| block->page.id().page_no() != index->page); || block->page.id().page_no() != index->page);
ut_ad(page_get_n_recs(block->frame) == 1); ut_ad(page_get_n_recs(block->page.frame) == 1);
ut_ad(page_is_leaf(block->frame)); ut_ad(page_is_leaf(block->page.frame));
ut_ad(!page_has_prev(block->frame)); ut_ad(!page_has_prev(block->page.frame));
cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE; cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
return; return;
} }
@@ -171,7 +172,7 @@ before_first:
rec = page_rec_get_next(rec); rec = page_rec_get_next(rec);
if (rec_is_metadata(rec, *index)) { if (rec_is_metadata(rec, *index)) {
ut_ad(!page_has_prev(block->frame)); ut_ad(!page_has_prev(block->page.frame));
rec = page_rec_get_next(rec); rec = page_rec_get_next(rec);
if (page_rec_is_supremum(rec)) { if (page_rec_is_supremum(rec)) {
goto before_first; goto before_first;

View File

@@ -409,14 +409,10 @@ static
bool bool
btr_search_update_block_hash_info(btr_search_t* info, buf_block_t* block) btr_search_update_block_hash_info(btr_search_t* info, buf_block_t* block)
{ {
ut_ad(block->lock.have_x() || block->lock.have_s()); ut_ad(block->page.lock.have_x() || block->page.lock.have_s());
info->last_hash_succ = FALSE; info->last_hash_succ = FALSE;
ut_d(auto state= block->page.state()); ut_ad(buf_pool.is_uncompressed(block));
ut_ad(state == BUF_BLOCK_NOT_USED
|| state == BUF_BLOCK_FILE_PAGE
|| state == BUF_BLOCK_MEMORY
|| state == BUF_BLOCK_REMOVE_HASH);
ut_ad(info->magic_n == BTR_SEARCH_MAGIC_N); ut_ad(info->magic_n == BTR_SEARCH_MAGIC_N);
if ((block->n_hash_helps > 0) if ((block->n_hash_helps > 0)
@@ -444,13 +440,13 @@ btr_search_update_block_hash_info(btr_search_t* info, buf_block_t* block)
block->left_side = info->left_side; block->left_side = info->left_side;
} }
if ((block->n_hash_helps > page_get_n_recs(block->frame) if ((block->n_hash_helps > page_get_n_recs(block->page.frame)
/ BTR_SEARCH_PAGE_BUILD_LIMIT) / BTR_SEARCH_PAGE_BUILD_LIMIT)
&& (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) { && (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) {
if ((!block->index) if ((!block->index)
|| (block->n_hash_helps || (block->n_hash_helps
> 2U * page_get_n_recs(block->frame)) > 2U * page_get_n_recs(block->page.frame))
|| (block->n_fields != block->curr_n_fields) || (block->n_fields != block->curr_n_fields)
|| (block->n_bytes != block->curr_n_bytes) || (block->n_bytes != block->curr_n_bytes)
|| (block->left_side != block->curr_left_side)) { || (block->left_side != block->curr_left_side)) {
@@ -489,7 +485,7 @@ static bool ha_insert_for_fold(hash_table_t *table, mem_heap_t* heap,
const rec_t *data) const rec_t *data)
{ {
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(block->frame == page_align(data)); ut_a(block->page.frame == page_align(data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
ut_ad(btr_search_enabled); ut_ad(btr_search_enabled);
@@ -502,7 +498,7 @@ static bool ha_insert_for_fold(hash_table_t *table, mem_heap_t* heap,
{ {
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t *prev_block= prev->block; buf_block_t *prev_block= prev->block;
ut_a(prev_block->frame == page_align(prev->data)); ut_a(prev_block->page.frame == page_align(prev->data));
ut_a(prev_block->n_pointers-- < MAX_N_POINTERS); ut_a(prev_block->n_pointers-- < MAX_N_POINTERS);
ut_a(block->n_pointers++ < MAX_N_POINTERS); ut_a(block->n_pointers++ < MAX_N_POINTERS);
@@ -550,7 +546,7 @@ static void ha_delete_hash_node(hash_table_t *table, mem_heap_t *heap,
{ {
ut_ad(btr_search_enabled); ut_ad(btr_search_enabled);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(del_node->block->frame == page_align(del_node->data)); ut_a(del_node->block->page.frame == page_align(del_node->data));
ut_a(del_node->block->n_pointers-- < MAX_N_POINTERS); ut_a(del_node->block->n_pointers-- < MAX_N_POINTERS);
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
@@ -650,7 +646,7 @@ static bool ha_search_and_update_if_found(hash_table_t *table, ulint fold,
const rec_t *new_data) const rec_t *new_data)
{ {
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(new_block->frame == page_align(new_data)); ut_a(new_block->page.frame == page_align(new_data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
if (!btr_search_enabled) if (!btr_search_enabled)
@@ -697,9 +693,9 @@ btr_search_update_hash_ref(
{ {
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL); ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
ut_ad(block->lock.have_x() || block->lock.have_s()); ut_ad(block->page.lock.have_x() || block->page.lock.have_s());
ut_ad(page_align(btr_cur_get_rec(cursor)) == block->frame); ut_ad(page_align(btr_cur_get_rec(cursor)) == block->page.frame);
ut_ad(page_is_leaf(block->frame)); ut_ad(page_is_leaf(block->page.frame));
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
dict_index_t* index = block->index; dict_index_t* index = block->index;
@@ -935,15 +931,15 @@ inline void buf_pool_t::clear_hash_index()
continue; continue;
} }
ut_d(buf_page_state state= block->page.state()); ut_d(const auto s= block->page.state());
/* Another thread may have set the state to /* Another thread may have set the state to
BUF_BLOCK_REMOVE_HASH in buf_LRU_block_remove_hashed(). REMOVE_HASH in buf_LRU_block_remove_hashed().
The state change in buf_pool_t::realloc() is not observable The state change in buf_pool_t::realloc() is not observable
here, because in that case we would have !block->index. here, because in that case we would have !block->index.
In the end, the entire adaptive hash index will be removed. */ In the end, the entire adaptive hash index will be removed. */
ut_ad(state == BUF_BLOCK_FILE_PAGE || state == BUF_BLOCK_REMOVE_HASH); ut_ad(s >= buf_page_t::UNFIXED || s == buf_page_t::REMOVE_HASH);
# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG # if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
block->n_pointers= 0; block->n_pointers= 0;
# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ # endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
@@ -974,18 +970,19 @@ inline buf_block_t* buf_pool_t::block_from_ahi(const byte *ptr) const
? chunk_map->rbegin()->second ? chunk_map->rbegin()->second
: (--it)->second; : (--it)->second;
const size_t offs= size_t(ptr - chunk->blocks->frame) >> srv_page_size_shift; const size_t offs= size_t(ptr - chunk->blocks->page.frame) >>
srv_page_size_shift;
ut_a(offs < chunk->size); ut_a(offs < chunk->size);
buf_block_t *block= &chunk->blocks[offs]; buf_block_t *block= &chunk->blocks[offs];
/* buf_pool_t::chunk_t::init() invokes buf_block_init() so that /* buf_pool_t::chunk_t::init() invokes buf_block_init() so that
block[n].frame == block->frame + n * srv_page_size. Check it. */ block[n].frame == block->page.frame + n * srv_page_size. Check it. */
ut_ad(block->frame == page_align(ptr)); ut_ad(block->page.frame == page_align(ptr));
/* Read the state of the block without holding hash_lock. /* Read the state of the block without holding hash_lock.
A state transition from BUF_BLOCK_FILE_PAGE to A state transition to REMOVE_HASH is possible during
BUF_BLOCK_REMOVE_HASH is possible during this execution. */ this execution. */
ut_d(const buf_page_state state = block->page.state()); ut_ad(block->page.state() >= buf_page_t::REMOVE_HASH);
ut_ad(state == BUF_BLOCK_FILE_PAGE || state == BUF_BLOCK_REMOVE_HASH);
return block; return block;
} }
@@ -1093,48 +1090,47 @@ fail:
if (!ahi_latch) { if (!ahi_latch) {
buf_pool_t::hash_chain& chain = buf_pool.page_hash.cell_get( buf_pool_t::hash_chain& chain = buf_pool.page_hash.cell_get(
block->page.id().fold()); block->page.id().fold());
bool fail; bool fail, got_latch;
{ {
transactional_shared_lock_guard<page_hash_latch> g{ transactional_shared_lock_guard<page_hash_latch> g{
buf_pool.page_hash.lock_get(chain)}; buf_pool.page_hash.lock_get(chain)};
switch (block->page.state()) { const auto state = block->page.state();
case BUF_BLOCK_REMOVE_HASH: if (state == buf_page_t::REMOVE_HASH) {
/* Another thread is just freeing the block /* Another thread is just freeing the block
from the LRU list of the buffer pool: do not from the LRU list of the buffer pool: do not
try to access this page. */ try to access this page. */
goto fail; goto fail;
case BUF_BLOCK_FILE_PAGE: }
break; if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED)) {
default:
#ifndef NO_ELISION #ifndef NO_ELISION
xend(); xend();
#endif #endif
ut_error; ut_error;
} }
block->fix();
fail = index != block->index fail = index != block->index
&& index_id == block->index->id; && index_id == block->index->id;
got_latch = (latch_mode == BTR_SEARCH_LEAF)
? block->page.lock.s_lock_try()
: block->page.lock.x_lock_try();
} }
ut_a(!fail || block->index->freed()); ut_a(!fail || block->index->freed());
block->page.set_accessed(); if (!got_latch) {
goto fail;
}
block->page.fix();
block->page.set_accessed();
buf_page_make_young_if_needed(&block->page); buf_page_make_young_if_needed(&block->page);
mtr_memo_type_t fix_type; mtr_memo_type_t fix_type;
if (latch_mode == BTR_SEARCH_LEAF) { if (latch_mode == BTR_SEARCH_LEAF) {
if (!block->lock.s_lock_try()) {
got_no_latch:
buf_block_buf_fix_dec(block);
goto fail;
}
fix_type = MTR_MEMO_PAGE_S_FIX; fix_type = MTR_MEMO_PAGE_S_FIX;
ut_ad(!block->page.is_read_fixed());
} else { } else {
if (!block->lock.x_lock_try()) {
goto got_no_latch;
}
fix_type = MTR_MEMO_PAGE_X_FIX; fix_type = MTR_MEMO_PAGE_X_FIX;
ut_ad(!block->page.is_io_fixed());
} }
mtr->memo_push(block, fix_type); mtr->memo_push(block, fix_type);
@@ -1146,16 +1142,15 @@ got_no_latch:
goto fail_and_release_page; goto fail_and_release_page;
} }
DBUG_ASSERT(block->page.status != buf_page_t::FREED); DBUG_ASSERT(!block->page.is_freed());
} else if (UNIV_UNLIKELY(index != block->index } else if (UNIV_UNLIKELY(index != block->index
&& index_id == block->index->id)) { && index_id == block->index->id)) {
ut_a(block->index->freed()); ut_a(block->index->freed());
goto fail_and_release_page; goto fail_and_release_page;
} }
if (block->page.state() != BUF_BLOCK_FILE_PAGE) { if (!block->page.in_file()) {
ut_ad(block->page.state() == buf_page_t::REMOVE_HASH);
ut_ad(block->page.state() == BUF_BLOCK_REMOVE_HASH);
fail_and_release_page: fail_and_release_page:
if (!ahi_latch) { if (!ahi_latch) {
@@ -1177,7 +1172,7 @@ fail_and_release_page:
is positioned on. We cannot look at the next of the previous is positioned on. We cannot look at the next of the previous
record to determine if our guess for the cursor position is record to determine if our guess for the cursor position is
right. */ right. */
if (index_id != btr_page_get_index_id(block->frame) if (index_id != btr_page_get_index_id(block->page.frame)
|| !btr_search_check_guess(cursor, !!ahi_latch, tuple, mode)) { || !btr_search_check_guess(cursor, !!ahi_latch, tuple, mode)) {
goto fail_and_release_page; goto fail_and_release_page;
} }
@@ -1268,17 +1263,21 @@ retry:
return; return;
} }
ut_ad(!block->page.buf_fix_count() ut_d(const auto state = block->page.state());
|| block->page.state() == BUF_BLOCK_REMOVE_HASH ut_ad(state == buf_page_t::REMOVE_HASH
|| block->lock.have_any()); || state >= buf_page_t::UNFIXED);
ut_ad(page_is_leaf(block->frame)); ut_ad(state == buf_page_t::REMOVE_HASH
|| !(~buf_page_t::LRU_MASK & state)
|| block->page.lock.have_any());
ut_ad(state < buf_page_t::READ_FIX || state >= buf_page_t::WRITE_FIX);
ut_ad(page_is_leaf(block->page.frame));
/* We must not dereference block->index here, because it could be freed /* We must not dereference block->index here, because it could be freed
if (!index->table->get_ref_count() && !dict_sys.frozen()). if (!index->table->get_ref_count() && !dict_sys.frozen()).
Determine the ahi_slot based on the block contents. */ Determine the ahi_slot based on the block contents. */
const index_id_t index_id const index_id_t index_id
= btr_page_get_index_id(block->frame); = btr_page_get_index_id(block->page.frame);
auto part = btr_search_sys.get_part(index_id, auto part = btr_search_sys.get_part(index_id,
block->page.id().space()); block->page.id().space());
@@ -1322,7 +1321,7 @@ retry:
ut_a(n_fields > 0 || n_bytes > 0); ut_a(n_fields > 0 || n_bytes > 0);
page = block->frame; page = block->page.frame;
n_recs = page_get_n_recs(page); n_recs = page_get_n_recs(page);
/* Calculate and cache fold values into an array for fast deletion /* Calculate and cache fold values into an array for fast deletion
@@ -1441,7 +1440,7 @@ void btr_search_drop_page_hash_when_freed(const page_id_t page_id)
if (block) { if (block) {
/* If AHI is still valid, page can't be in free state. /* If AHI is still valid, page can't be in free state.
AHI is dropped when page is freed. */ AHI is dropped when page is freed. */
DBUG_ASSERT(block->page.status != buf_page_t::FREED); DBUG_ASSERT(!block->page.is_freed());
if (block->index) { if (block->index) {
/* In all our callers, the table handle should /* In all our callers, the table handle should
@@ -1499,9 +1498,9 @@ btr_search_build_page_hash_index(
ut_ad(index); ut_ad(index);
ut_ad(block->page.id().space() == index->table->space_id); ut_ad(block->page.id().space() == index->table->space_id);
ut_ad(!dict_index_is_ibuf(index)); ut_ad(!dict_index_is_ibuf(index));
ut_ad(page_is_leaf(block->frame)); ut_ad(page_is_leaf(block->page.frame));
ut_ad(block->lock.have_x() || block->lock.have_s()); ut_ad(block->page.lock.have_x() || block->page.lock.have_s());
ut_ad(block->page.id().page_no() >= 3); ut_ad(block->page.id().page_no() >= 3);
ahi_latch->rd_lock(SRW_LOCK_CALL); ahi_latch->rd_lock(SRW_LOCK_CALL);
@@ -1722,8 +1721,8 @@ btr_search_move_or_delete_hash_entries(
buf_block_t* new_block, buf_block_t* new_block,
buf_block_t* block) buf_block_t* block)
{ {
ut_ad(block->lock.have_x()); ut_ad(block->page.lock.have_x());
ut_ad(new_block->lock.have_x()); ut_ad(new_block->page.lock.have_x());
if (!btr_search_enabled) { if (!btr_search_enabled) {
return; return;
@@ -1804,7 +1803,7 @@ void btr_search_update_hash_on_delete(btr_cur_t *cursor)
block = btr_cur_get_block(cursor); block = btr_cur_get_block(cursor);
ut_ad(block->lock.have_x()); ut_ad(block->page.lock.have_x());
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
index = block->index; index = block->index;
@@ -1879,7 +1878,7 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
block = btr_cur_get_block(cursor); block = btr_cur_get_block(cursor);
ut_ad(block->lock.have_x()); ut_ad(block->page.lock.have_x());
index = block->index; index = block->index;
@@ -1962,7 +1961,7 @@ void btr_search_update_hash_on_insert(btr_cur_t *cursor,
block = btr_cur_get_block(cursor); block = btr_cur_get_block(cursor);
ut_ad(block->lock.have_x()); ut_ad(block->page.lock.have_x());
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
index = block->index; index = block->index;
@@ -2210,9 +2209,7 @@ btr_search_hash_table_validate(ulint hash_table_id)
= buf_pool.block_from_ahi((byte*) node->data); = buf_pool.block_from_ahi((byte*) node->data);
index_id_t page_index_id; index_id_t page_index_id;
if (UNIV_LIKELY(block->page.state() if (UNIV_LIKELY(block->page.in_file())) {
== BUF_BLOCK_FILE_PAGE)) {
/* The space and offset are only valid /* The space and offset are only valid
for file blocks. It is possible that for file blocks. It is possible that
the block is being freed the block is being freed
@@ -2233,13 +2230,15 @@ btr_search_hash_table_validate(ulint hash_table_id)
the block from buf_pool.page_hash by calling the block from buf_pool.page_hash by calling
buf_LRU_block_remove_hashed_page(). Then it buf_LRU_block_remove_hashed_page(). Then it
invokes btr_search_drop_page_hash_index(). */ invokes btr_search_drop_page_hash_index(). */
ut_a(block->page.state() == BUF_BLOCK_REMOVE_HASH); ut_a(block->page.state() == buf_page_t::REMOVE_HASH);
state_ok: state_ok:
ut_ad(!dict_index_is_ibuf(block->index)); ut_ad(!dict_index_is_ibuf(block->index));
ut_ad(block->page.id().space() ut_ad(block->page.id().space()
== block->index->table->space_id); == block->index->table->space_id);
page_index_id = btr_page_get_index_id(block->frame); const page_t* page = block->page.frame;
page_index_id = btr_page_get_index_id(page);
offsets = rec_get_offsets( offsets = rec_get_offsets(
node->data, block->index, offsets, node->data, block->index, offsets,
@@ -2255,8 +2254,6 @@ state_ok:
page_index_id); page_index_id);
if (node->fold != fold) { if (node->fold != fold) {
const page_t* page = block->frame;
ok = FALSE; ok = FALSE;
ib::error() << "Error in an adaptive hash" ib::error() << "Error in an adaptive hash"

View File

@@ -43,16 +43,15 @@ void Block_hint::buffer_fix_block_if_still_valid()
different page, and that slice of buf_pool.page_hash could be protected different page, and that slice of buf_pool.page_hash could be protected
by another hash_lock that we are not holding.) by another hash_lock that we are not holding.)
Finally, assuming that we have correct hash bucket latched, we must Finally, we must ensure that the block is not being freed. */
validate m_block->state() to ensure that the block is not being freed. */
if (m_block) if (m_block)
{ {
auto &cell= buf_pool.page_hash.cell_get(m_page_id.fold()); auto &cell= buf_pool.page_hash.cell_get(m_page_id.fold());
transactional_shared_lock_guard<page_hash_latch> g transactional_shared_lock_guard<page_hash_latch> g
{buf_pool.page_hash.lock_get(cell)}; {buf_pool.page_hash.lock_get(cell)};
if (buf_pool.is_uncompressed(m_block) && m_page_id == m_block->page.id() && if (buf_pool.is_uncompressed(m_block) && m_page_id == m_block->page.id() &&
m_block->page.state() == BUF_BLOCK_FILE_PAGE) m_block->page.frame && m_block->page.in_file())
m_block->fix(); m_block->page.fix();
else else
clear(); clear();
} }

View File

@@ -354,11 +354,11 @@ buf_buddy_block_free(void* buf)
ut_a(!ut_align_offset(buf, srv_page_size)); ut_a(!ut_align_offset(buf, srv_page_size));
HASH_SEARCH(hash, &buf_pool.zip_hash, fold, buf_page_t*, bpage, HASH_SEARCH(hash, &buf_pool.zip_hash, fold, buf_page_t*, bpage,
ut_ad(bpage->state() == BUF_BLOCK_MEMORY ut_ad(bpage->state() == buf_page_t::MEMORY
&& bpage->in_zip_hash), && bpage->in_zip_hash),
((buf_block_t*) bpage)->frame == buf); bpage->frame == buf);
ut_a(bpage); ut_a(bpage);
ut_a(bpage->state() == BUF_BLOCK_MEMORY); ut_a(bpage->state() == buf_page_t::MEMORY);
ut_ad(bpage->in_zip_hash); ut_ad(bpage->in_zip_hash);
ut_d(bpage->in_zip_hash = false); ut_d(bpage->in_zip_hash = false);
HASH_DELETE(buf_page_t, hash, &buf_pool.zip_hash, fold, bpage); HASH_DELETE(buf_page_t, hash, &buf_pool.zip_hash, fold, bpage);
@@ -383,10 +383,10 @@ buf_buddy_block_register(
buf_block_t* block) /*!< in: buffer frame to allocate */ buf_block_t* block) /*!< in: buffer frame to allocate */
{ {
const ulint fold = BUF_POOL_ZIP_FOLD(block); const ulint fold = BUF_POOL_ZIP_FOLD(block);
ut_ad(block->page.state() == BUF_BLOCK_MEMORY); ut_ad(block->page.state() == buf_page_t::MEMORY);
ut_a(block->frame); ut_a(block->page.frame);
ut_a(!ut_align_offset(block->frame, srv_page_size)); ut_a(!ut_align_offset(block->page.frame, srv_page_size));
ut_ad(!block->page.in_zip_hash); ut_ad(!block->page.in_zip_hash);
ut_d(block->page.in_zip_hash = true); ut_d(block->page.in_zip_hash = true);
@@ -462,8 +462,8 @@ byte *buf_buddy_alloc_low(ulint i, bool *lru)
alloc_big: alloc_big:
buf_buddy_block_register(block); buf_buddy_block_register(block);
block = (buf_block_t*) buf_buddy_alloc_from( block = reinterpret_cast<buf_block_t*>(
block->frame, i, BUF_BUDDY_SIZES); buf_buddy_alloc_from(block->page.frame, i, BUF_BUDDY_SIZES));
func_exit: func_exit:
buf_pool.buddy_stat[i].used++; buf_pool.buddy_stat[i].used++;
@@ -694,7 +694,7 @@ buf_buddy_realloc(void* buf, ulint size)
block = reinterpret_cast<buf_block_t*>( block = reinterpret_cast<buf_block_t*>(
buf_buddy_alloc_from( buf_buddy_alloc_from(
block->frame, i, BUF_BUDDY_SIZES)); block->page.frame, i, BUF_BUDDY_SIZES));
} }
buf_pool.buddy_stat[i].used++; buf_pool.buddy_stat[i].used++;

File diff suppressed because it is too large Load Diff

View File

@@ -86,11 +86,12 @@ start_again:
buf_block_t *trx_sys_block= buf_dblwr_trx_sys_get(&mtr); buf_block_t *trx_sys_block= buf_dblwr_trx_sys_get(&mtr);
if (mach_read_from_4(TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC + if (mach_read_from_4(TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC +
trx_sys_block->frame) == TRX_SYS_DOUBLEWRITE_MAGIC_N) trx_sys_block->page.frame) ==
TRX_SYS_DOUBLEWRITE_MAGIC_N)
{ {
/* The doublewrite buffer has already been created: just read in /* The doublewrite buffer has already been created: just read in
some numbers */ some numbers */
init(TRX_SYS_DOUBLEWRITE + trx_sys_block->frame); init(TRX_SYS_DOUBLEWRITE + trx_sys_block->page.frame);
mtr.commit(); mtr.commit();
return true; return true;
} }
@@ -121,7 +122,7 @@ too_small:
} }
byte *fseg_header= TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG + byte *fseg_header= TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG +
trx_sys_block->frame; trx_sys_block->page.frame;
for (uint32_t prev_page_no= 0, i= 0, extent_size= FSP_EXTENT_SIZE; for (uint32_t prev_page_no= 0, i= 0, extent_size= FSP_EXTENT_SIZE;
i < 2 * size + extent_size / 2; i++) i < 2 * size + extent_size / 2; i++)
{ {
@@ -149,12 +150,12 @@ too_small:
tablespace, then the page has not been written to in tablespace, then the page has not been written to in
doublewrite. */ doublewrite. */
ut_ad(new_block->lock.not_recursive()); ut_ad(new_block->page.lock.not_recursive());
const page_id_t id= new_block->page.id(); const page_id_t id= new_block->page.id();
/* We only do this in the debug build, to ensure that the check in /* We only do this in the debug build, to ensure that the check in
buf_flush_init_for_writing() will see a valid page type. The buf_flush_init_for_writing() will see a valid page type. The
flushes of new_block are actually unnecessary here. */ flushes of new_block are actually unnecessary here. */
ut_d(mtr.write<2>(*new_block, FIL_PAGE_TYPE + new_block->frame, ut_d(mtr.write<2>(*new_block, FIL_PAGE_TYPE + new_block->page.frame,
FIL_PAGE_TYPE_SYS)); FIL_PAGE_TYPE_SYS));
if (i == size / 2) if (i == size / 2)
@@ -162,10 +163,10 @@ too_small:
ut_a(id.page_no() == size); ut_a(id.page_no() == size);
mtr.write<4>(*trx_sys_block, mtr.write<4>(*trx_sys_block,
TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_BLOCK1 + TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_BLOCK1 +
trx_sys_block->frame, id.page_no()); trx_sys_block->page.frame, id.page_no());
mtr.write<4>(*trx_sys_block, mtr.write<4>(*trx_sys_block,
TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_REPEAT + TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_REPEAT +
TRX_SYS_DOUBLEWRITE_BLOCK1 + trx_sys_block->frame, TRX_SYS_DOUBLEWRITE_BLOCK1 + trx_sys_block->page.frame,
id.page_no()); id.page_no());
} }
else if (i == size / 2 + size) else if (i == size / 2 + size)
@@ -173,10 +174,10 @@ too_small:
ut_a(id.page_no() == 2 * size); ut_a(id.page_no() == 2 * size);
mtr.write<4>(*trx_sys_block, mtr.write<4>(*trx_sys_block,
TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_BLOCK2 + TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_BLOCK2 +
trx_sys_block->frame, id.page_no()); trx_sys_block->page.frame, id.page_no());
mtr.write<4>(*trx_sys_block, mtr.write<4>(*trx_sys_block,
TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_REPEAT + TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_REPEAT +
TRX_SYS_DOUBLEWRITE_BLOCK2 + trx_sys_block->frame, TRX_SYS_DOUBLEWRITE_BLOCK2 + trx_sys_block->page.frame,
id.page_no()); id.page_no());
} }
else if (i > size / 2) else if (i > size / 2)
@@ -193,7 +194,7 @@ too_small:
mtr.start(); mtr.start();
trx_sys_block= buf_dblwr_trx_sys_get(&mtr); trx_sys_block= buf_dblwr_trx_sys_get(&mtr);
fseg_header= TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG + fseg_header= TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG +
trx_sys_block->frame; trx_sys_block->page.frame;
} }
prev_page_no= id.page_no(); prev_page_no= id.page_no();
@@ -201,15 +202,16 @@ too_small:
mtr.write<4>(*trx_sys_block, mtr.write<4>(*trx_sys_block,
TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC + TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC +
trx_sys_block->frame, TRX_SYS_DOUBLEWRITE_MAGIC_N); trx_sys_block->page.frame, TRX_SYS_DOUBLEWRITE_MAGIC_N);
mtr.write<4>(*trx_sys_block, mtr.write<4>(*trx_sys_block,
TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC + TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC +
TRX_SYS_DOUBLEWRITE_REPEAT + trx_sys_block->frame, TRX_SYS_DOUBLEWRITE_REPEAT + trx_sys_block->page.frame,
TRX_SYS_DOUBLEWRITE_MAGIC_N); TRX_SYS_DOUBLEWRITE_MAGIC_N);
mtr.write<4>(*trx_sys_block, mtr.write<4>(*trx_sys_block,
TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED + TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED +
trx_sys_block->frame, TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N); trx_sys_block->page.frame,
TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N);
mtr.commit(); mtr.commit();
/* Flush the modified pages to disk and make a checkpoint */ /* Flush the modified pages to disk and make a checkpoint */
@@ -519,8 +521,9 @@ static void buf_dblwr_check_page_lsn(const buf_page_t &b, const byte *page)
/** Check the LSN values on the page with which this block is associated. */ /** Check the LSN values on the page with which this block is associated. */
static void buf_dblwr_check_block(const buf_page_t *bpage) static void buf_dblwr_check_block(const buf_page_t *bpage)
{ {
ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE); ut_ad(bpage->in_file());
const page_t *page= reinterpret_cast<const buf_block_t*>(bpage)->frame; const page_t *page= bpage->frame;
ut_ad(page);
switch (fil_page_get_type(page)) { switch (fil_page_get_type(page)) {
case FIL_PAGE_INDEX: case FIL_PAGE_INDEX:
@@ -594,8 +597,8 @@ bool buf_dblwr_t::flush_buffered_writes(const ulint size)
ut_d(buf_dblwr_check_page_lsn(*bpage, write_buf + len2)); ut_d(buf_dblwr_check_page_lsn(*bpage, write_buf + len2));
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
const IORequest request(nullptr, fil_system.sys_space->chain.start, const IORequest request{nullptr, nullptr, fil_system.sys_space->chain.start,
IORequest::DBLWR_BATCH); IORequest::DBLWR_BATCH};
ut_a(fil_system.sys_space->acquire()); ut_a(fil_system.sys_space->acquire());
if (multi_batch) if (multi_batch)
{ {
@@ -614,6 +617,14 @@ bool buf_dblwr_t::flush_buffered_writes(const ulint size)
return true; return true;
} }
static void *get_frame(const IORequest &request)
{
if (request.slot)
return request.slot->out_buf;
const buf_page_t *bpage= request.bpage;
return bpage->zip.data ? bpage->zip.data : bpage->frame;
}
void buf_dblwr_t::flush_buffered_writes_completed(const IORequest &request) void buf_dblwr_t::flush_buffered_writes_completed(const IORequest &request)
{ {
ut_ad(this == &buf_dblwr); ut_ad(this == &buf_dblwr);
@@ -651,9 +662,8 @@ void buf_dblwr_t::flush_buffered_writes_completed(const IORequest &request)
buf_page_t* bpage= e.request.bpage; buf_page_t* bpage= e.request.bpage;
ut_ad(bpage->in_file()); ut_ad(bpage->in_file());
/* We request frame here to get correct buffer in case of void *frame= get_frame(e.request);
encryption and/or page compression */ ut_ad(frame);
void *frame= buf_page_get_frame(bpage);
auto e_size= e.size; auto e_size= e.size;
@@ -664,7 +674,6 @@ void buf_dblwr_t::flush_buffered_writes_completed(const IORequest &request)
} }
else else
{ {
ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE);
ut_ad(!bpage->zip_size()); ut_ad(!bpage->zip_size());
ut_d(buf_dblwr_check_page_lsn(*bpage, static_cast<const byte*>(frame))); ut_d(buf_dblwr_check_page_lsn(*bpage, static_cast<const byte*>(frame)));
} }
@@ -732,13 +741,9 @@ void buf_dblwr_t::add_to_batch(const IORequest &request, size_t size)
byte *p= active_slot->write_buf + srv_page_size * active_slot->first_free; byte *p= active_slot->write_buf + srv_page_size * active_slot->first_free;
/* We request frame here to get correct buffer in case of
encryption and/or page compression */
void *frame= buf_page_get_frame(request.bpage);
/* "frame" is at least 1024-byte aligned for ROW_FORMAT=COMPRESSED pages, /* "frame" is at least 1024-byte aligned for ROW_FORMAT=COMPRESSED pages,
and at least srv_page_size (4096-byte) for everything else. */ and at least srv_page_size (4096-byte) for everything else. */
memcpy_aligned<UNIV_ZIP_SIZE_MIN>(p, frame, size); memcpy_aligned<UNIV_ZIP_SIZE_MIN>(p, get_frame(request), size);
/* fil_page_compress() for page_compressed guarantees 256-byte alignment */ /* fil_page_compress() for page_compressed guarantees 256-byte alignment */
memset_aligned<256>(p + size, 0, srv_page_size - size); memset_aligned<256>(p + size, 0, srv_page_size - size);
/* FIXME: Inform the compiler that "size" and "srv_page_size - size" /* FIXME: Inform the compiler that "size" and "srv_page_size - size"

View File

@@ -328,19 +328,18 @@ buf_dump(
for (bpage = UT_LIST_GET_FIRST(buf_pool.LRU), j = 0; for (bpage = UT_LIST_GET_FIRST(buf_pool.LRU), j = 0;
bpage != NULL && j < n_pages; bpage != NULL && j < n_pages;
bpage = UT_LIST_GET_NEXT(LRU, bpage)) { bpage = UT_LIST_GET_NEXT(LRU, bpage)) {
const auto status = bpage->state();
ut_a(bpage->in_file()); if (status < buf_page_t::UNFIXED) {
const page_id_t id(bpage->id()); ut_a(status >= buf_page_t::FREED);
continue;
}
const page_id_t id{bpage->id()};
if (id.space() == SRV_TMP_SPACE_ID) { if (id.space() == SRV_TMP_SPACE_ID) {
/* Ignore the innodb_temporary tablespace. */ /* Ignore the innodb_temporary tablespace. */
continue; continue;
} }
if (bpage->status == buf_page_t::FREED) {
continue;
}
dump[j++] = id; dump[j++] = id;
} }

View File

@@ -195,7 +195,7 @@ void buf_pool_t::insert_into_flush_list(buf_block_t *block, lsn_t lsn)
block->page.set_oldest_modification(lsn); block->page.set_oldest_modification(lsn);
MEM_CHECK_DEFINED(block->page.zip.data MEM_CHECK_DEFINED(block->page.zip.data
? block->page.zip.data : block->frame, ? block->page.zip.data : block->page.frame,
block->physical_size()); block->physical_size());
UT_LIST_ADD_FIRST(flush_list, &block->page); UT_LIST_ADD_FIRST(flush_list, &block->page);
ut_d(buf_flush_validate_skip()); ut_d(buf_flush_validate_skip());
@@ -236,15 +236,15 @@ void buf_flush_remove_pages(uint32_t id)
for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; ) for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; )
{ {
ut_d(const auto s= bpage->state()); const auto s= bpage->state();
ut_ad(s == BUF_BLOCK_ZIP_PAGE || s == BUF_BLOCK_FILE_PAGE || ut_ad(s >= buf_page_t::REMOVE_HASH);
s == BUF_BLOCK_REMOVE_HASH); ut_ad(s < buf_page_t::READ_FIX || s >= buf_page_t::WRITE_FIX);
buf_page_t *prev= UT_LIST_GET_PREV(list, bpage); buf_page_t *prev= UT_LIST_GET_PREV(list, bpage);
const page_id_t bpage_id(bpage->id()); const page_id_t bpage_id(bpage->id());
if (bpage_id < first || bpage_id >= end); if (bpage_id < first || bpage_id >= end);
else if (bpage->io_fix() != BUF_IO_NONE) else if (s >= buf_page_t::WRITE_FIX)
deferred= true; deferred= true;
else else
buf_pool.delete_from_flush_list(bpage); buf_pool.delete_from_flush_list(bpage);
@@ -322,42 +322,59 @@ buf_flush_relocate_on_flush_list(
ut_d(buf_flush_validate_low()); ut_d(buf_flush_validate_low());
} }
/** Note that a block is no longer dirty, while not removing
it from buf_pool.flush_list */
inline void buf_page_t::write_complete(bool temporary)
{
ut_ad(temporary == fsp_is_system_temporary(id().space()));
if (temporary)
{
ut_ad(oldest_modification() == 2);
oldest_modification_= 0;
}
else
{
/* We use release memory order to guarantee that callers of
oldest_modification_acquire() will observe the block as
being detached from buf_pool.flush_list, after reading the value 0. */
ut_ad(oldest_modification() > 2);
oldest_modification_.store(1, std::memory_order_release);
}
const auto s= state();
ut_ad(s >= WRITE_FIX);
zip.fix.fetch_sub((s >= WRITE_FIX_REINIT)
? (WRITE_FIX_REINIT - UNFIXED)
: (WRITE_FIX - UNFIXED));
lock.u_unlock(true);
}
/** Complete write of a file page from buf_pool. /** Complete write of a file page from buf_pool.
@param request write request */ @param request write request */
void buf_page_write_complete(const IORequest &request) void buf_page_write_complete(const IORequest &request)
{ {
ut_ad(request.is_write()); ut_ad(request.is_write());
ut_ad(!srv_read_only_mode/* || ut_ad(!srv_read_only_mode);
request.node->space->purpose == FIL_TYPE_TEMPORARY*/);
buf_page_t *bpage= request.bpage; buf_page_t *bpage= request.bpage;
ut_ad(bpage); ut_ad(bpage);
ut_ad(bpage->in_file()); const auto state= bpage->state();
/* bpage->io_fix() can only be changed by buf_page_write_complete() /* io-fix can only be cleared by buf_page_t::write_complete()
and buf_page_read_complete() from BUF_IO_READ or BUF_IO_WRITE */ and buf_page_t::read_complete() */
ut_ad(bpage->io_fix() == BUF_IO_WRITE); ut_ad(state >= buf_page_t::WRITE_FIX);
ut_ad(!buf_dblwr.is_inside(bpage->id())); ut_ad(!buf_dblwr.is_inside(bpage->id()));
ut_ad(request.node->space->id == bpage->id().space()); ut_ad(request.node->space->id == bpage->id().space());
if (bpage->status == buf_page_t::INIT_ON_FLUSH) if (state < buf_page_t::WRITE_FIX_REINIT &&
bpage->status= buf_page_t::NORMAL; request.node->space->use_doublewrite())
else
{ {
ut_ad(bpage->status == buf_page_t::NORMAL); ut_ad(request.node->space != fil_system.temp_space);
if (request.node->space->use_doublewrite()) buf_dblwr.write_completed();
{
ut_ad(request.node->space != fil_system.temp_space);
buf_dblwr.write_completed();
}
} }
if (bpage->slot) if (request.slot)
{ request.slot->release();
bpage->slot->release();
bpage->slot= nullptr;
}
if (UNIV_UNLIKELY(MONITOR_IS_ON(MONITOR_MODULE_BUF_PAGE))) if (UNIV_UNLIKELY(MONITOR_IS_ON(MONITOR_MODULE_BUF_PAGE)))
buf_page_monitor(bpage, BUF_IO_WRITE); buf_page_monitor(*bpage, false);
DBUG_PRINT("ib_buf", ("write page %u:%u", DBUG_PRINT("ib_buf", ("write page %u:%u",
bpage->id().space(), bpage->id().page_no())); bpage->id().space(), bpage->id().page_no()));
const bool temp= fsp_is_system_temporary(bpage->id().space()); const bool temp= fsp_is_system_temporary(bpage->id().space());
@@ -365,16 +382,7 @@ void buf_page_write_complete(const IORequest &request)
mysql_mutex_lock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.mutex);
mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex); mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex);
buf_pool.stat.n_pages_written++; buf_pool.stat.n_pages_written++;
/* While we do not need any mutex for clearing oldest_modification bpage->write_complete(temp);
here, we hope that it will be in the same cache line with io_fix,
whose changes must be protected by buf_pool.mutex. */
ut_ad(temp || bpage->oldest_modification() > 2);
bpage->clear_oldest_modification(temp);
ut_ad(bpage->io_fix() == BUF_IO_WRITE);
bpage->set_io_fix(BUF_IO_NONE);
if (bpage->state() == BUF_BLOCK_FILE_PAGE)
reinterpret_cast<buf_block_t*>(bpage)->lock.u_unlock(true);
if (request.is_LRU()) if (request.is_LRU())
{ {
@@ -437,16 +445,14 @@ buf_flush_init_for_writing(
void* page_zip_, void* page_zip_,
bool use_full_checksum) bool use_full_checksum)
{ {
if (block != NULL && block->frame != page) { if (block && block->page.frame != page) {
/* If page is encrypted in full crc32 format then /* If page is encrypted in full crc32 format then
checksum stored already as a part of fil_encrypt_buf() */ checksum stored already as a part of fil_encrypt_buf() */
ut_ad(use_full_checksum); ut_ad(use_full_checksum);
return; return;
} }
ut_ad(block == NULL || block->frame == page); ut_ad(!block || block->page.frame == page);
ut_ad(block == NULL || page_zip_ == NULL
|| &block->page.zip == page_zip_);
ut_ad(page); ut_ad(page);
if (page_zip_) { if (page_zip_) {
@@ -454,6 +460,7 @@ buf_flush_init_for_writing(
ulint size; ulint size;
page_zip = static_cast<page_zip_des_t*>(page_zip_); page_zip = static_cast<page_zip_des_t*>(page_zip_);
ut_ad(!block || &block->page.zip == page_zip);
size = page_zip_get_size(page_zip); size = page_zip_get_size(page_zip);
ut_ad(size); ut_ad(size);
@@ -618,10 +625,11 @@ a page is written to disk.
@return page frame to be written to file @return page frame to be written to file
(may be src_frame or an encrypted/compressed copy of it) */ (may be src_frame or an encrypted/compressed copy of it) */
static byte *buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s, static byte *buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s,
size_t *size) buf_tmp_buffer_t **slot, size_t *size)
{ {
ut_ad(bpage->status != buf_page_t::FREED); ut_ad(!bpage->is_freed());
ut_ad(space->id == bpage->id().space()); ut_ad(space->id == bpage->id().space());
ut_ad(!*slot);
ut_d(fil_page_type_validate(space, s)); ut_d(fil_page_type_validate(space, s));
const uint32_t page_no= bpage->id().page_no(); const uint32_t page_no= bpage->id().page_no();
@@ -677,31 +685,25 @@ static byte *buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s,
ut_ad(!bpage->zip_size() || !page_compressed); ut_ad(!bpage->zip_size() || !page_compressed);
/* Find free slot from temporary memory array */ /* Find free slot from temporary memory array */
buf_tmp_buffer_t *slot= buf_pool.io_buf_reserve(); *slot= buf_pool.io_buf_reserve();
ut_a(slot); ut_a(*slot);
slot->allocate(); (*slot)->allocate();
slot->out_buf= NULL;
bpage->slot= slot;
byte *d= slot->crypt_buf; byte *d= (*slot)->crypt_buf;
if (!page_compressed) if (!page_compressed)
{ {
not_compressed: not_compressed:
byte *tmp= space->purpose == FIL_TYPE_TEMPORARY d= space->purpose == FIL_TYPE_TEMPORARY
? buf_tmp_page_encrypt(page_no, s, d) ? buf_tmp_page_encrypt(page_no, s, d)
: fil_space_encrypt(space, page_no, s, d); : fil_space_encrypt(space, page_no, s, d);
slot->out_buf= d= tmp;
ut_d(fil_page_type_validate(space, tmp));
} }
else else
{ {
ut_ad(space->purpose != FIL_TYPE_TEMPORARY); ut_ad(space->purpose != FIL_TYPE_TEMPORARY);
/* First we compress the page content */ /* First we compress the page content */
buf_tmp_reserve_compression_buf(slot); buf_tmp_reserve_compression_buf(*slot);
byte *tmp= slot->comp_buf; byte *tmp= (*slot)->comp_buf;
ulint len= fil_page_compress(s, tmp, space->flags, ulint len= fil_page_compress(s, tmp, space->flags,
fil_space_get_block_size(space, page_no), fil_space_get_block_size(space, page_no),
encrypted); encrypted);
@@ -729,7 +731,7 @@ not_compressed:
ut_d(fil_page_type_validate(space, tmp)); ut_d(fil_page_type_validate(space, tmp));
if (encrypted) if (encrypted)
tmp = fil_space_encrypt(space, page_no, tmp, d); tmp= fil_space_encrypt(space, page_no, tmp, d);
if (full_crc32) if (full_crc32)
{ {
@@ -738,26 +740,23 @@ not_compressed:
ut_ad(!buf_page_is_corrupted(true, tmp, space->flags)); ut_ad(!buf_page_is_corrupted(true, tmp, space->flags));
} }
slot->out_buf= d= tmp; d= tmp;
} }
ut_d(fil_page_type_validate(space, d)); ut_d(fil_page_type_validate(space, d));
(*slot)->out_buf= d;
return d; return d;
} }
/** Free a page whose underlying file page has been freed. */ /** Free a page whose underlying file page has been freed. */
inline void buf_pool_t::release_freed_page(buf_page_t *bpage) inline void buf_pool_t::release_freed_page(buf_page_t *bpage)
{ {
ut_ad(bpage->in_file()); mysql_mutex_assert_owner(&mutex);
const bool uncompressed= bpage->state() == BUF_BLOCK_FILE_PAGE;
mysql_mutex_lock(&mutex);
bpage->set_io_fix(BUF_IO_NONE);
bpage->status= buf_page_t::NORMAL;
mysql_mutex_lock(&flush_list_mutex); mysql_mutex_lock(&flush_list_mutex);
ut_d(const lsn_t oldest_modification= bpage->oldest_modification();) ut_d(const lsn_t oldest_modification= bpage->oldest_modification();)
if (fsp_is_system_temporary(bpage->id().space())) if (fsp_is_system_temporary(bpage->id().space()))
{ {
ut_ad(uncompressed); ut_ad(bpage->frame);
ut_ad(oldest_modification == 2); ut_ad(oldest_modification == 2);
} }
else else
@@ -767,166 +766,152 @@ inline void buf_pool_t::release_freed_page(buf_page_t *bpage)
} }
bpage->clear_oldest_modification(); bpage->clear_oldest_modification();
mysql_mutex_unlock(&flush_list_mutex); mysql_mutex_unlock(&flush_list_mutex);
bpage->lock.u_unlock(true);
if (uncompressed)
reinterpret_cast<buf_block_t*>(bpage)->lock.u_unlock(true);
buf_LRU_free_page(bpage, true); buf_LRU_free_page(bpage, true);
mysql_mutex_unlock(&mutex);
} }
/** Write a flushable page from buf_pool to a file. /** Write a flushable page to a file. buf_pool.mutex must be held.
buf_pool.mutex must be held.
@param bpage buffer control block
@param lru true=buf_pool.LRU; false=buf_pool.flush_list @param lru true=buf_pool.LRU; false=buf_pool.flush_list
@param space tablespace @param space tablespace
@return whether the page was flushed and buf_pool.mutex was released */ @return whether the page was flushed and buf_pool.mutex was released */
static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) inline bool buf_page_t::flush(bool lru, fil_space_t *space)
{ {
ut_ad(bpage->in_file()); ut_ad(in_file());
ut_ad(bpage->ready_for_flush()); ut_ad(in_LRU_list);
ut_ad((space->purpose == FIL_TYPE_TEMPORARY) == ut_ad((space->purpose == FIL_TYPE_TEMPORARY) ==
(space == fil_system.temp_space)); (space == fil_system.temp_space));
ut_ad(space->referenced()); ut_ad(space->referenced());
ut_ad(lru || space != fil_system.temp_space); ut_ad(lru || space != fil_system.temp_space);
block_lock *rw_lock; if (!lock.u_lock_try(true))
return false;
if (bpage->state() != BUF_BLOCK_FILE_PAGE) const auto s= state();
rw_lock= nullptr; ut_a(s >= FREED);
else
if (s < UNFIXED)
{ {
rw_lock= &reinterpret_cast<buf_block_t*>(bpage)->lock; buf_pool.release_freed_page(this);
if (!rw_lock->u_lock_try(true)) mysql_mutex_unlock(&buf_pool.mutex);
return false; return true;
} }
bpage->set_io_fix(BUF_IO_WRITE); if (s >= READ_FIX || oldest_modification() < 2)
/* Because bpage->status can only be changed while buf_block_t
exists, it cannot be modified for ROW_FORMAT=COMPRESSED pages
without first allocating the uncompressed page frame. Such
allocation cannot be completed due to our io_fix. So, bpage->status
is protected even if !rw_lock. */
const auto status= bpage->status;
if (status != buf_page_t::FREED)
{ {
if (lru) lock.u_unlock(true);
buf_pool.n_flush_LRU_++; return false;
else
buf_pool.n_flush_list_++;
buf_flush_page_count++;
} }
mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex); mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex);
/* We are holding rw_lock = buf_block_t::lock in SX mode except if /* Apart from the U-lock, this block will also be protected by
this is a ROW_FORMAT=COMPRESSED page whose uncompressed page frame is_write_fixed() and oldest_modification()>1.
has been evicted from the buffer pool. Thus, it cannot be relocated or removed. */
Apart from possible rw_lock protection, bpage is also protected by
io_fix and oldest_modification()!=0. Thus, it cannot be relocated in
the buffer pool or removed from flush_list or LRU_list. */
DBUG_PRINT("ib_buf", ("%s %u page %u:%u", DBUG_PRINT("ib_buf", ("%s %u page %u:%u",
lru ? "LRU" : "flush_list", lru ? "LRU" : "flush_list",
bpage->id().space(), bpage->id().page_no())); id().space(), id().page_no()));
ut_ad(bpage->io_fix() == BUF_IO_WRITE); ut_d(const auto f=) zip.fix.fetch_add(WRITE_FIX - UNFIXED);
ut_d(const lsn_t oldest_modification= bpage->oldest_modification()); ut_ad(f >= UNFIXED);
ut_ad(f < READ_FIX);
ut_ad(space == fil_system.temp_space ut_ad(space == fil_system.temp_space
? oldest_modification == 2 ? oldest_modification() == 2
: oldest_modification > 2); : oldest_modification() > 2);
ut_ad(bpage->state() == if (lru)
(rw_lock ? BUF_BLOCK_FILE_PAGE : BUF_BLOCK_ZIP_PAGE)); {
ut_ad(ULINT_UNDEFINED > ut_ad(buf_pool.n_flush_LRU_ < ULINT_UNDEFINED);
(lru ? buf_pool.n_flush_LRU_ : buf_pool.n_flush_list_)); buf_pool.n_flush_LRU_++;
mysql_mutex_unlock(&buf_pool.mutex); }
buf_block_t *block= reinterpret_cast<buf_block_t*>(bpage);
page_t *frame= bpage->zip.data;
if (status == buf_page_t::FREED)
buf_pool.release_freed_page(&block->page);
else else
{ {
space->reacquire(); ut_ad(buf_pool.n_flush_list_ < ULINT_UNDEFINED);
ut_ad(status == buf_page_t::NORMAL || status == buf_page_t::INIT_ON_FLUSH); buf_pool.n_flush_list_++;
size_t size;
#if defined HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || defined _WIN32
size_t orig_size;
#endif
IORequest::Type type= lru ? IORequest::WRITE_LRU : IORequest::WRITE_ASYNC;
if (UNIV_UNLIKELY(!rw_lock)) /* ROW_FORMAT=COMPRESSED */
{
ut_ad(!space->full_crc32());
ut_ad(!space->is_compressed()); /* not page_compressed */
size= bpage->zip_size();
#if defined HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || defined _WIN32
orig_size= size;
#endif
buf_flush_update_zip_checksum(frame, size);
frame= buf_page_encrypt(space, bpage, frame, &size);
ut_ad(size == bpage->zip_size());
}
else
{
byte *page= block->frame;
size= block->physical_size();
#if defined HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || defined _WIN32
orig_size= size;
#endif
if (space->full_crc32())
{
/* innodb_checksum_algorithm=full_crc32 is not implemented for
ROW_FORMAT=COMPRESSED pages. */
ut_ad(!frame);
page= buf_page_encrypt(space, bpage, page, &size);
buf_flush_init_for_writing(block, page, nullptr, true);
}
else
{
buf_flush_init_for_writing(block, page, frame ? &bpage->zip : nullptr,
false);
page= buf_page_encrypt(space, bpage, frame ? frame : page, &size);
}
#if defined HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || defined _WIN32
if (size != orig_size)
{
switch (space->chain.start->punch_hole) {
case 1:
type= lru ? IORequest::PUNCH_LRU : IORequest::PUNCH;
break;
case 2:
size= orig_size;
}
}
#endif
frame=page;
}
ut_ad(status == bpage->status);
ut_ad(oldest_modification == bpage->oldest_modification());
if (status != buf_page_t::NORMAL || !space->use_doublewrite())
{
if (UNIV_LIKELY(space->purpose == FIL_TYPE_TABLESPACE))
{
const lsn_t lsn= mach_read_from_8(my_assume_aligned<8>
(FIL_PAGE_LSN + (frame ? frame
: block->frame)));
ut_ad(lsn >= oldest_modification);
if (lsn > log_sys.get_flushed_lsn())
log_write_up_to(lsn, true);
}
space->io(IORequest(type, bpage),
bpage->physical_offset(), size, frame, bpage);
}
else
buf_dblwr.add_to_batch(IORequest(bpage, space->chain.start, type), size);
} }
buf_flush_page_count++;
mysql_mutex_unlock(&buf_pool.mutex);
buf_block_t *block= reinterpret_cast<buf_block_t*>(this);
page_t *write_frame= zip.data;
space->reacquire();
size_t size;
#if defined HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || defined _WIN32
size_t orig_size;
#endif
IORequest::Type type= lru ? IORequest::WRITE_LRU : IORequest::WRITE_ASYNC;
buf_tmp_buffer_t *slot= nullptr;
if (UNIV_UNLIKELY(!frame)) /* ROW_FORMAT=COMPRESSED */
{
ut_ad(!space->full_crc32());
ut_ad(!space->is_compressed()); /* not page_compressed */
size= zip_size();
#if defined HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || defined _WIN32
orig_size= size;
#endif
buf_flush_update_zip_checksum(write_frame, size);
write_frame= buf_page_encrypt(space, this, write_frame, &slot, &size);
ut_ad(size == zip_size());
}
else
{
byte *page= frame;
size= block->physical_size();
#if defined HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || defined _WIN32
orig_size= size;
#endif
if (space->full_crc32())
{
/* innodb_checksum_algorithm=full_crc32 is not implemented for
ROW_FORMAT=COMPRESSED pages. */
ut_ad(!write_frame);
page= buf_page_encrypt(space, this, page, &slot, &size);
buf_flush_init_for_writing(block, page, nullptr, true);
}
else
{
buf_flush_init_for_writing(block, page, write_frame ? &zip : nullptr,
false);
page= buf_page_encrypt(space, this, write_frame ? write_frame : page,
&slot, &size);
}
#if defined HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || defined _WIN32
if (size != orig_size)
{
switch (space->chain.start->punch_hole) {
case 1:
type= lru ? IORequest::PUNCH_LRU : IORequest::PUNCH;
break;
case 2:
size= orig_size;
}
}
#endif
write_frame= page;
}
if ((s & LRU_MASK) == REINIT || !space->use_doublewrite())
{
if (UNIV_LIKELY(space->purpose == FIL_TYPE_TABLESPACE))
{
const lsn_t lsn=
mach_read_from_8(my_assume_aligned<8>(FIL_PAGE_LSN +
(write_frame ? write_frame
: frame)));
ut_ad(lsn >= oldest_modification());
if (lsn > log_sys.get_flushed_lsn())
log_write_up_to(lsn, true);
}
space->io(IORequest{type, this, slot}, physical_offset(), size,
write_frame, this);
}
else
buf_dblwr.add_to_batch(IORequest{this, slot, space->chain.start, type},
size);
/* Increment the I/O operation count used for selecting LRU policy. */ /* Increment the I/O operation count used for selecting LRU policy. */
buf_LRU_stat_inc_io(); buf_LRU_stat_inc_io();
@@ -968,7 +953,9 @@ static page_id_t buf_flush_check_neighbors(const fil_space_t &space,
page_id_t &id, bool contiguous, page_id_t &id, bool contiguous,
bool lru) bool lru)
{ {
ut_ad(id.page_no() < space.size); ut_ad(id.page_no() < space.size +
(space.physical_size() == 2048 ? 1
: space.physical_size() == 1024 ? 3 : 0));
/* When flushed, dirty blocks are searched in neighborhoods of this /* When flushed, dirty blocks are searched in neighborhoods of this
size, and flushed along with the original page. */ size, and flushed along with the original page. */
const ulint s= buf_pool.curr_size / 16; const ulint s= buf_pool.curr_size / 16;
@@ -1116,8 +1103,8 @@ static ulint buf_flush_try_neighbors(fil_space_t *space,
if (!lru || id == page_id || bpage->is_old()) if (!lru || id == page_id || bpage->is_old())
{ {
if (!buf_pool.watch_is_sentinel(*bpage) && if (!buf_pool.watch_is_sentinel(*bpage) &&
bpage->oldest_modification() > 1 && bpage->oldest_modification() > 1 && bpage->ready_for_flush() &&
bpage->ready_for_flush() && buf_flush_page(bpage, lru, space)) bpage->flush(lru, space))
{ {
++count; ++count;
continue; continue;
@@ -1216,24 +1203,17 @@ static void buf_flush_discard_page(buf_page_t *bpage)
ut_ad(bpage->in_file()); ut_ad(bpage->in_file());
ut_ad(bpage->oldest_modification()); ut_ad(bpage->oldest_modification());
block_lock *rw_lock; if (!bpage->lock.u_lock_try(false))
return;
if (bpage->state() != BUF_BLOCK_FILE_PAGE)
rw_lock= nullptr;
else
{
rw_lock= &reinterpret_cast<buf_block_t*>(bpage)->lock;
if (!rw_lock->u_lock_try(false))
return;
}
bpage->status= buf_page_t::NORMAL;
mysql_mutex_lock(&buf_pool.flush_list_mutex); mysql_mutex_lock(&buf_pool.flush_list_mutex);
buf_pool.delete_from_flush_list(bpage); buf_pool.delete_from_flush_list(bpage);
mysql_mutex_unlock(&buf_pool.flush_list_mutex); mysql_mutex_unlock(&buf_pool.flush_list_mutex);
if (rw_lock) ut_d(const auto state= bpage->state());
rw_lock->u_unlock(); ut_ad(state == buf_page_t::FREED || state == buf_page_t::UNFIXED ||
state == buf_page_t::IBUF_EXIST || state == buf_page_t::REINIT);
bpage->lock.u_unlock();
buf_LRU_free_page(bpage, true); buf_LRU_free_page(bpage, true);
} }
@@ -1265,15 +1245,19 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n)
buf_page_t *prev= UT_LIST_GET_PREV(LRU, bpage); buf_page_t *prev= UT_LIST_GET_PREV(LRU, bpage);
const lsn_t oldest_modification= bpage->oldest_modification(); const lsn_t oldest_modification= bpage->oldest_modification();
buf_pool.lru_hp.set(prev); buf_pool.lru_hp.set(prev);
const auto state= bpage->state();
ut_ad(state >= buf_page_t::FREED);
ut_ad(bpage->in_LRU_list);
if (oldest_modification <= 1 && bpage->can_relocate()) if (oldest_modification <= 1)
{ {
/* block is ready for eviction i.e., it is clean and is not if (state != buf_page_t::FREED &&
IO-fixed or buffer fixed. */ (state >= buf_page_t::READ_FIX || (~buf_page_t::LRU_MASK & state)))
goto must_skip;
if (buf_LRU_free_page(bpage, true)) if (buf_LRU_free_page(bpage, true))
++n->evicted; ++n->evicted;
} }
else if (oldest_modification > 1 && bpage->ready_for_flush()) else if (state < buf_page_t::READ_FIX)
{ {
/* Block is ready for flush. Dispatch an IO request. The IO /* Block is ready for flush. Dispatch an IO request. The IO
helper thread will put it on free list in IO completion routine. */ helper thread will put it on free list in IO completion routine. */
@@ -1307,13 +1291,14 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n)
reacquire_mutex: reacquire_mutex:
mysql_mutex_lock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.mutex);
} }
else if (buf_flush_page(bpage, true, space)) else if (bpage->flush(true, space))
{ {
++n->flushed; ++n->flushed;
goto reacquire_mutex; goto reacquire_mutex;
} }
} }
else else
must_skip:
/* Can't evict or dispatch this block. Go to previous. */ /* Can't evict or dispatch this block. Go to previous. */
ut_ad(buf_pool.lru_hp.is_hp(prev)); ut_ad(buf_pool.lru_hp.is_hp(prev));
bpage= buf_pool.lru_hp.get(); bpage= buf_pool.lru_hp.get();
@@ -1398,7 +1383,6 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn)
} }
ut_ad(oldest_modification > 2); ut_ad(oldest_modification > 2);
ut_ad(bpage->in_file());
if (!bpage->ready_for_flush()) if (!bpage->ready_for_flush())
goto skip; goto skip;
@@ -1445,7 +1429,7 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn)
reacquire_mutex: reacquire_mutex:
mysql_mutex_lock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.mutex);
} }
else if (buf_flush_page(bpage, false, space)) else if (bpage->flush(false, space))
{ {
++count; ++count;
goto reacquire_mutex; goto reacquire_mutex;
@@ -1556,9 +1540,6 @@ bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed)
for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; ) for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; )
{ {
ut_d(const auto s= bpage->state());
ut_ad(s == BUF_BLOCK_ZIP_PAGE || s == BUF_BLOCK_FILE_PAGE ||
s == BUF_BLOCK_REMOVE_HASH);
ut_ad(bpage->oldest_modification()); ut_ad(bpage->oldest_modification());
ut_ad(bpage->in_file()); ut_ad(bpage->in_file());
@@ -1594,7 +1575,7 @@ bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed)
acquired= false; acquired= false;
goto was_freed; goto was_freed;
} }
if (!buf_flush_page(bpage, false, space)) if (!bpage->flush(false, space))
{ {
may_have_skipped= true; may_have_skipped= true;
mysql_mutex_lock(&buf_pool.flush_list_mutex); mysql_mutex_lock(&buf_pool.flush_list_mutex);
@@ -2482,8 +2463,7 @@ static void buf_flush_validate_low()
in the flush list waiting to acquire the in the flush list waiting to acquire the
buf_pool.flush_list_mutex to complete the relocation. */ buf_pool.flush_list_mutex to complete the relocation. */
ut_d(const auto s= bpage->state()); ut_d(const auto s= bpage->state());
ut_ad(s == BUF_BLOCK_ZIP_PAGE || s == BUF_BLOCK_FILE_PAGE ut_ad(s >= buf_page_t::REMOVE_HASH);
|| s == BUF_BLOCK_REMOVE_HASH);
ut_ad(om == 1 || om > 2); ut_ad(om == 1 || om > 2);
bpage = UT_LIST_GET_NEXT(list, bpage); bpage = UT_LIST_GET_NEXT(list, bpage);

View File

@@ -108,7 +108,7 @@ uint buf_LRU_old_threshold_ms;
/** Remove bpage from buf_pool.LRU and buf_pool.page_hash. /** Remove bpage from buf_pool.LRU and buf_pool.page_hash.
If bpage->state() == BUF_BLOCK_ZIP_PAGE && bpage->oldest_modification() <= 1, If !bpage->frame && bpage->oldest_modification() <= 1,
the object will be freed. the object will be freed.
@param bpage buffer block @param bpage buffer block
@@ -117,9 +117,9 @@ the object will be freed.
@param zip whether bpage->zip of BUF_BLOCK_FILE_PAGE should be freed @param zip whether bpage->zip of BUF_BLOCK_FILE_PAGE should be freed
If a compressed page is freed other compressed pages may be relocated. If a compressed page is freed other compressed pages may be relocated.
@retval true if BUF_BLOCK_FILE_PAGE was removed from page_hash. The @retval true if bpage with bpage->frame was removed from page_hash. The
caller needs to free the page to the free list caller needs to free the page to the free list
@retval false if BUF_BLOCK_ZIP_PAGE was removed from page_hash. In @retval false if block without bpage->frame was removed from page_hash. In
this case the block is already returned to the buddy allocator. */ this case the block is already returned to the buddy allocator. */
static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id, static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id,
buf_pool_t::hash_chain &chain, buf_pool_t::hash_chain &chain,
@@ -203,7 +203,8 @@ static bool buf_LRU_free_from_unzip_LRU_list(ulint limit)
block && scanned < limit; ++scanned) { block && scanned < limit; ++scanned) {
buf_block_t* prev_block = UT_LIST_GET_PREV(unzip_LRU, block); buf_block_t* prev_block = UT_LIST_GET_PREV(unzip_LRU, block);
ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); ut_ad(block->page.in_file());
ut_ad(block->page.belongs_to_unzip_LRU());
ut_ad(block->in_unzip_LRU_list); ut_ad(block->in_unzip_LRU_list);
ut_ad(block->page.in_LRU_list); ut_ad(block->page.in_LRU_list);
@@ -268,17 +269,6 @@ static bool buf_LRU_free_from_common_LRU_list(ulint limit)
return(freed); return(freed);
} }
/** Try to free a replaceable block.
@param limit maximum number of blocks to scan
@return true if found and freed */
bool buf_LRU_scan_and_free_block(ulint limit)
{
mysql_mutex_assert_owner(&buf_pool.mutex);
return buf_LRU_free_from_unzip_LRU_list(limit) ||
buf_LRU_free_from_common_LRU_list(limit);
}
/** @return a buffer block from the buf_pool.free list /** @return a buffer block from the buf_pool.free list
@retval NULL if the free list is empty */ @retval NULL if the free list is empty */
buf_block_t* buf_LRU_get_free_only() buf_block_t* buf_LRU_get_free_only()
@@ -306,15 +296,13 @@ buf_block_t* buf_LRU_get_free_only()
a free block. */ a free block. */
assert_block_ahi_empty(block); assert_block_ahi_empty(block);
block->page.set_state(BUF_BLOCK_MEMORY); block->page.set_state(buf_page_t::MEMORY);
MEM_MAKE_ADDRESSABLE(block->frame, srv_page_size); MEM_MAKE_ADDRESSABLE(block->page.frame, srv_page_size);
break; break;
} }
/* This should be withdrawn */ /* This should be withdrawn */
UT_LIST_ADD_LAST( UT_LIST_ADD_LAST(buf_pool.withdraw, &block->page);
buf_pool.withdraw,
&block->page);
ut_d(block->in_withdraw_list = true); ut_d(block->in_withdraw_list = true);
block = reinterpret_cast<buf_block_t*>( block = reinterpret_cast<buf_block_t*>(
@@ -428,7 +416,7 @@ got_block:
if (!have_mutex) { if (!have_mutex) {
mysql_mutex_unlock(&buf_pool.mutex); mysql_mutex_unlock(&buf_pool.mutex);
} }
memset(&block->page.zip, 0, sizeof block->page.zip); block->page.zip.clear();
return block; return block;
} }
@@ -771,6 +759,9 @@ buf_LRU_add_block(
/** Move a block to the start of the LRU list. */ /** Move a block to the start of the LRU list. */
void buf_page_make_young(buf_page_t *bpage) void buf_page_make_young(buf_page_t *bpage)
{ {
if (bpage->is_read_fixed())
return;
ut_ad(bpage->in_file()); ut_ad(bpage->in_file());
mysql_mutex_lock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.mutex);
@@ -793,12 +784,10 @@ The caller must hold buf_pool.mutex.
@retval false if the page was not freed */ @retval false if the page was not freed */
bool buf_LRU_free_page(buf_page_t *bpage, bool zip) bool buf_LRU_free_page(buf_page_t *bpage, bool zip)
{ {
const page_id_t id(bpage->id()); const page_id_t id{bpage->id()};
buf_page_t* b = nullptr; buf_page_t* b = nullptr;
mysql_mutex_assert_owner(&buf_pool.mutex); mysql_mutex_assert_owner(&buf_pool.mutex);
ut_ad(bpage->in_file());
ut_ad(bpage->in_LRU_list);
/* First, perform a quick check before we acquire hash_lock. */ /* First, perform a quick check before we acquire hash_lock. */
if (!bpage->can_relocate()) { if (!bpage->can_relocate()) {
@@ -839,23 +828,21 @@ bool buf_LRU_free_page(buf_page_t *bpage, bool zip)
if (oldest_modification) { if (oldest_modification) {
goto func_exit; goto func_exit;
} }
} else if (oldest_modification } else if (oldest_modification && !bpage->frame) {
&& bpage->state() != BUF_BLOCK_FILE_PAGE) {
func_exit: func_exit:
hash_lock.unlock(); hash_lock.unlock();
return(false); return(false);
} else if (bpage->state() == BUF_BLOCK_FILE_PAGE) { } else if (bpage->frame) {
b = buf_page_alloc_descriptor(); b = static_cast<buf_page_t*>(ut_zalloc_nokey(sizeof *b));
ut_a(b); ut_a(b);
mysql_mutex_lock(&buf_pool.flush_list_mutex); mysql_mutex_lock(&buf_pool.flush_list_mutex);
new (b) buf_page_t(*bpage); new (b) buf_page_t(*bpage);
b->set_state(BUF_BLOCK_ZIP_PAGE); b->frame = nullptr;
b->set_state(buf_page_t::UNFIXED + 1);
} }
mysql_mutex_assert_owner(&buf_pool.mutex); mysql_mutex_assert_owner(&buf_pool.mutex);
ut_ad(bpage->in_file());
ut_ad(bpage->in_LRU_list);
DBUG_PRINT("ib_buf", ("free page %u:%u", DBUG_PRINT("ib_buf", ("free page %u:%u",
id.space(), id.page_no())); id.space(), id.page_no()));
@@ -887,9 +874,7 @@ func_exit:
buf_LRU_block_remove_hashed(), which buf_LRU_block_remove_hashed(), which
invokes buf_LRU_remove_block(). */ invokes buf_LRU_remove_block(). */
ut_ad(!bpage->in_LRU_list); ut_ad(!bpage->in_LRU_list);
ut_ad(bpage->frame);
/* bpage->state was BUF_BLOCK_FILE_PAGE because
b != nullptr. The type cast below is thus valid. */
ut_ad(!((buf_block_t*) bpage)->in_unzip_LRU_list); ut_ad(!((buf_block_t*) bpage)->in_unzip_LRU_list);
/* The fields of bpage were copied to b before /* The fields of bpage were copied to b before
@@ -952,13 +937,9 @@ func_exit:
page_zip_set_size(&bpage->zip, 0); page_zip_set_size(&bpage->zip, 0);
/* Prevent buf_page_get_gen() from b->lock.x_lock();
decompressing the block while we release hash_lock.unlock();
hash_lock. */
b->set_io_fix(BUF_IO_PIN);
goto release;
} else if (!zip) { } else if (!zip) {
release:
hash_lock.unlock(); hash_lock.unlock();
} }
@@ -974,21 +955,16 @@ release:
the contents of the page valid (which it still is) in the contents of the page valid (which it still is) in
order to avoid bogus Valgrind or MSAN warnings.*/ order to avoid bogus Valgrind or MSAN warnings.*/
MEM_MAKE_DEFINED(block->frame, srv_page_size); MEM_MAKE_DEFINED(block->page.frame, srv_page_size);
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
MEM_UNDEFINED(block->frame, srv_page_size); MEM_UNDEFINED(block->page.frame, srv_page_size);
if (UNIV_LIKELY_NULL(b)) {
ut_ad(b->zip_size());
b->io_unfix();
}
mysql_mutex_lock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.mutex);
} else }
#endif #endif
if (UNIV_LIKELY_NULL(b)) { if (UNIV_LIKELY_NULL(b)) {
ut_ad(b->zip_size()); ut_ad(b->zip_size());
b->io_unfix(); b->lock.x_unlock();
b->unfix();
} }
buf_LRU_block_free_hashed_page(block); buf_LRU_block_free_hashed_page(block);
@@ -1005,22 +981,22 @@ buf_LRU_block_free_non_file_page(
{ {
void* data; void* data;
ut_ad(block->page.state() == BUF_BLOCK_MEMORY); ut_ad(block->page.state() == buf_page_t::MEMORY);
assert_block_ahi_empty(block); assert_block_ahi_empty(block);
ut_ad(!block->page.in_free_list); ut_ad(!block->page.in_free_list);
ut_ad(!block->page.oldest_modification()); ut_ad(!block->page.oldest_modification());
ut_ad(!block->page.in_LRU_list); ut_ad(!block->page.in_LRU_list);
ut_ad(!block->page.hash); ut_ad(!block->page.hash);
block->page.set_state(BUF_BLOCK_NOT_USED); block->page.set_state(buf_page_t::NOT_USED);
MEM_UNDEFINED(block->frame, srv_page_size); MEM_UNDEFINED(block->page.frame, srv_page_size);
/* Wipe page_no and space_id */ /* Wipe page_no and space_id */
static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment"); static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
memset_aligned<4>(block->frame + FIL_PAGE_OFFSET, 0xfe, 4); memset_aligned<4>(block->page.frame + FIL_PAGE_OFFSET, 0xfe, 4);
static_assert(FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID % 4 == 2, static_assert(FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID % 4 == 2,
"not perfect alignment"); "not perfect alignment");
memset_aligned<2>(block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, memset_aligned<2>(block->page.frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
0xfe, 4); 0xfe, 4);
data = block->page.zip.data; data = block->page.zip.data;
@@ -1050,7 +1026,7 @@ buf_LRU_block_free_non_file_page(
pthread_cond_signal(&buf_pool.done_free); pthread_cond_signal(&buf_pool.done_free);
} }
MEM_NOACCESS(block->frame, srv_page_size); MEM_NOACCESS(block->page.frame, srv_page_size);
} }
/** Release a memory block to the buffer pool. */ /** Release a memory block to the buffer pool. */
@@ -1065,8 +1041,7 @@ ATTRIBUTE_COLD void buf_pool_t::free_block(buf_block_t *block)
/** Remove bpage from buf_pool.LRU and buf_pool.page_hash. /** Remove bpage from buf_pool.LRU and buf_pool.page_hash.
If bpage->state() == BUF_BLOCK_ZIP_PAGE && !bpage->oldest_modification(), If !bpage->frame && !bpage->oldest_modification(), the object will be freed.
the object will be freed.
@param bpage buffer block @param bpage buffer block
@param id page identifier @param id page identifier
@@ -1082,24 +1057,19 @@ static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id,
buf_pool_t::hash_chain &chain, buf_pool_t::hash_chain &chain,
bool zip) bool zip)
{ {
mysql_mutex_assert_owner(&buf_pool.mutex); ut_a(bpage->can_relocate());
ut_ad(buf_pool.page_hash.lock_get(chain).is_write_locked()); ut_ad(buf_pool.page_hash.lock_get(chain).is_write_locked());
ut_a(bpage->io_fix() == BUF_IO_NONE);
ut_a(!bpage->buf_fix_count());
buf_LRU_remove_block(bpage); buf_LRU_remove_block(bpage);
buf_pool.freed_page_clock += 1; buf_pool.freed_page_clock += 1;
switch (bpage->state()) { if (UNIV_LIKELY(bpage->frame != nullptr)) {
case BUF_BLOCK_FILE_PAGE:
MEM_CHECK_ADDRESSABLE(bpage, sizeof(buf_block_t)); MEM_CHECK_ADDRESSABLE(bpage, sizeof(buf_block_t));
MEM_CHECK_ADDRESSABLE(((buf_block_t*) bpage)->frame, MEM_CHECK_ADDRESSABLE(bpage->frame, srv_page_size);
srv_page_size);
buf_block_modify_clock_inc((buf_block_t*) bpage); buf_block_modify_clock_inc((buf_block_t*) bpage);
if (bpage->zip.data) { if (UNIV_LIKELY_NULL(bpage->zip.data)) {
const page_t* page = ((buf_block_t*) bpage)->frame; const page_t* page = bpage->frame;
ut_a(!zip || !bpage->oldest_modification()); ut_a(!zip || !bpage->oldest_modification());
ut_ad(bpage->zip_size()); ut_ad(bpage->zip_size());
@@ -1147,27 +1117,20 @@ static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id,
putc('\n', stderr); putc('\n', stderr);
ut_error; ut_error;
} }
} else {
break; goto evict_zip;
} }
/* fall through */ } else {
case BUF_BLOCK_ZIP_PAGE: evict_zip:
ut_a(!bpage->oldest_modification()); ut_a(!bpage->oldest_modification());
MEM_CHECK_ADDRESSABLE(bpage->zip.data, bpage->zip_size()); MEM_CHECK_ADDRESSABLE(bpage->zip.data, bpage->zip_size());
break;
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
ut_error;
break;
} }
ut_ad(!bpage->in_zip_hash); ut_ad(!bpage->in_zip_hash);
buf_pool.page_hash.remove(chain, bpage); buf_pool.page_hash.remove(chain, bpage);
page_hash_latch& hash_lock = buf_pool.page_hash.lock_get(chain); page_hash_latch& hash_lock = buf_pool.page_hash.lock_get(chain);
switch (bpage->state()) { if (UNIV_UNLIKELY(!bpage->frame)) {
case BUF_BLOCK_ZIP_PAGE:
ut_ad(!bpage->in_free_list); ut_ad(!bpage->in_free_list);
ut_ad(!bpage->in_LRU_list); ut_ad(!bpage->in_LRU_list);
ut_a(bpage->zip.data); ut_a(bpage->zip.data);
@@ -1180,20 +1143,19 @@ static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id,
buf_buddy_free(bpage->zip.data, bpage->zip_size()); buf_buddy_free(bpage->zip.data, bpage->zip_size());
buf_pool_mutex_exit_allow(); buf_pool_mutex_exit_allow();
buf_page_free_descriptor(bpage); bpage->lock.free();
return(false); ut_free(bpage);
return false;
case BUF_BLOCK_FILE_PAGE: } else {
static_assert(FIL_NULL == 0xffffffffU, "fill pattern"); static_assert(FIL_NULL == 0xffffffffU, "fill pattern");
static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment"); static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
memset_aligned<4>(reinterpret_cast<buf_block_t*>(bpage)->frame memset_aligned<4>(bpage->frame + FIL_PAGE_OFFSET, 0xff, 4);
+ FIL_PAGE_OFFSET, 0xff, 4);
static_assert(FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID % 4 == 2, static_assert(FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID % 4 == 2,
"not perfect alignment"); "not perfect alignment");
memset_aligned<2>(reinterpret_cast<buf_block_t*>(bpage)->frame memset_aligned<2>(bpage->frame
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xff, 4); + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xff, 4);
MEM_UNDEFINED(((buf_block_t*) bpage)->frame, srv_page_size); MEM_UNDEFINED(bpage->frame, srv_page_size);
bpage->set_state(BUF_BLOCK_REMOVE_HASH); bpage->set_state(buf_page_t::REMOVE_HASH);
if (!zip) { if (!zip) {
return true; return true;
@@ -1237,41 +1199,36 @@ static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id,
page_zip_set_size(&bpage->zip, 0); page_zip_set_size(&bpage->zip, 0);
} }
return(true); return true;
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
break;
} }
ut_error;
return(false);
} }
/** Release and evict a corrupted page. /** Release and evict a corrupted page.
@param bpage page that was being read */ @param bpage page that was being read */
ATTRIBUTE_COLD void buf_pool_t::corrupted_evict(buf_page_t *bpage) ATTRIBUTE_COLD void buf_pool_t::corrupted_evict(buf_page_t *bpage)
{ {
const page_id_t id(bpage->id()); const page_id_t id{bpage->id()};
buf_pool_t::hash_chain &chain= buf_pool.page_hash.cell_get(id.fold()); buf_pool_t::hash_chain &chain= buf_pool.page_hash.cell_get(id.fold());
page_hash_latch &hash_lock= buf_pool.page_hash.lock_get(chain); page_hash_latch &hash_lock= buf_pool.page_hash.lock_get(chain);
mysql_mutex_lock(&mutex); mysql_mutex_lock(&mutex);
hash_lock.lock(); hash_lock.lock();
ut_ad(bpage->io_fix() == BUF_IO_READ);
ut_ad(!bpage->oldest_modification()); ut_ad(!bpage->oldest_modification());
bpage->set_corrupt_id(); bpage->set_corrupt_id();
bpage->io_unfix(); constexpr auto read_unfix= buf_page_t::READ_FIX - buf_page_t::UNFIXED;
auto s= bpage->zip.fix.fetch_sub(read_unfix) - read_unfix;
bpage->lock.x_unlock(true);
if (bpage->state() == BUF_BLOCK_FILE_PAGE) while (s != buf_page_t::UNFIXED)
reinterpret_cast<buf_block_t*>(bpage)->lock.x_unlock(true); {
ut_ad(s > buf_page_t::UNFIXED);
while (bpage->buf_fix_count()) ut_ad(s < buf_page_t::READ_FIX);
/* Wait for other threads to release the fix count /* Wait for other threads to release the fix count
before releasing the bpage from LRU list. */ before releasing the bpage from LRU list. */
(void) LF_BACKOFF(); (void) LF_BACKOFF();
s= bpage->state();
}
/* remove from LRU and page_hash */ /* remove from LRU and page_hash */
if (buf_LRU_block_remove_hashed(bpage, id, chain, true)) if (buf_LRU_block_remove_hashed(bpage, id, chain, true))
@@ -1357,6 +1314,23 @@ func_exit:
memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur); memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur);
} }
#if defined __aarch64__&&defined __GNUC__&&__GNUC__==4&&!defined __clang__
/* Avoid GCC 4.8.5 internal compiler error "could not split insn".
We would only need this for buf_LRU_scan_and_free_block(),
but GCC 4.8.5 does not support pop_options. */
# pragma GCC optimize ("no-expensive-optimizations")
#endif
/** Try to free a replaceable block.
@param limit maximum number of blocks to scan
@return true if found and freed */
bool buf_LRU_scan_and_free_block(ulint limit)
{
mysql_mutex_assert_owner(&buf_pool.mutex);
return buf_LRU_free_from_unzip_LRU_list(limit) ||
buf_LRU_free_from_common_LRU_list(limit);
}
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/** Validate the LRU list. */ /** Validate the LRU list. */
void buf_LRU_validate() void buf_LRU_validate()
@@ -1389,20 +1363,11 @@ void buf_LRU_validate()
for (buf_page_t* bpage = UT_LIST_GET_FIRST(buf_pool.LRU); for (buf_page_t* bpage = UT_LIST_GET_FIRST(buf_pool.LRU);
bpage != NULL; bpage != NULL;
bpage = UT_LIST_GET_NEXT(LRU, bpage)) { bpage = UT_LIST_GET_NEXT(LRU, bpage)) {
ut_ad(bpage->in_file());
switch (bpage->state()) { ut_ad(!bpage->frame
case BUF_BLOCK_NOT_USED: || reinterpret_cast<buf_block_t*>(bpage)
case BUF_BLOCK_MEMORY: ->in_unzip_LRU_list
case BUF_BLOCK_REMOVE_HASH: == bpage->belongs_to_unzip_LRU());
ut_error;
break;
case BUF_BLOCK_FILE_PAGE:
ut_ad(reinterpret_cast<buf_block_t*>(bpage)
->in_unzip_LRU_list
== bpage->belongs_to_unzip_LRU());
case BUF_BLOCK_ZIP_PAGE:
break;
}
if (bpage->is_old()) { if (bpage->is_old()) {
const buf_page_t* prev const buf_page_t* prev
@@ -1428,7 +1393,7 @@ void buf_LRU_validate()
bpage != NULL; bpage != NULL;
bpage = UT_LIST_GET_NEXT(list, bpage)) { bpage = UT_LIST_GET_NEXT(list, bpage)) {
ut_a(bpage->state() == BUF_BLOCK_NOT_USED); ut_a(bpage->state() == buf_page_t::NOT_USED);
} }
CheckUnzipLRUAndLRUList::validate(); CheckUnzipLRUAndLRUList::validate();
@@ -1464,38 +1429,28 @@ void buf_LRU_print()
fputs("old ", stderr); fputs("old ", stderr);
} }
if (const uint32_t buf_fix_count = bpage->buf_fix_count()) { const unsigned s = bpage->state();
fprintf(stderr, "buffix count %u ", buf_fix_count); if (s > buf_page_t::UNFIXED) {
} fprintf(stderr, "fix %u ", s - buf_page_t::UNFIXED);
} else {
if (const auto io_fix = bpage->io_fix()) { ut_ad(s == buf_page_t::UNFIXED
fprintf(stderr, "io_fix %d ", io_fix); || s == buf_page_t::REMOVE_HASH);
} }
if (bpage->oldest_modification()) { if (bpage->oldest_modification()) {
fputs("modif. ", stderr); fputs("modif. ", stderr);
} }
switch (const auto state = bpage->state()) { if (const byte* frame = bpage->zip.data) {
const byte* frame;
case BUF_BLOCK_FILE_PAGE:
frame = buf_block_get_frame((buf_block_t*) bpage);
fprintf(stderr, "\ntype %u index id " IB_ID_FMT "\n",
fil_page_get_type(frame),
btr_page_get_index_id(frame));
break;
case BUF_BLOCK_ZIP_PAGE:
frame = bpage->zip.data;
fprintf(stderr, "\ntype %u size " ULINTPF fprintf(stderr, "\ntype %u size " ULINTPF
" index id " IB_ID_FMT "\n", " index id " IB_ID_FMT "\n",
fil_page_get_type(frame), fil_page_get_type(frame),
bpage->zip_size(), bpage->zip_size(),
btr_page_get_index_id(frame)); btr_page_get_index_id(frame));
break; } else {
fprintf(stderr, "\ntype %u index id " IB_ID_FMT "\n",
default: fil_page_get_type(bpage->frame),
fprintf(stderr, "\n!state %d!\n", state); btr_page_get_index_id(bpage->frame));
break;
} }
} }

View File

@@ -59,12 +59,9 @@ inline void buf_pool_t::watch_remove(buf_page_t *watch,
ut_ad(page_hash.lock_get(chain).is_write_locked()); ut_ad(page_hash.lock_get(chain).is_write_locked());
ut_a(watch_is_sentinel(*watch)); ut_a(watch_is_sentinel(*watch));
if (watch->buf_fix_count()) if (watch->buf_fix_count())
{
page_hash.remove(chain, watch); page_hash.remove(chain, watch);
watch->set_buf_fix_count(0);
}
ut_ad(!watch->in_page_hash); ut_ad(!watch->in_page_hash);
watch->set_state(BUF_BLOCK_NOT_USED); watch->set_state(buf_page_t::NOT_USED);
watch->id_= page_id_t(~0ULL); watch->id_= page_id_t(~0ULL);
} }
@@ -109,10 +106,10 @@ static buf_page_t* buf_page_init_for_read(ulint mode, const page_id_t page_id,
if (!zip_size || unzip || recv_recovery_is_on()) if (!zip_size || unzip || recv_recovery_is_on())
{ {
block= buf_LRU_get_free_block(false); block= buf_LRU_get_free_block(false);
block->initialise(page_id, zip_size); block->initialise(page_id, zip_size, buf_page_t::READ_FIX);
/* x_unlock() will be invoked /* x_unlock() will be invoked
in buf_page_read_complete() by the io-handler thread. */ in buf_page_t::read_complete() by the io-handler thread. */
block->lock.x_lock(true); block->page.lock.x_lock(true);
} }
buf_pool_t::hash_chain &chain= buf_pool.page_hash.cell_get(page_id.fold()); buf_pool_t::hash_chain &chain= buf_pool.page_hash.cell_get(page_id.fold());
@@ -125,7 +122,8 @@ static buf_page_t* buf_page_init_for_read(ulint mode, const page_id_t page_id,
/* The page is already in the buffer pool. */ /* The page is already in the buffer pool. */
if (block) if (block)
{ {
block->lock.x_unlock(true); block->page.lock.x_unlock(true);
ut_d(block->page.set_state(buf_page_t::MEMORY));
buf_LRU_block_free_non_file_page(block); buf_LRU_block_free_non_file_page(block);
} }
goto func_exit; goto func_exit;
@@ -143,14 +141,13 @@ static buf_page_t* buf_page_init_for_read(ulint mode, const page_id_t page_id,
if (hash_page) if (hash_page)
{ {
/* Preserve the reference count. */ /* Preserve the reference count. */
auto buf_fix_count= hash_page->buf_fix_count(); uint32_t buf_fix_count= hash_page->state();
ut_a(buf_fix_count > 0); ut_a(buf_fix_count >= buf_page_t::UNFIXED);
block->page.add_buf_fix_count(buf_fix_count); ut_a(buf_fix_count < buf_page_t::READ_FIX);
buf_pool.watch_remove(hash_page, chain); buf_pool.watch_remove(hash_page, chain);
block->page.fix(buf_fix_count - buf_page_t::UNFIXED);
} }
block->page.set_io_fix(BUF_IO_READ);
block->page.set_state(BUF_BLOCK_FILE_PAGE);
buf_pool.page_hash.append(chain, &block->page); buf_pool.page_hash.append(chain, &block->page);
} }
@@ -198,13 +195,14 @@ static buf_page_t* buf_page_init_for_read(ulint mode, const page_id_t page_id,
} }
} }
bpage= buf_page_alloc_descriptor(); bpage= static_cast<buf_page_t*>(ut_zalloc_nokey(sizeof *bpage));
page_zip_des_init(&bpage->zip); page_zip_des_init(&bpage->zip);
page_zip_set_size(&bpage->zip, zip_size); page_zip_set_size(&bpage->zip, zip_size);
bpage->zip.data = (page_zip_t*) data; bpage->zip.data = (page_zip_t*) data;
bpage->init(BUF_BLOCK_ZIP_PAGE, page_id); bpage->init(buf_page_t::READ_FIX, page_id);
bpage->lock.x_lock(true);
{ {
transactional_lock_guard<page_hash_latch> g transactional_lock_guard<page_hash_latch> g
@@ -215,12 +213,14 @@ static buf_page_t* buf_page_init_for_read(ulint mode, const page_id_t page_id,
/* Preserve the reference count. It can be 0 if /* Preserve the reference count. It can be 0 if
buf_pool_t::watch_unset() is executing concurrently, buf_pool_t::watch_unset() is executing concurrently,
waiting for buf_pool.mutex, which we are holding. */ waiting for buf_pool.mutex, which we are holding. */
bpage->add_buf_fix_count(hash_page->buf_fix_count()); uint32_t buf_fix_count= hash_page->state();
ut_a(buf_fix_count >= buf_page_t::UNFIXED);
ut_a(buf_fix_count < buf_page_t::READ_FIX);
bpage->fix(buf_fix_count - buf_page_t::UNFIXED);
buf_pool.watch_remove(hash_page, chain); buf_pool.watch_remove(hash_page, chain);
} }
buf_pool.page_hash.append(chain, bpage); buf_pool.page_hash.append(chain, bpage);
bpage->set_io_fix(BUF_IO_READ);
} }
/* The block must be put to the LRU list, to the old blocks. /* The block must be put to the LRU list, to the old blocks.
@@ -315,16 +315,7 @@ nothing_read:
"read page " << page_id << " zip_size=" << zip_size "read page " << page_id << " zip_size=" << zip_size
<< " unzip=" << unzip << ',' << (sync ? "sync" : "async")); << " unzip=" << unzip << ',' << (sync ? "sync" : "async"));
void* dst; void* dst = zip_size ? bpage->zip.data : bpage->frame;
if (zip_size) {
dst = bpage->zip.data;
} else {
ut_a(bpage->state() == BUF_BLOCK_FILE_PAGE);
dst = ((buf_block_t*) bpage)->frame;
}
const ulint len = zip_size ? zip_size : srv_page_size; const ulint len = zip_size ? zip_size : srv_page_size;
auto fio = space->io(IORequest(sync auto fio = space->io(IORequest(sync
@@ -347,7 +338,7 @@ nothing_read:
thd_wait_end(NULL); thd_wait_end(NULL);
/* The i/o was already completed in space->io() */ /* The i/o was already completed in space->io() */
*err = buf_page_read_complete(bpage, *fio.node); *err = bpage->read_complete(*fio.node);
space->release(); space->release();
if (*err != DB_SUCCESS) { if (*err != DB_SUCCESS) {
@@ -628,19 +619,7 @@ failed:
on the page, we do not acquire an s-latch on the page, this is to on the page, we do not acquire an s-latch on the page, this is to
prevent deadlocks. The hash_lock is only protecting the prevent deadlocks. The hash_lock is only protecting the
buf_pool.page_hash for page i, not the bpage contents itself. */ buf_pool.page_hash for page i, not the bpage contents itself. */
const byte *f; const byte *f= bpage->frame ? bpage->frame : bpage->zip.data;
switch (UNIV_EXPECT(bpage->state(), BUF_BLOCK_FILE_PAGE)) {
case BUF_BLOCK_FILE_PAGE:
f= reinterpret_cast<const buf_block_t*>(bpage)->frame;
break;
case BUF_BLOCK_ZIP_PAGE:
f= bpage->zip.data;
break;
default:
ut_ad("invalid state" == 0);
goto fail;
}
uint32_t prev= mach_read_from_4(my_assume_aligned<4>(f + FIL_PAGE_PREV)); uint32_t prev= mach_read_from_4(my_assume_aligned<4>(f + FIL_PAGE_PREV));
uint32_t next= mach_read_from_4(my_assume_aligned<4>(f + FIL_PAGE_NEXT)); uint32_t next= mach_read_from_4(my_assume_aligned<4>(f + FIL_PAGE_NEXT));
if (prev == FIL_NULL || next == FIL_NULL) if (prev == FIL_NULL || next == FIL_NULL)

View File

@@ -55,29 +55,29 @@ dict_hdr_get_new_id(
if (table_id) { if (table_id) {
id = mach_read_from_8(DICT_HDR + DICT_HDR_TABLE_ID id = mach_read_from_8(DICT_HDR + DICT_HDR_TABLE_ID
+ dict_hdr->frame); + dict_hdr->page.frame);
id++; id++;
mtr.write<8>(*dict_hdr, DICT_HDR + DICT_HDR_TABLE_ID mtr.write<8>(*dict_hdr, DICT_HDR + DICT_HDR_TABLE_ID
+ dict_hdr->frame, id); + dict_hdr->page.frame, id);
*table_id = id; *table_id = id;
} }
if (index_id) { if (index_id) {
id = mach_read_from_8(DICT_HDR + DICT_HDR_INDEX_ID id = mach_read_from_8(DICT_HDR + DICT_HDR_INDEX_ID
+ dict_hdr->frame); + dict_hdr->page.frame);
id++; id++;
mtr.write<8>(*dict_hdr, DICT_HDR + DICT_HDR_INDEX_ID mtr.write<8>(*dict_hdr, DICT_HDR + DICT_HDR_INDEX_ID
+ dict_hdr->frame, id); + dict_hdr->page.frame, id);
*index_id = id; *index_id = id;
} }
if (space_id) { if (space_id) {
*space_id = mach_read_from_4(DICT_HDR + DICT_HDR_MAX_SPACE_ID *space_id = mach_read_from_4(DICT_HDR + DICT_HDR_MAX_SPACE_ID
+ dict_hdr->frame); + dict_hdr->page.frame);
if (fil_assign_new_space_id(space_id)) { if (fil_assign_new_space_id(space_id)) {
mtr.write<4>(*dict_hdr, mtr.write<4>(*dict_hdr,
DICT_HDR + DICT_HDR_MAX_SPACE_ID DICT_HDR + DICT_HDR_MAX_SPACE_ID
+ dict_hdr->frame, *space_id); + dict_hdr->page.frame, *space_id);
} }
} }
@@ -90,7 +90,7 @@ void dict_hdr_flush_row_id(row_id_t id)
mtr_t mtr; mtr_t mtr;
mtr.start(); mtr.start();
buf_block_t* d= dict_hdr_get(&mtr); buf_block_t* d= dict_hdr_get(&mtr);
byte *row_id= DICT_HDR + DICT_HDR_ROW_ID + d->frame; byte *row_id= DICT_HDR + DICT_HDR_ROW_ID + d->page.frame;
if (mach_read_from_8(row_id) < id) if (mach_read_from_8(row_id) < id)
mtr.write<8>(*d, row_id, id); mtr.write<8>(*d, row_id, id);
mtr.commit(); mtr.commit();
@@ -119,17 +119,18 @@ static bool dict_hdr_create()
/* Start counting row, table, index, and tree ids from /* Start counting row, table, index, and tree ids from
DICT_HDR_FIRST_ID */ DICT_HDR_FIRST_ID */
mtr.write<8>(*d, DICT_HDR + DICT_HDR_ROW_ID + d->frame, mtr.write<8>(*d, DICT_HDR + DICT_HDR_ROW_ID + d->page.frame,
DICT_HDR_FIRST_ID); DICT_HDR_FIRST_ID);
mtr.write<8>(*d, DICT_HDR + DICT_HDR_TABLE_ID + d->frame, mtr.write<8>(*d, DICT_HDR + DICT_HDR_TABLE_ID + d->page.frame,
DICT_HDR_FIRST_ID); DICT_HDR_FIRST_ID);
mtr.write<8>(*d, DICT_HDR + DICT_HDR_INDEX_ID + d->frame, mtr.write<8>(*d, DICT_HDR + DICT_HDR_INDEX_ID + d->page.frame,
DICT_HDR_FIRST_ID); DICT_HDR_FIRST_ID);
ut_ad(!mach_read_from_4(DICT_HDR + DICT_HDR_MAX_SPACE_ID + d->frame)); ut_ad(!mach_read_from_4(DICT_HDR + DICT_HDR_MAX_SPACE_ID
+ d->page.frame));
/* Obsolete, but we must initialize it anyway. */ /* Obsolete, but we must initialize it anyway. */
mtr.write<4>(*d, DICT_HDR + DICT_HDR_MIX_ID_LOW + d->frame, mtr.write<4>(*d, DICT_HDR + DICT_HDR_MIX_ID_LOW + d->page.frame,
DICT_HDR_FIRST_ID); DICT_HDR_FIRST_ID);
/* Create the B-tree roots for the clustered indexes of the basic /* Create the B-tree roots for the clustered indexes of the basic
@@ -145,7 +146,8 @@ failed:
goto func_exit; goto func_exit;
} }
mtr.write<4>(*d, DICT_HDR + DICT_HDR_TABLES + d->frame, root_page_no); mtr.write<4>(*d, DICT_HDR + DICT_HDR_TABLES + d->page.frame,
root_page_no);
/*--------------------------*/ /*--------------------------*/
root_page_no = btr_create(DICT_UNIQUE, root_page_no = btr_create(DICT_UNIQUE,
fil_system.sys_space, DICT_TABLE_IDS_ID, fil_system.sys_space, DICT_TABLE_IDS_ID,
@@ -154,7 +156,7 @@ failed:
goto failed; goto failed;
} }
mtr.write<4>(*d, DICT_HDR + DICT_HDR_TABLE_IDS + d->frame, mtr.write<4>(*d, DICT_HDR + DICT_HDR_TABLE_IDS + d->page.frame,
root_page_no); root_page_no);
/*--------------------------*/ /*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
@@ -164,7 +166,7 @@ failed:
goto failed; goto failed;
} }
mtr.write<4>(*d, DICT_HDR + DICT_HDR_COLUMNS + d->frame, mtr.write<4>(*d, DICT_HDR + DICT_HDR_COLUMNS + d->page.frame,
root_page_no); root_page_no);
/*--------------------------*/ /*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
@@ -174,7 +176,8 @@ failed:
goto failed; goto failed;
} }
mtr.write<4>(*d, DICT_HDR + DICT_HDR_INDEXES + d->frame, root_page_no); mtr.write<4>(*d, DICT_HDR + DICT_HDR_INDEXES + d->page.frame,
root_page_no);
/*--------------------------*/ /*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_FIELDS_ID, fil_system.sys_space, DICT_FIELDS_ID,
@@ -183,7 +186,8 @@ failed:
goto failed; goto failed;
} }
mtr.write<4>(*d, DICT_HDR + DICT_HDR_FIELDS + d->frame, root_page_no); mtr.write<4>(*d, DICT_HDR + DICT_HDR_FIELDS + d->page.frame,
root_page_no);
func_exit: func_exit:
mtr.commit(); mtr.commit();
return fail; return fail;
@@ -228,7 +232,7 @@ dict_boot(void)
dict_sys.lock(SRW_LOCK_CALL); dict_sys.lock(SRW_LOCK_CALL);
/* Get the dictionary header */ /* Get the dictionary header */
const byte* dict_hdr = &dict_hdr_get(&mtr)->frame[DICT_HDR]; const byte* dict_hdr = &dict_hdr_get(&mtr)->page.frame[DICT_HDR];
/* Because we only write new row ids to disk-based data structure /* Because we only write new row ids to disk-based data structure
(dictionary header) when it is divisible by (dictionary header) when it is divisible by

View File

@@ -314,11 +314,11 @@ btr_get_size_and_reserved(
mtr->x_lock_space(index->table->space); mtr->x_lock_space(index->table->space);
ulint n = fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF ulint n = fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF
+ root->frame, used, mtr); + root->page.frame, used, mtr);
if (flag == BTR_TOTAL_SIZE) { if (flag == BTR_TOTAL_SIZE) {
n += fseg_n_reserved_pages(*root, n += fseg_n_reserved_pages(*root,
PAGE_HEADER + PAGE_BTR_SEG_TOP PAGE_HEADER + PAGE_BTR_SEG_TOP
+ root->frame, &dummy, mtr); + root->page.frame, &dummy, mtr);
*used += dummy; *used += dummy;
} }

View File

@@ -934,7 +934,8 @@ void dict_check_tablespaces_and_store_max_id()
mtr.start(); mtr.start();
uint32_t max_space_id = mach_read_from_4(DICT_HDR_MAX_SPACE_ID uint32_t max_space_id = mach_read_from_4(DICT_HDR_MAX_SPACE_ID
+ DICT_HDR + DICT_HDR
+ dict_hdr_get(&mtr)->frame); + dict_hdr_get(&mtr)
->page.frame);
mtr.commit(); mtr.commit();
fil_set_max_space_id_if_bigger(max_space_id); fil_set_max_space_id_if_bigger(max_space_id);
@@ -949,7 +950,8 @@ void dict_check_tablespaces_and_store_max_id()
} }
/** Error message for a delete-marked record in dict_load_column_low() */ /** Error message for a delete-marked record in dict_load_column_low() */
static const char* dict_load_column_del = "delete-marked record in SYS_COLUMN"; static const char *dict_load_column_del= "delete-marked record in SYS_COLUMNS";
static const char *dict_load_column_none= "SYS_COLUMNS record not found";
/** Load a table column definition from a SYS_COLUMNS record to dict_table_t. /** Load a table column definition from a SYS_COLUMNS record to dict_table_t.
@return error message @return error message
@@ -1001,7 +1003,7 @@ err_len:
if (table_id) { if (table_id) {
*table_id = mach_read_from_8(field); *table_id = mach_read_from_8(field);
} else if (table->id != mach_read_from_8(field)) { } else if (table->id != mach_read_from_8(field)) {
return("SYS_COLUMNS.TABLE_ID mismatch"); return dict_load_column_none;
} }
field = rec_get_nth_field_old( field = rec_get_nth_field_old(
@@ -1124,7 +1126,8 @@ err_len:
} }
/** Error message for a delete-marked record in dict_load_virtual_low() */ /** Error message for a delete-marked record in dict_load_virtual_low() */
static const char* dict_load_virtual_del = "delete-marked record in SYS_VIRTUAL"; static const char *dict_load_virtual_del= "delete-marked record in SYS_VIRTUAL";
static const char *dict_load_virtual_none= "SYS_VIRTUAL record not found";
/** Load a virtual column "mapping" (to base columns) information /** Load a virtual column "mapping" (to base columns) information
from a SYS_VIRTUAL record from a SYS_VIRTUAL record
@@ -1168,7 +1171,7 @@ err_len:
if (table_id != NULL) { if (table_id != NULL) {
*table_id = mach_read_from_8(field); *table_id = mach_read_from_8(field);
} else if (table->id != mach_read_from_8(field)) { } else if (table->id != mach_read_from_8(field)) {
return("SYS_VIRTUAL.TABLE_ID mismatch"); return dict_load_virtual_none;
} }
field = rec_get_nth_field_old( field = rec_get_nth_field_old(
@@ -1267,16 +1270,21 @@ dict_load_columns(
rec = btr_pcur_get_rec(&pcur); rec = btr_pcur_get_rec(&pcur);
ut_a(btr_pcur_is_on_user_rec(&pcur)); err_msg = btr_pcur_is_on_user_rec(&pcur)
? dict_load_column_low(table, heap, NULL, NULL,
&name, rec, &nth_v_col)
: dict_load_column_none;
err_msg = dict_load_column_low(table, heap, NULL, NULL, if (!err_msg) {
&name, rec, &nth_v_col); } else if (err_msg == dict_load_column_del) {
if (err_msg == dict_load_column_del) {
n_skipped++; n_skipped++;
goto next_rec; goto next_rec;
} else if (err_msg) { } else if (err_msg == dict_load_column_none
ib::fatal() << err_msg; && strstr(table->name.m_name,
"/" TEMP_FILE_PREFIX_INNODB)) {
break;
} else {
ib::fatal() << err_msg << " for table " << table->name;
} }
/* Note: Currently we have one DOC_ID column that is /* Note: Currently we have one DOC_ID column that is
@@ -1339,7 +1347,6 @@ dict_load_virtual_one_col(
btr_pcur_t pcur; btr_pcur_t pcur;
dtuple_t* tuple; dtuple_t* tuple;
dfield_t* dfield; dfield_t* dfield;
const rec_t* rec;
byte* buf; byte* buf;
ulint i = 0; ulint i = 0;
mtr_t mtr; mtr_t mtr;
@@ -1384,28 +1391,26 @@ dict_load_virtual_one_col(
BTR_SEARCH_LEAF, &pcur, &mtr); BTR_SEARCH_LEAF, &pcur, &mtr);
for (i = 0; i < unsigned{v_col->num_base} + skipped; i++) { for (i = 0; i < unsigned{v_col->num_base} + skipped; i++) {
const char* err_msg;
ulint pos; ulint pos;
const char* err_msg
ut_ad(btr_pcur_is_on_user_rec(&pcur)); = btr_pcur_is_on_user_rec(&pcur)
? dict_load_virtual_low(table,
rec = btr_pcur_get_rec(&pcur);
ut_a(btr_pcur_is_on_user_rec(&pcur));
err_msg = dict_load_virtual_low(table,
&v_col->base_col[i - skipped], &v_col->base_col[i - skipped],
NULL, NULL,
&pos, NULL, rec); &pos, NULL,
btr_pcur_get_rec(&pcur))
: dict_load_virtual_none;
if (err_msg) { if (!err_msg) {
if (err_msg != dict_load_virtual_del) {
ib::fatal() << err_msg;
} else {
skipped++;
}
} else {
ut_ad(pos == vcol_pos); ut_ad(pos == vcol_pos);
} else if (err_msg == dict_load_virtual_del) {
skipped++;
} else if (err_msg == dict_load_virtual_none
&& strstr(table->name.m_name,
"/" TEMP_FILE_PREFIX_INNODB)) {
break;
} else {
ib::fatal() << err_msg << " for table " << table->name;
} }
btr_pcur_move_to_next_user_rec(&pcur, &mtr); btr_pcur_move_to_next_user_rec(&pcur, &mtr);
@@ -1433,7 +1438,9 @@ dict_load_virtual(
} }
/** Error message for a delete-marked record in dict_load_field_low() */ /** Error message for a delete-marked record in dict_load_field_low() */
static const char* dict_load_field_del = "delete-marked record in SYS_FIELDS"; static const char *dict_load_field_del= "delete-marked record in SYS_FIELDS";
static const char *dict_load_field_none= "SYS_FIELDS record not found";
/** Load an index field definition from a SYS_FIELDS record to dict_index_t. /** Load an index field definition from a SYS_FIELDS record to dict_index_t.
@return error message @return error message
@@ -1488,7 +1495,7 @@ err_len:
} else { } else {
first_field = (index->n_def == 0); first_field = (index->n_def == 0);
if (memcmp(field, index_id, 8)) { if (memcmp(field, index_id, 8)) {
return("SYS_FIELDS.INDEX_ID mismatch"); return dict_load_field_none;
} }
} }
@@ -1569,7 +1576,6 @@ dict_load_fields(
btr_pcur_t pcur; btr_pcur_t pcur;
dtuple_t* tuple; dtuple_t* tuple;
dfield_t* dfield; dfield_t* dfield;
const rec_t* rec;
byte* buf; byte* buf;
ulint i; ulint i;
mtr_t mtr; mtr_t mtr;
@@ -1596,27 +1602,29 @@ dict_load_fields(
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr); BTR_SEARCH_LEAF, &pcur, &mtr);
for (i = 0; i < index->n_fields; i++) { for (i = 0; i < index->n_fields; i++) {
const char* err_msg; const char *err_msg = btr_pcur_is_on_user_rec(&pcur)
? dict_load_field_low(buf, index, NULL, NULL, NULL,
heap, btr_pcur_get_rec(&pcur))
: dict_load_field_none;
rec = btr_pcur_get_rec(&pcur); if (!err_msg) {
} else if (err_msg == dict_load_field_del) {
ut_a(btr_pcur_is_on_user_rec(&pcur));
err_msg = dict_load_field_low(buf, index, NULL, NULL, NULL,
heap, rec);
if (err_msg == dict_load_field_del) {
/* There could be delete marked records in /* There could be delete marked records in
SYS_FIELDS because SYS_FIELDS.INDEX_ID can be SYS_FIELDS because SYS_FIELDS.INDEX_ID can be
updated by ALTER TABLE ADD INDEX. */ updated by ALTER TABLE ADD INDEX. */
} else {
goto next_rec; if (err_msg != dict_load_field_none
} else if (err_msg) { || strstr(index->table->name.m_name,
ib::error() << err_msg; "/" TEMP_FILE_PREFIX_INNODB)) {
ib::error() << err_msg << " for index "
<< index->name
<< " of table "
<< index->table->name;
}
error = DB_CORRUPTION; error = DB_CORRUPTION;
goto func_exit; goto func_exit;
} }
next_rec:
btr_pcur_move_to_next_user_rec(&pcur, &mtr); btr_pcur_move_to_next_user_rec(&pcur, &mtr);
} }
@@ -1628,11 +1636,11 @@ func_exit:
} }
/** Error message for a delete-marked record in dict_load_index_low() */ /** Error message for a delete-marked record in dict_load_index_low() */
static const char* dict_load_index_del = "delete-marked record in SYS_INDEXES"; static const char *dict_load_index_del= "delete-marked record in SYS_INDEXES";
/** Error message for table->id mismatch in dict_load_index_low() */ /** Error message for table->id mismatch in dict_load_index_low() */
static const char* dict_load_index_id_err = "SYS_INDEXES.TABLE_ID mismatch"; static const char *dict_load_index_none= "SYS_INDEXES record not found";
/** Error message for SYS_TABLES flags mismatch in dict_load_table_low() */ /** Error message for SYS_TABLES flags mismatch in dict_load_table_low() */
static const char* dict_load_table_flags = "incorrect flags in SYS_TABLES"; static const char *dict_load_table_flags= "incorrect flags in SYS_TABLES";
/** Load an index definition from a SYS_INDEXES record to dict_index_t. /** Load an index definition from a SYS_INDEXES record to dict_index_t.
If allocate=TRUE, we will create a dict_index_t structure and fill it If allocate=TRUE, we will create a dict_index_t structure and fill it
@@ -1705,7 +1713,7 @@ err_len:
} else if (memcmp(field, table_id, 8)) { } else if (memcmp(field, table_id, 8)) {
/* Caller supplied table_id, verify it is the same /* Caller supplied table_id, verify it is the same
id as on the index record */ id as on the index record */
return(dict_load_index_id_err); return dict_load_index_none;
} }
field = rec_get_nth_field_old( field = rec_get_nth_field_old(
@@ -1858,7 +1866,7 @@ dict_load_indexes(
err_msg = dict_load_index_low(buf, heap, rec, TRUE, &index); err_msg = dict_load_index_low(buf, heap, rec, TRUE, &index);
ut_ad(!index == !!err_msg); ut_ad(!index == !!err_msg);
if (err_msg == dict_load_index_id_err) { if (err_msg == dict_load_index_none) {
/* We have ran out of index definitions for /* We have ran out of index definitions for
the table. */ the table. */
break; break;
@@ -1962,8 +1970,8 @@ corrupted:
of the database server */ of the database server */
dict_mem_index_free(index); dict_mem_index_free(index);
} else { } else {
dict_load_fields(index, heap);
index->table = table; index->table = table;
dict_load_fields(index, heap);
/* The data dictionary tables should never contain /* The data dictionary tables should never contain
invalid index definitions. If we ignored this error invalid index definitions. If we ignored this error
@@ -2360,15 +2368,15 @@ corrupted:
page_id, table->space->zip_size(), page_id, table->space->zip_size(),
RW_S_LATCH, &mtr); RW_S_LATCH, &mtr);
const bool corrupted = !block const bool corrupted = !block
|| page_get_space_id(block->frame) || page_get_space_id(block->page.frame)
!= page_id.space() != page_id.space()
|| page_get_page_no(block->frame) || page_get_page_no(block->page.frame)
!= page_id.page_no() != page_id.page_no()
|| (mach_read_from_2(FIL_PAGE_TYPE || (mach_read_from_2(FIL_PAGE_TYPE
+ block->frame) + block->page.frame)
!= FIL_PAGE_INDEX != FIL_PAGE_INDEX
&& mach_read_from_2(FIL_PAGE_TYPE && mach_read_from_2(FIL_PAGE_TYPE
+ block->frame) + block->page.frame)
!= FIL_PAGE_TYPE_INSTANT); != FIL_PAGE_TYPE_INSTANT);
mtr.commit(); mtr.commit();
if (corrupted) { if (corrupted) {

View File

@@ -1442,10 +1442,12 @@ invalid:
index->stat_index_size index->stat_index_size
= fseg_n_reserved_pages(*root, PAGE_HEADER = fseg_n_reserved_pages(*root, PAGE_HEADER
+ PAGE_BTR_SEG_LEAF + PAGE_BTR_SEG_LEAF
+ root->frame, &size, &mtr) + root->page.frame, &size,
&mtr)
+ fseg_n_reserved_pages(*root, PAGE_HEADER + fseg_n_reserved_pages(*root, PAGE_HEADER
+ PAGE_BTR_SEG_TOP + PAGE_BTR_SEG_TOP
+ root->frame, &dummy, &mtr); + root->page.frame, &dummy,
&mtr);
mtr.commit(); mtr.commit();
@@ -2529,17 +2531,19 @@ empty_index:
DBUG_RETURN(result); DBUG_RETURN(result);
} }
root_level = btr_page_get_level(root->frame); root_level = btr_page_get_level(root->page.frame);
mtr.x_lock_space(index->table->space); mtr.x_lock_space(index->table->space);
ulint dummy, size; ulint dummy, size;
result.index_size result.index_size
= fseg_n_reserved_pages(*root, PAGE_HEADER = fseg_n_reserved_pages(*root, PAGE_HEADER
+ PAGE_BTR_SEG_LEAF + PAGE_BTR_SEG_LEAF
+ root->frame, &size, &mtr) + root->page.frame,
&size, &mtr)
+ fseg_n_reserved_pages(*root, PAGE_HEADER + fseg_n_reserved_pages(*root, PAGE_HEADER
+ PAGE_BTR_SEG_TOP + PAGE_BTR_SEG_TOP
+ root->frame, &dummy, &mtr); + root->page.frame,
&dummy, &mtr);
result.n_leaf_pages = size ? size : 1; result.n_leaf_pages = size ? size : 1;
} }
@@ -2647,7 +2651,7 @@ empty_index:
mtr_sx_lock_index(index, &mtr); mtr_sx_lock_index(index, &mtr);
buf_block_t *root = btr_root_block_get(index, RW_S_LATCH, buf_block_t *root = btr_root_block_get(index, RW_S_LATCH,
&mtr); &mtr);
if (!root || root_level != btr_page_get_level(root->frame) if (!root || root_level != btr_page_get_level(root->page.frame)
|| index->table->bulk_trx_id != bulk_trx_id) { || index->table->bulk_trx_id != bulk_trx_id) {
/* Just quit if the tree has changed beyond /* Just quit if the tree has changed beyond
recognition here. The old stats from previous recognition here. The old stats from previous

View File

@@ -216,7 +216,7 @@ void dict_stats_recalc_pool_del(table_id_t id, bool have_mdl_exclusive)
mysql_mutex_lock(&recalc_pool_mutex); mysql_mutex_lock(&recalc_pool_mutex);
const auto end= recalc_pool.end(); auto end= recalc_pool.end();
auto i= std::find_if(recalc_pool.begin(), end, auto i= std::find_if(recalc_pool.begin(), end,
[&](const recalc &r){return r.id == id;}); [&](const recalc &r){return r.id == id;});
if (i != end) if (i != end)
@@ -227,7 +227,14 @@ void dict_stats_recalc_pool_del(table_id_t id, bool have_mdl_exclusive)
{ {
i->state= recalc::IN_PROGRESS_DELETING; i->state= recalc::IN_PROGRESS_DELETING;
do do
{
my_cond_wait(&recalc_pool_cond, &recalc_pool_mutex.m_mutex); my_cond_wait(&recalc_pool_cond, &recalc_pool_mutex.m_mutex);
end= recalc_pool.end();
i= std::find_if(recalc_pool.begin(), end,
[&](const recalc &r){return r.id == id;});
if (i == end)
goto done;
}
while (i->state == recalc::IN_PROGRESS_DELETING); while (i->state == recalc::IN_PROGRESS_DELETING);
} }
/* fall through */ /* fall through */
@@ -241,6 +248,7 @@ void dict_stats_recalc_pool_del(table_id_t id, bool have_mdl_exclusive)
} }
} }
done:
mysql_mutex_unlock(&recalc_pool_mutex); mysql_mutex_unlock(&recalc_pool_mutex);
} }

View File

@@ -379,7 +379,7 @@ void fil_space_crypt_t::write_page0(buf_block_t* block, mtr_t* mtr)
{ {
const ulint offset = FSP_HEADER_OFFSET const ulint offset = FSP_HEADER_OFFSET
+ fsp_header_get_encryption_offset(block->zip_size()); + fsp_header_get_encryption_offset(block->zip_size());
byte* b = block->frame + offset; byte* b = block->page.frame + offset;
mtr->memcpy<mtr_t::MAYBE_NOP>(*block, b, CRYPT_MAGIC, MAGIC_SZ); mtr->memcpy<mtr_t::MAYBE_NOP>(*block, b, CRYPT_MAGIC, MAGIC_SZ);
@@ -628,24 +628,19 @@ byte* fil_space_encrypt(
@param[in] crypt_data crypt_data @param[in] crypt_data crypt_data
@param[in] tmp_frame Temporary buffer @param[in] tmp_frame Temporary buffer
@param[in,out] src_frame Page to decrypt @param[in,out] src_frame Page to decrypt
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED @return DB_SUCCESS or error */
@return true if page decrypted, false if not.*/ static dberr_t fil_space_decrypt_full_crc32(
static bool fil_space_decrypt_full_crc32(
ulint space, ulint space,
fil_space_crypt_t* crypt_data, fil_space_crypt_t* crypt_data,
byte* tmp_frame, byte* tmp_frame,
byte* src_frame, byte* src_frame)
dberr_t* err)
{ {
uint key_version = mach_read_from_4( uint key_version = mach_read_from_4(
src_frame + FIL_PAGE_FCRC32_KEY_VERSION); src_frame + FIL_PAGE_FCRC32_KEY_VERSION);
lsn_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN); lsn_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN);
uint offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET); uint offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET);
*err = DB_SUCCESS;
if (key_version == ENCRYPTION_KEY_NOT_ENCRYPTED) { ut_a(key_version != ENCRYPTION_KEY_NOT_ENCRYPTED);
return false;
}
ut_ad(crypt_data); ut_ad(crypt_data);
ut_ad(crypt_data->is_encrypted()); ut_ad(crypt_data->is_encrypted());
@@ -659,9 +654,7 @@ static bool fil_space_decrypt_full_crc32(
bool corrupted = false; bool corrupted = false;
uint size = buf_page_full_crc32_size(src_frame, NULL, &corrupted); uint size = buf_page_full_crc32_size(src_frame, NULL, &corrupted);
if (UNIV_UNLIKELY(corrupted)) { if (UNIV_UNLIKELY(corrupted)) {
fail: return DB_DECRYPTION_FAILED;
*err = DB_DECRYPTION_FAILED;
return false;
} }
uint srclen = size - (FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION uint srclen = size - (FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
@@ -673,7 +666,7 @@ fail:
if (rc != MY_AES_OK || dstlen != srclen) { if (rc != MY_AES_OK || dstlen != srclen) {
if (rc == -1) { if (rc == -1) {
goto fail; return DB_DECRYPTION_FAILED;
} }
ib::fatal() << "Unable to decrypt data-block " ib::fatal() << "Unable to decrypt data-block "
@@ -690,7 +683,7 @@ fail:
srv_stats.pages_decrypted.inc(); srv_stats.pages_decrypted.inc();
return true; /* page was decrypted */ return DB_SUCCESS; /* page was decrypted */
} }
/** Decrypt a page for non full checksum format. /** Decrypt a page for non full checksum format.
@@ -698,14 +691,12 @@ fail:
@param[in] tmp_frame Temporary buffer @param[in] tmp_frame Temporary buffer
@param[in] physical_size page size @param[in] physical_size page size
@param[in,out] src_frame Page to decrypt @param[in,out] src_frame Page to decrypt
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED @return DB_SUCCESS or error */
@return true if page decrypted, false if not.*/ static dberr_t fil_space_decrypt_for_non_full_checksum(
static bool fil_space_decrypt_for_non_full_checksum(
fil_space_crypt_t* crypt_data, fil_space_crypt_t* crypt_data,
byte* tmp_frame, byte* tmp_frame,
ulint physical_size, ulint physical_size,
byte* src_frame, byte* src_frame)
dberr_t* err)
{ {
uint key_version = mach_read_from_4( uint key_version = mach_read_from_4(
src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
@@ -716,12 +707,7 @@ static bool fil_space_decrypt_for_non_full_checksum(
src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
ib_uint64_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN); ib_uint64_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN);
*err = DB_SUCCESS; ut_a(key_version != ENCRYPTION_KEY_NOT_ENCRYPTED);
if (key_version == ENCRYPTION_KEY_NOT_ENCRYPTED) {
return false;
}
ut_a(crypt_data != NULL && crypt_data->is_encrypted()); ut_a(crypt_data != NULL && crypt_data->is_encrypted());
/* read space & lsn */ /* read space & lsn */
@@ -751,8 +737,7 @@ static bool fil_space_decrypt_for_non_full_checksum(
if (! ((rc == MY_AES_OK) && ((ulint) dstlen == srclen))) { if (! ((rc == MY_AES_OK) && ((ulint) dstlen == srclen))) {
if (rc == -1) { if (rc == -1) {
*err = DB_DECRYPTION_FAILED; return DB_DECRYPTION_FAILED;
return false;
} }
ib::fatal() << "Unable to decrypt data-block " ib::fatal() << "Unable to decrypt data-block "
@@ -777,7 +762,7 @@ static bool fil_space_decrypt_for_non_full_checksum(
srv_stats.pages_decrypted.inc(); srv_stats.pages_decrypted.inc();
return true; /* page was decrypted */ return DB_SUCCESS; /* page was decrypted */
} }
/** Decrypt a page. /** Decrypt a page.
@@ -788,25 +773,24 @@ static bool fil_space_decrypt_for_non_full_checksum(
@param[in] physical_size page size @param[in] physical_size page size
@param[in,out] src_frame Page to decrypt @param[in,out] src_frame Page to decrypt
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED @param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
@return true if page decrypted, false if not.*/ @return DB_SUCCESS or error */
bool dberr_t
fil_space_decrypt( fil_space_decrypt(
uint32_t space_id, uint32_t space_id,
uint32_t fsp_flags, uint32_t fsp_flags,
fil_space_crypt_t* crypt_data, fil_space_crypt_t* crypt_data,
byte* tmp_frame, byte* tmp_frame,
ulint physical_size, ulint physical_size,
byte* src_frame, byte* src_frame)
dberr_t* err)
{ {
if (fil_space_t::full_crc32(fsp_flags)) { if (fil_space_t::full_crc32(fsp_flags)) {
return fil_space_decrypt_full_crc32( return fil_space_decrypt_full_crc32(
space_id, crypt_data, tmp_frame, src_frame, err); space_id, crypt_data, tmp_frame, src_frame);
} }
return fil_space_decrypt_for_non_full_checksum(crypt_data, tmp_frame, return fil_space_decrypt_for_non_full_checksum(crypt_data, tmp_frame,
physical_size, src_frame, physical_size,
err); src_frame);
} }
/** /**
@@ -822,29 +806,23 @@ fil_space_decrypt(
byte* tmp_frame, byte* tmp_frame,
byte* src_frame) byte* src_frame)
{ {
dberr_t err = DB_SUCCESS;
byte* res = NULL;
const ulint physical_size = space->physical_size(); const ulint physical_size = space->physical_size();
ut_ad(space->crypt_data != NULL && space->crypt_data->is_encrypted()); ut_ad(space->crypt_data != NULL && space->crypt_data->is_encrypted());
ut_ad(space->referenced()); ut_ad(space->referenced());
bool encrypted = fil_space_decrypt(space->id, space->flags, if (DB_SUCCESS != fil_space_decrypt(space->id, space->flags,
space->crypt_data, space->crypt_data,
tmp_frame, physical_size, tmp_frame, physical_size,
src_frame, &err); src_frame)) {
return nullptr;
if (err == DB_SUCCESS) {
if (encrypted) {
/* Copy the decrypted page back to page buffer, not
really any other options. */
memcpy(src_frame, tmp_frame, physical_size);
}
res = src_frame;
} }
return res; /* Copy the decrypted page back to page buffer, not
really any other options. */
memcpy(src_frame, tmp_frame, physical_size);
return src_frame;
} }
/***********************************************************************/ /***********************************************************************/
@@ -961,13 +939,13 @@ fil_crypt_read_crypt_data(fil_space_t* space)
nullptr, nullptr,
BUF_GET_POSSIBLY_FREED, BUF_GET_POSSIBLY_FREED,
&mtr)) { &mtr)) {
if (block->page.status == buf_page_t::FREED) { if (block->page.is_freed()) {
goto func_exit; goto func_exit;
} }
mysql_mutex_lock(&fil_system.mutex); mysql_mutex_lock(&fil_system.mutex);
if (!space->crypt_data && !space->is_stopping()) { if (!space->crypt_data && !space->is_stopping()) {
space->crypt_data = fil_space_read_crypt_data( space->crypt_data = fil_space_read_crypt_data(
zip_size, block->frame); zip_size, block->page.frame);
} }
mysql_mutex_unlock(&fil_system.mutex); mysql_mutex_unlock(&fil_system.mutex);
} }
@@ -1024,7 +1002,7 @@ func_exit:
page_id_t(space->id, 0), space->zip_size(), page_id_t(space->id, 0), space->zip_size(),
RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED,
&mtr, &err)) { &mtr, &err)) {
if (block->page.status == buf_page_t::FREED) { if (block->page.is_freed()) {
goto abort; goto abort;
} }
@@ -1816,7 +1794,7 @@ fil_crypt_rotate_page(
const lsn_t block_lsn = mach_read_from_8(FIL_PAGE_LSN + frame); const lsn_t block_lsn = mach_read_from_8(FIL_PAGE_LSN + frame);
uint kv = buf_page_get_key_version(frame, space->flags); uint kv = buf_page_get_key_version(frame, space->flags);
if (block->page.status == buf_page_t::FREED) { if (block->page.is_freed()) {
/* Do not modify freed pages to avoid an assertion /* Do not modify freed pages to avoid an assertion
failure on recovery.*/ failure on recovery.*/
} else if (block->page.oldest_modification() > 1) { } else if (block->page.oldest_modification() > 1) {
@@ -1996,7 +1974,7 @@ fil_crypt_flush_space(
if (buf_block_t* block = buf_page_get_gen( if (buf_block_t* block = buf_page_get_gen(
page_id_t(space->id, 0), space->zip_size(), page_id_t(space->id, 0), space->zip_size(),
RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, &mtr)) { RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, &mtr)) {
if (block->page.status != buf_page_t::FREED) { if (block->page.is_freed()) {
mtr.set_named_space(space); mtr.set_named_space(space);
crypt_data->write_page0(block, &mtr); crypt_data->write_page0(block, &mtr);
} }
@@ -2438,11 +2416,14 @@ encrypted, or corrupted.
@return true if page is encrypted AND OK, false otherwise */ @return true if page is encrypted AND OK, false otherwise */
bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size) bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size)
{ {
ut_ad(mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION)); if (ENCRYPTION_KEY_NOT_ENCRYPTED == mach_read_from_4(
page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION)) {
return false;
}
/* Compressed and encrypted pages do not have checksum. Assume not /* Compressed and encrypted pages do not have checksum. Assume not
corrupted. Page verification happens after decompression in corrupted. Page verification happens after decompression in
buf_page_read_complete() using buf_page_is_corrupted(). */ buf_page_t::read_complete() using buf_page_is_corrupted(). */
if (fil_page_get_type(page) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) { if (fil_page_get_type(page) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) {
return true; return true;
} }

View File

@@ -2650,7 +2650,7 @@ void fsp_flags_try_adjust(fil_space_t *space, uint32_t flags)
if (buf_block_t* b = buf_page_get( if (buf_block_t* b = buf_page_get(
page_id_t(space->id, 0), space->zip_size(), page_id_t(space->id, 0), space->zip_size(),
RW_X_LATCH, &mtr)) { RW_X_LATCH, &mtr)) {
uint32_t f = fsp_header_get_flags(b->frame); uint32_t f = fsp_header_get_flags(b->page.frame);
if (fil_space_t::full_crc32(f)) { if (fil_space_t::full_crc32(f)) {
goto func_exit; goto func_exit;
} }
@@ -2668,7 +2668,7 @@ void fsp_flags_try_adjust(fil_space_t *space, uint32_t flags)
mtr.set_named_space(space); mtr.set_named_space(space);
mtr.write<4,mtr_t::FORCED>(*b, mtr.write<4,mtr_t::FORCED>(*b,
FSP_HEADER_OFFSET + FSP_SPACE_FLAGS FSP_HEADER_OFFSET + FSP_SPACE_FLAGS
+ b->frame, flags); + b->page.frame, flags);
} }
func_exit: func_exit:
mtr.commit(); mtr.commit();
@@ -2836,7 +2836,7 @@ fail:
goto release_sync_write; goto release_sync_write;
} else { } else {
/* Queue the aio request */ /* Queue the aio request */
err = os_aio(IORequest(bpage, node, type.type), err = os_aio(IORequest{bpage, type.slot, node, type.type},
buf, offset, len); buf, offset, len);
} }
@@ -2892,7 +2892,7 @@ write_completed:
files and never issue asynchronous reads of change buffer pages. */ files and never issue asynchronous reads of change buffer pages. */
const page_id_t id(request.bpage->id()); const page_id_t id(request.bpage->id());
if (dberr_t err= buf_page_read_complete(request.bpage, *request.node)) if (dberr_t err= request.bpage->read_complete(*request.node))
{ {
if (recv_recovery_is_on() && !srv_force_recovery) if (recv_recovery_is_on() && !srv_force_recovery)
{ {

View File

@@ -130,10 +130,10 @@ static buf_block_t *fsp_get_header(const fil_space_t *space, mtr_t *mtr)
buf_block_t *block= buf_page_get_gen(page_id_t(space->id, 0), buf_block_t *block= buf_page_get_gen(page_id_t(space->id, 0),
space->zip_size(), RW_SX_LATCH, space->zip_size(), RW_SX_LATCH,
nullptr, BUF_GET_POSSIBLY_FREED, mtr); nullptr, BUF_GET_POSSIBLY_FREED, mtr);
if (!block || block->page.status == buf_page_t::FREED) if (!block || block->page.is_freed())
return nullptr; return nullptr;
ut_ad(space->id == mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + ut_ad(space->id == mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_ID +
block->frame)); block->page.frame));
return block; return block;
} }
@@ -150,7 +150,7 @@ inline void xdes_set_free(const buf_block_t &block, xdes_t *descr,
ut_ad(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_SX_FIX | ut_ad(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_SX_FIX |
MTR_MEMO_PAGE_X_FIX)); MTR_MEMO_PAGE_X_FIX));
ut_ad(offset < FSP_EXTENT_SIZE); ut_ad(offset < FSP_EXTENT_SIZE);
ut_ad(page_align(descr) == block.frame); ut_ad(page_align(descr) == block.page.frame);
compile_time_assert(XDES_BITS_PER_PAGE == 2); compile_time_assert(XDES_BITS_PER_PAGE == 2);
compile_time_assert(XDES_FREE_BIT == 0); compile_time_assert(XDES_FREE_BIT == 0);
compile_time_assert(XDES_CLEAN_BIT == 1); compile_time_assert(XDES_CLEAN_BIT == 1);
@@ -222,7 +222,7 @@ inline void xdes_set_state(const buf_block_t &block, xdes_t *descr,
ut_ad(state <= XDES_FSEG); ut_ad(state <= XDES_FSEG);
ut_ad(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_SX_FIX | ut_ad(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_SX_FIX |
MTR_MEMO_PAGE_X_FIX)); MTR_MEMO_PAGE_X_FIX));
ut_ad(page_align(descr) == block.frame); ut_ad(page_align(descr) == block.page.frame);
ut_ad(mach_read_from_4(descr + XDES_STATE) <= XDES_FSEG); ut_ad(mach_read_from_4(descr + XDES_STATE) <= XDES_FSEG);
mtr->write<1>(block, XDES_STATE + 3 + descr, state); mtr->write<1>(block, XDES_STATE + 3 + descr, state);
} }
@@ -250,7 +250,7 @@ inline void xdes_init(const buf_block_t &block, xdes_t *descr, mtr_t *mtr)
{ {
ut_ad(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_SX_FIX | ut_ad(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_SX_FIX |
MTR_MEMO_PAGE_X_FIX)); MTR_MEMO_PAGE_X_FIX));
mtr->memset(&block, uint16_t(descr - block.frame) + XDES_BITMAP, mtr->memset(&block, uint16_t(descr - block.page.frame) + XDES_BITMAP,
XDES_SIZE - XDES_BITMAP, 0xff); XDES_SIZE - XDES_BITMAP, 0xff);
xdes_set_state(block, descr, XDES_FREE, mtr); xdes_set_state(block, descr, XDES_FREE, mtr);
} }
@@ -267,13 +267,13 @@ void
fseg_mark_page_used(fseg_inode_t *seg_inode, buf_block_t *iblock, fseg_mark_page_used(fseg_inode_t *seg_inode, buf_block_t *iblock,
ulint page, xdes_t *descr, buf_block_t *xdes, mtr_t *mtr) ulint page, xdes_t *descr, buf_block_t *xdes, mtr_t *mtr)
{ {
ut_ad(fil_page_get_type(iblock->frame) == FIL_PAGE_INODE); ut_ad(fil_page_get_type(iblock->page.frame) == FIL_PAGE_INODE);
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
ut_ad(!memcmp(seg_inode + FSEG_ID, descr + XDES_ID, 4)); ut_ad(!memcmp(seg_inode + FSEG_ID, descr + XDES_ID, 4));
const uint16_t xoffset= uint16_t(descr - xdes->frame + XDES_FLST_NODE); const uint16_t xoffset= uint16_t(descr - xdes->page.frame + XDES_FLST_NODE);
const uint16_t ioffset= uint16_t(seg_inode - iblock->frame); const uint16_t ioffset= uint16_t(seg_inode - iblock->page.frame);
if (!xdes_get_n_used(descr)) if (!xdes_get_n_used(descr))
{ {
@@ -325,9 +325,9 @@ xdes_get_descriptor_with_space_hdr(
| MTR_MEMO_PAGE_X_FIX)); | MTR_MEMO_PAGE_X_FIX));
/* Read free limit and space size */ /* Read free limit and space size */
uint32_t limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT uint32_t limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ header->frame); + header->page.frame);
uint32_t size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE uint32_t size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE
+ header->frame); + header->page.frame);
ut_ad(limit == space->free_limit ut_ad(limit == space->free_limit
|| (space->free_limit == 0 || (space->free_limit == 0
&& (init_space && (init_space
@@ -351,7 +351,7 @@ xdes_get_descriptor_with_space_hdr(
block = buf_page_get_gen(page_id_t(space->id, descr_page_no), block = buf_page_get_gen(page_id_t(space->id, descr_page_no),
zip_size, RW_SX_LATCH, nullptr, zip_size, RW_SX_LATCH, nullptr,
BUF_GET_POSSIBLY_FREED, mtr); BUF_GET_POSSIBLY_FREED, mtr);
if (block && block->page.status == buf_page_t::FREED) { if (block && block->page.is_freed()) {
block = nullptr; block = nullptr;
} }
} }
@@ -363,7 +363,7 @@ xdes_get_descriptor_with_space_hdr(
return block return block
? XDES_ARR_OFFSET + XDES_SIZE ? XDES_ARR_OFFSET + XDES_SIZE
* xdes_calc_descriptor_index(zip_size, offset) * xdes_calc_descriptor_index(zip_size, offset)
+ block->frame + block->page.frame
: nullptr; : nullptr;
} }
@@ -385,7 +385,7 @@ static xdes_t *xdes_get_descriptor(const fil_space_t *space, page_no_t offset,
buf_block_t *block= buf_page_get_gen(page_id_t(space->id, 0), buf_block_t *block= buf_page_get_gen(page_id_t(space->id, 0),
space->zip_size(), RW_SX_LATCH, space->zip_size(), RW_SX_LATCH,
nullptr, BUF_GET_POSSIBLY_FREED, mtr); nullptr, BUF_GET_POSSIBLY_FREED, mtr);
if (!block || block->page.status == buf_page_t::FREED) if (!block || block->page.is_freed())
return nullptr; return nullptr;
return xdes_get_descriptor_with_space_hdr(block, space, offset, mtr, xdes); return xdes_get_descriptor_with_space_hdr(block, space, offset, mtr, xdes);
} }
@@ -422,18 +422,18 @@ xdes_get_descriptor_const(
nullptr, nullptr,
BUF_GET_POSSIBLY_FREED, BUF_GET_POSSIBLY_FREED,
mtr)) { mtr)) {
if (block->page.status == buf_page_t::FREED) { if (block->page.is_freed()) {
return nullptr; return nullptr;
} }
ut_ad(page != 0 || space->free_limit == mach_read_from_4( ut_ad(page != 0 || space->free_limit == mach_read_from_4(
FSP_FREE_LIMIT + FSP_HEADER_OFFSET FSP_FREE_LIMIT + FSP_HEADER_OFFSET
+ block->frame)); + block->page.frame));
ut_ad(page != 0 || space->size_in_header == mach_read_from_4( ut_ad(page != 0 || space->size_in_header == mach_read_from_4(
FSP_SIZE + FSP_HEADER_OFFSET FSP_SIZE + FSP_HEADER_OFFSET
+ block->frame)); + block->page.frame));
return(block->frame + XDES_ARR_OFFSET + XDES_SIZE return(block->page.frame + XDES_ARR_OFFSET + XDES_SIZE
* xdes_calc_descriptor_index(zip_size, offset)); * xdes_calc_descriptor_index(zip_size, offset));
} }
@@ -473,26 +473,27 @@ static uint32_t xdes_get_offset(const xdes_t *descr)
@param[in,out] block buffer pool block */ @param[in,out] block buffer pool block */
void fsp_apply_init_file_page(buf_block_t *block) void fsp_apply_init_file_page(buf_block_t *block)
{ {
memset_aligned<UNIV_PAGE_SIZE_MIN>(block->frame, 0, srv_page_size); memset_aligned<UNIV_PAGE_SIZE_MIN>(block->page.frame, 0, srv_page_size);
const page_id_t id(block->page.id()); const page_id_t id(block->page.id());
mach_write_to_4(block->frame + FIL_PAGE_OFFSET, id.page_no()); mach_write_to_4(block->page.frame + FIL_PAGE_OFFSET, id.page_no());
if (log_sys.is_physical()) if (log_sys.is_physical())
memset_aligned<8>(block->frame + FIL_PAGE_PREV, 0xff, 8); memset_aligned<8>(block->page.frame + FIL_PAGE_PREV, 0xff, 8);
mach_write_to_4(block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id.space()); mach_write_to_4(block->page.frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
id.space());
if (page_zip_des_t* page_zip= buf_block_get_page_zip(block)) if (page_zip_des_t* page_zip= buf_block_get_page_zip(block))
{ {
memset_aligned<UNIV_ZIP_SIZE_MIN>(page_zip->data, 0, memset_aligned<UNIV_ZIP_SIZE_MIN>(page_zip->data, 0,
page_zip_get_size(page_zip)); page_zip_get_size(page_zip));
static_assert(FIL_PAGE_OFFSET == 4, "compatibility"); static_assert(FIL_PAGE_OFFSET == 4, "compatibility");
memcpy_aligned<4>(page_zip->data + FIL_PAGE_OFFSET, memcpy_aligned<4>(page_zip->data + FIL_PAGE_OFFSET,
block->frame + FIL_PAGE_OFFSET, 4); block->page.frame + FIL_PAGE_OFFSET, 4);
if (log_sys.is_physical()) if (log_sys.is_physical())
memset_aligned<8>(page_zip->data + FIL_PAGE_PREV, 0xff, 8); memset_aligned<8>(page_zip->data + FIL_PAGE_PREV, 0xff, 8);
static_assert(FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID % 4 == 2, static_assert(FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID % 4 == 2,
"not perfect alignment"); "not perfect alignment");
memcpy_aligned<2>(page_zip->data + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, memcpy_aligned<2>(page_zip->data + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 4); block->page.frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 4);
} }
} }
@@ -552,28 +553,28 @@ void fsp_header_init(fil_space_t* space, uint32_t size, mtr_t* mtr)
fsp_init_file_page(space, block, mtr); fsp_init_file_page(space, block, mtr);
mtr->write<2>(*block, block->frame + FIL_PAGE_TYPE, mtr->write<2>(*block, block->page.frame + FIL_PAGE_TYPE,
FIL_PAGE_TYPE_FSP_HDR); FIL_PAGE_TYPE_FSP_HDR);
mtr->write<4,mtr_t::MAYBE_NOP>(*block, FSP_HEADER_OFFSET + FSP_SPACE_ID mtr->write<4,mtr_t::MAYBE_NOP>(*block, FSP_HEADER_OFFSET + FSP_SPACE_ID
+ block->frame, space->id); + block->page.frame, space->id);
ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_NOT_USED ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_NOT_USED
+ block->frame)); + block->page.frame));
/* recv_sys_t::parse() expects to find a WRITE record that /* recv_sys_t::parse() expects to find a WRITE record that
covers all 4 bytes. Therefore, we must specify mtr_t::FORCED covers all 4 bytes. Therefore, we must specify mtr_t::FORCED
in order to avoid optimizing away any unchanged most in order to avoid optimizing away any unchanged most
significant bytes of FSP_SIZE. */ significant bytes of FSP_SIZE. */
mtr->write<4,mtr_t::FORCED>(*block, FSP_HEADER_OFFSET + FSP_SIZE mtr->write<4,mtr_t::FORCED>(*block, FSP_HEADER_OFFSET + FSP_SIZE
+ block->frame, size); + block->page.frame, size);
ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ block->frame)); + block->page.frame));
if (auto f = space->flags & ~FSP_FLAGS_MEM_MASK) { if (auto f = space->flags & ~FSP_FLAGS_MEM_MASK) {
mtr->write<4,mtr_t::FORCED>(*block, mtr->write<4,mtr_t::FORCED>(*block,
FSP_HEADER_OFFSET + FSP_SPACE_FLAGS FSP_HEADER_OFFSET + FSP_SPACE_FLAGS
+ block->frame, f); + block->page.frame, f);
} }
ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FRAG_N_USED ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ block->frame)); + block->page.frame));
flst_init(block, FSP_HEADER_OFFSET + FSP_FREE, mtr); flst_init(block, FSP_HEADER_OFFSET + FSP_FREE, mtr);
flst_init(block, FSP_HEADER_OFFSET + FSP_FREE_FRAG, mtr); flst_init(block, FSP_HEADER_OFFSET + FSP_FREE_FRAG, mtr);
@@ -581,7 +582,8 @@ void fsp_header_init(fil_space_t* space, uint32_t size, mtr_t* mtr)
flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL, mtr); flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL, mtr);
flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, mtr); flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, mtr);
mtr->write<8>(*block, FSP_HEADER_OFFSET + FSP_SEG_ID + block->frame, mtr->write<8>(*block, FSP_HEADER_OFFSET + FSP_SEG_ID
+ block->page.frame,
1U); 1U);
fsp_fill_free_list(!is_system_tablespace(space->id), fsp_fill_free_list(!is_system_tablespace(space->id),
@@ -617,7 +619,8 @@ fsp_try_extend_data_file_with_pages(
ut_a(!is_system_tablespace(space->id)); ut_a(!is_system_tablespace(space->id));
ut_d(space->modify_check(*mtr)); ut_d(space->modify_check(*mtr));
size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE + header->frame); size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE
+ header->page.frame);
ut_ad(size == space->size_in_header); ut_ad(size == space->size_in_header);
ut_a(page_no >= size); ut_a(page_no >= size);
@@ -629,7 +632,7 @@ fsp_try_extend_data_file_with_pages(
in order to avoid optimizing away any unchanged most in order to avoid optimizing away any unchanged most
significant bytes of FSP_SIZE. */ significant bytes of FSP_SIZE. */
mtr->write<4,mtr_t::FORCED>(*header, FSP_HEADER_OFFSET + FSP_SIZE mtr->write<4,mtr_t::FORCED>(*header, FSP_HEADER_OFFSET + FSP_SIZE
+ header->frame, space->size); + header->page.frame, space->size);
space->size_in_header = space->size; space->size_in_header = space->size;
return(success); return(success);
@@ -722,7 +725,7 @@ fsp_try_extend_data_file(fil_space_t *space, buf_block_t *header, mtr_t *mtr)
} }
uint32_t size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE uint32_t size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE
+ header->frame); + header->page.frame);
ut_ad(size == space->size_in_header); ut_ad(size == space->size_in_header);
uint32_t size_increase; uint32_t size_increase;
@@ -770,7 +773,8 @@ fsp_try_extend_data_file(fil_space_t *space, buf_block_t *header, mtr_t *mtr)
in order to avoid optimizing away any unchanged most in order to avoid optimizing away any unchanged most
significant bytes of FSP_SIZE. */ significant bytes of FSP_SIZE. */
mtr->write<4,mtr_t::FORCED>(*header, FSP_HEADER_OFFSET + FSP_SIZE mtr->write<4,mtr_t::FORCED>(*header, FSP_HEADER_OFFSET + FSP_SIZE
+ header->frame, space->size_in_header); + header->page.frame,
space->size_in_header);
return(size_increase); return(size_increase);
} }
@@ -785,10 +789,9 @@ Any other pages were written with uninitialized bytes in FIL_PAGE_TYPE.
ATTRIBUTE_COLD ATTRIBUTE_COLD
void fil_block_reset_type(const buf_block_t& block, ulint type, mtr_t* mtr) void fil_block_reset_type(const buf_block_t& block, ulint type, mtr_t* mtr)
{ {
ib::info() ib::info() << "Resetting invalid page " << block.page.id() << " type "
<< "Resetting invalid page " << block.page.id() << " type " << fil_page_get_type(block.page.frame) << " to " << type << ".";
<< fil_page_get_type(block.frame) << " to " << type << "."; mtr->write<2>(block, block.page.frame + FIL_PAGE_TYPE, type);
mtr->write<2>(block, block.frame + FIL_PAGE_TYPE, type);
} }
/** Put new extents to the free list if there are free extents above the free /** Put new extents to the free list if there are free extents above the free
@@ -812,9 +815,9 @@ fsp_fill_free_list(
/* Check if we can fill free list from above the free list limit */ /* Check if we can fill free list from above the free list limit */
uint32_t size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE uint32_t size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE
+ header->frame); + header->page.frame);
uint32_t limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT uint32_t limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ header->frame); + header->page.frame);
ut_ad(size == space->size_in_header); ut_ad(size == space->size_in_header);
ut_ad(limit == space->free_limit); ut_ad(limit == space->free_limit);
@@ -849,7 +852,7 @@ fsp_fill_free_list(
space->free_limit = i + extent_size; space->free_limit = i + extent_size;
mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_FREE_LIMIT mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ header->frame, i + extent_size); + header->page.frame, i + extent_size);
if (init_xdes) { if (init_xdes) {
@@ -868,8 +871,8 @@ fsp_fill_free_list(
buf_pool.free_block(f); buf_pool.free_block(f);
} }
fsp_init_file_page(space, block, mtr); fsp_init_file_page(space, block, mtr);
mtr->write<2>(*block, mtr->write<2>(*block, FIL_PAGE_TYPE
FIL_PAGE_TYPE + block->frame, + block->page.frame,
FIL_PAGE_TYPE_XDES); FIL_PAGE_TYPE_XDES);
} }
@@ -884,8 +887,8 @@ fsp_fill_free_list(
buf_pool.free_block(f); buf_pool.free_block(f);
} }
fsp_init_file_page(space, block, mtr); fsp_init_file_page(space, block, mtr);
mtr->write<2>(*block, mtr->write<2>(*block, FIL_PAGE_TYPE
block->frame + FIL_PAGE_TYPE, + block->page.frame,
FIL_PAGE_IBUF_BITMAP); FIL_PAGE_IBUF_BITMAP);
} }
} }
@@ -903,7 +906,7 @@ fsp_fill_free_list(
} }
xdes_init(*xdes, descr, mtr); xdes_init(*xdes, descr, mtr);
const uint16_t xoffset= static_cast<uint16_t>( const uint16_t xoffset= static_cast<uint16_t>(
descr - xdes->frame + XDES_FLST_NODE); descr - xdes->page.frame + XDES_FLST_NODE);
if (UNIV_UNLIKELY(init_xdes)) { if (UNIV_UNLIKELY(init_xdes)) {
@@ -920,7 +923,7 @@ fsp_fill_free_list(
FSP_HEADER_OFFSET + FSP_FREE_FRAG, FSP_HEADER_OFFSET + FSP_FREE_FRAG,
xdes, xoffset, mtr); xdes, xoffset, mtr);
byte* n_used = FSP_HEADER_OFFSET + FSP_FRAG_N_USED byte* n_used = FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ header->frame; + header->page.frame;
mtr->write<4>(*header, n_used, mtr->write<4>(*header, n_used,
2U + mach_read_from_4(n_used)); 2U + mach_read_from_4(n_used));
} else { } else {
@@ -974,13 +977,13 @@ fsp_alloc_free_extent(
} else { } else {
/* Take the first extent in the free list */ /* Take the first extent in the free list */
first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE
+ header->frame); + header->page.frame);
if (first.page == FIL_NULL) { if (first.page == FIL_NULL) {
fsp_fill_free_list(false, space, header, mtr); fsp_fill_free_list(false, space, header, mtr);
first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE
+ header->frame); + header->page.frame);
if (first.page == FIL_NULL) { if (first.page == FIL_NULL) {
return nullptr; /* No free extents left */ return nullptr; /* No free extents left */
} }
@@ -996,7 +999,8 @@ fsp_alloc_free_extent(
flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE, desc_block, flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE, desc_block,
static_cast<uint16_t>( static_cast<uint16_t>(
descr - desc_block->frame + XDES_FLST_NODE), mtr); descr - desc_block->page.frame + XDES_FLST_NODE),
mtr);
space->free_len--; space->free_len--;
*xdes = desc_block; *xdes = desc_block;
@@ -1018,14 +1022,15 @@ fsp_alloc_from_free_frag(buf_block_t *header, buf_block_t *xdes, xdes_t *descr,
xdes_set_free<false>(*xdes, descr, bit, mtr); xdes_set_free<false>(*xdes, descr, bit, mtr);
/* Update the FRAG_N_USED field */ /* Update the FRAG_N_USED field */
byte* n_used_p = FSP_HEADER_OFFSET + FSP_FRAG_N_USED + header->frame; byte* n_used_p = FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ header->page.frame;
uint32_t n_used = mach_read_from_4(n_used_p) + 1; uint32_t n_used = mach_read_from_4(n_used_p) + 1;
if (xdes_is_full(descr)) { if (xdes_is_full(descr)) {
/* The fragment is full: move it to another list */ /* The fragment is full: move it to another list */
const uint16_t xoffset= static_cast<uint16_t>( const uint16_t xoffset= static_cast<uint16_t>(
descr - xdes->frame + XDES_FLST_NODE); descr - xdes->page.frame + XDES_FLST_NODE);
flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE_FRAG, flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE_FRAG,
xdes, xoffset, mtr); xdes, xoffset, mtr);
xdes_set_state(*xdes, descr, XDES_FULL_FRAG, mtr); xdes_set_state(*xdes, descr, XDES_FULL_FRAG, mtr);
@@ -1063,7 +1068,7 @@ fsp_page_create(fil_space_t *space, page_no_t offset, mtr_t *mtr)
if (block) if (block)
{ {
ut_ad(block->page.buf_fix_count() >= 1); ut_ad(block->page.buf_fix_count() >= 1);
ut_ad(block->lock.x_lock_count() == 1); ut_ad(block->page.lock.x_lock_count() == 1);
ut_ad(mtr->have_x_latch(*block)); ut_ad(mtr->have_x_latch(*block));
free_block= block; free_block= block;
goto got_free_block; goto got_free_block;
@@ -1119,7 +1124,7 @@ fsp_alloc_free_page(
} else { } else {
/* Else take the first extent in free_frag list */ /* Else take the first extent in free_frag list */
first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE_FRAG first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE_FRAG
+ block->frame); + block->page.frame);
if (first.page == FIL_NULL) { if (first.page == FIL_NULL) {
/* There are no partially full fragments: allocate /* There are no partially full fragments: allocate
@@ -1139,7 +1144,7 @@ fsp_alloc_free_page(
xdes_set_state(*xdes, descr, XDES_FREE_FRAG, mtr); xdes_set_state(*xdes, descr, XDES_FREE_FRAG, mtr);
flst_add_last(block, FSP_HEADER_OFFSET + FSP_FREE_FRAG, flst_add_last(block, FSP_HEADER_OFFSET + FSP_FREE_FRAG,
xdes, static_cast<uint16_t>( xdes, static_cast<uint16_t>(
descr - xdes->frame descr - xdes->page.frame
+ XDES_FLST_NODE), mtr); + XDES_FLST_NODE), mtr);
} else { } else {
descr = xdes_lst_get_descriptor(*space, first, mtr, descr = xdes_lst_get_descriptor(*space, first, mtr,
@@ -1169,7 +1174,7 @@ fsp_alloc_free_page(
uint32_t page_no = xdes_get_offset(descr) + free; uint32_t page_no = xdes_get_offset(descr) + free;
uint32_t space_size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE uint32_t space_size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE
+ block->frame); + block->page.frame);
ut_ad(space_size == space->size_in_header ut_ad(space_size == space->size_in_header
|| (space_id == TRX_SYS_SPACE || (space_id == TRX_SYS_SPACE
&& srv_startup_is_before_trx_rollback_phase)); && srv_startup_is_before_trx_rollback_phase));
@@ -1271,9 +1276,9 @@ static void fsp_free_page(fil_space_t* space, page_no_t offset, mtr_t* mtr)
xdes_set_free<true>(*xdes, descr, bit, mtr); xdes_set_free<true>(*xdes, descr, bit, mtr);
frag_n_used = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FRAG_N_USED frag_n_used = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ header->frame); + header->page.frame);
const uint16_t xoffset= static_cast<uint16_t>(descr - xdes->frame const uint16_t xoffset= static_cast<uint16_t>(descr - xdes->page.frame
+ XDES_FLST_NODE); + XDES_FLST_NODE);
if (state == XDES_FULL_FRAG) { if (state == XDES_FULL_FRAG) {
@@ -1284,12 +1289,12 @@ static void fsp_free_page(fil_space_t* space, page_no_t offset, mtr_t* mtr)
flst_add_last(header, FSP_HEADER_OFFSET + FSP_FREE_FRAG, flst_add_last(header, FSP_HEADER_OFFSET + FSP_FREE_FRAG,
xdes, xoffset, mtr); xdes, xoffset, mtr);
mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_FRAG_N_USED mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ header->frame, + header->page.frame,
frag_n_used + FSP_EXTENT_SIZE - 1); frag_n_used + FSP_EXTENT_SIZE - 1);
} else { } else {
ut_a(frag_n_used > 0); ut_a(frag_n_used > 0);
mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_FRAG_N_USED mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ header->frame, frag_n_used - 1); + header->page.frame, frag_n_used - 1);
} }
if (!xdes_get_n_used(descr)) { if (!xdes_get_n_used(descr)) {
@@ -1325,7 +1330,7 @@ static void fsp_free_extent(fil_space_t* space, page_no_t offset, mtr_t* mtr)
xdes_init(*xdes, descr, mtr); xdes_init(*xdes, descr, mtr);
flst_add_last(block, FSP_HEADER_OFFSET + FSP_FREE, flst_add_last(block, FSP_HEADER_OFFSET + FSP_FREE,
xdes, static_cast<uint16_t>(descr - xdes->frame + xdes, static_cast<uint16_t>(descr - xdes->page.frame +
XDES_FLST_NODE), mtr); XDES_FLST_NODE), mtr);
space->free_len++; space->free_len++;
} }
@@ -1408,12 +1413,12 @@ fsp_alloc_seg_inode_page(fil_space_t *space, buf_block_t *header, mtr_t *mtr)
if (!block) if (!block)
return false; return false;
ut_ad(block->lock.not_recursive()); ut_ad(block->page.lock.not_recursive());
mtr->write<2>(*block, block->frame + FIL_PAGE_TYPE, FIL_PAGE_INODE); mtr->write<2>(*block, block->page.frame + FIL_PAGE_TYPE, FIL_PAGE_INODE);
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
const byte *inode= FSEG_ID + FSEG_ARR_OFFSET + block->frame; const byte *inode= FSEG_ID + FSEG_ARR_OFFSET + block->page.frame;
for (ulint i= FSP_SEG_INODES_PER_PAGE(space->physical_size()); i--; for (ulint i= FSP_SEG_INODES_PER_PAGE(space->physical_size()); i--;
inode += FSEG_INODE_SIZE) inode += FSEG_INODE_SIZE)
ut_ad(!mach_read_from_8(inode)); ut_ad(!mach_read_from_8(inode));
@@ -1441,18 +1446,18 @@ fsp_alloc_seg_inode(fil_space_t *space, buf_block_t *header,
/* Allocate a new segment inode page if needed. */ /* Allocate a new segment inode page if needed. */
if (!flst_get_len(FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE if (!flst_get_len(FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE
+ header->frame) + header->page.frame)
&& !fsp_alloc_seg_inode_page(space, header, mtr)) { && !fsp_alloc_seg_inode_page(space, header, mtr)) {
return(NULL); return(NULL);
} }
const page_id_t page_id( const page_id_t page_id(
space->id, space->id,
flst_get_first(FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE flst_get_first(FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE
+ header->frame).page); + header->page.frame).page);
block = buf_page_get_gen(page_id, space->zip_size(), RW_SX_LATCH, block = buf_page_get_gen(page_id, space->zip_size(), RW_SX_LATCH,
nullptr, BUF_GET_POSSIBLY_FREED, mtr); nullptr, BUF_GET_POSSIBLY_FREED, mtr);
if (!block || block->page.status == buf_page_t::FREED) { if (!block || block->page.is_freed()) {
return nullptr; return nullptr;
} }
@@ -1462,13 +1467,14 @@ fsp_alloc_seg_inode(fil_space_t *space, buf_block_t *header,
const ulint physical_size = space->physical_size(); const ulint physical_size = space->physical_size();
ulint n = fsp_seg_inode_page_find_free(block->frame, 0, physical_size); ulint n = fsp_seg_inode_page_find_free(block->page.frame, 0,
physical_size);
ut_a(n < FSP_SEG_INODES_PER_PAGE(physical_size)); ut_a(n < FSP_SEG_INODES_PER_PAGE(physical_size));
inode = fsp_seg_inode_page_get_nth_inode(block->frame, n); inode = fsp_seg_inode_page_get_nth_inode(block->page.frame, n);
if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(block->frame, if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(block->page.frame,
n + 1, n + 1,
physical_size)) { physical_size)) {
/* There are no other unused headers left on the page: move it /* There are no other unused headers left on the page: move it
@@ -1508,7 +1514,8 @@ static void fsp_free_seg_inode(
const ulint physical_size = space->physical_size(); const ulint physical_size = space->physical_size();
if (ULINT_UNDEFINED if (ULINT_UNDEFINED
== fsp_seg_inode_page_find_free(iblock->frame, 0, physical_size)) { == fsp_seg_inode_page_find_free(iblock->page.frame, 0,
physical_size)) {
/* Move the page to another list */ /* Move the page to another list */
flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL, flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL,
iblock, FSEG_INODE_PAGE_NODE, mtr); iblock, FSEG_INODE_PAGE_NODE, mtr);
@@ -1518,8 +1525,8 @@ static void fsp_free_seg_inode(
mtr->memset(iblock, page_offset(inode) + FSEG_ID, FSEG_INODE_SIZE, 0); mtr->memset(iblock, page_offset(inode) + FSEG_ID, FSEG_INODE_SIZE, 0);
if (ULINT_UNDEFINED if (ULINT_UNDEFINED == fsp_seg_inode_page_find_used(iblock->page.frame,
== fsp_seg_inode_page_find_used(iblock->frame, physical_size)) { physical_size)) {
/* There are no other used headers left on the page: free it */ /* There are no other used headers left on the page: free it */
flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE,
iblock, FSEG_INODE_PAGE_NODE, mtr); iblock, FSEG_INODE_PAGE_NODE, mtr);
@@ -1735,9 +1742,10 @@ fseg_create(fil_space_t *space, ulint byte_offset, mtr_t *mtr,
value in space header */ value in space header */
seg_id = mach_read_from_8(FSP_HEADER_OFFSET + FSP_SEG_ID seg_id = mach_read_from_8(FSP_HEADER_OFFSET + FSP_SEG_ID
+ header->frame); + header->page.frame);
mtr->write<8>(*header, FSP_HEADER_OFFSET + FSP_SEG_ID + header->frame, mtr->write<8>(*header,
FSP_HEADER_OFFSET + FSP_SEG_ID + header->page.frame,
seg_id + 1); seg_id + 1);
mtr->write<8>(*iblock, inode + FSEG_ID, seg_id); mtr->write<8>(*iblock, inode + FSEG_ID, seg_id);
ut_ad(!mach_read_from_4(inode + FSEG_NOT_FULL_N_USED)); ut_ad(!mach_read_from_4(inode + FSEG_NOT_FULL_N_USED));
@@ -1749,7 +1757,8 @@ fseg_create(fil_space_t *space, ulint byte_offset, mtr_t *mtr,
mtr->write<4>(*iblock, inode + FSEG_MAGIC_N, FSEG_MAGIC_N_VALUE); mtr->write<4>(*iblock, inode + FSEG_MAGIC_N, FSEG_MAGIC_N_VALUE);
compile_time_assert(FSEG_FRAG_SLOT_SIZE == 4); compile_time_assert(FSEG_FRAG_SLOT_SIZE == 4);
compile_time_assert(FIL_NULL == 0xffffffff); compile_time_assert(FIL_NULL == 0xffffffff);
mtr->memset(iblock, uint16_t(inode - iblock->frame) + FSEG_FRAG_ARR, mtr->memset(iblock,
uint16_t(inode - iblock->page.frame) + FSEG_FRAG_ARR,
FSEG_FRAG_SLOT_SIZE * FSEG_FRAG_ARR_N_SLOTS, 0xff); FSEG_FRAG_SLOT_SIZE * FSEG_FRAG_ARR_N_SLOTS, 0xff);
if (!block) { if (!block) {
@@ -1769,23 +1778,23 @@ fseg_create(fil_space_t *space, ulint byte_offset, mtr_t *mtr,
goto funct_exit; goto funct_exit;
} }
ut_d(const auto x = block->lock.x_lock_count()); ut_d(const auto x = block->page.lock.x_lock_count());
ut_ad(x || block->lock.not_recursive()); ut_ad(x || block->page.lock.not_recursive());
ut_ad(x == 1 || space->is_being_truncated); ut_ad(x == 1 || space->is_being_truncated);
ut_ad(x <= 2); ut_ad(x <= 2);
ut_ad(!fil_page_get_type(block->frame)); ut_ad(!fil_page_get_type(block->page.frame));
mtr->write<1>(*block, FIL_PAGE_TYPE + 1 + block->frame, mtr->write<1>(*block, FIL_PAGE_TYPE + 1 + block->page.frame,
FIL_PAGE_TYPE_SYS); FIL_PAGE_TYPE_SYS);
} }
mtr->write<2>(*block, byte_offset + FSEG_HDR_OFFSET mtr->write<2>(*block, byte_offset + FSEG_HDR_OFFSET
+ block->frame, page_offset(inode)); + block->page.frame, page_offset(inode));
mtr->write<4>(*block, byte_offset + FSEG_HDR_PAGE_NO mtr->write<4>(*block, byte_offset + FSEG_HDR_PAGE_NO
+ block->frame, iblock->page.id().page_no()); + block->page.frame, iblock->page.id().page_no());
mtr->write<4,mtr_t::MAYBE_NOP>(*block, byte_offset + FSEG_HDR_SPACE mtr->write<4,mtr_t::MAYBE_NOP>(*block, byte_offset + FSEG_HDR_SPACE
+ block->frame, space->id); + block->page.frame, space->id);
funct_exit: funct_exit:
if (!has_done_reservation) { if (!has_done_reservation) {
@@ -1828,7 +1837,7 @@ ulint fseg_n_reserved_pages(const buf_block_t &block,
const fseg_header_t *header, ulint *used, const fseg_header_t *header, ulint *used,
mtr_t *mtr) mtr_t *mtr)
{ {
ut_ad(page_align(header) == block.frame); ut_ad(page_align(header) == block.page.frame);
return fseg_n_reserved_pages_low(fseg_inode_get(header, return fseg_n_reserved_pages_low(fseg_inode_get(header,
block.page.id().space(), block.page.id().space(),
block.zip_size(), mtr), block.zip_size(), mtr),
@@ -1897,9 +1906,9 @@ fseg_fill_free_list(
mtr->write<8>(*xdes, descr + XDES_ID, seg_id); mtr->write<8>(*xdes, descr + XDES_ID, seg_id);
flst_add_last(iblock, flst_add_last(iblock,
static_cast<uint16_t>(inode - iblock->frame static_cast<uint16_t>(inode - iblock->page.frame
+ FSEG_FREE), xdes, + FSEG_FREE), xdes,
static_cast<uint16_t>(descr - xdes->frame static_cast<uint16_t>(descr - xdes->page.frame
+ XDES_FLST_NODE), mtr); + XDES_FLST_NODE), mtr);
hint += FSP_EXTENT_SIZE; hint += FSP_EXTENT_SIZE;
} }
@@ -1960,9 +1969,9 @@ fseg_alloc_free_extent(
mtr->write<8,mtr_t::MAYBE_NOP>(**xdes, descr + XDES_ID, mtr->write<8,mtr_t::MAYBE_NOP>(**xdes, descr + XDES_ID,
seg_id); seg_id);
flst_add_last(iblock, flst_add_last(iblock,
static_cast<uint16_t>(inode - iblock->frame static_cast<uint16_t>(inode - iblock->page.frame
+ FSEG_FREE), *xdes, + FSEG_FREE), *xdes,
static_cast<uint16_t>(descr - (*xdes)->frame static_cast<uint16_t>(descr - (*xdes)->page.frame
+ XDES_FLST_NODE), mtr); + XDES_FLST_NODE), mtr);
/* Try to fill the segment free list */ /* Try to fill the segment free list */
@@ -2076,9 +2085,11 @@ take_hinted_page:
mtr->write<8,mtr_t::MAYBE_NOP>(*xdes, ret_descr + XDES_ID, mtr->write<8,mtr_t::MAYBE_NOP>(*xdes, ret_descr + XDES_ID,
seg_id); seg_id);
flst_add_last(iblock, flst_add_last(iblock,
static_cast<uint16_t>(seg_inode - iblock->frame static_cast<uint16_t>(seg_inode
- iblock->page.frame
+ FSEG_FREE), xdes, + FSEG_FREE), xdes,
static_cast<uint16_t>(ret_descr - xdes->frame static_cast<uint16_t>(ret_descr
- xdes->page.frame
+ XDES_FLST_NODE), mtr); + XDES_FLST_NODE), mtr);
/* Try to fill the segment free list */ /* Try to fill the segment free list */
@@ -2409,7 +2420,7 @@ fsp_reserve_free_extents(
} }
try_again: try_again:
uint32_t size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE uint32_t size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE
+ header->frame); + header->page.frame);
ut_ad(size == space->size_in_header); ut_ad(size == space->size_in_header);
if (size < extent_size && n_pages < extent_size / 2) { if (size < extent_size && n_pages < extent_size / 2) {
@@ -2420,12 +2431,12 @@ try_again:
} }
uint32_t n_free_list_ext = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE uint32_t n_free_list_ext = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE
+ header->frame); + header->page.frame);
ut_ad(space->free_len == n_free_list_ext); ut_ad(space->free_len == n_free_list_ext);
uint32_t free_limit = mach_read_from_4(FSP_HEADER_OFFSET uint32_t free_limit = mach_read_from_4(FSP_HEADER_OFFSET
+ FSP_FREE_LIMIT + FSP_FREE_LIMIT
+ header->frame); + header->page.frame);
ut_ad(space->free_limit == free_limit); ut_ad(space->free_limit == free_limit);
/* Below we play safe when counting free extents above the free limit: /* Below we play safe when counting free extents above the free limit:
@@ -2516,7 +2527,7 @@ fseg_free_page_low(
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
== FSEG_MAGIC_N_VALUE); == FSEG_MAGIC_N_VALUE);
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
ut_ad(iblock->frame == page_align(seg_inode)); ut_ad(iblock->page.frame == page_align(seg_inode));
ut_d(space->modify_check(*mtr)); ut_d(space->modify_check(*mtr));
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
@@ -2550,7 +2561,8 @@ fseg_free_page_low(
} }
compile_time_assert(FIL_NULL == 0xffffffff); compile_time_assert(FIL_NULL == 0xffffffff);
mtr->memset(iblock, uint16_t(seg_inode - iblock->frame) mtr->memset(iblock, uint16_t(seg_inode
- iblock->page.frame)
+ FSEG_FRAG_ARR + FSEG_FRAG_ARR
+ i * FSEG_FRAG_SLOT_SIZE, 4, 0xff); + i * FSEG_FRAG_SLOT_SIZE, 4, 0xff);
break; break;
@@ -2576,8 +2588,9 @@ fseg_free_page_low(
byte* p_not_full = seg_inode + FSEG_NOT_FULL_N_USED; byte* p_not_full = seg_inode + FSEG_NOT_FULL_N_USED;
uint32_t not_full_n_used = mach_read_from_4(p_not_full); uint32_t not_full_n_used = mach_read_from_4(p_not_full);
const uint16_t xoffset= uint16_t(descr - xdes->frame + XDES_FLST_NODE); const uint16_t xoffset= uint16_t(descr - xdes->page.frame
const uint16_t ioffset= uint16_t(seg_inode - iblock->frame); + XDES_FLST_NODE);
const uint16_t ioffset= uint16_t(seg_inode - iblock->page.frame);
if (xdes_is_full(descr)) { if (xdes_is_full(descr)) {
/* The fragment is full: move it to another list */ /* The fragment is full: move it to another list */
@@ -2704,8 +2717,9 @@ fseg_free_extent(
ut_d(space->modify_check(*mtr)); ut_d(space->modify_check(*mtr));
const uint32_t first_page_in_extent = page - (page % FSP_EXTENT_SIZE); const uint32_t first_page_in_extent = page - (page % FSP_EXTENT_SIZE);
const uint16_t xoffset= uint16_t(descr - xdes->frame + XDES_FLST_NODE); const uint16_t xoffset= uint16_t(descr - xdes->page.frame
const uint16_t ioffset= uint16_t(seg_inode - iblock->frame); + XDES_FLST_NODE);
const uint16_t ioffset= uint16_t(seg_inode - iblock->page.frame);
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
if (ahi) { if (ahi) {

View File

@@ -74,7 +74,7 @@ static void flst_write_addr(const buf_block_t& block, byte *faddr,
static void flst_zero_both(const buf_block_t& b, byte *addr, mtr_t *mtr) static void flst_zero_both(const buf_block_t& b, byte *addr, mtr_t *mtr)
{ {
if (mach_read_from_4(addr + FIL_ADDR_PAGE) != FIL_NULL) if (mach_read_from_4(addr + FIL_ADDR_PAGE) != FIL_NULL)
mtr->memset(&b, ulint(addr - b.frame) + FIL_ADDR_PAGE, 4, 0xff); mtr->memset(&b, ulint(addr - b.page.frame) + FIL_ADDR_PAGE, 4, 0xff);
mtr->write<2,mtr_t::MAYBE_NOP>(b, addr + FIL_ADDR_BYTE, 0U); mtr->write<2,mtr_t::MAYBE_NOP>(b, addr + FIL_ADDR_BYTE, 0U);
/* Initialize the other address by (MEMMOVE|0x80,offset,FIL_ADDR_SIZE,source) /* Initialize the other address by (MEMMOVE|0x80,offset,FIL_ADDR_SIZE,source)
which is 4 bytes, or less than FIL_ADDR_SIZE. */ which is 4 bytes, or less than FIL_ADDR_SIZE. */
@@ -95,12 +95,13 @@ static void flst_add_to_empty(buf_block_t *base, uint16_t boffset,
ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX |
MTR_MEMO_PAGE_SX_FIX)); MTR_MEMO_PAGE_SX_FIX));
ut_ad(!mach_read_from_4(base->frame + boffset + FLST_LEN)); ut_ad(!mach_read_from_4(base->page.frame + boffset + FLST_LEN));
mtr->write<1>(*base, base->frame + boffset + (FLST_LEN + 3), 1U); mtr->write<1>(*base, base->page.frame + boffset + (FLST_LEN + 3), 1U);
/* Update first and last fields of base node */ /* Update first and last fields of base node */
flst_write_addr(*base, base->frame + boffset + FLST_FIRST, flst_write_addr(*base, base->page.frame + boffset + FLST_FIRST,
add->page.id().page_no(), aoffset, mtr); add->page.id().page_no(), aoffset, mtr);
memcpy(base->frame + boffset + FLST_LAST, base->frame + boffset + FLST_FIRST, memcpy(base->page.frame + boffset + FLST_LAST,
base->page.frame + boffset + FLST_FIRST,
FIL_ADDR_SIZE); FIL_ADDR_SIZE);
/* Initialize FLST_LAST by (MEMMOVE|0x80,offset,FIL_ADDR_SIZE,source) /* Initialize FLST_LAST by (MEMMOVE|0x80,offset,FIL_ADDR_SIZE,source)
which is 4 bytes, or less than FIL_ADDR_SIZE. */ which is 4 bytes, or less than FIL_ADDR_SIZE. */
@@ -109,7 +110,7 @@ static void flst_add_to_empty(buf_block_t *base, uint16_t boffset,
/* Set prev and next fields of node to add */ /* Set prev and next fields of node to add */
static_assert(FLST_NEXT == FLST_PREV + FIL_ADDR_SIZE, "compatibility"); static_assert(FLST_NEXT == FLST_PREV + FIL_ADDR_SIZE, "compatibility");
flst_zero_both(*add, add->frame + aoffset + FLST_PREV, mtr); flst_zero_both(*add, add->page.frame + aoffset + FLST_PREV, mtr);
} }
/** Insert a node after another one. /** Insert a node after another one.
@@ -137,15 +138,15 @@ static void flst_insert_after(buf_block_t *base, uint16_t boffset,
ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX |
MTR_MEMO_PAGE_SX_FIX)); MTR_MEMO_PAGE_SX_FIX));
fil_addr_t next_addr= flst_get_next_addr(cur->frame + coffset); fil_addr_t next_addr= flst_get_next_addr(cur->page.frame + coffset);
flst_write_addr(*add, add->frame + aoffset + FLST_PREV, flst_write_addr(*add, add->page.frame + aoffset + FLST_PREV,
cur->page.id().page_no(), coffset, mtr); cur->page.id().page_no(), coffset, mtr);
flst_write_addr(*add, add->frame + aoffset + FLST_NEXT, flst_write_addr(*add, add->page.frame + aoffset + FLST_NEXT,
next_addr.page, next_addr.boffset, mtr); next_addr.page, next_addr.boffset, mtr);
if (next_addr.page == FIL_NULL) if (next_addr.page == FIL_NULL)
flst_write_addr(*base, base->frame + boffset + FLST_LAST, flst_write_addr(*base, base->page.frame + boffset + FLST_LAST,
add->page.id().page_no(), aoffset, mtr); add->page.id().page_no(), aoffset, mtr);
else else
{ {
@@ -156,10 +157,10 @@ static void flst_insert_after(buf_block_t *base, uint16_t boffset,
add->page.id().page_no(), aoffset, mtr); add->page.id().page_no(), aoffset, mtr);
} }
flst_write_addr(*cur, cur->frame + coffset + FLST_NEXT, flst_write_addr(*cur, cur->page.frame + coffset + FLST_NEXT,
add->page.id().page_no(), aoffset, mtr); add->page.id().page_no(), aoffset, mtr);
byte *len= &base->frame[boffset + FLST_LEN]; byte *len= &base->page.frame[boffset + FLST_LEN];
mtr->write<4>(*base, len, mach_read_from_4(len) + 1); mtr->write<4>(*base, len, mach_read_from_4(len) + 1);
} }
@@ -188,15 +189,15 @@ static void flst_insert_before(buf_block_t *base, uint16_t boffset,
ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX |
MTR_MEMO_PAGE_SX_FIX)); MTR_MEMO_PAGE_SX_FIX));
fil_addr_t prev_addr= flst_get_prev_addr(cur->frame + coffset); fil_addr_t prev_addr= flst_get_prev_addr(cur->page.frame + coffset);
flst_write_addr(*add, add->frame + aoffset + FLST_PREV, flst_write_addr(*add, add->page.frame + aoffset + FLST_PREV,
prev_addr.page, prev_addr.boffset, mtr); prev_addr.page, prev_addr.boffset, mtr);
flst_write_addr(*add, add->frame + aoffset + FLST_NEXT, flst_write_addr(*add, add->page.frame + aoffset + FLST_NEXT,
cur->page.id().page_no(), coffset, mtr); cur->page.id().page_no(), coffset, mtr);
if (prev_addr.page == FIL_NULL) if (prev_addr.page == FIL_NULL)
flst_write_addr(*base, base->frame + boffset + FLST_FIRST, flst_write_addr(*base, base->page.frame + boffset + FLST_FIRST,
add->page.id().page_no(), aoffset, mtr); add->page.id().page_no(), aoffset, mtr);
else else
{ {
@@ -207,10 +208,10 @@ static void flst_insert_before(buf_block_t *base, uint16_t boffset,
add->page.id().page_no(), aoffset, mtr); add->page.id().page_no(), aoffset, mtr);
} }
flst_write_addr(*cur, cur->frame + coffset + FLST_PREV, flst_write_addr(*cur, cur->page.frame + coffset + FLST_PREV,
add->page.id().page_no(), aoffset, mtr); add->page.id().page_no(), aoffset, mtr);
byte *len= &base->frame[boffset + FLST_LEN]; byte *len= &base->page.frame[boffset + FLST_LEN];
mtr->write<4>(*base, len, mach_read_from_4(len) + 1); mtr->write<4>(*base, len, mach_read_from_4(len) + 1);
} }
@@ -244,19 +245,19 @@ void flst_add_last(buf_block_t *base, uint16_t boffset,
ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX |
MTR_MEMO_PAGE_SX_FIX)); MTR_MEMO_PAGE_SX_FIX));
if (!flst_get_len(base->frame + boffset)) if (!flst_get_len(base->page.frame + boffset))
flst_add_to_empty(base, boffset, add, aoffset, mtr); flst_add_to_empty(base, boffset, add, aoffset, mtr);
else else
{ {
fil_addr_t addr= flst_get_last(base->frame + boffset); fil_addr_t addr= flst_get_last(base->page.frame + boffset);
buf_block_t *cur= add; buf_block_t *cur= add;
const flst_node_t *c= addr.page == add->page.id().page_no() const flst_node_t *c= addr.page == add->page.id().page_no()
? add->frame + addr.boffset ? add->page.frame + addr.boffset
: fut_get_ptr(add->page.id().space(), add->zip_size(), addr, : fut_get_ptr(add->page.id().space(), add->zip_size(), addr,
RW_SX_LATCH, mtr, &cur); RW_SX_LATCH, mtr, &cur);
if (c) if (c)
flst_insert_after(base, boffset, cur, flst_insert_after(base, boffset, cur,
static_cast<uint16_t>(c - cur->frame), static_cast<uint16_t>(c - cur->page.frame),
add, aoffset, mtr); add, aoffset, mtr);
} }
} }
@@ -278,19 +279,19 @@ void flst_add_first(buf_block_t *base, uint16_t boffset,
ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX |
MTR_MEMO_PAGE_SX_FIX)); MTR_MEMO_PAGE_SX_FIX));
if (!flst_get_len(base->frame + boffset)) if (!flst_get_len(base->page.frame + boffset))
flst_add_to_empty(base, boffset, add, aoffset, mtr); flst_add_to_empty(base, boffset, add, aoffset, mtr);
else else
{ {
fil_addr_t addr= flst_get_first(base->frame + boffset); fil_addr_t addr= flst_get_first(base->page.frame + boffset);
buf_block_t *cur= add; buf_block_t *cur= add;
const flst_node_t *c= addr.page == add->page.id().page_no() const flst_node_t *c= addr.page == add->page.id().page_no()
? add->frame + addr.boffset ? add->page.frame + addr.boffset
: fut_get_ptr(add->page.id().space(), add->zip_size(), addr, : fut_get_ptr(add->page.id().space(), add->zip_size(), addr,
RW_SX_LATCH, mtr, &cur); RW_SX_LATCH, mtr, &cur);
if (c) if (c)
flst_insert_before(base, boffset, cur, flst_insert_before(base, boffset, cur,
static_cast<uint16_t>(c - cur->frame), static_cast<uint16_t>(c - cur->page.frame),
add, aoffset, mtr); add, aoffset, mtr);
} }
} }
@@ -311,17 +312,17 @@ void flst_remove(buf_block_t *base, uint16_t boffset,
ut_ad(mtr->memo_contains_flagged(cur, MTR_MEMO_PAGE_X_FIX | ut_ad(mtr->memo_contains_flagged(cur, MTR_MEMO_PAGE_X_FIX |
MTR_MEMO_PAGE_SX_FIX)); MTR_MEMO_PAGE_SX_FIX));
const fil_addr_t prev_addr= flst_get_prev_addr(cur->frame + coffset); const fil_addr_t prev_addr= flst_get_prev_addr(cur->page.frame + coffset);
const fil_addr_t next_addr= flst_get_next_addr(cur->frame + coffset); const fil_addr_t next_addr= flst_get_next_addr(cur->page.frame + coffset);
if (prev_addr.page == FIL_NULL) if (prev_addr.page == FIL_NULL)
flst_write_addr(*base, base->frame + boffset + FLST_FIRST, flst_write_addr(*base, base->page.frame + boffset + FLST_FIRST,
next_addr.page, next_addr.boffset, mtr); next_addr.page, next_addr.boffset, mtr);
else else
{ {
buf_block_t *block= cur; buf_block_t *block= cur;
if (flst_node_t *prev= prev_addr.page == cur->page.id().page_no() if (flst_node_t *prev= prev_addr.page == cur->page.id().page_no()
? cur->frame + prev_addr.boffset ? cur->page.frame + prev_addr.boffset
: fut_get_ptr(cur->page.id().space(), cur->zip_size(), prev_addr, : fut_get_ptr(cur->page.id().space(), cur->zip_size(), prev_addr,
RW_SX_LATCH, mtr, &block)) RW_SX_LATCH, mtr, &block))
flst_write_addr(*block, prev + FLST_NEXT, flst_write_addr(*block, prev + FLST_NEXT,
@@ -329,20 +330,20 @@ void flst_remove(buf_block_t *base, uint16_t boffset,
} }
if (next_addr.page == FIL_NULL) if (next_addr.page == FIL_NULL)
flst_write_addr(*base, base->frame + boffset + FLST_LAST, flst_write_addr(*base, base->page.frame + boffset + FLST_LAST,
prev_addr.page, prev_addr.boffset, mtr); prev_addr.page, prev_addr.boffset, mtr);
else else
{ {
buf_block_t *block= cur; buf_block_t *block= cur;
if (flst_node_t *next= next_addr.page == cur->page.id().page_no() if (flst_node_t *next= next_addr.page == cur->page.id().page_no()
? cur->frame + next_addr.boffset ? cur->page.frame + next_addr.boffset
: fut_get_ptr(cur->page.id().space(), cur->zip_size(), next_addr, : fut_get_ptr(cur->page.id().space(), cur->zip_size(), next_addr,
RW_SX_LATCH, mtr, &block)) RW_SX_LATCH, mtr, &block))
flst_write_addr(*block, next + FLST_PREV, flst_write_addr(*block, next + FLST_PREV,
prev_addr.page, prev_addr.boffset, mtr); prev_addr.page, prev_addr.boffset, mtr);
} }
byte *len= &base->frame[boffset + FLST_LEN]; byte *len= &base->page.frame[boffset + FLST_LEN];
ut_ad(mach_read_from_4(len) > 0); ut_ad(mach_read_from_4(len) > 0);
mtr->write<4>(*base, len, mach_read_from_4(len) - 1); mtr->write<4>(*base, len, mach_read_from_4(len) - 1);
} }
@@ -362,8 +363,8 @@ void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr)
the x-locked pages could fill the buffer, resulting in a deadlock. */ the x-locked pages could fill the buffer, resulting in a deadlock. */
mtr_t mtr2; mtr_t mtr2;
const uint32_t len= flst_get_len(base->frame + boffset); const uint32_t len= flst_get_len(base->page.frame + boffset);
fil_addr_t addr= flst_get_first(base->frame + boffset); fil_addr_t addr= flst_get_first(base->page.frame + boffset);
for (uint32_t i= len; i--; ) for (uint32_t i= len; i--; )
{ {
@@ -378,7 +379,7 @@ void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr)
ut_ad(addr.page == FIL_NULL); ut_ad(addr.page == FIL_NULL);
addr= flst_get_last(base->frame + boffset); addr= flst_get_last(base->page.frame + boffset);
for (uint32_t i= len; i--; ) for (uint32_t i= len; i--; )
{ {

View File

@@ -231,7 +231,7 @@ rtr_update_mbr_field(
ut_ad(page == buf_block_get_frame(block)); ut_ad(page == buf_block_get_frame(block));
child = btr_node_ptr_get_child_page_no(rec, offsets); child = btr_node_ptr_get_child_page_no(rec, offsets);
const ulint n_core = page_is_leaf(block->frame) const ulint n_core = page_is_leaf(block->page.frame)
? index->n_core_fields : 0; ? index->n_core_fields : 0;
if (new_rec) { if (new_rec) {
@@ -590,8 +590,8 @@ rtr_adjust_upper_level(
page_cursor = btr_cur_get_page_cur(&cursor); page_cursor = btr_cur_get_page_cur(&cursor);
rtr_update_mbr_field(&cursor, offsets, NULL, block->frame, mbr, NULL, rtr_update_mbr_field(&cursor, offsets, nullptr, block->page.frame, mbr,
mtr); nullptr, mtr);
/* Already updated parent MBR, reset in our path */ /* Already updated parent MBR, reset in our path */
if (sea_cur->rtr_info) { if (sea_cur->rtr_info) {
@@ -605,7 +605,7 @@ rtr_adjust_upper_level(
/* Insert the node for the new page. */ /* Insert the node for the new page. */
node_ptr_upper = rtr_index_build_node_ptr( node_ptr_upper = rtr_index_build_node_ptr(
index, new_mbr, index, new_mbr,
page_rec_get_next(page_get_infimum_rec(new_block->frame)), page_rec_get_next(page_get_infimum_rec(new_block->page.frame)),
new_page_no, heap); new_page_no, heap);
ulint up_match = 0; ulint up_match = 0;
@@ -660,15 +660,15 @@ rtr_adjust_upper_level(
ut_ad(block->zip_size() == index->table->space->zip_size()); ut_ad(block->zip_size() == index->table->space->zip_size());
const uint32_t next_page_no = btr_page_get_next(block->frame); const uint32_t next_page_no = btr_page_get_next(block->page.frame);
if (next_page_no != FIL_NULL) { if (next_page_no != FIL_NULL) {
buf_block_t* next_block = btr_block_get( buf_block_t* next_block = btr_block_get(
*index, next_page_no, RW_X_LATCH, false, mtr); *index, next_page_no, RW_X_LATCH, false, mtr);
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) ut_a(page_is_comp(next_block->page.frame)
== page_is_comp(block->frame)); == page_is_comp(block->page.frame));
ut_a(btr_page_get_prev(next_block->frame) ut_a(btr_page_get_prev(next_block->page.frame)
== block->page.id().page_no()); == block->page.id().page_no());
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
@@ -744,8 +744,7 @@ rtr_split_page_move_rec_list(
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
} }
max_to_move = page_get_n_recs( max_to_move = page_get_n_recs(buf_block_get_frame(block));
buf_block_get_frame(block));
rec_move = static_cast<rtr_rec_move_t*>(mem_heap_alloc( rec_move = static_cast<rtr_rec_move_t*>(mem_heap_alloc(
heap, heap,
sizeof (*rec_move) * max_to_move)); sizeof (*rec_move) * max_to_move));
@@ -979,7 +978,7 @@ func_start:
if (page_level && UNIV_LIKELY_NULL(new_page_zip)) { if (page_level && UNIV_LIKELY_NULL(new_page_zip)) {
/* ROW_FORMAT=COMPRESSED non-leaf pages are not expected /* ROW_FORMAT=COMPRESSED non-leaf pages are not expected
to contain FIL_NULL in FIL_PAGE_PREV at this stage. */ to contain FIL_NULL in FIL_PAGE_PREV at this stage. */
memset_aligned<4>(new_block->frame + FIL_PAGE_PREV, 0, 4); memset_aligned<4>(new_block->page.frame + FIL_PAGE_PREV, 0, 4);
} }
btr_page_create(new_block, new_page_zip, cursor->index, btr_page_create(new_block, new_page_zip, cursor->index,
page_level, mtr); page_level, mtr);
@@ -1879,7 +1878,7 @@ err_exit:
/* Scan records in root page and calculate area. */ /* Scan records in root page and calculate area. */
double area = 0; double area = 0;
for (const rec_t* rec = page_rec_get_next( for (const rec_t* rec = page_rec_get_next(
page_get_infimum_rec(block->frame)); page_get_infimum_rec(block->page.frame));
!page_rec_is_supremum(rec); !page_rec_is_supremum(rec);
rec = page_rec_get_next_const(rec)) { rec = page_rec_get_next_const(rec)) {
rtr_mbr_t mbr; rtr_mbr_t mbr;

View File

@@ -260,7 +260,7 @@ rtr_pcur_getnext_from_path(
ut_ad(my_latch_mode == BTR_MODIFY_TREE ut_ad(my_latch_mode == BTR_MODIFY_TREE
|| my_latch_mode == BTR_CONT_MODIFY_TREE || my_latch_mode == BTR_CONT_MODIFY_TREE
|| !page_is_leaf(btr_cur_get_page(btr_cur)) || !page_is_leaf(btr_cur_get_page(btr_cur))
|| !btr_cur->page_cur.block->lock.have_any()); || !btr_cur->page_cur.block->page.lock.have_any());
block = buf_page_get_gen( block = buf_page_get_gen(
page_id_t(index->table->space_id, page_id_t(index->table->space_id,
@@ -395,14 +395,14 @@ rtr_pcur_getnext_from_path(
} }
if (rw_latch == RW_NO_LATCH) { if (rw_latch == RW_NO_LATCH) {
block->lock.s_lock(); block->page.lock.s_lock();
} }
lock_prdt_lock(block, &prdt, index, LOCK_S, lock_prdt_lock(block, &prdt, index, LOCK_S,
LOCK_PREDICATE, btr_cur->rtr_info->thr); LOCK_PREDICATE, btr_cur->rtr_info->thr);
if (rw_latch == RW_NO_LATCH) { if (rw_latch == RW_NO_LATCH) {
block->lock.s_unlock(); block->page.lock.s_unlock();
} }
} }
@@ -926,7 +926,7 @@ rtr_create_rtr_info(
mysql_mutex_init(rtr_match_mutex_key, mysql_mutex_init(rtr_match_mutex_key,
&rtr_info->matches->rtr_match_mutex, &rtr_info->matches->rtr_match_mutex,
nullptr); nullptr);
rtr_info->matches->block.lock.init(); rtr_info->matches->block.page.lock.init();
} }
rtr_info->path = UT_NEW_NOKEY(rtr_node_path_t()); rtr_info->path = UT_NEW_NOKEY(rtr_node_path_t());
@@ -1071,7 +1071,7 @@ rtr_clean_rtr_info(
UT_DELETE(rtr_info->matches->matched_recs); UT_DELETE(rtr_info->matches->matched_recs);
} }
rtr_info->matches->block.lock.free(); rtr_info->matches->block.page.lock.free();
mysql_mutex_destroy( mysql_mutex_destroy(
&rtr_info->matches->rtr_match_mutex); &rtr_info->matches->rtr_match_mutex);
@@ -1387,7 +1387,7 @@ rtr_leaf_push_match_rec(
ulint data_len; ulint data_len;
rtr_rec_t rtr_rec; rtr_rec_t rtr_rec;
buf = match_rec->block.frame + match_rec->used; buf = match_rec->block.page.frame + match_rec->used;
ut_ad(page_rec_is_leaf(rec)); ut_ad(page_rec_is_leaf(rec));
copy = rec_copy(buf, rec, offsets); copy = rec_copy(buf, rec, offsets);
@@ -1484,7 +1484,7 @@ rtr_non_leaf_insert_stack_push(
new_seq, level, child_no, my_cursor, mbr_inc); new_seq, level, child_no, my_cursor, mbr_inc);
} }
/** Copy a buf_block_t, except "block->lock". /** Copy a buf_block_t, except "block->page.lock".
@param[in,out] matches copy to match->block @param[in,out] matches copy to match->block
@param[in] block block to copy */ @param[in] block block to copy */
static static
@@ -1498,8 +1498,9 @@ rtr_copy_buf(
from the dummy buf_block_t we create here and because memcpy()ing from the dummy buf_block_t we create here and because memcpy()ing
it generates (valid) compiler warnings that the vtable pointer it generates (valid) compiler warnings that the vtable pointer
will be copied. */ will be copied. */
matches->block.page.lock.free();
new (&matches->block.page) buf_page_t(block->page); new (&matches->block.page) buf_page_t(block->page);
matches->block.frame = block->frame; matches->block.page.frame = block->page.frame;
matches->block.unzip_LRU = block->unzip_LRU; matches->block.unzip_LRU = block->unzip_LRU;
ut_d(matches->block.in_unzip_LRU_list = block->in_unzip_LRU_list); ut_d(matches->block.in_unzip_LRU_list = block->in_unzip_LRU_list);
@@ -1534,13 +1535,12 @@ rtr_init_match(
ut_ad(matches->matched_recs->empty()); ut_ad(matches->matched_recs->empty());
matches->locked = false; matches->locked = false;
rtr_copy_buf(matches, block); rtr_copy_buf(matches, block);
matches->block.frame = matches->bufp; matches->block.page.frame = matches->bufp;
matches->valid = false; matches->valid = false;
/* We have to copy PAGE_W*_SUPREMUM_END bytes so that we can /* We have to copy PAGE_*_SUPREMUM_END bytes so that we can
use infimum/supremum of this page as normal btr page for search. */ use infimum/supremum of this page as normal btr page for search. */
memcpy(matches->block.frame, page, page_is_comp(page) memcpy(matches->block.page.frame, page, page_is_comp(page)
? PAGE_NEW_SUPREMUM_END ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END);
: PAGE_OLD_SUPREMUM_END);
matches->used = page_is_comp(page) matches->used = page_is_comp(page)
? PAGE_NEW_SUPREMUM_END ? PAGE_NEW_SUPREMUM_END
: PAGE_OLD_SUPREMUM_END; : PAGE_OLD_SUPREMUM_END;

View File

@@ -17509,8 +17509,10 @@ func_exit:
if (block != NULL) { if (block != NULL) {
ib::info() << "Dirtying page: " << block->page.id(); ib::info() << "Dirtying page: " << block->page.id();
mtr.write<1,mtr_t::FORCED>(*block, mtr.write<1,mtr_t::FORCED>(*block,
block->frame + FIL_PAGE_SPACE_ID, block->page.frame
block->frame[FIL_PAGE_SPACE_ID]); + FIL_PAGE_SPACE_ID,
block->page.frame
[FIL_PAGE_SPACE_ID]);
} }
mtr.commit(); mtr.commit();
log_write_up_to(mtr.commit_lsn(), true); log_write_up_to(mtr.commit_lsn(), true);
@@ -17964,7 +17966,8 @@ static bool innodb_buffer_pool_evict_uncompressed()
for (buf_block_t* block = UT_LIST_GET_LAST(buf_pool.unzip_LRU); for (buf_block_t* block = UT_LIST_GET_LAST(buf_pool.unzip_LRU);
block != NULL; ) { block != NULL; ) {
buf_block_t* prev_block = UT_LIST_GET_PREV(unzip_LRU, block); buf_block_t* prev_block = UT_LIST_GET_PREV(unzip_LRU, block);
ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); ut_ad(block->page.in_file());
ut_ad(block->page.belongs_to_unzip_LRU());
ut_ad(block->in_unzip_LRU_list); ut_ad(block->in_unzip_LRU_list);
ut_ad(block->page.in_LRU_list); ut_ad(block->page.in_LRU_list);

View File

@@ -1914,10 +1914,15 @@ innobase_fts_check_doc_id_col(
} }
/** Check whether the table is empty. /** Check whether the table is empty.
@param[in] table table to be checked @param[in] table table to be checked
@param[in] ignore_delete_marked Ignore the delete marked
flag record
@return true if table is empty */ @return true if table is empty */
static bool innobase_table_is_empty(const dict_table_t *table) static bool innobase_table_is_empty(const dict_table_t *table,
bool ignore_delete_marked=true)
{ {
if (!table->space)
return false;
dict_index_t *clust_index= dict_table_get_first_index(table); dict_index_t *clust_index= dict_table_get_first_index(table);
mtr_t mtr; mtr_t mtr;
btr_pcur_t pcur; btr_pcur_t pcur;
@@ -1955,12 +1960,16 @@ next_page:
} }
rec= page_cur_get_rec(cur); rec= page_cur_get_rec(cur);
if (rec_get_deleted_flag(rec, dict_table_is_comp(table))); if (rec_get_deleted_flag(rec, dict_table_is_comp(table)))
else if (!page_rec_is_supremum(rec))
{ {
if (ignore_delete_marked)
goto scan_leaf;
non_empty:
mtr.commit(); mtr.commit();
return false; return false;
} }
else if (!page_rec_is_supremum(rec))
goto non_empty;
else else
{ {
next_page= true; next_page= true;
@@ -5816,8 +5825,8 @@ add_all_virtual:
btr_pcur_move_to_next_on_page(&pcur); btr_pcur_move_to_next_on_page(&pcur);
buf_block_t* block = btr_pcur_get_block(&pcur); buf_block_t* block = btr_pcur_get_block(&pcur);
ut_ad(page_is_leaf(block->frame)); ut_ad(page_is_leaf(block->page.frame));
ut_ad(!page_has_prev(block->frame)); ut_ad(!page_has_prev(block->page.frame));
ut_ad(!buf_block_get_page_zip(block)); ut_ad(!buf_block_get_page_zip(block));
const rec_t* rec = btr_pcur_get_rec(&pcur); const rec_t* rec = btr_pcur_get_rec(&pcur);
que_thr_t* thr = pars_complete_graph_for_exec( que_thr_t* thr = pars_complete_graph_for_exec(
@@ -5830,8 +5839,8 @@ add_all_virtual:
if (is_root if (is_root
&& !rec_is_alter_metadata(rec, *index) && !rec_is_alter_metadata(rec, *index)
&& !index->table->instant && !index->table->instant
&& !page_has_next(block->frame) && !page_has_next(block->page.frame)
&& page_rec_is_last(rec, block->frame)) { && page_rec_is_last(rec, block->page.frame)) {
goto empty_table; goto empty_table;
} }
@@ -5843,7 +5852,8 @@ add_all_virtual:
buf_block_t* root = btr_root_block_get(index, RW_X_LATCH, buf_block_t* root = btr_root_block_get(index, RW_X_LATCH,
&mtr); &mtr);
DBUG_ASSERT(root); DBUG_ASSERT(root);
if (fil_page_get_type(root->frame) != FIL_PAGE_TYPE_INSTANT) { if (fil_page_get_type(root->page.frame)
!= FIL_PAGE_TYPE_INSTANT) {
DBUG_ASSERT("wrong page type" == 0); DBUG_ASSERT("wrong page type" == 0);
err = DB_CORRUPTION; err = DB_CORRUPTION;
goto func_exit; goto func_exit;
@@ -5914,8 +5924,8 @@ add_all_virtual:
&& !index->table->instant) { && !index->table->instant) {
empty_table: empty_table:
/* The table is empty. */ /* The table is empty. */
ut_ad(fil_page_index_page_check(block->frame)); ut_ad(fil_page_index_page_check(block->page.frame));
ut_ad(!page_has_siblings(block->frame)); ut_ad(!page_has_siblings(block->page.frame));
ut_ad(block->page.id().page_no() == index->page); ut_ad(block->page.id().page_no() == index->page);
/* MDEV-17383: free metadata BLOBs! */ /* MDEV-17383: free metadata BLOBs! */
btr_page_empty(block, NULL, index, 0, &mtr); btr_page_empty(block, NULL, index, 0, &mtr);
@@ -5933,7 +5943,7 @@ empty_table:
mtr.start(); mtr.start();
index->set_modified(mtr); index->set_modified(mtr);
if (buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, &mtr)) { if (buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, &mtr)) {
if (fil_page_get_type(root->frame) != FIL_PAGE_INDEX) { if (fil_page_get_type(root->page.frame) != FIL_PAGE_INDEX) {
DBUG_ASSERT("wrong page type" == 0); DBUG_ASSERT("wrong page type" == 0);
goto err_exit; goto err_exit;
} }
@@ -6753,6 +6763,7 @@ wrong_column_name:
DBUG_ASSERT(num_fts_index <= 1); DBUG_ASSERT(num_fts_index <= 1);
DBUG_ASSERT(!ctx->online || num_fts_index == 0); DBUG_ASSERT(!ctx->online || num_fts_index == 0);
DBUG_ASSERT(!ctx->online DBUG_ASSERT(!ctx->online
|| !ha_alter_info->mdl_exclusive_after_prepare
|| ctx->add_autoinc == ULINT_UNDEFINED); || ctx->add_autoinc == ULINT_UNDEFINED);
DBUG_ASSERT(!ctx->online DBUG_ASSERT(!ctx->online
|| !innobase_need_rebuild(ha_alter_info, old_table) || !innobase_need_rebuild(ha_alter_info, old_table)
@@ -7548,6 +7559,20 @@ ha_innobase::prepare_inplace_alter_table(
DBUG_RETURN(false); DBUG_RETURN(false);
} }
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (table->part_info == NULL) {
#endif
/* Ignore the MDL downgrade when table is empty.
This optimization is disabled for partition table. */
ha_alter_info->mdl_exclusive_after_prepare =
innobase_table_is_empty(m_prebuilt->table, false);
if (ha_alter_info->online
&& ha_alter_info->mdl_exclusive_after_prepare) {
ha_alter_info->online = false;
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
}
#endif
indexed_table = m_prebuilt->table; indexed_table = m_prebuilt->table;
/* ALTER TABLE will not implicitly move a table from a single-table /* ALTER TABLE will not implicitly move a table from a single-table
@@ -8344,7 +8369,9 @@ ha_innobase::inplace_alter_table(
DEBUG_SYNC(m_user_thd, "innodb_inplace_alter_table_enter"); DEBUG_SYNC(m_user_thd, "innodb_inplace_alter_table_enter");
if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA)) { /* Ignore the inplace alter phase when table is empty */
if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA)
|| ha_alter_info->mdl_exclusive_after_prepare) {
ok_exit: ok_exit:
DEBUG_SYNC(m_user_thd, "innodb_after_inplace_alter_table"); DEBUG_SYNC(m_user_thd, "innodb_after_inplace_alter_table");
DBUG_RETURN(false); DBUG_RETURN(false);
@@ -10467,7 +10494,8 @@ commit_cache_norebuild(
space->zip_size(), space->zip_size(),
RW_X_LATCH, &mtr)) { RW_X_LATCH, &mtr)) {
byte* f = FSP_HEADER_OFFSET byte* f = FSP_HEADER_OFFSET
+ FSP_SPACE_FLAGS + b->frame; + FSP_SPACE_FLAGS
+ b->page.frame;
const auto sf = space->flags const auto sf = space->flags
& ~FSP_FLAGS_MEM_MASK; & ~FSP_FLAGS_MEM_MASK;
if (mach_read_from_4(f) != sf) { if (mach_read_from_4(f) != sf) {

View File

@@ -116,10 +116,8 @@ struct buf_page_info_t{
ulint block_id; /*!< Buffer Pool block ID */ ulint block_id; /*!< Buffer Pool block ID */
/** page identifier */ /** page identifier */
page_id_t id; page_id_t id;
unsigned access_time:32; /*!< Time of first access */ uint32_t access_time; /*!< Time of first access */
unsigned io_fix:2; /*!< type of pending I/O operation */ uint32_t state; /*!< buf_page_t::state() */
uint32_t fix_count; /*!< Count of how manyfold this block
is bufferfixed */
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
unsigned hashed:1; /*!< Whether hash index has been unsigned hashed:1; /*!< Whether hash index has been
built on this page */ built on this page */
@@ -130,7 +128,7 @@ struct buf_page_info_t{
buf_pool.freed_page_clock */ buf_pool.freed_page_clock */
unsigned zip_ssize:PAGE_ZIP_SSIZE_BITS; unsigned zip_ssize:PAGE_ZIP_SSIZE_BITS;
/*!< Compressed page size */ /*!< Compressed page size */
unsigned page_state:3; /*!< Page state */ unsigned compressed_only:1; /*!< ROW_FORMAT=COMPRESSED only */
unsigned page_type:I_S_PAGE_TYPE_BITS; /*!< Page type */ unsigned page_type:I_S_PAGE_TYPE_BITS; /*!< Page type */
unsigned num_recs:UNIV_PAGE_SIZE_SHIFT_MAX-2; unsigned num_recs:UNIV_PAGE_SIZE_SHIFT_MAX-2;
/*!< Number of records on Page */ /*!< Number of records on Page */
@@ -3816,12 +3814,11 @@ static const LEX_CSTRING io_values[] =
{ {
{ STRING_WITH_LEN("IO_NONE") }, { STRING_WITH_LEN("IO_NONE") },
{ STRING_WITH_LEN("IO_READ") }, { STRING_WITH_LEN("IO_READ") },
{ STRING_WITH_LEN("IO_WRITE") }, { STRING_WITH_LEN("IO_WRITE") }
{ STRING_WITH_LEN("IO_PIN") }
}; };
static TypelibBuffer<4> io_values_typelib(io_values); static TypelibBuffer<3> io_values_typelib(io_values);
namespace Show { namespace Show {
/* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */ /* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */
@@ -3944,7 +3941,7 @@ i_s_innodb_buffer_page_fill(
OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store(0, true)); OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store(0, true));
OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store( OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store(
page_info->fix_count, true)); ~buf_page_t::LRU_MASK & page_info->state, true));
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
OK(fields[IDX_BUFFER_PAGE_HASHED]->store( OK(fields[IDX_BUFFER_PAGE_HASHED]->store(
@@ -4017,12 +4014,27 @@ i_s_innodb_buffer_page_fill(
? (UNIV_ZIP_SIZE_MIN >> 1) << page_info->zip_ssize ? (UNIV_ZIP_SIZE_MIN >> 1) << page_info->zip_ssize
: 0, true)); : 0, true));
OK(fields[IDX_BUFFER_PAGE_STATE]->store( static_assert(buf_page_t::NOT_USED == 0, "compatibility");
1 + std::min<unsigned>(page_info->page_state, static_assert(buf_page_t::MEMORY == 1, "compatibility");
BUF_BLOCK_FILE_PAGE), true)); static_assert(buf_page_t::REMOVE_HASH == 2, "compatibility");
OK(fields[IDX_BUFFER_PAGE_IO_FIX]->store( OK(fields[IDX_BUFFER_PAGE_STATE]->store(
1 + page_info->io_fix, true)); std::min<uint32_t>(3, page_info->state) + 1, true));
static_assert(buf_page_t::UNFIXED == 1U << 29, "comp.");
static_assert(buf_page_t::READ_FIX == 4U << 29, "comp.");
static_assert(buf_page_t::WRITE_FIX == 5U << 29, "comp.");
unsigned io_fix = page_info->state >> 29;
if (io_fix < 4) {
io_fix = 1;
} else if (io_fix > 5) {
io_fix = 3;
} else {
io_fix -= 2;
}
OK(fields[IDX_BUFFER_PAGE_IO_FIX]->store(io_fix, true));
OK(fields[IDX_BUFFER_PAGE_IS_OLD]->store( OK(fields[IDX_BUFFER_PAGE_IS_OLD]->store(
page_info->is_old, true)); page_info->is_old, true));
@@ -4106,61 +4118,51 @@ i_s_innodb_buffer_page_get_info(
{ {
page_info->block_id = pos; page_info->block_id = pos;
compile_time_assert(BUF_BLOCK_NOT_USED == 0); static_assert(buf_page_t::NOT_USED == 0, "compatibility");
compile_time_assert(BUF_BLOCK_MEMORY == 1); static_assert(buf_page_t::MEMORY == 1, "compatibility");
compile_time_assert(BUF_BLOCK_REMOVE_HASH == 2); static_assert(buf_page_t::REMOVE_HASH == 2, "compatibility");
compile_time_assert(BUF_BLOCK_FILE_PAGE == 3); static_assert(buf_page_t::UNFIXED == 1U << 29, "compatibility");
compile_time_assert(BUF_BLOCK_ZIP_PAGE == 4); static_assert(buf_page_t::READ_FIX == 4U << 29, "compatibility");
static_assert(buf_page_t::WRITE_FIX == 5U << 29, "compatibility");
auto state = bpage->state(); page_info->state = bpage->state();
page_info->page_state= int{state} & 7;
switch (state) { if (page_info->state < buf_page_t::FREED) {
default:
page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
break; page_info->compressed_only = false;
case BUF_BLOCK_FILE_PAGE: } else {
case BUF_BLOCK_ZIP_PAGE:
const byte* frame; const byte* frame;
page_info->id = bpage->id(); page_info->id = bpage->id();
page_info->fix_count = bpage->buf_fix_count();
page_info->oldest_mod = bpage->oldest_modification(); page_info->oldest_mod = bpage->oldest_modification();
page_info->access_time = bpage->access_time; page_info->access_time = bpage->access_time;
page_info->zip_ssize = bpage->zip.ssize; page_info->zip_ssize = bpage->zip.ssize;
page_info->io_fix = bpage->io_fix() & 3;
page_info->is_old = bpage->old; page_info->is_old = bpage->old;
page_info->freed_page_clock = bpage->freed_page_clock; page_info->freed_page_clock = bpage->freed_page_clock;
switch (bpage->io_fix()) { if (page_info->state >= buf_page_t::READ_FIX
case BUF_IO_NONE: && page_info->state < buf_page_t::WRITE_FIX) {
case BUF_IO_WRITE:
case BUF_IO_PIN:
break;
case BUF_IO_READ:
page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
page_info->newest_mod = 0; page_info->newest_mod = 0;
return; return;
} }
if (state == BUF_BLOCK_FILE_PAGE) { page_info->compressed_only = !bpage->frame,
const buf_block_t*block; frame = bpage->frame;
if (UNIV_LIKELY(frame != nullptr)) {
block = reinterpret_cast<const buf_block_t*>(bpage);
frame = block->frame;
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
/* Note: this may be a false positive, that /* Note: this may be a false positive, that
is, block->index will not always be set to is, block->index will not always be set to
NULL when the last adaptive hash index NULL when the last adaptive hash index
reference is dropped. */ reference is dropped. */
page_info->hashed = (block->index != NULL); page_info->hashed =
reinterpret_cast<const buf_block_t*>(bpage)
->index != nullptr;
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
} else { } else {
ut_ad(page_info->zip_ssize); ut_ad(page_info->zip_ssize);
@@ -4447,7 +4449,7 @@ i_s_innodb_buf_page_lru_fill(
OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store(0, true)); OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store(0, true));
OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store( OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store(
page_info->fix_count, true)); ~buf_page_t::LRU_MASK & page_info->state, true));
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
OK(fields[IDX_BUF_LRU_PAGE_HASHED]->store( OK(fields[IDX_BUF_LRU_PAGE_HASHED]->store(
@@ -4520,11 +4522,22 @@ i_s_innodb_buf_page_lru_fill(
? 512 << page_info->zip_ssize : 0, true)); ? 512 << page_info->zip_ssize : 0, true));
OK(fields[IDX_BUF_LRU_PAGE_STATE]->store( OK(fields[IDX_BUF_LRU_PAGE_STATE]->store(
page_info->page_state == BUF_BLOCK_ZIP_PAGE, page_info->compressed_only, true));
true));
OK(fields[IDX_BUF_LRU_PAGE_IO_FIX]->store( static_assert(buf_page_t::UNFIXED == 1U << 29, "comp.");
1 + page_info->io_fix, true)); static_assert(buf_page_t::READ_FIX == 4U << 29, "comp.");
static_assert(buf_page_t::WRITE_FIX == 5U << 29, "comp.");
unsigned io_fix = page_info->state >> 29;
if (io_fix < 4) {
io_fix = 1;
} else if (io_fix > 5) {
io_fix = 3;
} else {
io_fix -= 2;
}
OK(fields[IDX_BUF_LRU_PAGE_IO_FIX]->store(io_fix, true));
OK(fields[IDX_BUF_LRU_PAGE_IS_OLD]->store( OK(fields[IDX_BUF_LRU_PAGE_IS_OLD]->store(
page_info->is_old, true)); page_info->is_old, true));

View File

@@ -321,7 +321,7 @@ ibuf_header_page_get(
page_id_t(IBUF_SPACE_ID, FSP_IBUF_HEADER_PAGE_NO), page_id_t(IBUF_SPACE_ID, FSP_IBUF_HEADER_PAGE_NO),
0, RW_X_LATCH, mtr); 0, RW_X_LATCH, mtr);
return block ? block->frame : nullptr; return block ? block->page.frame : nullptr;
} }
/** Acquire the change buffer root page. /** Acquire the change buffer root page.
@@ -341,7 +341,7 @@ static buf_block_t *ibuf_tree_root_get(mtr_t *mtr)
page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO), page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO),
0, RW_SX_LATCH, mtr); 0, RW_SX_LATCH, mtr);
ut_ad(ibuf.empty == page_is_empty(block->frame)); ut_ad(ibuf.empty == page_is_empty(block->page.frame));
return block; return block;
} }
@@ -430,7 +430,7 @@ ibuf_init_at_db_start(void)
fseg_n_reserved_pages(*header_page, fseg_n_reserved_pages(*header_page,
IBUF_HEADER + IBUF_TREE_SEG_HEADER IBUF_HEADER + IBUF_TREE_SEG_HEADER
+ header_page->frame, &n_used, &mtr); + header_page->page.frame, &n_used, &mtr);
ut_ad(n_used >= 2); ut_ad(n_used >= 2);
@@ -613,7 +613,7 @@ ibuf_bitmap_page_set_bits(
ut_ad(byte_offset + IBUF_BITMAP < srv_page_size); ut_ad(byte_offset + IBUF_BITMAP < srv_page_size);
byte* map_byte = &block->frame[IBUF_BITMAP + byte_offset]; byte* map_byte = &block->page.frame[IBUF_BITMAP + byte_offset];
byte b = *map_byte; byte b = *map_byte;
if (bit == IBUF_BITMAP_FREE) { if (bit == IBUF_BITMAP_FREE) {
@@ -687,7 +687,7 @@ ibuf_set_free_bits_low(
mtr_t* mtr) /*!< in/out: mtr */ mtr_t* mtr) /*!< in/out: mtr */
{ {
ut_ad(mtr->is_named_space(block->page.id().space())); ut_ad(mtr->is_named_space(block->page.id().space()));
if (!page_is_leaf(block->frame)) { if (!page_is_leaf(block->page.frame)) {
return; return;
} }
@@ -721,7 +721,7 @@ ibuf_set_free_bits_func(
#endif /* UNIV_IBUF_DEBUG */ #endif /* UNIV_IBUF_DEBUG */
ulint val) /*!< in: value to set: < 4 */ ulint val) /*!< in: value to set: < 4 */
{ {
if (!page_is_leaf(block->frame)) { if (!page_is_leaf(block->page.frame)) {
return; return;
} }
@@ -831,7 +831,7 @@ ibuf_update_free_bits_zip(
buf_block_t* block, /*!< in/out: index page */ buf_block_t* block, /*!< in/out: index page */
mtr_t* mtr) /*!< in/out: mtr */ mtr_t* mtr) /*!< in/out: mtr */
{ {
ut_ad(page_is_leaf(block->frame)); ut_ad(page_is_leaf(block->page.frame));
ut_ad(block->zip_size()); ut_ad(block->zip_size());
ulint after = ibuf_index_page_calc_free_zip(block); ulint after = ibuf_index_page_calc_free_zip(block);
@@ -956,7 +956,7 @@ ibuf_page_low(
&local_mtr, &err); &local_mtr, &err);
ret = ibuf_bitmap_page_get_bits_low( ret = ibuf_bitmap_page_get_bits_low(
block->frame, page_id, zip_size, block->page.frame, page_id, zip_size,
MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF); MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF);
mtr_commit(&local_mtr); mtr_commit(&local_mtr);
@@ -971,7 +971,7 @@ ibuf_page_low(
ret = ibuf_bitmap_page_get_bits(ibuf_bitmap_get_map_page( ret = ibuf_bitmap_page_get_bits(ibuf_bitmap_get_map_page(
page_id, zip_size, page_id, zip_size,
mtr)->frame, mtr)->page.frame,
page_id, zip_size, page_id, zip_size,
IBUF_BITMAP_IBUF, mtr); IBUF_BITMAP_IBUF, mtr);
@@ -1814,11 +1814,11 @@ static bool ibuf_add_free_page()
return false; return false;
} }
ut_ad(block->lock.not_recursive()); ut_ad(block->page.lock.not_recursive());
ibuf_enter(&mtr); ibuf_enter(&mtr);
mysql_mutex_lock(&ibuf_mutex); mysql_mutex_lock(&ibuf_mutex);
mtr.write<2>(*block, block->frame + FIL_PAGE_TYPE, mtr.write<2>(*block, block->page.frame + FIL_PAGE_TYPE,
FIL_PAGE_IBUF_FREE_LIST); FIL_PAGE_IBUF_FREE_LIST);
/* Add the page to the free list and update the ibuf size data */ /* Add the page to the free list and update the ibuf size data */
@@ -1889,7 +1889,7 @@ ibuf_remove_free_page(void)
mysql_mutex_unlock(&ibuf_mutex); mysql_mutex_unlock(&ibuf_mutex);
uint32_t page_no = flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST uint32_t page_no = flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST
+ root->frame).page; + root->page.frame).page;
/* NOTE that we must release the latch on the ibuf tree root /* 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 because in fseg_free_page we access level 1 pages, and the root
@@ -1917,7 +1917,7 @@ ibuf_remove_free_page(void)
root = ibuf_tree_root_get(&mtr); root = ibuf_tree_root_get(&mtr);
ut_ad(page_no == flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST ut_ad(page_no == flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST
+ root->frame).page); + root->page.frame).page);
buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr); buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr);
@@ -3297,7 +3297,7 @@ fail_exit:
buffer pool, but we do not have to care about it, since we are buffer pool, but we do not have to care about it, since we are
holding a latch on the insert buffer leaf page that contains holding a latch on the insert buffer leaf page that contains
buffered changes for (space, page_no). If the page enters the buffered changes for (space, page_no). If the page enters the
buffer pool, buf_page_read_complete() for (space, page_no) will buffer pool, buf_page_t::read_complete() for (space, page_no) will
have to acquire a latch on the same insert buffer leaf page, have to acquire a latch on the same insert buffer leaf page,
which it cannot do until we have buffered the IBUF_OP_DELETE which it cannot do until we have buffered the IBUF_OP_DELETE
and done mtr_commit(&mtr) to release the latch. */ and done mtr_commit(&mtr) to release the latch. */
@@ -3322,7 +3322,7 @@ commit_exit:
if (op == IBUF_OP_INSERT) { if (op == IBUF_OP_INSERT) {
ulint bits = ibuf_bitmap_page_get_bits( ulint bits = ibuf_bitmap_page_get_bits(
bitmap_page->frame, page_id, physical_size, bitmap_page->page.frame, page_id, physical_size,
IBUF_BITMAP_FREE, &bitmap_mtr); IBUF_BITMAP_FREE, &bitmap_mtr);
if (buffered + entry_size + page_dir_calc_reserved_space(1) if (buffered + entry_size + page_dir_calc_reserved_space(1)
@@ -3402,7 +3402,7 @@ commit_exit:
which would cause the sx-latching of the root after that to which would cause the sx-latching of the root after that to
break the latching order. */ break the latching order. */
root = ibuf_tree_root_get(&mtr)->frame; root = ibuf_tree_root_get(&mtr)->page.frame;
err = btr_cur_optimistic_insert( err = btr_cur_optimistic_insert(
BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG, BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
@@ -3638,7 +3638,7 @@ ibuf_insert_to_index_page_low(
} }
ib::error() << "Insert buffer insert fails; page free " ib::error() << "Insert buffer insert fails; page free "
<< page_get_max_insert_size(block->frame, 1) << page_get_max_insert_size(block->page.frame, 1)
<< ", dtuple size " << ", dtuple size "
<< rec_get_converted_size(index, entry, 0); << rec_get_converted_size(index, entry, 0);
@@ -3653,9 +3653,10 @@ ibuf_insert_to_index_page_low(
ib::error() << "page " << block->page.id() << ", size " ib::error() << "page " << block->page.id() << ", size "
<< block->physical_size() << ", bitmap bits " << block->physical_size() << ", bitmap bits "
<< ibuf_bitmap_page_get_bits(bitmap_page->frame, << ibuf_bitmap_page_get_bits(
block->page.id(), block->zip_size(), bitmap_page->page.frame,
IBUF_BITMAP_FREE, mtr); block->page.id(), block->zip_size(),
IBUF_BITMAP_FREE, mtr);
} }
ib::error() << BUG_REPORT_MSG; ib::error() << BUG_REPORT_MSG;
@@ -4098,7 +4099,7 @@ bool ibuf_delete_rec(const page_id_t page_id, btr_pcur_t* pcur,
goto func_exit; goto func_exit;
} }
root = ibuf_tree_root_get(mtr)->frame; root = ibuf_tree_root_get(mtr)->page.frame;
btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur), 0, btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur), 0,
false, mtr); false, mtr);
@@ -4139,7 +4140,7 @@ bool ibuf_page_exists(const page_id_t id, ulint zip_size)
if (const buf_block_t* bitmap_page = ibuf_bitmap_get_map_page( if (const buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
id, zip_size, &mtr)) { id, zip_size, &mtr)) {
bitmap_bits = ibuf_bitmap_page_get_bits( bitmap_bits = ibuf_bitmap_page_get_bits(
bitmap_page->frame, id, zip_size, bitmap_page->page.frame, id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr) != 0; IBUF_BITMAP_BUFFERED, &mtr) != 0;
} }
ibuf_mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
@@ -4197,8 +4198,9 @@ void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
ulint dops[IBUF_OP_COUNT]; ulint dops[IBUF_OP_COUNT];
ut_ad(!block || page_id == block->page.id()); ut_ad(!block || page_id == block->page.id());
ut_ad(!block || block->page.state() == BUF_BLOCK_FILE_PAGE); ut_ad(!block || block->page.frame);
ut_ad(!block || block->page.status == buf_page_t::NORMAL); ut_ad(!block || !block->page.is_ibuf_exist());
ut_ad(!block || !block->page.is_reinit());
ut_ad(!trx_sys_hdr_page(page_id)); ut_ad(!trx_sys_hdr_page(page_id));
ut_ad(page_id < page_id_t(SRV_SPACE_ID_UPPER_BOUND, 0)); ut_ad(page_id < page_id_t(SRV_SPACE_ID_UPPER_BOUND, 0));
@@ -4222,10 +4224,10 @@ void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
page_id, zip_size, &mtr); page_id, zip_size, &mtr);
if (bitmap_page if (bitmap_page
&& fil_page_get_type(bitmap_page->frame) && fil_page_get_type(bitmap_page->page.frame)
!= FIL_PAGE_TYPE_ALLOCATED) { != FIL_PAGE_TYPE_ALLOCATED) {
bitmap_bits = ibuf_bitmap_page_get_bits( bitmap_bits = ibuf_bitmap_page_get_bits(
bitmap_page->frame, page_id, zip_size, bitmap_page->page.frame, page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr); IBUF_BITMAP_BUFFERED, &mtr);
} }
@@ -4258,17 +4260,17 @@ void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
is needed for the insert operations to the index page to pass is needed for the insert operations to the index page to pass
the debug checks. */ the debug checks. */
block->lock.claim_ownership(); block->page.lock.claim_ownership();
if (!fil_page_index_page_check(block->frame) if (!fil_page_index_page_check(block->page.frame)
|| !page_is_leaf(block->frame)) { || !page_is_leaf(block->page.frame)) {
corruption_noticed = true; corruption_noticed = true;
ib::error() << "Corruption in the tablespace. Bitmap" ib::error() << "Corruption in the tablespace. Bitmap"
" shows insert buffer records to page " " shows insert buffer records to page "
<< page_id << " though the page type is " << page_id << " though the page type is "
<< fil_page_get_type(block->frame) << fil_page_get_type(block->page.frame)
<< ", which is not an index leaf page. We try" << ", which is not an index leaf page. We try"
" to resolve the problem by skipping the" " to resolve the problem by skipping the"
" insert buffer merge for this page. Please" " insert buffer merge for this page. Please"
@@ -4291,8 +4293,8 @@ loop:
&pcur, &mtr); &pcur, &mtr);
if (block) { if (block) {
buf_block_buf_fix_inc(block); block->page.fix();
block->lock.x_lock_recursive(); block->page.lock.x_lock_recursive();
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX); mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
} }
@@ -4351,7 +4353,7 @@ loop:
dummy_index->table->space = space; dummy_index->table->space = space;
dummy_index->table->space_id = space->id; dummy_index->table->space_id = space->id;
ut_ad(page_validate(block->frame, dummy_index)); ut_ad(page_validate(block->page.frame, dummy_index));
switch (op) { switch (op) {
case IBUF_OP_INSERT: case IBUF_OP_INSERT:
@@ -4401,8 +4403,8 @@ loop:
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
mtr.set_named_space(space); mtr.set_named_space(space);
buf_block_buf_fix_inc(block); block->page.lock.x_lock_recursive();
block->lock.x_lock_recursive(); block->fix();
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX); mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
if (!ibuf_restore_pos(page_id, search_tuple, if (!ibuf_restore_pos(page_id, search_tuple,
@@ -4552,7 +4554,7 @@ ibuf_is_empty(void)
ut_d(mysql_mutex_lock(&ibuf_mutex)); ut_d(mysql_mutex_lock(&ibuf_mutex));
const buf_block_t* root = ibuf_tree_root_get(&mtr); const buf_block_t* root = ibuf_tree_root_get(&mtr);
bool is_empty = page_is_empty(root->frame); bool is_empty = page_is_empty(root->page.frame);
ut_a(is_empty == ibuf.empty); ut_a(is_empty == ibuf.empty);
ut_d(mysql_mutex_unlock(&ibuf_mutex)); ut_d(mysql_mutex_unlock(&ibuf_mutex));
ibuf_mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
@@ -4634,7 +4636,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
return DB_CORRUPTION; return DB_CORRUPTION;
} }
if (buf_is_zeroes(span<const byte>(bitmap_page->frame, if (buf_is_zeroes(span<const byte>(bitmap_page->page.frame,
physical_size))) { physical_size))) {
/* This means we got all-zero page instead of /* This means we got all-zero page instead of
ibuf bitmap page. The subsequent page should be ibuf bitmap page. The subsequent page should be
@@ -4663,7 +4665,8 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
const page_id_t cur_page_id(space->id, offset); const page_id_t cur_page_id(space->id, offset);
if (ibuf_bitmap_page_get_bits( if (ibuf_bitmap_page_get_bits(
bitmap_page->frame, cur_page_id, zip_size, bitmap_page->page.frame,
cur_page_id, zip_size,
IBUF_BITMAP_IBUF, &mtr)) { IBUF_BITMAP_IBUF, &mtr)) {
mysql_mutex_unlock(&ibuf_mutex); mysql_mutex_unlock(&ibuf_mutex);
@@ -4681,7 +4684,8 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
} }
if (ibuf_bitmap_page_get_bits( if (ibuf_bitmap_page_get_bits(
bitmap_page->frame, cur_page_id, zip_size, bitmap_page->page.frame,
cur_page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr)) { IBUF_BITMAP_BUFFERED, &mtr)) {
ib_errf(trx->mysql_thd, ib_errf(trx->mysql_thd,

View File

@@ -460,9 +460,9 @@ template<bool has_prev= false>
inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block, inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block,
mtr_t *mtr) mtr_t *mtr)
{ {
ut_ad(block.frame == page_align(rec)); ut_ad(block.page.frame == page_align(rec));
ut_ad(!page_is_leaf(block.frame)); ut_ad(!page_is_leaf(block.page.frame));
ut_ad(has_prev == page_has_prev(block.frame)); ut_ad(has_prev == page_has_prev(block.page.frame));
rec-= page_rec_is_comp(rec) ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS; rec-= page_rec_is_comp(rec) ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS;

View File

@@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2020, MariaDB Corporation. Copyright (c) 2015, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@@ -50,7 +50,7 @@ void btr_page_set_level(buf_block_t *block, ulint level, mtr_t *mtr)
{ {
ut_ad(level <= BTR_MAX_NODE_LEVEL); ut_ad(level <= BTR_MAX_NODE_LEVEL);
constexpr uint16_t field= PAGE_HEADER + PAGE_LEVEL; constexpr uint16_t field= PAGE_HEADER + PAGE_LEVEL;
byte *b= my_assume_aligned<2>(&block->frame[field]); byte *b= my_assume_aligned<2>(&block->page.frame[field]);
if (mtr->write<2,mtr_t::MAYBE_NOP>(*block, b, level) && if (mtr->write<2,mtr_t::MAYBE_NOP>(*block, b, level) &&
UNIV_LIKELY_NULL(block->page.zip.data)) UNIV_LIKELY_NULL(block->page.zip.data))
memcpy_aligned<2>(&block->page.zip.data[field], b, 2); memcpy_aligned<2>(&block->page.zip.data[field], b, 2);
@@ -63,7 +63,7 @@ void btr_page_set_level(buf_block_t *block, ulint level, mtr_t *mtr)
inline void btr_page_set_next(buf_block_t *block, ulint next, mtr_t *mtr) inline void btr_page_set_next(buf_block_t *block, ulint next, mtr_t *mtr)
{ {
constexpr uint16_t field= FIL_PAGE_NEXT; constexpr uint16_t field= FIL_PAGE_NEXT;
byte *b= my_assume_aligned<4>(&block->frame[field]); byte *b= my_assume_aligned<4>(&block->page.frame[field]);
if (mtr->write<4,mtr_t::MAYBE_NOP>(*block, b, next) && if (mtr->write<4,mtr_t::MAYBE_NOP>(*block, b, next) &&
UNIV_LIKELY_NULL(block->page.zip.data)) UNIV_LIKELY_NULL(block->page.zip.data))
memcpy_aligned<4>(&block->page.zip.data[field], b, 4); memcpy_aligned<4>(&block->page.zip.data[field], b, 4);
@@ -76,7 +76,7 @@ inline void btr_page_set_next(buf_block_t *block, ulint next, mtr_t *mtr)
inline void btr_page_set_prev(buf_block_t *block, ulint prev, mtr_t *mtr) inline void btr_page_set_prev(buf_block_t *block, ulint prev, mtr_t *mtr)
{ {
constexpr uint16_t field= FIL_PAGE_PREV; constexpr uint16_t field= FIL_PAGE_PREV;
byte *b= my_assume_aligned<4>(&block->frame[field]); byte *b= my_assume_aligned<4>(&block->page.frame[field]);
if (mtr->write<4,mtr_t::MAYBE_NOP>(*block, b, prev) && if (mtr->write<4,mtr_t::MAYBE_NOP>(*block, b, prev) &&
UNIV_LIKELY_NULL(block->page.zip.data)) UNIV_LIKELY_NULL(block->page.zip.data))
memcpy_aligned<4>(&block->page.zip.data[field], b, 4); memcpy_aligned<4>(&block->page.zip.data[field], b, 4);

View File

@@ -73,36 +73,10 @@ struct btr_latch_leaves_t {
#include "que0types.h" #include "que0types.h"
#include "row0types.h" #include "row0types.h"
#ifdef UNIV_DEBUG #define btr_cur_get_page_cur(cursor) (&(cursor)->page_cur)
/*********************************************************//** #define btr_cur_get_block(cursor) ((cursor)->page_cur.block)
Returns the page cursor component of a tree cursor. #define btr_cur_get_rec(cursor) ((cursor)->page_cur.rec)
@return pointer to page cursor component */
UNIV_INLINE
page_cur_t*
btr_cur_get_page_cur(
/*=================*/
const btr_cur_t* cursor);/*!< in: tree cursor */
/*********************************************************//**
Returns the buffer block on which the tree cursor is positioned.
@return pointer to buffer block */
UNIV_INLINE
buf_block_t*
btr_cur_get_block(
/*==============*/
const btr_cur_t* cursor);/*!< in: tree cursor */
/*********************************************************//**
Returns the record pointer of a tree cursor.
@return pointer to record */
UNIV_INLINE
rec_t*
btr_cur_get_rec(
/*============*/
const btr_cur_t* cursor);/*!< in: tree cursor */
#else /* UNIV_DEBUG */
# define btr_cur_get_page_cur(cursor) (&(cursor)->page_cur)
# define btr_cur_get_block(cursor) ((cursor)->page_cur.block)
# define btr_cur_get_rec(cursor) ((cursor)->page_cur.rec)
#endif /* UNIV_DEBUG */
/*********************************************************//** /*********************************************************//**
Returns the compressed page on which the tree cursor is positioned. Returns the compressed page on which the tree cursor is positioned.
@return pointer to compressed page, or NULL if the page is not compressed */ @return pointer to compressed page, or NULL if the page is not compressed */

View File

@@ -36,44 +36,6 @@ if (btr_cur_limit_optimistic_insert_debug > 1\
# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE) # define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
#ifdef UNIV_DEBUG
/*********************************************************//**
Returns the page cursor component of a tree cursor.
@return pointer to page cursor component */
UNIV_INLINE
page_cur_t*
btr_cur_get_page_cur(
/*=================*/
const btr_cur_t* cursor) /*!< in: tree cursor */
{
return(&((btr_cur_t*) cursor)->page_cur);
}
/*********************************************************//**
Returns the buffer block on which the tree cursor is positioned.
@return pointer to buffer block */
UNIV_INLINE
buf_block_t*
btr_cur_get_block(
/*==============*/
const btr_cur_t* cursor) /*!< in: tree cursor */
{
return(page_cur_get_block(btr_cur_get_page_cur(cursor)));
}
/*********************************************************//**
Returns the record pointer of a tree cursor.
@return pointer to record */
UNIV_INLINE
rec_t*
btr_cur_get_rec(
/*============*/
const btr_cur_t* cursor) /*!< in: tree cursor */
{
return(page_cur_get_rec(btr_cur_get_page_cur(cursor)));
}
#endif /* UNIV_DEBUG */
/*********************************************************//** /*********************************************************//**
Returns the compressed page on which the tree cursor is positioned. Returns the compressed page on which the tree cursor is positioned.
@return pointer to compressed page, or NULL if the page is not compressed */ @return pointer to compressed page, or NULL if the page is not compressed */

View File

@@ -335,54 +335,11 @@ btr_pcur_move_to_next_page(
btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the
last record of the current page */ last record of the current page */
mtr_t* mtr); /*!< in: mtr */ mtr_t* mtr); /*!< in: mtr */
#ifdef UNIV_DEBUG
/*********************************************************//** #define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
Returns the btr cursor component of a persistent cursor. #define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
@return pointer to btr cursor component */ #define btr_pcur_get_page(cursor) btr_pcur_get_block(cursor)->page.frame
UNIV_INLINE
btr_cur_t*
btr_pcur_get_btr_cur(
/*=================*/
const btr_pcur_t* cursor); /*!< in: persistent cursor */
/*********************************************************//**
Returns the page cursor component of a persistent cursor.
@return pointer to page cursor component */
UNIV_INLINE
page_cur_t*
btr_pcur_get_page_cur(
/*==================*/
const btr_pcur_t* cursor); /*!< in: persistent cursor */
/*********************************************************//**
Returns the page of a persistent cursor.
@return pointer to the page */
UNIV_INLINE
page_t*
btr_pcur_get_page(
/*==============*/
const btr_pcur_t* cursor);/*!< in: persistent cursor */
/*********************************************************//**
Returns the buffer block of a persistent cursor.
@return pointer to the block */
UNIV_INLINE
buf_block_t*
btr_pcur_get_block(
/*===============*/
const btr_pcur_t* cursor);/*!< in: persistent cursor */
/*********************************************************//**
Returns the record of a persistent cursor.
@return pointer to the record */
UNIV_INLINE
rec_t*
btr_pcur_get_rec(
/*=============*/
const btr_pcur_t* cursor);/*!< in: persistent cursor */
#else /* UNIV_DEBUG */
# define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
# define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
# define btr_pcur_get_page(cursor) ((cursor)->btr_cur.page_cur.block->frame)
# define btr_pcur_get_block(cursor) ((cursor)->btr_cur.page_cur.block)
# define btr_pcur_get_rec(cursor) ((cursor)->btr_cur.page_cur.rec)
#endif /* UNIV_DEBUG */
/*********************************************************//** /*********************************************************//**
Checks if the persistent cursor is on a user record. */ Checks if the persistent cursor is on a user record. */
UNIV_INLINE UNIV_INLINE
@@ -521,6 +478,25 @@ struct btr_pcur_t{
dict_index_t* index() const { return(btr_cur.index); } dict_index_t* index() const { return(btr_cur.index); }
}; };
inline buf_block_t *btr_pcur_get_block(btr_pcur_t *cursor)
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
return cursor->btr_cur.page_cur.block;
}
inline const buf_block_t *btr_pcur_get_block(const btr_pcur_t *cursor)
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
return cursor->btr_cur.page_cur.block;
}
inline rec_t *btr_pcur_get_rec(const btr_pcur_t *cursor)
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
return cursor->btr_cur.page_cur.rec;
}
#include "btr0pcur.ic" #include "btr0pcur.ic"
#endif #endif

View File

@@ -43,76 +43,6 @@ btr_pcur_get_rel_pos(
return(cursor->rel_pos); return(cursor->rel_pos);
} }
#ifdef UNIV_DEBUG
/*********************************************************//**
Returns the btr cursor component of a persistent cursor.
@return pointer to btr cursor component */
UNIV_INLINE
btr_cur_t*
btr_pcur_get_btr_cur(
/*=================*/
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
const btr_cur_t* btr_cur = &cursor->btr_cur;
return((btr_cur_t*) btr_cur);
}
/*********************************************************//**
Returns the page cursor component of a persistent cursor.
@return pointer to page cursor component */
UNIV_INLINE
page_cur_t*
btr_pcur_get_page_cur(
/*==================*/
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
return(btr_cur_get_page_cur(btr_pcur_get_btr_cur(cursor)));
}
/*********************************************************//**
Returns the page of a persistent cursor.
@return pointer to the page */
UNIV_INLINE
page_t*
btr_pcur_get_page(
/*==============*/
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
return(btr_cur_get_page(btr_pcur_get_btr_cur(cursor)));
}
/*********************************************************//**
Returns the buffer block of a persistent cursor.
@return pointer to the block */
UNIV_INLINE
buf_block_t*
btr_pcur_get_block(
/*===============*/
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
return(btr_cur_get_block(btr_pcur_get_btr_cur(cursor)));
}
/*********************************************************//**
Returns the record of a persistent cursor.
@return pointer to the record */
UNIV_INLINE
rec_t*
btr_pcur_get_rec(
/*=============*/
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
return(btr_cur_get_rec(btr_pcur_get_btr_cur(cursor)));
}
#endif /* UNIV_DEBUG */
/**************************************************************//** /**************************************************************//**
Gets the up_match value for a pcur after a search. Gets the up_match value for a pcur after a search.
@return number of matched fields at the cursor or to the right if @return number of matched fields at the cursor or to the right if

View File

@@ -56,7 +56,7 @@ public:
buf_block_t *block= m_block; buf_block_t *block= m_block;
bool res= f(block); bool res= f(block);
if (block) if (block)
buf_block_buf_fix_dec(block); block->page.unfix();
return res; return res;
} }

View File

@@ -73,22 +73,6 @@ extern my_bool buf_disable_resize_buffer_pool_debug; /*!< if TRUE, resizing
buffer pool is not allowed. */ buffer pool is not allowed. */
# endif /* UNIV_DEBUG */ # endif /* UNIV_DEBUG */
/** buf_page_t::state() values, distinguishing buf_page_t and buf_block_t */
enum buf_page_state
{
/** available in buf_pool.free or buf_pool.watch */
BUF_BLOCK_NOT_USED,
/** allocated for something else than a file page */
BUF_BLOCK_MEMORY,
/** a previously allocated file page, in transit to NOT_USED */
BUF_BLOCK_REMOVE_HASH,
/** a buf_block_t that is also in buf_pool.LRU */
BUF_BLOCK_FILE_PAGE,
/** the buf_page_t of a ROW_FORMAT=COMPRESSED page
whose uncompressed page frame has been evicted */
BUF_BLOCK_ZIP_PAGE
};
/** This structure defines information we will fetch from each buffer pool. It /** This structure defines information we will fetch from each buffer pool. It
will be used to print table IO stats */ will be used to print table IO stats */
struct buf_pool_info_t struct buf_pool_info_t
@@ -170,12 +154,9 @@ operator<<(
#ifndef UNIV_INNOCHECKSUM #ifndef UNIV_INNOCHECKSUM
# define buf_pool_get_curr_size() srv_buf_pool_curr_size # define buf_pool_get_curr_size() srv_buf_pool_curr_size
# define buf_page_alloc_descriptor() \
static_cast<buf_page_t*>(ut_zalloc_nokey(sizeof(buf_page_t)))
# define buf_page_free_descriptor(bpage) ut_free(bpage)
/** Allocate a buffer block. /** Allocate a buffer block.
@return own: the allocated block, in state BUF_BLOCK_MEMORY */ @return own: the allocated block, state()==MEMORY */
inline buf_block_t *buf_block_alloc(); inline buf_block_t *buf_block_alloc();
/********************************************************************//** /********************************************************************//**
Frees a buffer block which does not contain a file page. */ Frees a buffer block which does not contain a file page. */
@@ -200,17 +181,14 @@ error-prone programming not to set a latch, and it should be used
with care. */ with care. */
#define buf_page_get_with_no_latch(ID, SIZE, MTR) \ #define buf_page_get_with_no_latch(ID, SIZE, MTR) \
buf_page_get_gen(ID, SIZE, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH, MTR) buf_page_get_gen(ID, SIZE, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH, MTR)
/********************************************************************//** /** Try to acquire a page latch.
This is the general function used to get optimistic access to a database @param rw_latch RW_S_LATCH or RW_X_LATCH
page. @param block guessed block
@return TRUE if success */ @param modify_clock expected value of block->modify_clock
ibool @param mtr mini-transaction
buf_page_optimistic_get( @return whether the latch was acquired (the page is an allocated file page) */
/*====================*/ bool buf_page_optimistic_get(ulint rw_latch, buf_block_t *block,
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */ uint64_t modify_clock, mtr_t *mtr);
buf_block_t* block, /*!< in: guessed block */
ib_uint64_t modify_clock,/*!< in: modify clock value */
mtr_t* mtr); /*!< in: mini-transaction */
/** Try to S-latch a page. /** Try to S-latch a page.
Suitable for using when holding the lock_sys latches (as it avoids deadlock). Suitable for using when holding the lock_sys latches (as it avoids deadlock).
@@ -222,15 +200,15 @@ buf_block_t *buf_page_try_get(const page_id_t page_id, mtr_t *mtr);
/** Get read access to a compressed page (usually of type /** Get read access to a compressed page (usually of type
FIL_PAGE_TYPE_ZBLOB or FIL_PAGE_TYPE_ZBLOB2). FIL_PAGE_TYPE_ZBLOB or FIL_PAGE_TYPE_ZBLOB2).
The page must be released with buf_page_release_zip(). The page must be released with unfix().
NOTE: the page is not protected by any latch. Mutual exclusion has to NOTE: the page is not protected by any latch. Mutual exclusion has to
be implemented at a higher level. In other words, all possible be implemented at a higher level. In other words, all possible
accesses to a given page through this function must be protected by accesses to a given page through this function must be protected by
the same set of mutexes or latches. the same set of mutexes or latches.
@param[in] page_id page id @param page_id page identifier
@param[in] zip_size ROW_FORMAT=COMPRESSED page size @param zip_size ROW_FORMAT=COMPRESSED page size in bytes
@return pointer to the block */ @return pointer to the block, s-latched */
buf_page_t* buf_page_get_zip(const page_id_t page_id, ulint zip_size); buf_page_t *buf_page_get_zip(const page_id_t page_id, ulint zip_size);
/** Get access to a database page. Buffered redo log may be applied. /** Get access to a database page. Buffered redo log may be applied.
@param[in] page_id page id @param[in] page_id page id
@@ -282,8 +260,8 @@ buf_page_get_low(
/** Initialize a page in the buffer pool. The page is usually not read /** Initialize a page in the buffer pool. The page is usually not read
from a file even if it cannot be found in the buffer buf_pool. This is one from a file even if it cannot be found in the buffer buf_pool. This is one
of the functions which perform to a block a state transition NOT_USED => of the functions which perform to a block a state transition NOT_USED => LRU
FILE_PAGE (the other is buf_page_get_gen). (the other is buf_page_get_low()).
@param[in,out] space space object @param[in,out] space space object
@param[in] offset offset of the tablespace @param[in] offset offset of the tablespace
@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@@ -305,22 +283,6 @@ buf_block_t*
buf_page_create_deferred(uint32_t space_id, ulint zip_size, mtr_t *mtr, buf_page_create_deferred(uint32_t space_id, ulint zip_size, mtr_t *mtr,
buf_block_t *free_block); buf_block_t *free_block);
/********************************************************************//**
Releases a compressed-only page acquired with buf_page_get_zip(). */
UNIV_INLINE
void
buf_page_release_zip(
/*=================*/
buf_page_t* bpage); /*!< in: buffer block */
/********************************************************************//**
Releases a latch, if specified. */
UNIV_INLINE
void
buf_page_release_latch(
/*=====================*/
buf_block_t* block, /*!< in: buffer block */
ulint rw_latch); /*!< in: RW_S_LATCH, RW_X_LATCH,
RW_NO_LATCH */
/** Move a block to the start of the LRU list. */ /** Move a block to the start of the LRU list. */
void buf_page_make_young(buf_page_t *bpage); void buf_page_make_young(buf_page_t *bpage);
/** Mark the page status as FREED for the given tablespace and page number. /** Mark the page status as FREED for the given tablespace and page number.
@@ -371,13 +333,6 @@ ib_uint64_t
buf_block_get_modify_clock( buf_block_get_modify_clock(
/*=======================*/ /*=======================*/
buf_block_t* block); /*!< in: block */ buf_block_t* block); /*!< in: block */
/*******************************************************************//**
Increments the bufferfix count. */
# define buf_block_buf_fix_inc(block) (block)->fix()
/*******************************************************************//**
Decrements the bufferfix count. */
# define buf_block_buf_fix_dec(block) (block)->unfix()
#endif /* !UNIV_INNOCHECKSUM */ #endif /* !UNIV_INNOCHECKSUM */
/** Check if a buffer is all zeroes. /** Check if a buffer is all zeroes.
@@ -514,19 +469,7 @@ void buf_pool_invalidate();
--------------------------- LOWER LEVEL ROUTINES ------------------------- --------------------------- LOWER LEVEL ROUTINES -------------------------
=========================================================================*/ =========================================================================*/
#ifdef UNIV_DEBUG #define buf_block_get_frame(block) (block)->page.frame
/*********************************************************************//**
Gets a pointer to the memory frame of a block.
@return pointer to the frame */
UNIV_INLINE
buf_frame_t*
buf_block_get_frame(
/*================*/
const buf_block_t* block) /*!< in: pointer to the control block */
MY_ATTRIBUTE((warn_unused_result));
#else /* UNIV_DEBUG */
# define buf_block_get_frame(block) (block)->frame
#endif /* UNIV_DEBUG */
/*********************************************************************//** /*********************************************************************//**
Gets the compressed page descriptor corresponding to an uncompressed page Gets the compressed page descriptor corresponding to an uncompressed page
@@ -539,18 +482,8 @@ if applicable. */
/** Monitor the buffer page read/write activity, and increment corresponding /** Monitor the buffer page read/write activity, and increment corresponding
counter value in MONITOR_MODULE_BUF_PAGE. counter value in MONITOR_MODULE_BUF_PAGE.
@param bpage buffer page whose read or write was completed @param bpage buffer page whose read or write was completed
@param io_type BUF_IO_READ or BUF_IO_WRITE */ @param read true=read, false=write */
ATTRIBUTE_COLD __attribute__((nonnull)) ATTRIBUTE_COLD void buf_page_monitor(const buf_page_t &bpage, bool read);
void buf_page_monitor(const buf_page_t *bpage, buf_io_fix io_type);
/** Complete a read request of a file page to buf_pool.
@param bpage recently read page
@param node data file
@return whether the operation succeeded
@retval DB_SUCCESS always when writing, or if a read page was OK
@retval DB_PAGE_CORRUPTED if the checksum fails on a page read
@retval DB_DECRYPTION_FAILED if the page cannot be decrypted */
dberr_t buf_page_read_complete(buf_page_t *bpage, const fil_node_t &node);
/** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit, /** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit,
if needed. if needed.
@@ -618,6 +551,7 @@ class buf_page_t
{ {
friend buf_pool_t; friend buf_pool_t;
friend buf_block_t; friend buf_block_t;
/** @name General fields */ /** @name General fields */
/* @{ */ /* @{ */
@@ -625,10 +559,9 @@ public: // FIXME: fix fil_iterate()
/** Page id. Protected by buf_pool.page_hash.lock_get() when /** Page id. Protected by buf_pool.page_hash.lock_get() when
the page is in buf_pool.page_hash. */ the page is in buf_pool.page_hash. */
page_id_t id_; page_id_t id_;
/** buf_pool.page_hash link; protected by buf_pool.page_hash.lock_get() */
buf_page_t *hash;
private: private:
/** Count of how manyfold this block is currently bufferfixed. */
Atomic_counter<uint32_t> buf_fix_count_;
/** log sequence number of the START of the log entry written of the /** log sequence number of the START of the log entry written of the
oldest modification to this block which has not yet been written oldest modification to this block which has not yet been written
to the data file; to the data file;
@@ -639,53 +572,64 @@ private:
(because id().space() is the temporary tablespace). */ (because id().space() is the temporary tablespace). */
Atomic_relaxed<lsn_t> oldest_modification_; Atomic_relaxed<lsn_t> oldest_modification_;
/** type of pending I/O operation; protected by buf_pool.mutex
if in_LRU_list */
Atomic_relaxed<buf_io_fix> io_fix_;
/** Block state. @see in_file().
State transitions between in_file() states and to
BUF_BLOCK_REMOVE_HASH are protected by buf_pool.page_hash.lock_get()
when the block is in buf_pool.page_hash.
Other transitions when in_LRU_list are protected by buf_pool.mutex. */
buf_page_state state_;
public: public:
/** buf_pool.page_hash link; protected by buf_pool.page_hash.lock_get() */ /** state() of unused block (in buf_pool.free list) */
buf_page_t *hash; static constexpr uint32_t NOT_USED= 0;
/* @} */ /** state() of block allocated as general-purpose memory */
page_zip_des_t zip; /*!< compressed page; zip.data static constexpr uint32_t MEMORY= 1;
(but not the data it points to) is /** state() of block that is being freed */
also protected by buf_pool.mutex; static constexpr uint32_t REMOVE_HASH= 2;
state == BUF_BLOCK_ZIP_PAGE and /** smallest state() of a buffer page that is freed in the tablespace */
zip.data == NULL means an active static constexpr uint32_t FREED= 3;
buf_pool.watch */ /** smallest state() for a block that belongs to buf_pool.LRU */
static constexpr uint32_t UNFIXED= 1U << 29;
/** smallest state() of a block for which buffered changes may exist */
static constexpr uint32_t IBUF_EXIST= 2U << 29;
/** smallest state() of a (re)initialized page (no doublewrite needed) */
static constexpr uint32_t REINIT= 3U << 29;
/** smallest state() for an io-fixed block */
static constexpr uint32_t READ_FIX= 4U << 29;
/** smallest state() for a write-fixed block */
static constexpr uint32_t WRITE_FIX= 5U << 29;
/** smallest state() for a write-fixed block with buffered changes */
static constexpr uint32_t WRITE_FIX_IBUF= 6U << 29;
/** smallest state() for a write-fixed block (no doublewrite was used) */
static constexpr uint32_t WRITE_FIX_REINIT= 7U << 29;
/** buf_pool.LRU status mask in state() */
static constexpr uint32_t LRU_MASK= 7U << 29;
buf_tmp_buffer_t* slot; /*!< Slot for temporary memory /** lock covering the contents of frame */
used for encryption/compression block_lock lock;
or NULL */ /** pointer to aligned, uncompressed page frame of innodb_page_size */
byte *frame;
/* @} */
/** ROW_FORMAT=COMPRESSED page; zip.data (but not the data it points to)
is also protected by buf_pool.mutex;
!frame && !zip.data means an active buf_pool.watch */
page_zip_des_t zip;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/** whether this->list is in buf_pool.zip_hash; protected by buf_pool.mutex */ /** whether this->list is in buf_pool.zip_hash; protected by buf_pool.mutex */
bool in_zip_hash; bool in_zip_hash;
/** whether this->LRU is in buf_pool.LRU (in_file() holds); /** whether this->LRU is in buf_pool.LRU (in_file());
protected by buf_pool.mutex */ protected by buf_pool.mutex */
bool in_LRU_list; bool in_LRU_list;
/** whether this is in buf_pool.page_hash (in_file() holds); /** whether this is in buf_pool.page_hash (in_file());
protected by buf_pool.mutex */ protected by buf_pool.mutex */
bool in_page_hash; bool in_page_hash;
/** whether this->list is in buf_pool.free (state() == BUF_BLOCK_NOT_USED); /** whether this->list is in buf_pool.free (state() == NOT_USED);
protected by buf_pool.flush_list_mutex */ protected by buf_pool.flush_list_mutex */
bool in_free_list; bool in_free_list;
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/** list member in one of the lists of buf_pool; protected by /** list member in one of the lists of buf_pool; protected by
buf_pool.mutex or buf_pool.flush_list_mutex buf_pool.mutex or buf_pool.flush_list_mutex
state() == BUF_BLOCK_NOT_USED: buf_pool.free or buf_pool.withdraw state() == NOT_USED: buf_pool.free or buf_pool.withdraw
in_file() && oldest_modification(): in_file() && oldest_modification():
buf_pool.flush_list (protected by buf_pool.flush_list_mutex) buf_pool.flush_list (protected by buf_pool.flush_list_mutex)
The contents is undefined if in_file() && !oldest_modification(), The contents is undefined if in_file() && !oldest_modification(),
or if state() is BUF_BLOCK_MEMORY or BUF_BLOCK_REMOVE_HASH. */ or if state() == MEMORY or state() == REMOVE_HASH. */
UT_LIST_NODE_T(buf_page_t) list; UT_LIST_NODE_T(buf_page_t) list;
/** @name LRU replacement algorithm fields. /** @name LRU replacement algorithm fields.
@@ -709,7 +653,7 @@ public:
0 if the block was never accessed 0 if the block was never accessed
in the buffer pool. in the buffer pool.
For state==BUF_BLOCK_MEMORY For state() == MEMORY
blocks, this field can be repurposed blocks, this field can be repurposed
for something else. for something else.
@@ -717,89 +661,126 @@ public:
and bytes allocated for recv_sys.pages, and bytes allocated for recv_sys.pages,
the field is protected by the field is protected by
recv_sys_t::mutex. */ recv_sys_t::mutex. */
/** Change buffer entries for the page exist. buf_page_t() : id_{0}
Protected by io_fix()==BUF_IO_READ or by buf_block_t::lock. */
bool ibuf_exist;
/** Block initialization status. Can be modified while holding io_fix()
or buf_block_t::lock X-latch */
enum {
/** the page was read normally and should be flushed normally */
NORMAL = 0,
/** the page was (re)initialized, and the doublewrite buffer can be
skipped on the next flush */
INIT_ON_FLUSH,
/** the page was freed and need to be flushed.
For page_compressed, page flush will punch a hole to free space.
Else if innodb_immediate_scrub_data_uncompressed, the page will
be overwritten with zeroes. */
FREED
} status;
buf_page_t() : id_(0)
{ {
static_assert(BUF_BLOCK_NOT_USED == 0, "compatibility"); static_assert(NOT_USED == 0, "compatibility");
memset((void*) this, 0, sizeof *this); memset((void*) this, 0, sizeof *this);
} }
/** Initialize some fields */ buf_page_t(const buf_page_t &b) :
void init() id_(b.id_), hash(b.hash),
oldest_modification_(b.oldest_modification_),
lock() /* not copied */,
frame(b.frame), zip(b.zip),
#ifdef UNIV_DEBUG
in_zip_hash(b.in_zip_hash), in_LRU_list(b.in_LRU_list),
in_page_hash(b.in_page_hash), in_free_list(b.in_free_list),
#endif /* UNIV_DEBUG */
list(b.list), LRU(b.LRU), old(b.old), freed_page_clock(b.freed_page_clock),
access_time(b.access_time)
{ {
io_fix_= BUF_IO_NONE; lock.init();
buf_fix_count_= 0; }
old= 0;
freed_page_clock= 0; /** Initialize some more fields */
access_time= 0; void init(uint32_t state, page_id_t id)
{
ut_ad(state < REMOVE_HASH || state >= UNFIXED);
id_= id;
zip.fix= state;
oldest_modification_= 0; oldest_modification_= 0;
slot= nullptr; lock.init();
ibuf_exist= false;
status= NORMAL;
ut_d(in_zip_hash= false); ut_d(in_zip_hash= false);
ut_d(in_free_list= false); ut_d(in_free_list= false);
ut_d(in_LRU_list= false); ut_d(in_LRU_list= false);
ut_d(in_page_hash= false); ut_d(in_page_hash= false);
} old= 0;
freed_page_clock= 0;
/** Initialize some more fields */ access_time= 0;
void init(buf_page_state state, page_id_t id, uint32_t buf_fix_count= 0)
{
init();
state_= state;
id_= id;
buf_fix_count_= buf_fix_count;
}
/** Initialize some more fields */
void init(page_id_t id, uint32_t buf_fix_count= 0)
{
init();
id_= id;
buf_fix_count_= buf_fix_count;
hash= nullptr;
} }
public: public:
const page_id_t &id() const { return id_; } const page_id_t &id() const { return id_; }
buf_page_state state() const { return state_; } uint32_t state() const { return zip.fix; }
uint32_t buf_fix_count() const { return buf_fix_count_; } uint32_t buf_fix_count() const
buf_io_fix io_fix() const { return io_fix_; }
void io_unfix()
{ {
ut_d(const auto old_io_fix= io_fix()); uint32_t f= state();
ut_ad(old_io_fix == BUF_IO_READ || old_io_fix == BUF_IO_PIN); ut_ad(f >= FREED);
io_fix_= BUF_IO_NONE; return f < UNFIXED ? (f - FREED) : (~LRU_MASK & f);
} }
/** @return whether this block is read or write fixed;
read_complete() or write_complete() will always release
the io-fix before releasing U-lock or X-lock */
bool is_io_fixed() const
{ const auto s= state(); ut_ad(s >= FREED); return s >= READ_FIX; }
/** @return whether this block is write fixed;
write_complete() will always release the write-fix before releasing U-lock */
bool is_write_fixed() const { return state() >= WRITE_FIX; }
/** @return whether this block is read fixed; this should never hold
when a thread is holding the block lock in any mode */
bool is_read_fixed() const { return is_io_fixed() && !is_write_fixed(); }
/** @return if this belongs to buf_pool.unzip_LRU */ /** @return if this belongs to buf_pool.unzip_LRU */
bool belongs_to_unzip_LRU() const bool belongs_to_unzip_LRU() const
{ return UNIV_LIKELY_NULL(zip.data) && frame; }
bool is_freed() const
{ const auto s= state(); ut_ad(s >= FREED); return s < UNFIXED; }
bool is_ibuf_exist() const
{ {
return zip.data && state() != BUF_BLOCK_ZIP_PAGE; const auto s= state();
ut_ad(s >= UNFIXED);
ut_ad(s < READ_FIX);
return (s & LRU_MASK) == IBUF_EXIST;
}
bool is_reinit() const { return !(~state() & REINIT); }
void set_reinit(uint32_t prev_state)
{
ut_ad(prev_state < READ_FIX);
ut_d(const auto s=) zip.fix.fetch_add(REINIT - prev_state);
ut_ad(s > prev_state);
ut_ad(s < prev_state + UNFIXED);
} }
inline void add_buf_fix_count(uint32_t count); void set_ibuf_exist()
inline void set_buf_fix_count(uint32_t count); {
inline void set_state(buf_page_state state); ut_ad(lock.is_write_locked());
inline void set_io_fix(buf_io_fix io_fix); ut_ad(id() < page_id_t(SRV_SPACE_ID_UPPER_BOUND, 0));
const auto s= state();
ut_ad(s >= UNFIXED);
ut_ad(s < READ_FIX);
ut_ad(s < IBUF_EXIST || s >= REINIT);
zip.fix.fetch_add(IBUF_EXIST - (LRU_MASK & s));
}
void clear_ibuf_exist()
{
ut_ad(lock.is_write_locked());
ut_ad(id() < page_id_t(SRV_SPACE_ID_UPPER_BOUND, 0));
ut_d(const auto s=) zip.fix.fetch_sub(IBUF_EXIST - UNFIXED);
ut_ad(s >= IBUF_EXIST);
ut_ad(s < REINIT);
}
void read_unfix(uint32_t s)
{
ut_ad(lock.is_write_locked());
ut_ad(s == UNFIXED + 1 || s == IBUF_EXIST + 1 || s == REINIT + 1);
ut_d(auto old_state=) zip.fix.fetch_add(s - READ_FIX);
ut_ad(old_state >= READ_FIX);
ut_ad(old_state < WRITE_FIX);
}
void set_freed(uint32_t prev_state, uint32_t count= 0)
{
ut_ad(lock.is_write_locked());
ut_ad(prev_state >= UNFIXED);
ut_ad(prev_state < READ_FIX);
ut_d(auto s=) zip.fix.fetch_sub((prev_state & LRU_MASK) - FREED - count);
ut_ad(!((prev_state ^ s) & LRU_MASK));
}
inline void set_state(uint32_t s);
inline void set_corrupt_id(); inline void set_corrupt_id();
/** @return the log sequence number of the oldest pending modification /** @return the log sequence number of the oldest pending modification
@@ -819,15 +800,35 @@ public:
inline void set_oldest_modification(lsn_t lsn); inline void set_oldest_modification(lsn_t lsn);
/** Clear oldest_modification after removing from buf_pool.flush_list */ /** Clear oldest_modification after removing from buf_pool.flush_list */
inline void clear_oldest_modification(); inline void clear_oldest_modification();
/** Reset the oldest_modification when marking a persistent page freed */
void reset_oldest_modification()
{
ut_ad(oldest_modification() > 2);
oldest_modification_.store(1, std::memory_order_release);
}
/** Complete a read of a page.
@param node data file
@return whether the operation succeeded
@retval DB_PAGE_CORRUPTED if the checksum fails
@retval DB_DECRYPTION_FAILED if the page cannot be decrypted */
dberr_t read_complete(const fil_node_t &node);
/** Note that a block is no longer dirty, while not removing /** Note that a block is no longer dirty, while not removing
it from buf_pool.flush_list */ it from buf_pool.flush_list */
inline void clear_oldest_modification(bool temporary); inline void write_complete(bool temporary);
/** Write a flushable page to a file. buf_pool.mutex must be held.
@param lru true=buf_pool.LRU; false=buf_pool.flush_list
@param space tablespace
@return whether the page was flushed and buf_pool.mutex was released */
inline bool flush(bool lru, fil_space_t *space);
/** Notify that a page in a temporary tablespace has been modified. */ /** Notify that a page in a temporary tablespace has been modified. */
void set_temp_modified() void set_temp_modified()
{ {
ut_ad(fsp_is_system_temporary(id().space())); ut_ad(fsp_is_system_temporary(id().space()));
ut_ad(state() == BUF_BLOCK_FILE_PAGE); ut_ad(in_file());
ut_ad(!oldest_modification()); ut_ad(!oldest_modification());
oldest_modification_= 2; oldest_modification_= 2;
} }
@@ -835,19 +836,35 @@ public:
/** Prepare to release a file page to buf_pool.free. */ /** Prepare to release a file page to buf_pool.free. */
void free_file_page() void free_file_page()
{ {
ut_ad(state() == BUF_BLOCK_REMOVE_HASH); ut_ad((zip.fix.fetch_sub(REMOVE_HASH - MEMORY)) == REMOVE_HASH);
/* buf_LRU_block_free_non_file_page() asserts !oldest_modification() */ /* buf_LRU_block_free_non_file_page() asserts !oldest_modification() */
ut_d(oldest_modification_= 0;) ut_d(oldest_modification_= 0;)
set_corrupt_id(); id_= page_id_t(~0ULL);
ut_d(set_state(BUF_BLOCK_MEMORY)); }
void fix_on_recovery()
{
ut_d(const auto f=) zip.fix.fetch_sub(READ_FIX - UNFIXED - 1);
ut_ad(f >= READ_FIX);
ut_ad(f < WRITE_FIX);
}
uint32_t fix(uint32_t count= 1)
{
ut_ad(count);
ut_ad(count < IBUF_EXIST);
uint32_t f= zip.fix.fetch_add(count);
ut_ad(f >= FREED);
ut_ad(!((f ^ (f + 1)) & LRU_MASK));
return f;
} }
void fix() { buf_fix_count_++; }
uint32_t unfix() uint32_t unfix()
{ {
uint32_t count= buf_fix_count_--; uint32_t f= zip.fix.fetch_sub(1);
ut_ad(count != 0); ut_ad(f > FREED);
return count - 1; ut_ad(!((f ^ (f - 1)) & LRU_MASK));
return f - 1;
} }
/** @return the physical size, in bytes */ /** @return the physical size, in bytes */
@@ -873,27 +890,10 @@ public:
} }
/** @return whether the block is mapped to a data file */ /** @return whether the block is mapped to a data file */
bool in_file() const bool in_file() const { return state() >= FREED; }
{
switch (state_) {
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_FILE_PAGE:
return true;
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
return false;
}
ut_error;
return false;
}
/** @return whether the block is modified and ready for flushing */ /** @return whether the block is modified and ready for flushing */
inline bool ready_for_flush() const; inline bool ready_for_flush() const;
/** @return whether the state can be changed to BUF_BLOCK_NOT_USED */
bool ready_for_replace() const
{ return !oldest_modification() && can_relocate(); }
/** @return whether the block can be relocated in memory. /** @return whether the block can be relocated in memory.
The block can be dirty, but it must not be I/O-fixed or bufferfixed. */ The block can be dirty, but it must not be I/O-fixed or bufferfixed. */
inline bool can_relocate() const; inline bool can_relocate() const;
@@ -925,27 +925,18 @@ struct buf_block_t{
be the first field, so that be the first field, so that
buf_pool.page_hash can point buf_pool.page_hash can point
to buf_page_t or buf_block_t */ to buf_page_t or buf_block_t */
byte* frame; /*!< pointer to buffer frame which
is of size srv_page_size, and
aligned to an address divisible by
srv_page_size */
/** read-write lock covering frame */
block_lock lock;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/** whether page.list is in buf_pool.withdraw /** whether page.list is in buf_pool.withdraw
((state() == BUF_BLOCK_NOT_USED)) and the buffer pool is being shrunk; ((state() == NOT_USED)) and the buffer pool is being shrunk;
protected by buf_pool.mutex */ protected by buf_pool.mutex */
bool in_withdraw_list; bool in_withdraw_list;
/** whether unzip_LRU is in buf_pool.unzip_LRU /** whether unzip_LRU is in buf_pool.unzip_LRU
(state() == BUF_BLOCK_FILE_PAGE and zip.data != nullptr); (in_file() && frame && zip.data);
protected by buf_pool.mutex */ protected by buf_pool.mutex */
bool in_unzip_LRU_list; bool in_unzip_LRU_list;
#endif #endif
UT_LIST_NODE_T(buf_block_t) unzip_LRU; /** member of buf_pool.unzip_LRU (if belongs_to_unzip_LRU()) */
/*!< node of the decompressed LRU list; UT_LIST_NODE_T(buf_block_t) unzip_LRU;
a block is in the unzip_LRU list
if page.state() == BUF_BLOCK_FILE_PAGE
and page.zip.data != NULL */
/* @} */ /* @} */
/** @name Optimistic search field */ /** @name Optimistic search field */
/* @{ */ /* @{ */
@@ -984,17 +975,15 @@ struct buf_block_t{
These 5 fields may only be modified when: These 5 fields may only be modified when:
we are holding the appropriate x-latch in btr_search_latches[], and we are holding the appropriate x-latch in btr_search_latches[], and
one of the following holds: one of the following holds:
(1) the block state is BUF_BLOCK_FILE_PAGE, and (1) in_file(), and we are holding lock in any mode, or
we are holding an s-latch or x-latch on buf_block_t::lock, or (2) !is_read_fixed()&&(state()>=UNFIXED||state()==REMOVE_HASH).
(2) buf_block_t::buf_fix_count == 0, or
(3) the block state is BUF_BLOCK_REMOVE_HASH.
An exception to this is when we init or create a page An exception to this is when we init or create a page
in the buffer pool in buf0buf.cc. in the buffer pool in buf0buf.cc.
Another exception for buf_pool_t::clear_hash_index() is that Another exception for buf_pool_t::clear_hash_index() is that
assigning block->index = NULL (and block->n_pointers = 0) assigning block->index = NULL (and block->n_pointers = 0)
is allowed whenever btr_search_own_all(RW_LOCK_X). is allowed whenever all AHI latches are exclusively locked.
Another exception is that ha_insert_for_fold() may Another exception is that ha_insert_for_fold() may
decrement n_pointers without holding the appropriate latch decrement n_pointers without holding the appropriate latch
@@ -1003,8 +992,8 @@ struct buf_block_t{
This implies that the fields may be read without race This implies that the fields may be read without race
condition whenever any of the following hold: condition whenever any of the following hold:
- the btr_search_latches[] s-latch or x-latch is being held, or - the btr_search_sys.partition[].latch is being held, or
- the block state is not BUF_BLOCK_FILE_PAGE or BUF_BLOCK_REMOVE_HASH, - state() == NOT_USED || state() == MEMORY,
and holding some latch prevents the state from changing to that. and holding some latch prevents the state from changing to that.
Some use of assert_block_ahi_empty() or assert_block_ahi_valid() Some use of assert_block_ahi_empty() or assert_block_ahi_valid()
@@ -1018,9 +1007,7 @@ struct buf_block_t{
Atomic_counter<ulint> Atomic_counter<ulint>
n_pointers; /*!< used in debugging: the number of n_pointers; /*!< used in debugging: the number of
pointers in the adaptive hash index pointers in the adaptive hash index
pointing to this frame; pointing to this frame */
protected by atomic memory access
or btr_search_own_all(). */
# define assert_block_ahi_empty(block) \ # define assert_block_ahi_empty(block) \
ut_a((block)->n_pointers == 0) ut_a((block)->n_pointers == 0)
# define assert_block_ahi_empty_on_init(block) do { \ # define assert_block_ahi_empty_on_init(block) do { \
@@ -1055,13 +1042,7 @@ struct buf_block_t{
# define assert_block_ahi_valid(block) /* nothing */ # define assert_block_ahi_valid(block) /* nothing */
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
void fix() { page.fix(); } void fix() { page.fix(); }
uint32_t unfix() uint32_t unfix() { return page.unfix(); }
{
ut_ad(page.buf_fix_count() || page.io_fix() != BUF_IO_NONE ||
page.state() == BUF_BLOCK_ZIP_PAGE ||
!lock.have_any());
return page.unfix();
}
/** @return the physical size, in bytes */ /** @return the physical size, in bytes */
ulint physical_size() const { return page.physical_size(); } ulint physical_size() const { return page.physical_size(); }
@@ -1073,15 +1054,15 @@ struct buf_block_t{
/** Initialize the block. /** Initialize the block.
@param page_id page identifier @param page_id page identifier
@param zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param fix initial buf_fix_count() */ @param state initial state() */
void initialise(const page_id_t page_id, ulint zip_size, uint32_t fix= 0); void initialise(const page_id_t page_id, ulint zip_size, uint32_t state);
}; };
/**********************************************************************//** /**********************************************************************//**
Compute the hash fold value for blocks in buf_pool.zip_hash. */ Compute the hash fold value for blocks in buf_pool.zip_hash. */
/* @{ */ /* @{ */
#define BUF_POOL_ZIP_FOLD_PTR(ptr) (ulint(ptr) >> srv_page_size_shift) #define BUF_POOL_ZIP_FOLD_PTR(ptr) (ulint(ptr) >> srv_page_size_shift)
#define BUF_POOL_ZIP_FOLD(b) BUF_POOL_ZIP_FOLD_PTR((b)->frame) #define BUF_POOL_ZIP_FOLD(b) BUF_POOL_ZIP_FOLD_PTR((b)->page.frame)
#define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b)) #define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
/* @} */ /* @} */
@@ -1277,7 +1258,7 @@ class buf_pool_t
size_t mem_size() const { return mem_pfx.m_size; } size_t mem_size() const { return mem_pfx.m_size; }
/** Register the chunk */ /** Register the chunk */
void reg() { map_reg->emplace(map::value_type(blocks->frame, this)); } void reg() { map_reg->emplace(map::value_type(blocks->page.frame, this)); }
/** Allocate a chunk of buffer frames. /** Allocate a chunk of buffer frames.
@param bytes requested size @param bytes requested size
@@ -1369,7 +1350,7 @@ public:
} }
/** Determine whether a frame is intended to be withdrawn during resize(). /** Determine whether a frame is intended to be withdrawn during resize().
@param ptr pointer within a buf_block_t::frame @param ptr pointer within a buf_page_t::frame
@return whether the frame will be withdrawn */ @return whether the frame will be withdrawn */
bool will_be_withdrawn(const byte *ptr) const bool will_be_withdrawn(const byte *ptr) const
{ {
@@ -1382,8 +1363,8 @@ public:
for (const chunk_t *chunk= chunks + n_chunks_new, for (const chunk_t *chunk= chunks + n_chunks_new,
* const echunk= chunks + n_chunks; * const echunk= chunks + n_chunks;
chunk != echunk; chunk++) chunk != echunk; chunk++)
if (ptr >= chunk->blocks->frame && if (ptr >= chunk->blocks->page.frame &&
ptr < (chunk->blocks + chunk->size - 1)->frame + srv_page_size) ptr < (chunk->blocks + chunk->size - 1)->page.frame + srv_page_size)
return true; return true;
return false; return false;
} }
@@ -1487,17 +1468,11 @@ public:
buf_page_t *bpage= page_hash.get(page_id, chain); buf_page_t *bpage= page_hash.get(page_id, chain);
if (bpage >= &watch[0] && bpage < &watch[UT_ARR_SIZE(watch)]) if (bpage >= &watch[0] && bpage < &watch[UT_ARR_SIZE(watch)])
{ {
ut_ad(bpage->state() == BUF_BLOCK_ZIP_PAGE);
ut_ad(!bpage->in_zip_hash); ut_ad(!bpage->in_zip_hash);
ut_ad(!bpage->zip.data); ut_ad(!bpage->zip.data);
if (!allow_watch) if (!allow_watch)
bpage= nullptr; bpage= nullptr;
} }
else if (bpage)
{
ut_ad(page_id == bpage->id());
ut_ad(bpage->in_file());
}
return bpage; return bpage;
} }
@@ -1511,15 +1486,9 @@ public:
page_hash.lock_get(page_hash.cell_get(bpage.id().fold())). page_hash.lock_get(page_hash.cell_get(bpage.id().fold())).
is_locked()); is_locked());
#endif /* SAFE_MUTEX */ #endif /* SAFE_MUTEX */
if (&bpage < &watch[0] || &bpage >= &watch[UT_ARR_SIZE(watch)]) ut_ad(bpage.in_file());
{ if (&bpage < &watch[0] || &bpage >= &watch[array_elements(watch)])
ut_ad(bpage.state() == BUF_BLOCK_ZIP_PAGE
? !!bpage.zip.data
: bpage.state() == BUF_BLOCK_FILE_PAGE);
return false; return false;
}
ut_ad(bpage.state() == BUF_BLOCK_ZIP_PAGE);
ut_ad(!bpage.in_zip_hash); ut_ad(!bpage.in_zip_hash);
ut_ad(!bpage.zip.data); ut_ad(!bpage.zip.data);
return true; return true;
@@ -1819,7 +1788,7 @@ public:
} }
// n_flush_LRU() + n_flush_list() // n_flush_LRU() + n_flush_list()
// is approximately COUNT(io_fix()==BUF_IO_WRITE) in flush_list // is approximately COUNT(is_write_fixed()) in flush_list
unsigned freed_page_clock;/*!< a sequence number used unsigned freed_page_clock;/*!< a sequence number used
to count the number of buffer to count the number of buffer
@@ -1992,6 +1961,7 @@ inline buf_page_t *buf_pool_t::page_hash_table::get(const page_id_t id,
for (buf_page_t *bpage= chain.first; bpage; bpage= bpage->hash) for (buf_page_t *bpage= chain.first; bpage; bpage= bpage->hash)
{ {
ut_ad(bpage->in_page_hash); ut_ad(bpage->in_page_hash);
ut_ad(bpage->in_file());
if (bpage->id() == id) if (bpage->id() == id)
return bpage; return bpage;
} }
@@ -2013,50 +1983,12 @@ inline void page_hash_latch::lock()
} }
#endif /* SUX_LOCK_GENERIC */ #endif /* SUX_LOCK_GENERIC */
inline void buf_page_t::add_buf_fix_count(uint32_t count) inline void buf_page_t::set_state(uint32_t s)
{ {
mysql_mutex_assert_owner(&buf_pool.mutex); mysql_mutex_assert_owner(&buf_pool.mutex);
buf_fix_count_+= count; ut_ad(s <= REMOVE_HASH || s >= UNFIXED);
} ut_ad(s <= READ_FIX);
zip.fix= s;
inline void buf_page_t::set_buf_fix_count(uint32_t count)
{
mysql_mutex_assert_owner(&buf_pool.mutex);
buf_fix_count_= count;
}
inline void buf_page_t::set_state(buf_page_state state)
{
mysql_mutex_assert_owner(&buf_pool.mutex);
#ifdef UNIV_DEBUG
switch (state) {
case BUF_BLOCK_REMOVE_HASH:
/* buf_pool_t::corrupted_evict() invokes set_corrupt_id()
before buf_LRU_free_one_page(), so we cannot assert that
we are holding the hash_lock. */
break;
case BUF_BLOCK_MEMORY:
break;
case BUF_BLOCK_NOT_USED:
break;
case BUF_BLOCK_ZIP_PAGE:
if (this >= &buf_pool.watch[0] &&
this <= &buf_pool.watch[UT_ARR_SIZE(buf_pool.watch)])
break;
/* fall through */
case BUF_BLOCK_FILE_PAGE:
ut_ad(buf_pool.page_hash.lock_get(buf_pool.page_hash.cell_get(id_.fold())).
is_write_locked());
break;
}
#endif
state_= state;
}
inline void buf_page_t::set_io_fix(buf_io_fix io_fix)
{
mysql_mutex_assert_owner(&buf_pool.mutex);
io_fix_= io_fix;
} }
inline void buf_page_t::set_corrupt_id() inline void buf_page_t::set_corrupt_id()
@@ -2073,17 +2005,12 @@ inline void buf_page_t::set_corrupt_id()
default: default:
ut_ad("block is dirty" == 0); ut_ad("block is dirty" == 0);
} }
switch (state()) { const auto f= state();
case BUF_BLOCK_REMOVE_HASH: if (f != REMOVE_HASH)
break; {
case BUF_BLOCK_ZIP_PAGE: ut_ad(f >= UNFIXED);
case BUF_BLOCK_FILE_PAGE:
ut_ad(buf_pool.page_hash.lock_get(buf_pool.page_hash.cell_get(id_.fold())). ut_ad(buf_pool.page_hash.lock_get(buf_pool.page_hash.cell_get(id_.fold())).
is_write_locked()); is_write_locked());
break;
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_MEMORY:
ut_ad("invalid state" == 0);
} }
#endif #endif
id_= page_id_t(~0ULL); id_= page_id_t(~0ULL);
@@ -2102,9 +2029,8 @@ inline void buf_page_t::set_oldest_modification(lsn_t lsn)
inline void buf_page_t::clear_oldest_modification() inline void buf_page_t::clear_oldest_modification()
{ {
mysql_mutex_assert_owner(&buf_pool.flush_list_mutex); mysql_mutex_assert_owner(&buf_pool.flush_list_mutex);
ut_d(const auto state= state_); ut_d(const auto s= state());
ut_ad(state == BUF_BLOCK_FILE_PAGE || state == BUF_BLOCK_ZIP_PAGE || ut_ad(s >= REMOVE_HASH);
state == BUF_BLOCK_REMOVE_HASH);
ut_ad(oldest_modification()); ut_ad(oldest_modification());
ut_ad(!list.prev); ut_ad(!list.prev);
ut_ad(!list.next); ut_ad(!list.next);
@@ -2114,36 +2040,15 @@ inline void buf_page_t::clear_oldest_modification()
oldest_modification_.store(0, std::memory_order_release); oldest_modification_.store(0, std::memory_order_release);
} }
/** Note that a block is no longer dirty, while not removing
it from buf_pool.flush_list */
inline void buf_page_t::clear_oldest_modification(bool temporary)
{
ut_ad(temporary == fsp_is_system_temporary(id().space()));
if (temporary)
{
ut_ad(oldest_modification() == 2);
oldest_modification_= 0;
}
else
{
/* We use release memory order to guarantee that callers of
oldest_modification_acquire() will observe the block as
being detached from buf_pool.flush_list, after reading the value 0. */
ut_ad(oldest_modification() > 2);
oldest_modification_.store(1, std::memory_order_release);
}
}
/** @return whether the block is modified and ready for flushing */ /** @return whether the block is modified and ready for flushing */
inline bool buf_page_t::ready_for_flush() const inline bool buf_page_t::ready_for_flush() const
{ {
mysql_mutex_assert_owner(&buf_pool.mutex); mysql_mutex_assert_owner(&buf_pool.mutex);
ut_ad(in_LRU_list); ut_ad(in_LRU_list);
ut_a(in_file()); const auto s= state();
ut_ad(fsp_is_system_temporary(id().space()) ut_a(s >= FREED);
? oldest_modification() == 2 ut_ad(!fsp_is_system_temporary(id().space()) || oldest_modification() == 2);
: oldest_modification() > 2); return s < READ_FIX;
return io_fix_ == BUF_IO_NONE;
} }
/** @return whether the block can be relocated in memory. /** @return whether the block can be relocated in memory.
@@ -2151,9 +2056,11 @@ The block can be dirty, but it must not be I/O-fixed or bufferfixed. */
inline bool buf_page_t::can_relocate() const inline bool buf_page_t::can_relocate() const
{ {
mysql_mutex_assert_owner(&buf_pool.mutex); mysql_mutex_assert_owner(&buf_pool.mutex);
ut_ad(in_file()); const auto f= state();
ut_ad(f >= FREED);
ut_ad(in_LRU_list); ut_ad(in_LRU_list);
return io_fix_ == BUF_IO_NONE && !buf_fix_count_; return (f == FREED || (f < READ_FIX && !(f & ~LRU_MASK))) &&
!lock.is_locked_or_waiting();
} }
/** @return whether the block has been flagged old in buf_pool.LRU */ /** @return whether the block has been flagged old in buf_pool.LRU */
@@ -2214,41 +2121,26 @@ inline void buf_page_t::set_old(bool old)
/********************************************************************** /**********************************************************************
Let us list the consistency conditions for different control block states. Let us list the consistency conditions for different control block states.
NOT_USED: is in free list, not in LRU list, not in flush list, nor NOT_USED: is in free list, not LRU, not flush_list, nor page_hash
page hash table MEMORY: is not in any of free, LRU, flush_list, page_hash
MEMORY: is not in free list, LRU list, or flush list, nor page in_file(): is not in free list, is in LRU list, id() is defined,
hash table is in page_hash (not necessarily if is_read_fixed())
FILE_PAGE: space and offset are defined, is in page hash table
if io_fix == BUF_IO_WRITE,
buf_pool.n_flush_LRU() || buf_pool.n_flush_list()
(1) if buf_fix_count == 0, then is in buf_pool.flush_list, if and only
is in LRU list, not in free list if oldest_modification == 1 || oldest_modification > 2
is in flush list,
if and only if oldest_modification > 0
is x-locked,
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 (1) if is_write_fixed(): is u-locked
is not in LRU list, not in free list (2) if is_read_fixed(): is x-locked
is in flush list,
if and only if oldest_modification > 0
if io_fix == BUF_IO_READ,
is x-locked
if io_fix == BUF_IO_WRITE,
is s-locked
State transitions: State transitions:
NOT_USED => MEMORY NOT_USED => MEMORY
MEMORY => FILE_PAGE
MEMORY => NOT_USED MEMORY => NOT_USED
FILE_PAGE => NOT_USED NOTE: This transition is allowed if and only if MEMORY => UNFIXED
(1) buf_fix_count == 0, UNFIXED => in_file()
(2) oldest_modification == 0, and in_file() => UNFIXED or FREED
(3) io_fix == 0. UNFIXED or FREED => REMOVE_HASH
REMOVE_HASH => NOT_USED (if and only if !oldest_modification())
*/ */
/** Select from where to start a scan. If we have scanned /** Select from where to start a scan. If we have scanned

View File

@@ -86,38 +86,6 @@ inline bool buf_page_peek_if_too_old(const buf_page_t *bpage)
} }
} }
#ifdef UNIV_DEBUG
/*********************************************************************//**
Gets a pointer to the memory frame of a block.
@return pointer to the frame */
UNIV_INLINE
buf_frame_t*
buf_block_get_frame(
/*================*/
const buf_block_t* block) /*!< in: pointer to the control block */
{
if (!block) {
return NULL;
}
switch (block->page.state()) {
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_NOT_USED:
ut_error;
break;
case BUF_BLOCK_FILE_PAGE:
ut_a(block->page.buf_fix_count());
/* fall through */
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
goto ok;
}
ut_error;
ok:
return((buf_frame_t*) block->frame);
}
#endif /* UNIV_DEBUG */
/** Allocate a buffer block. /** Allocate a buffer block.
@return own: the allocated block, in state BUF_BLOCK_MEMORY */ @return own: the allocated block, in state BUF_BLOCK_MEMORY */
inline buf_block_t *buf_block_alloc() inline buf_block_t *buf_block_alloc()
@@ -149,16 +117,11 @@ buf_block_modify_clock_inc(
buf_block_t* block) /*!< in: block */ buf_block_t* block) /*!< in: block */
{ {
#ifdef SAFE_MUTEX #ifdef SAFE_MUTEX
/* No latch is acquired for the shared temporary tablespace. */ ut_ad((mysql_mutex_is_owner(&buf_pool.mutex)
ut_ad(fsp_is_system_temporary(block->page.id().space()) && !block->page.buf_fix_count())
|| (mysql_mutex_is_owner(&buf_pool.mutex) || block->page.lock.have_u_or_x());
&& !block->page.buf_fix_count())
|| block->lock.have_u_or_x());
#else /* SAFE_MUTEX */ #else /* SAFE_MUTEX */
/* No latch is acquired for the shared temporary tablespace. */ ut_ad(!block->page.buf_fix_count() || block->page.lock.have_u_or_x());
ut_ad(fsp_is_system_temporary(block->page.id().space())
|| !block->page.buf_fix_count()
|| block->lock.have_u_or_x());
#endif /* SAFE_MUTEX */ #endif /* SAFE_MUTEX */
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
@@ -175,77 +138,10 @@ buf_block_get_modify_clock(
/*=======================*/ /*=======================*/
buf_block_t* block) /*!< in: block */ buf_block_t* block) /*!< in: block */
{ {
/* No latch is acquired for the shared temporary tablespace. */ ut_ad(block->page.lock.have_any());
ut_ad(fsp_is_system_temporary(block->page.id().space())
|| block->lock.have_any());
return(block->modify_clock); return(block->modify_clock);
} }
/********************************************************************//**
Releases a compressed-only page acquired with buf_page_get_zip(). */
UNIV_INLINE
void
buf_page_release_zip(
/*=================*/
buf_page_t* bpage) /*!< in: buffer block */
{
ut_ad(bpage);
ut_ad(bpage->buf_fix_count());
switch (bpage->state()) {
case BUF_BLOCK_FILE_PAGE:
case BUF_BLOCK_ZIP_PAGE:
bpage->unfix();
return;
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
break;
}
ut_error;
}
/********************************************************************//**
Releases a latch, if specified. */
UNIV_INLINE
void
buf_page_release_latch(
/*===================*/
buf_block_t* block, /*!< in: buffer block */
ulint rw_latch) /*!< in: RW_S_LATCH, RW_X_LATCH,
RW_NO_LATCH */
{
switch (rw_latch) {
case RW_S_LATCH:
block->lock.s_unlock();
break;
case RW_SX_LATCH:
case RW_X_LATCH:
block->lock.u_or_x_unlock(rw_latch == RW_SX_LATCH);
}
}
/********************************************************************//**
Get buf frame. */
UNIV_INLINE
void *
buf_page_get_frame(
/*===============*/
const buf_page_t* bpage) /*!< in: buffer pool page */
{
/* In encryption/compression buffer pool page may contain extra
buffer where result is stored. */
if (bpage->slot && bpage->slot->out_buf) {
return bpage->slot->out_buf;
} else if (bpage->zip.data) {
return bpage->zip.data;
} else {
return ((buf_block_t*) bpage)->frame;
}
}
/** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit, /** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit,
if needed. if needed.
@param[in] size size in bytes @param[in] size size in bytes

View File

@@ -24,12 +24,11 @@ The database buffer pool flush algorithm
Created 11/5/1995 Heikki Tuuri Created 11/5/1995 Heikki Tuuri
*******************************************************/ *******************************************************/
#ifndef buf0flu_h #pragma once
#define buf0flu_h
#include "ut0byte.h" #include "ut0byte.h"
#include "log0log.h" #include "log0log.h"
#include "buf0types.h" #include "buf0buf.h"
/** Number of pages flushed. Protected by buf_pool.mutex. */ /** Number of pages flushed. Protected by buf_pool.mutex. */
extern ulint buf_flush_page_count; extern ulint buf_flush_page_count;
@@ -122,15 +121,28 @@ ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious);
This function should be called at a mini-transaction commit, if a page was This function should be called at a mini-transaction commit, if a page was
modified in it. Puts the block to the list of modified blocks, if it not modified in it. Puts the block to the list of modified blocks, if it not
already in it. */ already in it. */
UNIV_INLINE inline void buf_flush_note_modification(buf_block_t *b, lsn_t start, lsn_t end)
void {
buf_flush_note_modification( ut_ad(!srv_read_only_mode);
/*========================*/ ut_d(const auto s= b->page.state());
buf_block_t* block, /*!< in: block which is modified */ ut_ad(s > buf_page_t::FREED);
lsn_t start_lsn, /*!< in: start lsn of the first mtr in a ut_ad(s < buf_page_t::READ_FIX);
set of mtr's */ ut_ad(mach_read_from_8(b->page.frame + FIL_PAGE_LSN) <= end);
lsn_t end_lsn); /*!< in: end lsn of the last mtr in the mach_write_to_8(b->page.frame + FIL_PAGE_LSN, end);
set of mtr's */ if (UNIV_LIKELY_NULL(b->page.zip.data))
memcpy_aligned<8>(FIL_PAGE_LSN + b->page.zip.data,
FIL_PAGE_LSN + b->page.frame, 8);
const lsn_t oldest_modification= b->page.oldest_modification();
if (oldest_modification > 1)
ut_ad(oldest_modification <= start);
else if (fsp_is_system_temporary(b->page.id().space()))
b->page.set_temp_modified();
else
buf_pool.insert_into_flush_list(b, start);
srv_stats.buf_pool_write_requests.inc();
}
/** Initialize page_cleaner. */ /** Initialize page_cleaner. */
ATTRIBUTE_COLD void buf_flush_page_cleaner_init(); ATTRIBUTE_COLD void buf_flush_page_cleaner_init();
@@ -149,7 +161,3 @@ void buf_flush_validate();
/** Synchronously flush dirty blocks. /** Synchronously flush dirty blocks.
NOTE: The calling thread is not allowed to hold any buffer page latches! */ NOTE: The calling thread is not allowed to hold any buffer page latches! */
void buf_flush_sync(); void buf_flush_sync();
#include "buf0flu.ic"
#endif

View File

@@ -1,66 +0,0 @@
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2019, 2021, MariaDB Corporation.
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; version 2 of the License.
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
*****************************************************************************/
/**************************************************//**
@file include/buf0flu.ic
The database buffer pool flush algorithm
Created 11/5/1995 Heikki Tuuri
*******************************************************/
#include "assume_aligned.h"
#include "buf0buf.h"
#include "srv0srv.h"
/********************************************************************//**
This function should be called at a mini-transaction commit, if a page was
modified in it. Puts the block to the list of modified blocks, if it is not
already in it. */
UNIV_INLINE
void
buf_flush_note_modification(
/*========================*/
buf_block_t* block, /*!< in: block which is modified */
lsn_t start_lsn, /*!< in: start lsn of the mtr that
modified this block */
lsn_t end_lsn) /*!< in: end lsn of the mtr that
modified this block */
{
ut_ad(!srv_read_only_mode);
ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE);
ut_ad(block->page.buf_fix_count());
ut_ad(mach_read_from_8(block->frame + FIL_PAGE_LSN) <= end_lsn);
mach_write_to_8(block->frame + FIL_PAGE_LSN, end_lsn);
if (UNIV_LIKELY_NULL(block->page.zip.data)) {
memcpy_aligned<8>(FIL_PAGE_LSN + block->page.zip.data,
FIL_PAGE_LSN + block->frame, 8);
}
const lsn_t oldest_modification = block->page.oldest_modification();
if (oldest_modification > 1) {
ut_ad(oldest_modification <= start_lsn);
} else if (fsp_is_system_temporary(block->page.id().space())) {
block->page.set_temp_modified();
} else {
buf_pool.insert_into_flush_list(block, start_lsn);
}
srv_stats.buf_pool_write_requests.inc();
}

View File

@@ -39,16 +39,6 @@ struct buf_buddy_stat_t;
/** A buffer frame. @see page_t */ /** A buffer frame. @see page_t */
typedef byte buf_frame_t; typedef byte buf_frame_t;
/** Flags for io_fix types */
enum buf_io_fix {
BUF_IO_NONE = 0, /**< no pending I/O */
BUF_IO_READ, /**< read pending */
BUF_IO_WRITE, /**< write pending */
BUF_IO_PIN /**< disallow relocation of
block and its removal of from
the flush_list */
};
/** Alternatives for srv_checksum_algorithm, which can be changed by /** Alternatives for srv_checksum_algorithm, which can be changed by
setting innodb_checksum_algorithm */ setting innodb_checksum_algorithm */
enum srv_checksum_algorithm_t { enum srv_checksum_algorithm_t {
@@ -189,10 +179,8 @@ public:
/** Acquire an exclusive lock */ /** Acquire an exclusive lock */
inline void lock(); inline void lock();
#ifdef UNIV_DEBUG
/** @return whether an exclusive lock is being held by any thread */ /** @return whether an exclusive lock is being held by any thread */
bool is_write_locked() const { return rw_lock::is_write_locked(); } bool is_write_locked() const { return rw_lock::is_write_locked(); }
#endif
/** @return whether any lock is being held by any thread */ /** @return whether any lock is being held by any thread */
bool is_locked() const { return rw_lock::is_locked(); } bool is_locked() const { return rw_lock::is_locked(); }

View File

@@ -296,17 +296,15 @@ byte* fil_space_encrypt(
@param[in] tmp_frame Temporary buffer @param[in] tmp_frame Temporary buffer
@param[in] physical_size page size @param[in] physical_size page size
@param[in,out] src_frame Page to decrypt @param[in,out] src_frame Page to decrypt
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED @return DB_SUCCESS or error */
@return true if page decrypted, false if not.*/ dberr_t
bool
fil_space_decrypt( fil_space_decrypt(
uint32_t space_id, uint32_t space_id,
uint32_t fsp_flags, uint32_t fsp_flags,
fil_space_crypt_t* crypt_data, fil_space_crypt_t* crypt_data,
byte* tmp_frame, byte* tmp_frame,
ulint physical_size, ulint physical_size,
byte* src_frame, byte* src_frame);
dberr_t* err);
/****************************************************************** /******************************************************************
Decrypt a page Decrypt a page

View File

@@ -545,9 +545,8 @@ fil_block_check_type(
ulint type, ulint type,
mtr_t* mtr) mtr_t* mtr)
{ {
if (UNIV_UNLIKELY(type != fil_page_get_type(block.frame))) { if (UNIV_UNLIKELY(type != fil_page_get_type(block.page.frame)))
fil_block_reset_type(block, type, mtr); fil_block_reset_type(block, type, mtr);
}
} }
/** Checks if a page address is an extent descriptor page address. /** Checks if a page address is an extent descriptor page address.

View File

@@ -61,7 +61,7 @@ fut_get_ptr(
rw_latch, nullptr, BUF_GET_POSSIBLY_FREED, rw_latch, nullptr, BUF_GET_POSSIBLY_FREED,
mtr); mtr);
if (!block) { if (!block) {
} else if (block->page.status == buf_page_t::FREED) { } else if (block->page.is_freed()) {
block = nullptr; block = nullptr;
} else { } else {
ptr = buf_block_get_frame(block) + addr.boffset; ptr = buf_block_get_frame(block) + addr.boffset;

View File

@@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, 2020, MariaDB Corporation. Copyright (c) 2018, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@@ -70,9 +70,10 @@ typedef byte flst_node_t;
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
inline void flst_init(const buf_block_t* block, uint16_t ofs, mtr_t* mtr) inline void flst_init(const buf_block_t* block, uint16_t ofs, mtr_t* mtr)
{ {
ut_ad(!mach_read_from_2(FLST_LEN + ofs + block->frame)); ut_d(const page_t *page= block->page.frame);
ut_ad(!mach_read_from_2(FLST_FIRST + FIL_ADDR_BYTE + ofs + block->frame)); ut_ad(!mach_read_from_2(FLST_LEN + ofs + page));
ut_ad(!mach_read_from_2(FLST_LAST + FIL_ADDR_BYTE + ofs + block->frame)); ut_ad(!mach_read_from_2(FLST_FIRST + FIL_ADDR_BYTE + ofs + page));
ut_ad(!mach_read_from_2(FLST_LAST + FIL_ADDR_BYTE + ofs + page));
compile_time_assert(FIL_NULL == 0xffU * 0x1010101U); compile_time_assert(FIL_NULL == 0xffU * 0x1010101U);
mtr->memset(block, FLST_FIRST + FIL_ADDR_PAGE + ofs, 4, 0xff); mtr->memset(block, FLST_FIRST + FIL_ADDR_PAGE + ofs, 4, 0xff);
mtr->memset(block, FLST_LAST + FIL_ADDR_PAGE + ofs, 4, 0xff); mtr->memset(block, FLST_LAST + FIL_ADDR_PAGE + ofs, 4, 0xff);

View File

@@ -37,7 +37,7 @@ lock_get_min_heap_no(
/*=================*/ /*=================*/
const buf_block_t* block) /*!< in: buffer block */ const buf_block_t* block) /*!< in: buffer block */
{ {
const page_t* page = block->frame; const page_t* page = block->page.frame;
if (page_is_comp(page)) { if (page_is_comp(page)) {
return(rec_get_heap_no_new( return(rec_get_heap_no_new(
@@ -74,6 +74,6 @@ lock_rec_create(
btr_assert_not_corrupted(block, index); btr_assert_not_corrupted(block, index);
return lock_rec_create_low( return lock_rec_create_low(
c_lock, c_lock,
type_mode, block->page.id(), block->frame, heap_no, type_mode, block->page.id(), block->page.frame, heap_no,
index, trx, caller_owns_trx_mutex); index, trx, caller_owns_trx_mutex);
} }

View File

@@ -225,7 +225,7 @@ private:
public: public:
/** whether we are applying redo log records during crash recovery */ /** whether we are applying redo log records during crash recovery */
bool recovery_on; bool recovery_on;
/** whether recv_recover_page(), invoked from buf_page_read_complete(), /** whether recv_recover_page(), invoked from buf_page_t::read_complete(),
should apply log records*/ should apply log records*/
bool apply_log_recs; bool apply_log_recs;
byte* buf; /*!< buffer for parsing log records */ byte* buf; /*!< buffer for parsing log records */

View File

@@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2019, 2020, MariaDB Corporation. Copyright (c) 2019, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@@ -170,7 +170,7 @@ inline uint32_t mlog_decode_len(const byte *log, const byte *end)
template<unsigned l,mtr_t::write_type w,typename V> template<unsigned l,mtr_t::write_type w,typename V>
inline bool mtr_t::write(const buf_block_t &block, void *ptr, V val) inline bool mtr_t::write(const buf_block_t &block, void *ptr, V val)
{ {
ut_ad(ut_align_down(ptr, srv_page_size) == block.frame); ut_ad(ut_align_down(ptr, srv_page_size) == block.page.frame);
static_assert(l == 1 || l == 2 || l == 4 || l == 8, "wrong length"); static_assert(l == 1 || l == 2 || l == 4 || l == 8, "wrong length");
byte buf[l]; byte buf[l];
@@ -242,7 +242,7 @@ inline void mtr_t::memset(const buf_block_t *b, ulint ofs, ulint len, byte val)
{ {
ut_ad(ofs <= ulint(srv_page_size)); ut_ad(ofs <= ulint(srv_page_size));
ut_ad(ofs + len <= ulint(srv_page_size)); ut_ad(ofs + len <= ulint(srv_page_size));
::memset(ofs + b->frame, val, len); ::memset(ofs + b->page.frame, val, len);
memset(*b, ofs, len, val); memset(*b, ofs, len, val);
} }
@@ -286,10 +286,10 @@ inline void mtr_t::memset(const buf_block_t *b, ulint ofs, size_t len,
size_t s= 0; size_t s= 0;
while (s < len) while (s < len)
{ {
::memcpy(ofs + s + b->frame, str, size); ::memcpy(ofs + s + b->page.frame, str, size);
s+= len; s+= len;
} }
::memcpy(ofs + s + b->frame, str, len - s); ::memcpy(ofs + s + b->page.frame, str, len - s);
memset(*b, ofs, len, str, size); memset(*b, ofs, len, str, size);
} }
@@ -303,7 +303,7 @@ inline void mtr_t::memcpy(const buf_block_t &b, ulint offset, ulint len)
ut_ad(len); ut_ad(len);
ut_ad(offset <= ulint(srv_page_size)); ut_ad(offset <= ulint(srv_page_size));
ut_ad(offset + len <= ulint(srv_page_size)); ut_ad(offset + len <= ulint(srv_page_size));
memcpy_low(b, uint16_t(offset), &b.frame[offset], len); memcpy_low(b, uint16_t(offset), &b.page.frame[offset], len);
} }
/** Log a write of a byte string to a page. /** Log a write of a byte string to a page.
@@ -484,7 +484,7 @@ template<mtr_t::write_type w>
inline void mtr_t::memcpy(const buf_block_t &b, void *dest, const void *str, inline void mtr_t::memcpy(const buf_block_t &b, void *dest, const void *str,
ulint len) ulint len)
{ {
ut_ad(ut_align_down(dest, srv_page_size) == b.frame); ut_ad(ut_align_down(dest, srv_page_size) == b.page.frame);
char *d= static_cast<char*>(dest); char *d= static_cast<char*>(dest);
const char *s= static_cast<const char*>(str); const char *s= static_cast<const char*>(str);
if (w != FORCED && m_log_mode == MTR_LOG_ALL) if (w != FORCED && m_log_mode == MTR_LOG_ALL)
@@ -525,7 +525,7 @@ inline void mtr_t::init(buf_block_t *b)
m_freed_space= nullptr; m_freed_space= nullptr;
} }
b->page.status= buf_page_t::INIT_ON_FLUSH; b->page.set_reinit(b->page.state() & buf_page_t::LRU_MASK);
if (m_log_mode != MTR_LOG_ALL) if (m_log_mode != MTR_LOG_ALL)
{ {

View File

@@ -30,7 +30,8 @@ Created 11/26/1995 Heikki Tuuri
@return true if the mtr is dirtying a clean page. */ @return true if the mtr is dirtying a clean page. */
inline bool mtr_t::is_block_dirtied(const buf_block_t *block) inline bool mtr_t::is_block_dirtied(const buf_block_t *block)
{ {
ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); ut_ad(block->page.in_file());
ut_ad(block->page.frame);
ut_ad(block->page.buf_fix_count()); ut_ad(block->page.buf_fix_count());
return block->page.oldest_modification() <= 1; return block->page.oldest_modification() <= 1;
} }
@@ -109,7 +110,8 @@ mtr_t::sx_latch_at_savepoint(
/* == RW_NO_LATCH */ /* == RW_NO_LATCH */
ut_a(slot->type == MTR_MEMO_BUF_FIX); ut_a(slot->type == MTR_MEMO_BUF_FIX);
block->lock.u_lock(); block->page.lock.u_lock();
ut_ad(!block->page.is_io_fixed());
if (!m_made_dirty) { if (!m_made_dirty) {
m_made_dirty = is_block_dirtied(block); m_made_dirty = is_block_dirtied(block);
@@ -142,7 +144,8 @@ mtr_t::x_latch_at_savepoint(
/* == RW_NO_LATCH */ /* == RW_NO_LATCH */
ut_a(slot->type == MTR_MEMO_BUF_FIX); ut_a(slot->type == MTR_MEMO_BUF_FIX);
block->lock.x_lock(); block->page.lock.x_lock();
ut_ad(!block->page.is_io_fixed());
if (!m_made_dirty) { if (!m_made_dirty) {
m_made_dirty = is_block_dirtied(block); m_made_dirty = is_block_dirtied(block);
@@ -159,15 +162,23 @@ mtr_t::release_block_at_savepoint(
ulint savepoint, ulint savepoint,
buf_block_t* block) buf_block_t* block)
{ {
ut_ad(is_active()); ut_ad(is_active());
mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint); mtr_memo_slot_t *slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_a(slot->object == block); ut_a(slot->object == block);
slot->object= nullptr;
block->page.unfix();
buf_page_release_latch(block, slot->type); switch (slot->type) {
case MTR_MEMO_PAGE_S_FIX:
reinterpret_cast<buf_block_t*>(block)->unfix(); block->page.lock.s_unlock();
break;
slot->object = NULL; case MTR_MEMO_PAGE_SX_FIX:
case MTR_MEMO_PAGE_X_FIX:
block->page.lock.u_or_x_unlock(slot->type == MTR_MEMO_PAGE_SX_FIX);
break;
default:
break;
}
} }

View File

@@ -51,6 +51,8 @@ extern bool os_has_said_disk_full;
/** File offset in bytes */ /** File offset in bytes */
typedef ib_uint64_t os_offset_t; typedef ib_uint64_t os_offset_t;
class buf_tmp_buffer_t;
#ifdef _WIN32 #ifdef _WIN32
/** We define always WIN_ASYNC_IO, and check at run-time whether /** We define always WIN_ASYNC_IO, and check at run-time whether
@@ -206,11 +208,13 @@ public:
PUNCH_RANGE= WRITE_SYNC | 128, PUNCH_RANGE= WRITE_SYNC | 128,
}; };
constexpr IORequest(buf_page_t *bpage, fil_node_t *node, Type type) : constexpr IORequest(buf_page_t *bpage, buf_tmp_buffer_t *slot,
bpage(bpage), node(node), type(type) {} fil_node_t *node, Type type) :
bpage(bpage), slot(slot), node(node), type(type) {}
constexpr IORequest(Type type= READ_SYNC, buf_page_t *bpage= nullptr) : constexpr IORequest(Type type= READ_SYNC, buf_page_t *bpage= nullptr,
bpage(bpage), type(type) {} buf_tmp_buffer_t *slot= nullptr) :
bpage(bpage), slot(slot), type(type) {}
bool is_read() const { return (type & READ_SYNC) != 0; } bool is_read() const { return (type & READ_SYNC) != 0; }
bool is_write() const { return (type & WRITE_SYNC) != 0; } bool is_write() const { return (type & WRITE_SYNC) != 0; }
@@ -237,7 +241,10 @@ private:
public: public:
/** Page to be written on write operation */ /** Page to be written on write operation */
buf_page_t* const bpage= nullptr; buf_page_t *const bpage= nullptr;
/** Memory to be used for encrypted or page_compressed pages */
buf_tmp_buffer_t *const slot= nullptr;
/** File descriptor */ /** File descriptor */
fil_node_t *const node= nullptr; fil_node_t *const node= nullptr;

View File

@@ -34,13 +34,7 @@ page_cur_get_page(
/*==============*/ /*==============*/
page_cur_t* cur) /*!< in: page cursor */ page_cur_t* cur) /*!< in: page cursor */
{ {
ut_ad(cur); return page_align(page_cur_get_rec(cur));
if (cur->rec) {
ut_ad(page_align(cur->rec) == cur->block->frame);
}
return(page_align(cur->rec));
} }
/*********************************************************//** /*********************************************************//**
@@ -52,13 +46,9 @@ page_cur_get_block(
/*===============*/ /*===============*/
page_cur_t* cur) /*!< in: page cursor */ page_cur_t* cur) /*!< in: page cursor */
{ {
ut_ad(cur); ut_ad(cur);
ut_ad(!cur->rec || page_align(cur->rec) == cur->block->page.frame);
if (cur->rec) { return cur->block;
ut_ad(page_align(cur->rec) == cur->block->frame);
}
return(cur->block);
} }
/*********************************************************//** /*********************************************************//**
@@ -82,13 +72,9 @@ page_cur_get_rec(
/*=============*/ /*=============*/
page_cur_t* cur) /*!< in: page cursor */ page_cur_t* cur) /*!< in: page cursor */
{ {
ut_ad(cur); ut_ad(cur);
ut_ad(!cur->rec || page_align(cur->rec) == cur->block->page.frame);
if (cur->rec) { return cur->rec;
ut_ad(page_align(cur->rec) == cur->block->frame);
}
return(cur->rec);
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
@@ -102,7 +88,7 @@ page_cur_set_before_first(
const buf_block_t* block, /*!< in: index page */ const buf_block_t* block, /*!< in: index page */
page_cur_t* cur) /*!< in: cursor */ page_cur_t* cur) /*!< in: cursor */
{ {
cur->block = (buf_block_t*) block; cur->block = const_cast<buf_block_t*>(block);
cur->rec = page_get_infimum_rec(buf_block_get_frame(cur->block)); cur->rec = page_get_infimum_rec(buf_block_get_frame(cur->block));
} }
@@ -116,7 +102,7 @@ page_cur_set_after_last(
const buf_block_t* block, /*!< in: index page */ const buf_block_t* block, /*!< in: index page */
page_cur_t* cur) /*!< in: cursor */ page_cur_t* cur) /*!< in: cursor */
{ {
cur->block = (buf_block_t*) block; cur->block = const_cast<buf_block_t*>(block);
cur->rec = page_get_supremum_rec(buf_block_get_frame(cur->block)); cur->rec = page_get_supremum_rec(buf_block_get_frame(cur->block));
} }
@@ -130,7 +116,7 @@ page_cur_is_before_first(
const page_cur_t* cur) /*!< in: cursor */ const page_cur_t* cur) /*!< in: cursor */
{ {
ut_ad(cur); ut_ad(cur);
ut_ad(page_align(cur->rec) == cur->block->frame); ut_ad(page_align(cur->rec) == cur->block->page.frame);
return(page_rec_is_infimum(cur->rec)); return(page_rec_is_infimum(cur->rec));
} }
@@ -144,7 +130,7 @@ page_cur_is_after_last(
const page_cur_t* cur) /*!< in: cursor */ const page_cur_t* cur) /*!< in: cursor */
{ {
ut_ad(cur); ut_ad(cur);
ut_ad(page_align(cur->rec) == cur->block->frame); ut_ad(page_align(cur->rec) == cur->block->page.frame);
return(page_rec_is_supremum(cur->rec)); return(page_rec_is_supremum(cur->rec));
} }
@@ -160,7 +146,7 @@ page_cur_position(
page_cur_t* cur) /*!< out: page cursor */ page_cur_t* cur) /*!< out: page cursor */
{ {
ut_ad(rec && block && cur); ut_ad(rec && block && cur);
ut_ad(page_align(rec) == block->frame); ut_ad(page_align(rec) == block->page.frame);
cur->rec = (rec_t*) rec; cur->rec = (rec_t*) rec;
cur->block = (buf_block_t*) block; cur->block = (buf_block_t*) block;
@@ -273,7 +259,7 @@ page_cur_tuple_insert(
index, tuple, n_ext); index, tuple, n_ext);
*offsets = rec_get_offsets(rec, index, *offsets, *offsets = rec_get_offsets(rec, index, *offsets,
page_is_leaf(cursor->block->frame) page_is_leaf(cursor->block->page.frame)
? index->n_core_fields : 0, ? index->n_core_fields : 0,
ULINT_UNDEFINED, heap); ULINT_UNDEFINED, heap);
ut_ad(size == rec_offs_size(*offsets)); ut_ad(size == rec_offs_size(*offsets));

View File

@@ -418,8 +418,8 @@ template<bool compressed>
inline void page_rec_set_n_owned(buf_block_t *block, rec_t *rec, ulint n_owned, inline void page_rec_set_n_owned(buf_block_t *block, rec_t *rec, ulint n_owned,
bool comp, mtr_t *mtr) bool comp, mtr_t *mtr)
{ {
ut_ad(block->frame == page_align(rec)); ut_ad(block->page.frame == page_align(rec));
ut_ad(comp == (page_is_comp(block->frame) != 0)); ut_ad(comp == (page_is_comp(block->page.frame) != 0));
if (page_zip_des_t *page_zip= compressed if (page_zip_des_t *page_zip= compressed
? buf_block_get_page_zip(block) : nullptr) ? buf_block_get_page_zip(block) : nullptr)

Some files were not shown because too many files have changed in this diff Show More