mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Merge 10.6 into 10.7
This commit is contained in:
@@ -182,16 +182,20 @@ IF(WIN32)
|
||||
SET(SIGNTOOL_PARAMETERS
|
||||
/a /t http://timestamp.globalsign.com/?signature=sha2
|
||||
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)
|
||||
MESSAGE(FATAL_ERROR
|
||||
"signtool is not found. Signing executables not possible")
|
||||
FILE(GLOB path_list
|
||||
"$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()
|
||||
MARK_AS_ADVANCED(SIGNTOOL_EXECUTABLE SIGNTOOL_PARAMETERS)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
@@ -2086,6 +2086,56 @@ a b a b
|
||||
1 3 1 3
|
||||
drop procedure sp;
|
||||
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
|
||||
#
|
||||
# MDEV-21673: several references to CTE that uses
|
||||
|
@@ -1554,6 +1554,42 @@ call sp();
|
||||
drop procedure sp;
|
||||
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 #
|
||||
|
@@ -32,8 +32,8 @@ COUNT(*)=8
|
||||
# Note: We only look for 00 because the 5c only served as an escape
|
||||
# in parsing.
|
||||
#
|
||||
# MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql
|
||||
FOUND 10 /00/ in dump.sql
|
||||
# MYSQL_DUMP test tb --hex-blob > MYSQL_TMP_DIR/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
|
||||
#
|
||||
|
@@ -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 # in parsing.
|
||||
--echo #
|
||||
--echo # MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql
|
||||
--exec $MYSQL_DUMP test tb --hex-blob | grep -A8 INSERT > $MYSQL_TMP_DIR/dump.sql
|
||||
--let SEARCH_PATTERN= 00
|
||||
--echo # MYSQL_DUMP test tb --hex-blob > MYSQL_TMP_DIR/dump.sql
|
||||
--exec $MYSQL_DUMP test tb --hex-blob > $MYSQL_TMP_DIR/dump.sql
|
||||
--let SEARCH_PATTERN= \([0-9]+,0x([1-9][0-9])*00([1-9][0-9])*\)
|
||||
--let SEARCH_FILE= $MYSQL_TMP_DIR/dump.sql
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
|
@@ -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;
|
@@ -67,13 +67,13 @@ test/t2
|
||||
test/t3
|
||||
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
|
||||
NAME
|
||||
innodb_system
|
||||
mysql/innodb_table_stats
|
||||
mysql/innodb_index_stats
|
||||
mysql/transaction_registry
|
||||
test/t4
|
||||
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
|
||||
NAME
|
||||
innodb_system
|
||||
mysql/innodb_index_stats
|
||||
mysql/innodb_table_stats
|
||||
mysql/transaction_registry
|
||||
test/t1
|
||||
test/t2
|
||||
test/t3
|
||||
|
@@ -66,7 +66,7 @@ innodb_encryption_threads 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';
|
||||
NAME
|
||||
innodb_system
|
||||
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';
|
||||
NAME
|
||||
innodb_system
|
||||
|
@@ -0,0 +1,4 @@
|
||||
[crc32]
|
||||
innodb-checksum-algorithm=crc32
|
||||
[full_crc32]
|
||||
innodb-checksum-algorithm=full_crc32
|
@@ -0,0 +1 @@
|
||||
--innodb-encrypt-tables=1
|
44
mysql-test/suite/encryption/t/encryption_key_corruption.test
Normal file
44
mysql-test/suite/encryption/t/encryption_key_corruption.test
Normal 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
|
@@ -90,6 +90,9 @@ AND NAME NOT LIKE 'innodb_undo%' AND NAME NOT LIKE 'mysql/innodb_%_stats' AND NA
|
||||
|
||||
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
|
||||
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';
|
||||
|
@@ -25,6 +25,7 @@ t1 CREATE TABLE `t1` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
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_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);
|
||||
@@ -33,6 +34,7 @@ SET DEBUG_SYNC="now WAIT_FOR con1_go";
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 1
|
||||
SET DEBUG_SYNC="now SIGNAL alter_signal";
|
||||
connection default;
|
||||
ERROR 23000: Duplicate entry '' for key '*UNKNOWN*'
|
||||
@@ -47,6 +49,7 @@ t1 CREATE TABLE `t1` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
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_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
|
||||
ALTER TABLE t1 ADD INDEX(f2);
|
||||
|
@@ -29,6 +29,7 @@ DROP TABLE t1;
|
||||
# new_vcol_info in index when rollback of alter happens
|
||||
|
||||
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_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);
|
||||
@@ -47,6 +48,7 @@ SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
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_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
|
||||
send ALTER TABLE t1 ADD INDEX(f2);
|
||||
|
@@ -34,6 +34,7 @@ CREATE TABLE t1(f1 INT, f2 INT,
|
||||
PRIMARY KEY(f1, f2),
|
||||
UNIQUE INDEX uidx2 (f1, f2),
|
||||
UNIQUE INDEX uidx1 (f2))ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(2, 2);
|
||||
ALTER TABLE t1 DROP PRIMARY KEY;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
@@ -66,7 +67,7 @@ test.t1 check status OK
|
||||
DROP TABLE t1;
|
||||
SET SQL_MODE= strict_trans_tables;
|
||||
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';
|
||||
ALTER TABLE t1 MODIFY COLUMN a INT NOT NULL;
|
||||
connection con1;
|
||||
|
@@ -80,6 +80,7 @@ SET DEBUG_SYNC='RESET';
|
||||
#
|
||||
CREATE TABLE t1 (f VARCHAR(8) CHARACTER SET latin1 COLLATE latin1_swedish_ci)
|
||||
ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES('ZERO');
|
||||
connection con1;
|
||||
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;
|
||||
@@ -96,5 +97,6 @@ ALTER TABLE t1 CHANGE f eins VARCHAR(257) COLLATE latin1_german1_ci NOT NULL,
|
||||
ALGORITHM=INSTANT;
|
||||
SELECT * FROM t1;
|
||||
eins
|
||||
ZERO
|
||||
one
|
||||
DROP TABLE t1;
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#
|
||||
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
CREATE TABLE t1 (c CHAR(2) NOT NULL) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES('cd');
|
||||
connect con1,localhost,root,,;
|
||||
BEGIN;
|
||||
INSERT INTO t0 VALUES(1);
|
||||
@@ -21,6 +22,7 @@ ERROR 23000: Duplicate entry 'a' for key 'PRIMARY'
|
||||
SET DEBUG_SYNC='RESET';
|
||||
SELECT * FROM t1;
|
||||
c
|
||||
cd
|
||||
ab
|
||||
ac
|
||||
DROP TABLE t0,t1;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=InnoDB;
|
||||
INSERT INTO t0 VALUES(100);
|
||||
INSERT INTO t1 VALUES(100, 100);
|
||||
connect con1,localhost,root,,test;
|
||||
BEGIN;
|
||||
INSERT INTO t0 SET pk=1;
|
||||
|
@@ -55,7 +55,7 @@ connect con1,localhost,root,,;
|
||||
BEGIN;
|
||||
DELETE FROM mysql.innodb_table_stats;
|
||||
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;
|
||||
connection default;
|
||||
SET DEBUG_SYNC='now WAIT_FOR blocked';
|
||||
|
@@ -81,6 +81,7 @@ COUNT(k1) k2 k3
|
||||
drop table t1;
|
||||
create table t1(k1 int auto_increment primary key,
|
||||
k2 char(200),k3 char(200))engine=innodb;
|
||||
INSERT INTO t1 VALUES(1, "test", "test");
|
||||
SET DEBUG_SYNC= 'row_merge_after_scan
|
||||
SIGNAL opened WAIT_FOR flushed';
|
||||
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
|
||||
480 aaa bbb
|
||||
480 aaaa bbbb
|
||||
1 test test
|
||||
disconnect con1;
|
||||
connection default;
|
||||
show create table t1;
|
||||
@@ -109,7 +111,7 @@ t1 CREATE TABLE `t1` (
|
||||
`k2` char(200) DEFAULT NULL,
|
||||
`k3` char(200) DEFAULT NULL,
|
||||
PRIMARY KEY (`k1`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1023 DEFAULT CHARSET=latin1
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1024 DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
drop table t480;
|
||||
#
|
||||
@@ -117,6 +119,7 @@ drop table t480;
|
||||
# in online table rebuild
|
||||
#
|
||||
CREATE TABLE t1 (j INT UNIQUE, i INT UNIQUE) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(2, 2);
|
||||
connect con1,localhost,root,,test;
|
||||
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL built WAIT_FOR log';
|
||||
ALTER TABLE t1 DROP j, FORCE;
|
||||
|
@@ -493,6 +493,7 @@ DROP TABLE t1;
|
||||
# MDEV-13205 assertion !dict_index_is_online_ddl(index) upon ALTER TABLE
|
||||
#
|
||||
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';
|
||||
ALTER TABLE t1 ADD UNIQUE(c);
|
||||
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")
|
||||
DROP TABLE t2,t1;
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(0,0);
|
||||
connect con1,localhost,root,,;
|
||||
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL created WAIT_FOR inserted';
|
||||
ALTER TABLE t1 ADD INDEX(b);
|
||||
@@ -523,6 +525,7 @@ disconnect con1;
|
||||
connection default;
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
0 0
|
||||
CHECK TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
|
@@ -434,6 +434,7 @@ t1 CREATE TABLE `t1` (
|
||||
SET GLOBAL innodb_monitor_disable = module_ddl;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY, b blob) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(0,NULL);
|
||||
connection con1;
|
||||
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL created WAIT_FOR ins';
|
||||
ALTER TABLE t1 FORCE;
|
||||
@@ -448,6 +449,7 @@ disconnect con1;
|
||||
connection default;
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
0 NULL
|
||||
DROP TABLE t1;
|
||||
SET DEBUG_SYNC = 'RESET';
|
||||
SET GLOBAL innodb_file_per_table = @global_innodb_file_per_table_orig;
|
||||
|
@@ -171,6 +171,7 @@ connect stop_purge,localhost,root;
|
||||
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
||||
connect ddl,localhost,root,,test;
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
|
||||
ALTER TABLE t1 FORCE;
|
||||
connection default;
|
||||
@@ -206,10 +207,11 @@ DELETE FROM t1;
|
||||
connection ddl;
|
||||
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
|
||||
ALTER TABLE t1 FORCE;
|
||||
connection default;
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR copied';
|
||||
connection stop_purge;
|
||||
COMMIT;
|
||||
connection default;
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR copied';
|
||||
InnoDB 1 transactions not purged
|
||||
INSERT INTO t1 SET a=1;
|
||||
INSERT INTO t1 SET a=2,b=3,c=4;
|
||||
@@ -229,9 +231,9 @@ DELETE FROM t1;
|
||||
connection ddl;
|
||||
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;
|
||||
disconnect stop_purge;
|
||||
connection default;
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR copied';
|
||||
disconnect stop_purge;
|
||||
InnoDB 1 transactions not purged
|
||||
INSERT INTO t1 SET a=1;
|
||||
INSERT INTO t1 SET a=2,c=4;
|
||||
@@ -449,6 +451,7 @@ DROP 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)
|
||||
ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(1, 2, 3, 4, 5, 6, 7, 8, "test");
|
||||
ALTER TABLE t1 MODIFY a INT NULL;
|
||||
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL alter WAIT_FOR go';
|
||||
ALTER TABLE t1 ADD PRIMARY KEY (a);
|
||||
@@ -462,6 +465,7 @@ connection default;
|
||||
disconnect con1;
|
||||
SELECT * FROM t1;
|
||||
a b c d e f g h i
|
||||
1 2 3 4 5 6 7 8 test
|
||||
DROP TABLE t1;
|
||||
SET DEBUG_SYNC=RESET;
|
||||
# End of 10.4 tests
|
||||
|
@@ -24,6 +24,7 @@ CREATE TABLE t1(f1 INT, f2 INT,
|
||||
PRIMARY KEY(f1, f2),
|
||||
UNIQUE INDEX uidx2 (f1, f2),
|
||||
UNIQUE INDEX uidx1 (f2))ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(2, 2);
|
||||
ALTER TABLE t1 DROP PRIMARY KEY;
|
||||
SHOW CREATE TABLE t1;
|
||||
SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter
|
||||
@@ -42,9 +43,7 @@ DROP TABLE t1;
|
||||
|
||||
SET SQL_MODE= strict_trans_tables;
|
||||
CREATE TABLE t1(a INT UNIQUE) ENGINE=InnoDB;
|
||||
# MDEV-515 takes X-lock on the table for the first insert.
|
||||
# So concurrent insert won't happen on the table
|
||||
INSERT INTO t1 VALUES(3);
|
||||
INSERT INTO t1 VALUES(1);
|
||||
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL dml WAIT_FOR dml_done';
|
||||
--send ALTER TABLE t1 MODIFY COLUMN a INT NOT NULL
|
||||
connection con1;
|
||||
|
@@ -75,7 +75,7 @@ SET DEBUG_SYNC='RESET';
|
||||
--echo #
|
||||
CREATE TABLE t1 (f VARCHAR(8) CHARACTER SET latin1 COLLATE latin1_swedish_ci)
|
||||
ENGINE=InnoDB;
|
||||
|
||||
INSERT INTO t1 VALUES('ZERO');
|
||||
connection con1;
|
||||
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;
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
CREATE TABLE t1 (c CHAR(2) NOT NULL) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES('cd');
|
||||
|
||||
connect (con1,localhost,root,,);
|
||||
BEGIN;
|
||||
|
@@ -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.
|
||||
# So concurrent insert won't happen on the table
|
||||
INSERT INTO t0 VALUES(100);
|
||||
|
||||
INSERT INTO t1 VALUES(100, 100);
|
||||
|
||||
--connect (con1,localhost,root,,test)
|
||||
BEGIN;
|
||||
INSERT INTO t0 SET pk=1;
|
||||
|
@@ -79,7 +79,7 @@ BEGIN;
|
||||
DELETE FROM mysql.innodb_table_stats;
|
||||
|
||||
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;
|
||||
|
||||
connection default;
|
||||
|
@@ -96,6 +96,7 @@ drop table t1;
|
||||
# Log file creation failure.
|
||||
create table t1(k1 int auto_increment primary key,
|
||||
k2 char(200),k3 char(200))engine=innodb;
|
||||
INSERT INTO t1 VALUES(1, "test", "test");
|
||||
SET DEBUG_SYNC= 'row_merge_after_scan
|
||||
SIGNAL opened WAIT_FOR flushed';
|
||||
send ALTER TABLE t1 FORCE, ADD COLUMN k4 int;
|
||||
@@ -122,6 +123,7 @@ drop table t480;
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (j INT UNIQUE, i INT UNIQUE) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(2, 2);
|
||||
--connect (con1,localhost,root,,test)
|
||||
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL built WAIT_FOR log';
|
||||
--send
|
||||
|
@@ -475,6 +475,7 @@ DROP TABLE t1;
|
||||
--echo # MDEV-13205 assertion !dict_index_is_online_ddl(index) upon ALTER TABLE
|
||||
--echo #
|
||||
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';
|
||||
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;
|
||||
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(0,0);
|
||||
|
||||
connect (con1,localhost,root,,);
|
||||
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL created WAIT_FOR inserted';
|
||||
|
@@ -395,6 +395,7 @@ SET GLOBAL innodb_monitor_disable = module_ddl;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY, b blob) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(0,NULL);
|
||||
|
||||
connection con1;
|
||||
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL created WAIT_FOR ins';
|
||||
|
@@ -186,6 +186,7 @@ connect stop_purge,localhost,root;
|
||||
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
||||
connect ddl,localhost,root,,test;
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
|
||||
send ALTER TABLE t1 FORCE;
|
||||
connection default;
|
||||
@@ -236,11 +237,11 @@ connection ddl;
|
||||
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
|
||||
send ALTER TABLE t1 FORCE;
|
||||
|
||||
connection stop_purge;
|
||||
COMMIT;
|
||||
|
||||
connection default;
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR copied';
|
||||
connection stop_purge;
|
||||
COMMIT;
|
||||
connection default;
|
||||
let $wait_all_purged = 1;
|
||||
--source include/wait_all_purged.inc
|
||||
let $wait_all_purged = 0;
|
||||
@@ -265,10 +266,9 @@ connection ddl;
|
||||
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;
|
||||
|
||||
disconnect stop_purge;
|
||||
|
||||
connection default;
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR copied';
|
||||
disconnect stop_purge;
|
||||
let $wait_all_purged = 1;
|
||||
--source include/wait_all_purged.inc
|
||||
let $wait_all_purged = 0;
|
||||
@@ -519,7 +519,7 @@ DROP 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)
|
||||
ENGINE=InnoDB;
|
||||
|
||||
INSERT INTO t1 VALUES(1, 2, 3, 4, 5, 6, 7, 8, "test");
|
||||
ALTER TABLE t1 MODIFY a INT NULL;
|
||||
|
||||
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL alter WAIT_FOR go';
|
||||
|
@@ -31,6 +31,7 @@ SET SESSION debug_dbug=@saved_debug_dbug;
|
||||
# MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX
|
||||
#
|
||||
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;
|
||||
SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter";
|
||||
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;
|
||||
SELECT * FROM t1;
|
||||
a b c
|
||||
1 test test_1
|
||||
SET DEBUG_SYNC='now SIGNAL g2';
|
||||
connection con1;
|
||||
ERROR HY000: Out of memory.
|
||||
|
@@ -60,6 +60,7 @@ SET SESSION debug_dbug=@saved_debug_dbug;
|
||||
--echo # MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX
|
||||
--echo #
|
||||
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);
|
||||
SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter";
|
||||
SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2';
|
||||
|
@@ -18,7 +18,7 @@ INNODB_BUFFER_PAGE CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE` (
|
||||
`DATA_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,
|
||||
`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,
|
||||
`FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT 0
|
||||
) ENGINE=MEMORY DEFAULT CHARSET=utf8mb3
|
||||
|
@@ -18,7 +18,7 @@ INNODB_BUFFER_PAGE_LRU CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE_LRU` (
|
||||
`DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0,
|
||||
`COMPRESSED_SIZE` bigint(21) unsigned 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,
|
||||
`FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT 0
|
||||
) ENGINE=MEMORY DEFAULT CHARSET=utf8mb3
|
||||
|
29
mysql-test/suite/rpl/r/rpl_query_cache.result
Normal file
29
mysql-test/suite/rpl/r/rpl_query_cache.result
Normal 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
|
27
mysql-test/suite/rpl/t/rpl_query_cache.test
Normal file
27
mysql-test/suite/rpl/t/rpl_query_cache.test
Normal 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
|
@@ -2625,6 +2625,9 @@ public:
|
||||
/** true when InnoDB should abort the alter when table is 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_info *alter_info_arg,
|
||||
KEY *key_info_arg, uint key_count_arg,
|
||||
|
@@ -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(),
|
||||
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);
|
||||
#endif /* WITH_WSREP && HAVE_QUERY_CACHE */
|
||||
#endif /* HAVE_QUERY_CACHE */
|
||||
}
|
||||
|
||||
table= m_table= rgi->m_table_map.get_table(m_table_id);
|
||||
|
@@ -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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -18,6 +18,14 @@
|
||||
#include "sql_string.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()
|
||||
{
|
||||
if (!document_start)
|
||||
@@ -26,9 +34,21 @@ void Json_writer::append_indent()
|
||||
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()
|
||||
{
|
||||
fmt_helper.on_start_object();
|
||||
on_start_object();
|
||||
|
||||
if (!element_started)
|
||||
start_element();
|
||||
@@ -38,10 +58,22 @@ void Json_writer::start_object()
|
||||
first_child=true;
|
||||
element_started= false;
|
||||
document_start= false;
|
||||
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
|
||||
got_name= false;
|
||||
#endif
|
||||
}
|
||||
|
||||
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())
|
||||
return;
|
||||
|
||||
@@ -58,6 +90,12 @@ void Json_writer::start_array()
|
||||
|
||||
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;
|
||||
if (!first_child)
|
||||
append_indent();
|
||||
@@ -68,6 +106,11 @@ void Json_writer::end_object()
|
||||
|
||||
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())
|
||||
return;
|
||||
indent_level-=INDENT_SIZE;
|
||||
@@ -80,31 +123,25 @@ void Json_writer::end_array()
|
||||
Json_writer& Json_writer::add_member(const char *name)
|
||||
{
|
||||
size_t len= strlen(name);
|
||||
if (fmt_helper.on_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;
|
||||
return add_member(name, len);
|
||||
}
|
||||
|
||||
Json_writer& Json_writer::add_member(const char *name, size_t len)
|
||||
{
|
||||
if (fmt_helper.on_add_member(name, len))
|
||||
return *this; // handled
|
||||
if (!fmt_helper.on_add_member(name, len))
|
||||
{
|
||||
// assert that we are in an object
|
||||
DBUG_ASSERT(!element_started);
|
||||
start_element();
|
||||
|
||||
// assert that we are in an object
|
||||
DBUG_ASSERT(!element_started);
|
||||
start_element();
|
||||
|
||||
output.append('"');
|
||||
output.append(name, len);
|
||||
output.append(STRING_WITH_LEN("\": "));
|
||||
output.append('"');
|
||||
output.append(name, len);
|
||||
output.append(STRING_WITH_LEN("\": "));
|
||||
}
|
||||
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
|
||||
if (!fmt_helper.is_making_writer_calls())
|
||||
got_name= true;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -200,7 +237,14 @@ void Json_writer::add_null()
|
||||
void Json_writer::add_unquoted_str(const char* 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;
|
||||
|
||||
if (!element_started)
|
||||
@@ -210,31 +254,19 @@ void Json_writer::add_unquoted_str(const char* str)
|
||||
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))
|
||||
return;
|
||||
|
||||
if (!element_started)
|
||||
start_element();
|
||||
|
||||
output.append(str, len);
|
||||
element_started= false;
|
||||
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
|
||||
got_name= false;
|
||||
#endif
|
||||
bool helped= fmt_helper.on_add_str(str, num_bytes);
|
||||
return helped;
|
||||
}
|
||||
|
||||
void Json_writer::add_str(const char *str)
|
||||
{
|
||||
size_t len= strlen(str);
|
||||
if (fmt_helper.on_add_str(str, len))
|
||||
return;
|
||||
|
||||
if (!element_started)
|
||||
start_element();
|
||||
|
||||
output.append('"');
|
||||
output.append(str, len);
|
||||
output.append('"');
|
||||
element_started= false;
|
||||
add_str(str, len);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -243,7 +275,9 @@ void Json_writer::add_str(const char *str)
|
||||
|
||||
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;
|
||||
|
||||
if (!element_started)
|
||||
|
@@ -17,9 +17,20 @@
|
||||
#define JSON_WRITER_INCLUDED
|
||||
|
||||
#include "my_base.h"
|
||||
#include "sql_select.h"
|
||||
|
||||
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST) || defined ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
|
||||
#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_context;
|
||||
@@ -96,9 +107,18 @@ public:
|
||||
bool on_end_array();
|
||||
void on_start_object();
|
||||
// on_end_object() is not needed.
|
||||
|
||||
|
||||
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 disable_and_flush();
|
||||
};
|
||||
@@ -185,6 +205,25 @@ private:
|
||||
|
||||
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:
|
||||
/* Add a member. We must be in an object. */
|
||||
Json_writer& add_member(const char *name);
|
||||
@@ -208,6 +247,10 @@ public:
|
||||
private:
|
||||
void add_unquoted_str(const char* val);
|
||||
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:
|
||||
/* Start a child object */
|
||||
void start_object();
|
||||
@@ -225,6 +268,9 @@ public:
|
||||
size_t get_truncated_bytes() { return output.get_truncated_bytes(); }
|
||||
|
||||
Json_writer() :
|
||||
#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
|
||||
got_name(false),
|
||||
#endif
|
||||
indent_level(0), document_start(true), element_started(false),
|
||||
first_child(true)
|
||||
{
|
||||
@@ -312,6 +358,9 @@ public:
|
||||
/* A common base for Json_writer_object and Json_writer_array */
|
||||
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
|
||||
static thread_local std::vector<bool> named_items_expectation;
|
||||
#endif
|
||||
@@ -372,24 +421,18 @@ private:
|
||||
my_writer->add_member(name);
|
||||
}
|
||||
public:
|
||||
explicit Json_writer_object(THD *thd)
|
||||
: 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)
|
||||
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->add_member(str).start_object();
|
||||
{
|
||||
if (str)
|
||||
my_writer->add_member(str);
|
||||
my_writer->start_object();
|
||||
}
|
||||
}
|
||||
|
||||
~Json_writer_object()
|
||||
|
@@ -7655,7 +7655,7 @@ static int mysql_init_variables(void)
|
||||
disable_log_notes= 0;
|
||||
mqh_used= 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;
|
||||
slave_open_temp_tables= 0;
|
||||
opt_endinfo= using_udf_functions= 0;
|
||||
|
@@ -370,7 +370,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
|
||||
double read_time);
|
||||
static
|
||||
TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
|
||||
double read_time);
|
||||
double read_time, bool named_trace= false);
|
||||
static
|
||||
TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge,
|
||||
TRP_INDEX_MERGE *imerge_trp,
|
||||
@@ -5084,7 +5084,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
|
||||
|
||||
static
|
||||
TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
|
||||
double read_time)
|
||||
double read_time, bool named_trace)
|
||||
{
|
||||
SEL_TREE **ptree;
|
||||
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)))
|
||||
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");
|
||||
/*
|
||||
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);
|
||||
|
||||
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
|
||||
{
|
||||
/*
|
||||
@@ -5676,7 +5677,7 @@ void print_keyparts(THD *thd, KEY *key, uint key_parts)
|
||||
DBUG_ASSERT(thd->trace_started());
|
||||
|
||||
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++)
|
||||
keyparts.add(part->field->field_name);
|
||||
}
|
||||
|
@@ -3839,9 +3839,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
|
||||
Json_writer_array semijoin_plan(thd, "join_order");
|
||||
for (i= first + sjm->tables; i <= tablenr; i++)
|
||||
{
|
||||
Json_writer_object trace_one_table(thd);
|
||||
if (unlikely(thd->trace_started()))
|
||||
{
|
||||
Json_writer_object trace_one_table(thd);
|
||||
trace_one_table.add_table_name(join->best_positions[i].table);
|
||||
}
|
||||
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");
|
||||
for (idx= first; idx <= tablenr; idx++)
|
||||
{
|
||||
Json_writer_object trace_one_table(thd);
|
||||
if (unlikely(thd->trace_started()))
|
||||
{
|
||||
Json_writer_object trace_one_table(thd);
|
||||
trace_one_table.add_table_name(join->best_positions[idx].table);
|
||||
}
|
||||
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");
|
||||
for (idx= first; idx <= tablenr; idx++)
|
||||
{
|
||||
Json_writer_object trace_one_table(thd);
|
||||
if (unlikely(thd->trace_started()))
|
||||
{
|
||||
Json_writer_object trace_one_table(thd);
|
||||
trace_one_table.add_table_name(join->best_positions[idx].table);
|
||||
}
|
||||
if (join->best_positions[idx].use_join_buffer || (idx == first))
|
||||
|
@@ -1048,6 +1048,15 @@ st_select_lex_unit *With_element::clone_parsed_spec(LEX *old_lex,
|
||||
lex_start(thd);
|
||||
lex->clone_spec_offset= unparsed_spec_offset;
|
||||
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.
|
||||
@@ -1092,6 +1101,29 @@ st_select_lex_unit *With_element::clone_parsed_spec(LEX *old_lex,
|
||||
if (parse_status)
|
||||
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
|
||||
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->sroutines_list_own_last= lex->sroutines_list_own_last;
|
||||
old_lex->sroutines_list_own_elements= lex->sroutines_list_own_elements;
|
||||
res= &lex->unit;
|
||||
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;
|
||||
while (last_clone_select->next_select_in_list())
|
||||
last_clone_select= last_clone_select->next_select_in_list();
|
||||
|
@@ -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
|
||||
exclusive lock is required for duration of the whole statement.
|
||||
*/
|
||||
if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
|
||||
((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
|
||||
if (!ha_alter_info->mdl_exclusive_after_prepare &&
|
||||
(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_NOCOPY_NO_LOCK ||
|
||||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
|
||||
inplace_supported == HA_ALTER_INPLACE_INSTANT) &&
|
||||
(thd->locked_tables_mode == LTM_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))
|
||||
goto cleanup;
|
||||
|
@@ -95,7 +95,6 @@ SET(INNOBASE_SOURCES
|
||||
include/buf0dblwr.h
|
||||
include/buf0dump.h
|
||||
include/buf0flu.h
|
||||
include/buf0flu.ic
|
||||
include/buf0lru.h
|
||||
include/buf0rea.h
|
||||
include/buf0types.h
|
||||
|
@@ -403,7 +403,7 @@ btr_page_create(
|
||||
{
|
||||
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
|
||||
byte *index_id= my_assume_aligned<2>(PAGE_HEADER + PAGE_INDEX_ID +
|
||||
block->frame);
|
||||
block->page.frame);
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip))
|
||||
{
|
||||
@@ -417,16 +417,17 @@ btr_page_create(
|
||||
{
|
||||
static_assert(((FIL_PAGE_INDEX & 0xff00) | byte(FIL_PAGE_RTREE)) ==
|
||||
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));
|
||||
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);
|
||||
}
|
||||
/* Set the level of the new index page */
|
||||
mtr->write<2,mtr_t::MAYBE_NOP>(*block,
|
||||
my_assume_aligned<2>(PAGE_HEADER +
|
||||
PAGE_LEVEL +
|
||||
block->frame), level);
|
||||
block->page.frame),
|
||||
level);
|
||||
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
|
||||
+ PAGE_BTR_IBUF_FREE_LIST
|
||||
+ root->frame);
|
||||
+ root->page.frame);
|
||||
ut_a(node_addr.page != FIL_NULL);
|
||||
|
||||
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
|
||||
if (block->index && !block->index->freed()) {
|
||||
ut_ad(!blob);
|
||||
ut_ad(page_is_leaf(block->frame));
|
||||
ut_ad(page_is_leaf(block->page.frame));
|
||||
}
|
||||
#endif
|
||||
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
|
||||
mini-transaction should not matter. */
|
||||
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_TOP];
|
||||
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);
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_root_fseg_validate(PAGE_HEADER + PAGE_BTR_SEG_TOP + block->frame,
|
||||
block->page.id().space()));
|
||||
ut_a(btr_root_fseg_validate(PAGE_HEADER + PAGE_BTR_SEG_TOP +
|
||||
block->page.frame,
|
||||
block->page.id().space()));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
/* Free the entire segment in small steps. */
|
||||
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))
|
||||
@@ -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);
|
||||
|
||||
if (!block);
|
||||
else if (block->page.status == buf_page_t::FREED)
|
||||
else if (block->page.is_freed())
|
||||
block= nullptr;
|
||||
else if (fil_page_index_page_check(block->frame) &&
|
||||
index_id == btr_page_get_index_id(block->frame))
|
||||
else if (fil_page_index_page_check(block->page.frame) &&
|
||||
index_id == btr_page_get_index_id(block->page.frame))
|
||||
/* This should be a root page. It should not be possible to
|
||||
reassign the same index_id for some other index in the
|
||||
tablespace. */
|
||||
ut_ad(!page_has_siblings(block->frame));
|
||||
ut_ad(!page_has_siblings(block->page.frame));
|
||||
else
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
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)) ==
|
||||
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));
|
||||
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);
|
||||
}
|
||||
/* Set the level of the new index page */
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -982,7 +986,7 @@ btr_create(
|
||||
allowed size fit on the root page: this fact is needed to ensure
|
||||
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);
|
||||
|
||||
return(block->page.id().page_no());
|
||||
@@ -1004,15 +1008,15 @@ btr_free_but_not_root(
|
||||
{
|
||||
mtr_t mtr;
|
||||
|
||||
ut_ad(fil_page_index_page_check(block->frame));
|
||||
ut_ad(!page_has_siblings(block->frame));
|
||||
ut_ad(fil_page_index_page_check(block->page.frame));
|
||||
ut_ad(!page_has_siblings(block->page.frame));
|
||||
leaf_loop:
|
||||
mtr_start(&mtr);
|
||||
ut_d(mtr.freeing_tree());
|
||||
mtr_set_log_mode(&mtr, log_mode);
|
||||
mtr.set_named_space_id(block->page.id().space());
|
||||
|
||||
page_t* root = block->frame;
|
||||
page_t* root = block->page.frame;
|
||||
|
||||
if (!root) {
|
||||
mtr_commit(&mtr);
|
||||
@@ -1046,7 +1050,7 @@ top_loop:
|
||||
mtr_set_log_mode(&mtr, log_mode);
|
||||
mtr.set_named_space_id(block->page.id().space());
|
||||
|
||||
root = block->frame;
|
||||
root = block->page.frame;
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
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),
|
||||
index->table->space->zip_size(),
|
||||
RW_S_LATCH, &mtr)) {
|
||||
autoinc = page_get_autoinc(block->frame);
|
||||
autoinc = page_get_autoinc(block->page.frame);
|
||||
} else {
|
||||
autoinc = 0;
|
||||
}
|
||||
@@ -1197,9 +1201,10 @@ btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no)
|
||||
index->table->space->zip_size(),
|
||||
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
|
||||
&& !page_is_empty(block->frame);
|
||||
&& !page_is_empty(block->page.frame);
|
||||
mtr.commit();
|
||||
|
||||
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(!is_buf_block_get_page_zip(block));
|
||||
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 ||
|
||||
block->page.id().space() == index->table->space->id);
|
||||
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();
|
||||
/* 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);
|
||||
|
||||
@@ -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());
|
||||
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)) ==
|
||||
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;
|
||||
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);
|
||||
|
||||
/* Copy the PAGE_MAX_TRX_ID or PAGE_ROOT_AUTO_INC. */
|
||||
ut_ad(!page_get_max_trx_id(block->frame));
|
||||
memcpy_aligned<8>(PAGE_MAX_TRX_ID + PAGE_HEADER + block->frame,
|
||||
PAGE_MAX_TRX_ID + PAGE_HEADER + old->frame, 8);
|
||||
ut_ad(!page_get_max_trx_id(block->page.frame));
|
||||
memcpy_aligned<8>(PAGE_MAX_TRX_ID + PAGE_HEADER + block->page.frame,
|
||||
PAGE_MAX_TRX_ID + PAGE_HEADER + old->page.frame, 8);
|
||||
#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
|
||||
clustered index root pages. */
|
||||
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);
|
||||
else
|
||||
/* 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
|
||||
page_create(). PAGE_MAX_TRX_ID must be nonzero on
|
||||
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));
|
||||
#endif
|
||||
|
||||
const uint16_t data_size1= page_get_data_size(old->frame);
|
||||
const uint16_t data_size2= page_get_data_size(block->frame);
|
||||
const ulint max1= page_get_max_insert_size_after_reorganize(old->frame, 1);
|
||||
const ulint max2= page_get_max_insert_size_after_reorganize(block->frame, 1);
|
||||
const uint16_t data_size1= page_get_data_size(old->page.frame);
|
||||
const uint16_t data_size2= page_get_data_size(block->page.frame);
|
||||
const ulint max1=
|
||||
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))
|
||||
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. */
|
||||
if (pos)
|
||||
cursor->rec = page_rec_get_nth(block->frame, pos);
|
||||
cursor->rec = page_rec_get_nth(block->page.frame, pos);
|
||||
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 &&
|
||||
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. */
|
||||
ut_ad(index->is_instant());
|
||||
memcpy_aligned<2>(FIL_PAGE_TYPE + block->frame,
|
||||
FIL_PAGE_TYPE + old->frame, 2);
|
||||
memcpy_aligned<2>(PAGE_HEADER + PAGE_INSTANT + block->frame,
|
||||
PAGE_HEADER + PAGE_INSTANT + old->frame, 2);
|
||||
memcpy_aligned<2>(FIL_PAGE_TYPE + block->page.frame,
|
||||
FIL_PAGE_TYPE + old->page.frame, 2);
|
||||
memcpy_aligned<2>(PAGE_HEADER + PAGE_INSTANT + block->page.frame,
|
||||
PAGE_HEADER + PAGE_INSTANT + old->page.frame, 2);
|
||||
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,
|
||||
PAGE_NEW_INFIMUM + old->frame, 8);
|
||||
memcpy(PAGE_NEW_SUPREMUM + block->frame,
|
||||
PAGE_NEW_SUPREMUM + old->frame, 8);
|
||||
memcpy(PAGE_NEW_INFIMUM + block->page.frame,
|
||||
PAGE_NEW_INFIMUM + old->page.frame, 8);
|
||||
memcpy(PAGE_NEW_SUPREMUM + block->page.frame,
|
||||
PAGE_NEW_SUPREMUM + old->page.frame, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(PAGE_OLD_INFIMUM + block->frame,
|
||||
PAGE_OLD_INFIMUM + old->frame, 8);
|
||||
memcpy(PAGE_OLD_SUPREMUM + block->frame,
|
||||
PAGE_OLD_SUPREMUM + old->frame, 8);
|
||||
memcpy(PAGE_OLD_INFIMUM + block->page.frame,
|
||||
PAGE_OLD_INFIMUM + old->page.frame, 8);
|
||||
memcpy(PAGE_OLD_SUPREMUM + block->page.frame,
|
||||
PAGE_OLD_SUPREMUM + old->page.frame, 8);
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(!memcmp(old->frame, block->frame, PAGE_HEADER));
|
||||
ut_ad(!memcmp(old->frame + PAGE_MAX_TRX_ID + PAGE_HEADER,
|
||||
block->frame + PAGE_MAX_TRX_ID + PAGE_HEADER,
|
||||
ut_ad(!memcmp(old->page.frame, block->page.frame, PAGE_HEADER));
|
||||
ut_ad(!memcmp(old->page.frame + PAGE_MAX_TRX_ID + PAGE_HEADER,
|
||||
block->page.frame + PAGE_MAX_TRX_ID + PAGE_HEADER,
|
||||
PAGE_DATA - (PAGE_MAX_TRX_ID + PAGE_HEADER)));
|
||||
|
||||
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;
|
||||
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;
|
||||
while (--e, old->frame[e] == block->frame[e]);
|
||||
while (--e, old->page.frame[e] == block->page.frame[e]);
|
||||
e++;
|
||||
ut_ad(a < e);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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 */
|
||||
ut_ad(!memcmp(PAGE_NEW_INFIMUM - REC_N_NEW_EXTRA_BYTES + block->frame,
|
||||
PAGE_NEW_INFIMUM - REC_N_NEW_EXTRA_BYTES + old->frame, 3));
|
||||
ut_ad(!memcmp(PAGE_NEW_INFIMUM - REC_N_NEW_EXTRA_BYTES +
|
||||
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. */
|
||||
a= PAGE_NEW_INFIMUM - 2;
|
||||
e= a + 2;
|
||||
if (block->frame[a] == old->frame[a])
|
||||
if (block->page.frame[a] == old->page.frame[a])
|
||||
a++;
|
||||
if (--e, block->frame[e] != old->frame[e])
|
||||
if (--e, block->page.frame[e] != old->page.frame[e])
|
||||
e++;
|
||||
if (ulint len= e - a)
|
||||
mtr->memcpy(*block, a, len);
|
||||
/* The infimum record itself must not change. */
|
||||
ut_ad(!memcmp(PAGE_NEW_INFIMUM + block->frame,
|
||||
PAGE_NEW_INFIMUM + old->frame, 8));
|
||||
ut_ad(!memcmp(PAGE_NEW_INFIMUM + block->page.frame,
|
||||
PAGE_NEW_INFIMUM + old->page.frame, 8));
|
||||
/* Log any change of the n_owned of the supremum record. */
|
||||
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);
|
||||
/* 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 +
|
||||
REC_N_NEW_EXTRA_BYTES - 1));
|
||||
|
||||
/* Log the differences in the payload. */
|
||||
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;
|
||||
while (--e, old->frame[e] == block->frame[e]);
|
||||
while (--e, old->page.frame[e] == block->page.frame[e]);
|
||||
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);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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,
|
||||
PAGE_OLD_INFIMUM - REC_N_OLD_EXTRA_BYTES + old->frame, 4));
|
||||
ut_ad(!memcmp(PAGE_OLD_INFIMUM - REC_N_OLD_EXTRA_BYTES +
|
||||
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. */
|
||||
a= PAGE_OLD_INFIMUM - 2;
|
||||
e= a + 2;
|
||||
if (block->frame[a] == old->frame[a])
|
||||
if (block->page.frame[a] == old->page.frame[a])
|
||||
a++;
|
||||
if (--e, block->frame[e] != old->frame[e])
|
||||
if (--e, block->page.frame[e] != old->page.frame[e])
|
||||
e++;
|
||||
if (ulint len= e - a)
|
||||
mtr->memcpy(*block, a, len);
|
||||
/* The infimum record itself must not change. */
|
||||
ut_ad(!memcmp(PAGE_OLD_INFIMUM + block->frame,
|
||||
PAGE_OLD_INFIMUM + old->frame, 8));
|
||||
ut_ad(!memcmp(PAGE_OLD_INFIMUM + block->page.frame,
|
||||
PAGE_OLD_INFIMUM + old->page.frame, 8));
|
||||
/* Log any change of the n_owned of the supremum record. */
|
||||
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);
|
||||
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 +
|
||||
REC_N_OLD_EXTRA_BYTES - 1));
|
||||
|
||||
/* Log the differences in the payload. */
|
||||
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;
|
||||
while (--e, old->frame[e] == block->frame[e]);
|
||||
while (--e, old->page.frame[e] == block->page.frame[e]);
|
||||
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);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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. */
|
||||
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. */
|
||||
for (; a < e; a++)
|
||||
{
|
||||
if (old->frame[a] == block->frame[a])
|
||||
if (old->page.frame[a] == block->page.frame[a])
|
||||
continue;
|
||||
while (--e, old->frame[e] == block->frame[e]);
|
||||
while (--e, old->page.frame[e] == block->page.frame[e]);
|
||||
e++;
|
||||
ut_ad(a < e);
|
||||
/* Write log for the changed page directory slots. */
|
||||
@@ -1542,10 +1555,10 @@ btr_page_reorganize(
|
||||
return false;
|
||||
}
|
||||
if (pos) {
|
||||
cursor->rec = page_rec_get_nth(cursor->block->frame, pos);
|
||||
cursor->rec = page_rec_get_nth(cursor->block->page.frame, pos);
|
||||
} else {
|
||||
ut_ad(cursor->rec == page_get_infimum_rec(
|
||||
cursor->block->frame));
|
||||
cursor->block->page.frame));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1570,7 +1583,8 @@ btr_page_empty(
|
||||
ut_ad(!index->is_dummy);
|
||||
ut_ad(index->table->space->id == block->page.id().space());
|
||||
#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 */
|
||||
|
||||
btr_search_drop_page_hash_index(block);
|
||||
@@ -1583,7 +1597,7 @@ btr_page_empty(
|
||||
const ib_uint64_t autoinc
|
||||
= dict_index_is_clust(index)
|
||||
&& index->page == block->page.id().page_no()
|
||||
? page_get_autoinc(block->frame)
|
||||
? page_get_autoinc(block->page.frame)
|
||||
: 0;
|
||||
|
||||
if (page_zip) {
|
||||
@@ -1594,19 +1608,20 @@ btr_page_empty(
|
||||
static_assert(((FIL_PAGE_INDEX & 0xff00)
|
||||
| byte(FIL_PAGE_RTREE))
|
||||
== 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));
|
||||
if (mach_read_from_8(block->frame
|
||||
if (mach_read_from_8(block->page.frame
|
||||
+ FIL_RTREE_SPLIT_SEQ_NUM)) {
|
||||
mtr->memset(block, FIL_RTREE_SPLIT_SEQ_NUM,
|
||||
8, 0);
|
||||
}
|
||||
}
|
||||
mtr->write<2,mtr_t::MAYBE_NOP>(*block, PAGE_HEADER + PAGE_LEVEL
|
||||
+ block->frame, level);
|
||||
+ block->page.frame, level);
|
||||
if (autoinc) {
|
||||
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 < REC_MAX_N_FIELDS);
|
||||
ut_ad(index.is_instant());
|
||||
ut_ad(fil_page_get_type(root->frame) == FIL_PAGE_TYPE_INSTANT
|
||||
|| fil_page_get_type(root->frame) == FIL_PAGE_INDEX);
|
||||
ut_ad(!page_has_siblings(root->frame));
|
||||
ut_ad(fil_page_get_type(root->page.frame) == FIL_PAGE_TYPE_INSTANT
|
||||
|| fil_page_get_type(root->page.frame) == FIL_PAGE_INDEX);
|
||||
ut_ad(!page_has_siblings(root->page.frame));
|
||||
ut_ad(root->page.id().page_no() == index.page);
|
||||
|
||||
rec_t* infimum = page_get_infimum_rec(root->frame);
|
||||
rec_t* supremum = page_get_supremum_rec(root->frame);
|
||||
byte* page_type = root->frame + FIL_PAGE_TYPE;
|
||||
uint16_t i = page_header_get_field(root->frame, PAGE_INSTANT);
|
||||
rec_t* infimum = page_get_infimum_rec(root->page.frame);
|
||||
rec_t* supremum = page_get_supremum_rec(root->page.frame);
|
||||
byte* page_type = root->page.frame + FIL_PAGE_TYPE;
|
||||
uint16_t i = page_header_get_field(root->page.frame, PAGE_INSTANT);
|
||||
|
||||
switch (mach_read_from_2(page_type)) {
|
||||
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)
|
||||
|| memcmp(supremum, "supremum", 8)) {
|
||||
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);
|
||||
/* fall through */
|
||||
case FIL_PAGE_INDEX:
|
||||
ut_ad(!page_is_comp(root->frame)
|
||||
|| !page_get_instant(root->frame));
|
||||
ut_ad(!page_is_comp(root->page.frame)
|
||||
|| !page_get_instant(root->page.frame));
|
||||
ut_ad(!memcmp(infimum, "infimum", 8));
|
||||
ut_ad(!memcmp(supremum, "supremum", 8));
|
||||
mtr->write<2>(*root, page_type, FIL_PAGE_TYPE_INSTANT);
|
||||
ut_ad(i <= PAGE_NO_DIRECTION);
|
||||
i |= static_cast<uint16_t>(index.n_core_fields << 3);
|
||||
mtr->write<2>(*root, PAGE_HEADER + PAGE_INSTANT + root->frame,
|
||||
i);
|
||||
mtr->write<2>(*root, PAGE_HEADER + PAGE_INSTANT
|
||||
+ root->page.frame, i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (index.table->instant) {
|
||||
mtr->memset(root, infimum - root->frame, 8, 0);
|
||||
mtr->memset(root, supremum - root->frame, 7, 0);
|
||||
mtr->memset(root, infimum - root->page.frame, 8, 0);
|
||||
mtr->memset(root, supremum - root->page.frame, 7, 0);
|
||||
mtr->write<1,mtr_t::MAYBE_NOP>(*root, &supremum[7],
|
||||
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());
|
||||
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)
|
||||
{
|
||||
ut_ad(mach_read_from_2(page_type) == FIL_PAGE_TYPE_INSTANT ||
|
||||
mach_read_from_2(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,
|
||||
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);
|
||||
static const byte supremuminfimum[8 + 8] = "supremuminfimum";
|
||||
uint16_t infimum, supremum;
|
||||
if (page_is_comp(root->frame))
|
||||
if (page_is_comp(root->page.frame))
|
||||
{
|
||||
infimum= PAGE_NEW_INFIMUM;
|
||||
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;
|
||||
supremum= PAGE_OLD_SUPREMUM;
|
||||
}
|
||||
ut_ad(!memcmp(&root->frame[infimum], supremuminfimum + 8, 8) ==
|
||||
!memcmp(&root->frame[supremum], supremuminfimum, 8));
|
||||
mtr->memcpy<mtr_t::MAYBE_NOP>(*root, &root->frame[infimum],
|
||||
ut_ad(!memcmp(&root->page.frame[infimum], supremuminfimum + 8, 8) ==
|
||||
!memcmp(&root->page.frame[supremum], supremuminfimum, 8));
|
||||
mtr->memcpy<mtr_t::MAYBE_NOP>(*root, &root->page.frame[infimum],
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1748,12 +1764,12 @@ btr_root_raise_and_insert(
|
||||
|
||||
root = btr_cur_get_block(cursor);
|
||||
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);
|
||||
ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable));
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
ut_a(!root_page_zip || page_zip_validate(root_page_zip, root->frame,
|
||||
index));
|
||||
ut_a(!root_page_zip
|
||||
|| page_zip_validate(root_page_zip, root->page.frame, index));
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
const page_id_t root_id{root->page.id()};
|
||||
|
||||
@@ -1762,9 +1778,9 @@ btr_root_raise_and_insert(
|
||||
ulint space = index->table->space_id;
|
||||
|
||||
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
|
||||
+ root->frame, space));
|
||||
+ root->page.frame, space));
|
||||
}
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
@@ -1792,11 +1808,12 @@ btr_root_raise_and_insert(
|
||||
== page_zip_get_size(root_page_zip));
|
||||
|
||||
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_NULL == 0xffffffff);
|
||||
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);
|
||||
if (UNIV_LIKELY_NULL(new_page_zip)) {
|
||||
memset_aligned<8>(new_page_zip->data + FIL_PAGE_PREV,
|
||||
@@ -1811,17 +1828,17 @@ btr_root_raise_and_insert(
|
||||
|| new_page_zip
|
||||
#endif /* UNIV_ZIP_COPY */
|
||||
|| !page_copy_rec_list_end(new_block, root,
|
||||
page_get_infimum_rec(root->frame),
|
||||
page_get_infimum_rec(root->page.frame),
|
||||
index, mtr)) {
|
||||
ut_a(new_page_zip);
|
||||
|
||||
/* Copy the page byte for byte. */
|
||||
page_zip_copy_recs(new_block,
|
||||
root_page_zip, root->frame, index, mtr);
|
||||
page_zip_copy_recs(new_block, root_page_zip,
|
||||
root->page.frame, index, mtr);
|
||||
|
||||
/* Update the lock table and possible hash index. */
|
||||
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 */
|
||||
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
|
||||
set PAGE_MAX_TRX_ID on all secondary index pages.) */
|
||||
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)) {
|
||||
mtr->memset(root, max_trx_id, 8, 0);
|
||||
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
|
||||
the field PAGE_MAX_TRX_ID for future use. */
|
||||
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)) {
|
||||
mtr->memset(new_block, max_trx_id, 8, 0);
|
||||
if (UNIV_LIKELY_NULL(new_block->page.zip.data)) {
|
||||
@@ -1878,7 +1895,7 @@ btr_root_raise_and_insert(
|
||||
*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();
|
||||
|
||||
/* 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 */
|
||||
btr_page_empty(root, root_page_zip, index, level + 1, mtr);
|
||||
/* 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()) {
|
||||
ut_ad(!root_page_zip);
|
||||
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);
|
||||
|
||||
@@ -2395,12 +2412,12 @@ btr_attach_half_pages(
|
||||
}
|
||||
|
||||
/* Get the level of the split pages */
|
||||
const ulint level = btr_page_get_level(buf_block_get_frame(block));
|
||||
ut_ad(level == btr_page_get_level(buf_block_get_frame(new_block)));
|
||||
const ulint level = btr_page_get_level(block->page.frame);
|
||||
ut_ad(level == btr_page_get_level(new_block->page.frame));
|
||||
|
||||
/* Get the previous and next pages of page */
|
||||
const uint32_t prev_page_no = btr_page_get_prev(block->frame);
|
||||
const uint32_t next_page_no = btr_page_get_next(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->page.frame);
|
||||
|
||||
/* for consistency, both blocks should be locked, before change */
|
||||
if (prev_page_no != FIL_NULL && direction == FSP_DOWN) {
|
||||
@@ -2432,9 +2449,9 @@ btr_attach_half_pages(
|
||||
|
||||
if (prev_block) {
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(prev_block->frame)
|
||||
== page_is_comp(block->frame));
|
||||
ut_a(btr_page_get_next(prev_block->frame)
|
||||
ut_a(page_is_comp(prev_block->page.frame)
|
||||
== page_is_comp(block->page.frame));
|
||||
ut_a(btr_page_get_next(prev_block->page.frame)
|
||||
== block->page.id().page_no());
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
btr_page_set_next(prev_block, lower_block->page.id().page_no(),
|
||||
@@ -2443,9 +2460,9 @@ btr_attach_half_pages(
|
||||
|
||||
if (next_block) {
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(next_block->frame)
|
||||
== page_is_comp(block->frame));
|
||||
ut_a(btr_page_get_prev(next_block->frame)
|
||||
ut_a(page_is_comp(next_block->page.frame)
|
||||
== page_is_comp(block->page.frame));
|
||||
ut_a(btr_page_get_prev(next_block->page.frame)
|
||||
== block->page.id().page_no());
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
btr_page_set_prev(next_block, upper_block->page.id().page_no(),
|
||||
@@ -2454,11 +2471,13 @@ btr_attach_half_pages(
|
||||
|
||||
if (direction == FSP_DOWN) {
|
||||
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);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -2490,10 +2509,10 @@ btr_page_tuple_smaller(
|
||||
page_cur_move_to_next(&pcur);
|
||||
first_rec = page_cur_get_rec(&pcur);
|
||||
|
||||
*offsets = rec_get_offsets(
|
||||
first_rec, cursor->index, *offsets,
|
||||
page_is_leaf(block->frame) ? cursor->index->n_core_fields : 0,
|
||||
n_uniq, heap);
|
||||
*offsets = rec_get_offsets(first_rec, cursor->index, *offsets,
|
||||
page_is_leaf(block->page.frame)
|
||||
? cursor->index->n_core_fields : 0,
|
||||
n_uniq, heap);
|
||||
|
||||
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());
|
||||
/* 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 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),
|
||||
mtr);
|
||||
#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_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));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
@@ -3083,10 +3103,11 @@ dberr_t btr_level_list_remove(const buf_block_t& block,
|
||||
return DB_ERROR;
|
||||
}
|
||||
#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_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));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
@@ -3203,7 +3224,7 @@ btr_lift_page_up(
|
||||
/* Make the father empty */
|
||||
btr_page_empty(father_block, father_page_zip, index, page_level, mtr);
|
||||
/* 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()
|
||||
&& 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. */
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -3272,7 +3294,7 @@ btr_lift_page_up(
|
||||
&& !index->table->is_temporary()) {
|
||||
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));
|
||||
|
||||
return(lift_father_up ? block_orig : father_block);
|
||||
@@ -3448,7 +3470,7 @@ retry:
|
||||
|
||||
offsets2 = rec_get_offsets(
|
||||
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,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
@@ -3627,7 +3649,7 @@ retry:
|
||||
|
||||
offsets2 = rec_get_offsets(
|
||||
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,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
@@ -3747,7 +3769,7 @@ func_exit:
|
||||
ut_ad(nth_rec > 0);
|
||||
btr_cur_position(
|
||||
index,
|
||||
page_rec_get_nth(merge_block->frame, nth_rec),
|
||||
page_rec_get_nth(merge_block->page.frame, nth_rec),
|
||||
merge_block, cursor);
|
||||
}
|
||||
|
||||
@@ -3758,7 +3780,7 @@ func_exit:
|
||||
err_exit:
|
||||
/* We play it safe and reset the free bits. */
|
||||
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)) {
|
||||
|
||||
ibuf_reset_free_bits(merge_block);
|
||||
@@ -3787,8 +3809,9 @@ btr_discard_only_page_on_level(
|
||||
ut_ad(!index->is_dummy);
|
||||
|
||||
/* 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 rec_t* r = page_rec_get_next(page_get_infimum_rec(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->page.frame));
|
||||
ut_ad(rec_is_metadata(r, *index) == index->is_instant());
|
||||
|
||||
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
|
||||
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
|
||||
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);
|
||||
ut_ad(page_is_leaf(buf_block_get_frame(block)));
|
||||
/* 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 (rec) {
|
||||
@@ -3923,15 +3946,15 @@ btr_discard_page(
|
||||
|
||||
/* Decide the page which will inherit the locks */
|
||||
|
||||
const uint32_t left_page_no = btr_page_get_prev(block->frame);
|
||||
const uint32_t right_page_no = btr_page_get_next(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->page.frame);
|
||||
|
||||
ut_d(bool parent_is_different = false);
|
||||
if (left_page_no != FIL_NULL) {
|
||||
merge_block = btr_block_get(*index, left_page_no, RW_X_LATCH,
|
||||
true, mtr);
|
||||
#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());
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
ut_d(parent_is_different =
|
||||
@@ -3944,14 +3967,14 @@ btr_discard_page(
|
||||
merge_block = btr_block_get(*index, right_page_no, RW_X_LATCH,
|
||||
true, mtr);
|
||||
#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());
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
ut_d(parent_is_different = page_rec_is_supremum(
|
||||
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(
|
||||
page_get_infimum_rec(merge_block->frame));
|
||||
page_get_infimum_rec(merge_block->page.frame));
|
||||
ut_ad(page_rec_is_user_rec(node_ptr));
|
||||
/* We have to mark the leftmost node pointer as the
|
||||
predefined minimum record. */
|
||||
@@ -3964,9 +3987,12 @@ btr_discard_page(
|
||||
return;
|
||||
}
|
||||
|
||||
ut_a(page_is_comp(merge_block->frame) == page_is_comp(block->frame));
|
||||
ut_ad(!memcmp_aligned<2>(&merge_block->frame[PAGE_HEADER + PAGE_LEVEL],
|
||||
&block->frame[PAGE_HEADER + PAGE_LEVEL], 2));
|
||||
ut_a(page_is_comp(merge_block->page.frame)
|
||||
== page_is_comp(block->page.frame));
|
||||
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);
|
||||
|
||||
if (dict_index_is_spatial(index)) {
|
||||
@@ -3983,8 +4009,8 @@ btr_discard_page(
|
||||
page_zip_des_t* merge_page_zip
|
||||
= buf_block_get_page_zip(merge_block);
|
||||
ut_a(!merge_page_zip
|
||||
|| page_zip_validate(merge_page_zip, merge_block->frame,
|
||||
index));
|
||||
|| page_zip_validate(merge_page_zip,
|
||||
merge_block->page.frame, index));
|
||||
}
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
|
||||
|
@@ -494,8 +494,8 @@ inline void PageBulk::finishPage()
|
||||
|
||||
inline bool PageBulk::needs_finish() const
|
||||
{
|
||||
ut_ad(page_align(m_cur_rec) == m_block->frame);
|
||||
ut_ad(m_page == m_block->frame);
|
||||
ut_ad(page_align(m_cur_rec) == m_block->page.frame);
|
||||
ut_ad(m_page == m_block->page.frame);
|
||||
if (!m_page[PAGE_HEADER + PAGE_DIRECTION_B])
|
||||
return true;
|
||||
ulint heap_no, n_heap= page_header_get_field(m_page, PAGE_N_HEAP);
|
||||
@@ -839,7 +839,7 @@ PageBulk::release()
|
||||
finish();
|
||||
|
||||
/* 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. */
|
||||
m_modify_clock = buf_block_get_modify_clock(m_block);
|
||||
@@ -873,11 +873,11 @@ PageBulk::latch()
|
||||
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(m_cur_rec > m_page && m_cur_rec < m_heap_top);
|
||||
ut_ad(buf_fix_count);
|
||||
ut_ad(m_cur_rec > m_page);
|
||||
ut_ad(m_cur_rec < m_heap_top);
|
||||
|
||||
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,
|
||||
false, &mtr);
|
||||
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));
|
||||
|
||||
/* Copy last page to root page. */
|
||||
|
@@ -224,6 +224,11 @@ btr_cur_latch_leaves(
|
||||
|
||||
spatial = dict_index_is_spatial(cursor->index) && cursor->rtr_info;
|
||||
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) {
|
||||
case BTR_SEARCH_LEAF:
|
||||
@@ -241,8 +246,8 @@ btr_cur_latch_leaves(
|
||||
true, mtr);
|
||||
latch_leaves.blocks[1] = get_block;
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(get_block->frame)
|
||||
== page_is_comp(block->frame));
|
||||
ut_a(page_is_comp(get_block->page.frame)
|
||||
== page_is_comp(block->page.frame));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
if (spatial) {
|
||||
cursor->rtr_info->tree_blocks[RTR_MAX_LEVELS]
|
||||
@@ -257,7 +262,7 @@ btr_cur_latch_leaves(
|
||||
MTR_MEMO_X_LOCK
|
||||
| MTR_MEMO_SX_LOCK));
|
||||
/* 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) {
|
||||
|
||||
@@ -290,15 +295,8 @@ btr_cur_latch_leaves(
|
||||
latch_leaves.blocks[1] = get_block;
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
/* Sanity check only after both the blocks are latched. */
|
||||
if (latch_leaves.blocks[0] != NULL) {
|
||||
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));
|
||||
ut_a(page_is_comp(get_block->page.frame)
|
||||
== page_is_comp(block->page.frame));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
if (spatial) {
|
||||
@@ -306,7 +304,7 @@ btr_cur_latch_leaves(
|
||||
= 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 (spatial) {
|
||||
@@ -321,9 +319,9 @@ btr_cur_latch_leaves(
|
||||
latch_leaves.blocks[2] = get_block;
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
if (get_block) {
|
||||
ut_a(page_is_comp(get_block->frame)
|
||||
== page_is_comp(block->frame));
|
||||
ut_a(btr_page_get_prev(get_block->frame)
|
||||
ut_a(page_is_comp(get_block->page.frame)
|
||||
== page_is_comp(block->page.frame));
|
||||
ut_a(btr_page_get_prev(get_block->page.frame)
|
||||
== block->page.id().page_no());
|
||||
}
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
@@ -338,10 +336,10 @@ btr_cur_latch_leaves(
|
||||
case BTR_SEARCH_PREV:
|
||||
case BTR_MODIFY_PREV:
|
||||
mode = latch_mode == BTR_SEARCH_PREV ? RW_S_LATCH : RW_X_LATCH;
|
||||
/* latch also left sibling */
|
||||
block->lock.s_lock();
|
||||
left_page_no = btr_page_get_prev(block->frame);
|
||||
block->lock.s_unlock();
|
||||
/* Because we are holding index->lock, no page splits
|
||||
or merges may run concurrently, and we may read
|
||||
FIL_PAGE_PREV from a buffer-fixed, unlatched page. */
|
||||
left_page_no = btr_page_get_prev(block->page.frame);
|
||||
|
||||
if (left_page_no != FIL_NULL) {
|
||||
latch_leaves.savepoints[0] = mtr_set_savepoint(mtr);
|
||||
@@ -351,9 +349,9 @@ btr_cur_latch_leaves(
|
||||
latch_leaves.blocks[0] = get_block;
|
||||
cursor->left_block = get_block;
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(get_block->frame)
|
||||
== page_is_comp(block->frame));
|
||||
ut_a(btr_page_get_next(get_block->frame)
|
||||
ut_a(page_is_comp(get_block->page.frame)
|
||||
== page_is_comp(block->page.frame));
|
||||
ut_a(btr_page_get_next(get_block->page.frame)
|
||||
== block->page.id().page_no());
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
}
|
||||
@@ -364,8 +362,8 @@ btr_cur_latch_leaves(
|
||||
true, mtr);
|
||||
latch_leaves.blocks[1] = get_block;
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(get_block->frame)
|
||||
== page_is_comp(block->frame));
|
||||
ut_a(page_is_comp(get_block->page.frame)
|
||||
== page_is_comp(block->page.frame));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
return(latch_leaves);
|
||||
case BTR_CONT_MODIFY_TREE:
|
||||
@@ -402,13 +400,13 @@ unreadable:
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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());
|
||||
return DB_SUCCESS;
|
||||
}
|
||||
@@ -426,7 +424,7 @@ unreadable:
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -551,20 +549,22 @@ incompatible:
|
||||
page_id_t(space->id,
|
||||
mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)),
|
||||
0, RW_S_LATCH, mtr);
|
||||
if (fil_page_get_type(block->frame) != FIL_PAGE_TYPE_BLOB
|
||||
|| mach_read_from_4(&block->frame[FIL_PAGE_DATA
|
||||
+ BTR_BLOB_HDR_NEXT_PAGE_NO])
|
||||
if (fil_page_get_type(block->page.frame) != FIL_PAGE_TYPE_BLOB
|
||||
|| mach_read_from_4(&block->page.frame
|
||||
[FIL_PAGE_DATA
|
||||
+ BTR_BLOB_HDR_NEXT_PAGE_NO])
|
||||
!= FIL_NULL
|
||||
|| mach_read_from_4(&block->frame[FIL_PAGE_DATA
|
||||
+ BTR_BLOB_HDR_PART_LEN])
|
||||
|| mach_read_from_4(&block->page.frame
|
||||
[FIL_PAGE_DATA
|
||||
+ BTR_BLOB_HDR_PART_LEN])
|
||||
!= len) {
|
||||
goto incompatible;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
* const end = block->frame + srv_page_size
|
||||
* const end = block->page.frame + srv_page_size
|
||||
- BTR_EXTERN_LEN;
|
||||
b < end; ) {
|
||||
if (*b++) {
|
||||
@@ -573,8 +573,8 @@ incompatible:
|
||||
}
|
||||
|
||||
if (index->table->deserialise_columns(
|
||||
&block->frame[FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE],
|
||||
len)) {
|
||||
&block->page.frame
|
||||
[FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE], len)) {
|
||||
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] mtr mini-transaction
|
||||
@return true if success */
|
||||
TRANSACTIONAL_TARGET
|
||||
bool
|
||||
btr_cur_optimistic_latch_leaves(
|
||||
buf_block_t* block,
|
||||
@@ -762,7 +763,8 @@ btr_cur_optimistic_latch_leaves(
|
||||
mtr_t* mtr)
|
||||
{
|
||||
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) {
|
||||
default:
|
||||
@@ -774,14 +776,16 @@ btr_cur_optimistic_latch_leaves(
|
||||
modify_clock, mtr));
|
||||
case BTR_SEARCH_PREV:
|
||||
case BTR_MODIFY_PREV:
|
||||
block->lock.s_lock();
|
||||
if (block->modify_clock != modify_clock) {
|
||||
block->lock.s_unlock();
|
||||
return false;
|
||||
uint32_t curr_page_no, left_page_no;
|
||||
{
|
||||
transactional_shared_lock_guard<block_lock> g{
|
||||
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
|
||||
? RW_S_LATCH : RW_X_LATCH;
|
||||
@@ -797,12 +801,10 @@ btr_cur_optimistic_latch_leaves(
|
||||
|
||||
if (!cursor->left_block) {
|
||||
cursor->index->table->file_unreadable = true;
|
||||
}
|
||||
|
||||
if (cursor->left_block->page.status
|
||||
== buf_page_t::FREED
|
||||
|| btr_page_get_next(cursor->left_block->frame)
|
||||
!= curr_page_no) {
|
||||
} else if (cursor->left_block->page.is_freed()
|
||||
|| btr_page_get_next(
|
||||
cursor->left_block->page.frame)
|
||||
!= curr_page_no) {
|
||||
/* release the left block */
|
||||
btr_leaf_page_release(
|
||||
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 (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
|
||||
entering the function and
|
||||
buf_page_optimistic_get() buffer-fixes
|
||||
@@ -1271,7 +1274,6 @@ btr_cur_search_to_nth_level_func(
|
||||
ulint n_releases = 0;
|
||||
bool detected_same_key_root = false;
|
||||
|
||||
bool retrying_for_search_prev = false;
|
||||
ulint leftmost_from_level = 0;
|
||||
buf_block_t** prev_tree_blocks = NULL;
|
||||
ulint* prev_tree_savepoints = NULL;
|
||||
@@ -1494,9 +1496,6 @@ x_latch_index:
|
||||
default:
|
||||
if (!srv_read_only_mode) {
|
||||
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) {
|
||||
/* BTR_SEARCH_TREE is intended to be used with
|
||||
BTR_ALREADY_S_LATCHED */
|
||||
@@ -1568,7 +1567,7 @@ search_loop:
|
||||
if (height != 0) {
|
||||
/* We are about to fetch the root or a non-leaf page. */
|
||||
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,
|
||||
each pages should be latched before reading. */
|
||||
if (height == ULINT_UNDEFINED
|
||||
@@ -1698,18 +1697,18 @@ retry_page_get:
|
||||
goto retry_page_get;
|
||||
}
|
||||
|
||||
if (retrying_for_search_prev && height != 0) {
|
||||
if (height && prev_tree_blocks) {
|
||||
/* also latch left sibling */
|
||||
uint32_t left_page_no;
|
||||
buf_block_t* get_block;
|
||||
|
||||
ut_ad(rw_latch == RW_NO_LATCH);
|
||||
|
||||
rw_latch = upper_rw_latch;
|
||||
|
||||
block->lock.s_lock();
|
||||
left_page_no = btr_page_get_prev(buf_block_get_frame(block));
|
||||
block->lock.s_unlock();
|
||||
/* Because we are holding index->lock, no page splits
|
||||
or merges may run concurrently, and we may read
|
||||
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) {
|
||||
ut_ad(prev_n_blocks < leftmost_from_level);
|
||||
@@ -1852,7 +1851,7 @@ retry_page_get:
|
||||
}
|
||||
|
||||
/* release upper blocks */
|
||||
if (retrying_for_search_prev) {
|
||||
if (prev_tree_blocks) {
|
||||
ut_ad(!autoinc);
|
||||
for (;
|
||||
prev_n_releases < prev_n_blocks;
|
||||
@@ -2006,14 +2005,14 @@ retry_page_get:
|
||||
}
|
||||
|
||||
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_PREDICATE, cursor->thr);
|
||||
|
||||
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(
|
||||
&index->lock, MTR_MEMO_X_LOCK
|
||||
| MTR_MEMO_SX_LOCK));
|
||||
block->lock.s_lock();
|
||||
block->page.lock.s_lock();
|
||||
add_latch = true;
|
||||
}
|
||||
|
||||
@@ -2119,7 +2118,7 @@ need_opposite_intention:
|
||||
}
|
||||
|
||||
if (add_latch) {
|
||||
block->lock.s_unlock();
|
||||
block->page.lock.s_unlock();
|
||||
}
|
||||
|
||||
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. */
|
||||
if ((latch_mode == BTR_SEARCH_PREV
|
||||
|| latch_mode == BTR_MODIFY_PREV)
|
||||
&& !retrying_for_search_prev) {
|
||||
&& !prev_tree_blocks) {
|
||||
/* block should be latched for consistent
|
||||
btr_page_get_prev() */
|
||||
ut_ad(mtr->memo_contains_flagged(
|
||||
@@ -2258,8 +2257,6 @@ need_opposite_intention:
|
||||
if (height == 0 && leftmost_from_level > 0) {
|
||||
/* should retry to get also prev_page
|
||||
from level==leftmost_from_level. */
|
||||
retrying_for_search_prev = true;
|
||||
|
||||
prev_tree_blocks = static_cast<buf_block_t**>(
|
||||
ut_malloc_nokey(sizeof(buf_block_t*)
|
||||
* leftmost_from_level));
|
||||
@@ -2481,10 +2478,8 @@ func_exit:
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
if (retrying_for_search_prev) {
|
||||
ut_free(prev_tree_blocks);
|
||||
ut_free(prev_tree_savepoints);
|
||||
}
|
||||
ut_free(prev_tree_blocks);
|
||||
ut_free(prev_tree_savepoints);
|
||||
|
||||
if (mbr_adj) {
|
||||
/* 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,
|
||||
const dict_index_t *index)
|
||||
{
|
||||
ut_ad(page_is_leaf(block->frame));
|
||||
ut_ad(page_is_leaf(block->page.frame));
|
||||
|
||||
if (index->is_ibuf())
|
||||
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 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;
|
||||
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);
|
||||
index = cursor->index;
|
||||
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,
|
||||
mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)),
|
||||
0, RW_S_LATCH, &mtr);
|
||||
ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_TYPE_BLOB);
|
||||
ut_ad(mach_read_from_4(&block->frame[FIL_PAGE_DATA
|
||||
+ BTR_BLOB_HDR_NEXT_PAGE_NO])
|
||||
ut_ad(fil_page_get_type(block->page.frame) == FIL_PAGE_TYPE_BLOB);
|
||||
ut_ad(mach_read_from_4(&block->page.frame
|
||||
[FIL_PAGE_DATA + BTR_BLOB_HDR_NEXT_PAGE_NO])
|
||||
== FIL_NULL);
|
||||
ut_ad(mach_read_from_4(&block->frame[FIL_PAGE_DATA
|
||||
+ BTR_BLOB_HDR_PART_LEN])
|
||||
ut_ad(mach_read_from_4(&block->page.frame
|
||||
[FIL_PAGE_DATA + BTR_BLOB_HDR_PART_LEN])
|
||||
== mach_read_from_4(ptr + BTR_EXTERN_LEN + 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();
|
||||
/* Rollback should not increase the number of 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(),
|
||||
mtr);
|
||||
#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());
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
@@ -4910,7 +4905,8 @@ btr_cur_pessimistic_update(
|
||||
MTR_MEMO_SX_LOCK));
|
||||
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
|
||||
#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 */
|
||||
ut_ad(!page_zip || !index->table->is_temporary());
|
||||
/* The insert buffer tree should never be updated in place. */
|
||||
@@ -4943,7 +4939,7 @@ btr_cur_pessimistic_update(
|
||||
if (page_zip
|
||||
&& optim_err != DB_ZIP_OVERFLOW
|
||||
&& !dict_index_is_clust(index)
|
||||
&& page_is_leaf(block->frame)) {
|
||||
&& page_is_leaf(block->page.frame)) {
|
||||
ut_ad(!index->table->is_temporary());
|
||||
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
|
||||
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));
|
||||
|
||||
if ((flags & BTR_NO_UNDO_LOG_FLAG)
|
||||
@@ -5016,7 +5012,7 @@ btr_cur_pessimistic_update(
|
||||
|
||||
if (page_zip_rec_needs_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),
|
||||
block->zip_size())
|
||||
|| (UNIV_UNLIKELY(update->is_alter_metadata())
|
||||
@@ -5032,7 +5028,7 @@ btr_cur_pessimistic_update(
|
||||
BTR_KEEP_IBUF_BITMAP. */
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
ut_a(!page_zip
|
||||
|| page_zip_validate(page_zip, block->frame,
|
||||
|| page_zip_validate(page_zip, block->page.frame,
|
||||
index));
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
index->table->space->release_free_extents(n_reserved);
|
||||
@@ -5040,7 +5036,7 @@ btr_cur_pessimistic_update(
|
||||
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(flags & BTR_KEEP_POS_FLAG);
|
||||
}
|
||||
@@ -5076,8 +5072,9 @@ btr_cur_pessimistic_update(
|
||||
}
|
||||
|
||||
const ulint max_ins_size = page_zip
|
||||
? 0 : page_get_max_insert_size_after_reorganize(block->frame,
|
||||
1);
|
||||
? 0
|
||||
: page_get_max_insert_size_after_reorganize(block->page.frame,
|
||||
1);
|
||||
|
||||
if (UNIV_UNLIKELY(is_metadata)) {
|
||||
ut_ad(new_entry->is_metadata());
|
||||
@@ -5105,7 +5102,8 @@ btr_cur_pessimistic_update(
|
||||
}
|
||||
|
||||
#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 */
|
||||
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);
|
||||
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 (adjust) {
|
||||
@@ -5159,7 +5157,7 @@ btr_cur_pessimistic_update(
|
||||
true, *offsets);
|
||||
}
|
||||
} 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.
|
||||
This is the same block which was skipped by
|
||||
BTR_KEEP_IBUF_BITMAP. */
|
||||
@@ -5174,7 +5172,7 @@ btr_cur_pessimistic_update(
|
||||
|
||||
if (!srv_read_only_mode
|
||||
&& !big_rec_vec
|
||||
&& page_is_leaf(block->frame)
|
||||
&& page_is_leaf(block->page.frame)
|
||||
&& !dict_index_is_online_ddl(index)) {
|
||||
|
||||
mtr_memo_release(mtr, &index->lock,
|
||||
@@ -5199,13 +5197,13 @@ btr_cur_pessimistic_update(
|
||||
BTR_KEEP_IBUF_BITMAP. */
|
||||
if (!dict_index_is_clust(index)
|
||||
&& !index->table->is_temporary()
|
||||
&& page_is_leaf(block->frame)) {
|
||||
&& page_is_leaf(block->page.frame)) {
|
||||
ibuf_reset_free_bits(block);
|
||||
}
|
||||
}
|
||||
|
||||
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(flags & BTR_KEEP_POS_FLAG);
|
||||
|
||||
@@ -5260,8 +5258,8 @@ btr_cur_pessimistic_update(
|
||||
/* The new inserted record owns its possible externally
|
||||
stored fields */
|
||||
#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 */
|
||||
btr_cur_unmark_extern_fields(btr_cur_get_block(cursor), rec,
|
||||
index, *offsets, mtr);
|
||||
@@ -5511,7 +5509,7 @@ btr_cur_optimistic_delete_func(
|
||||
}
|
||||
|
||||
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()
|
||||
&& !rec_is_metadata(rec, *cursor->index))
|
||||
&& !cursor->index->must_avoid_clear_instant_add())) {
|
||||
@@ -5523,7 +5521,7 @@ btr_cur_optimistic_delete_func(
|
||||
table becomes empty, clean up the whole page. */
|
||||
dict_index_t* index = cursor->index;
|
||||
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()
|
||||
|| rec_is_metadata(first_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);
|
||||
|
||||
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_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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -6811,7 +6809,7 @@ struct btr_blob_log_check_t {
|
||||
if (UNIV_UNLIKELY(m_op == BTR_STORE_INSERT_BULK)) {
|
||||
offs = page_offset(*m_rec);
|
||||
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);
|
||||
} else {
|
||||
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(
|
||||
*index, page_no, RW_X_LATCH, false, m_mtr);
|
||||
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;
|
||||
|
||||
buf_block_buf_fix_dec(m_pcur->btr_cur.page_cur.block);
|
||||
m_pcur->btr_cur.page_cur.block->page.unfix();
|
||||
} else {
|
||||
ut_ad(m_pcur->rel_pos == BTR_PCUR_ON);
|
||||
bool ret = btr_pcur_restore_position(
|
||||
@@ -7047,42 +7045,43 @@ btr_store_big_rec_extern_fields(
|
||||
|
||||
if (page_zip) {
|
||||
mtr.write<4>(*prev_block,
|
||||
prev_block->frame
|
||||
prev_block->page.frame
|
||||
+ FIL_PAGE_NEXT,
|
||||
page_no);
|
||||
memcpy_aligned<4>(
|
||||
buf_block_get_page_zip(
|
||||
prev_block)
|
||||
->data + FIL_PAGE_NEXT,
|
||||
prev_block->frame
|
||||
prev_block->page.frame
|
||||
+ FIL_PAGE_NEXT, 4);
|
||||
} else {
|
||||
mtr.write<4>(*prev_block,
|
||||
BTR_BLOB_HDR_NEXT_PAGE_NO
|
||||
+ FIL_PAGE_DATA
|
||||
+ prev_block->frame,
|
||||
+ prev_block->page.frame,
|
||||
page_no);
|
||||
}
|
||||
} else if (dict_index_is_online_ddl(index)) {
|
||||
row_log_table_blob_alloc(index, page_no);
|
||||
}
|
||||
|
||||
ut_ad(!page_has_siblings(block->frame));
|
||||
ut_ad(!fil_page_get_type(block->frame));
|
||||
ut_ad(!page_has_siblings(block->page.frame));
|
||||
ut_ad(!fil_page_get_type(block->page.frame));
|
||||
|
||||
if (page_zip) {
|
||||
int err;
|
||||
page_zip_des_t* blob_page_zip;
|
||||
|
||||
mtr.write<1>(*block,
|
||||
FIL_PAGE_TYPE + 1 + block->frame,
|
||||
FIL_PAGE_TYPE + 1
|
||||
+ block->page.frame,
|
||||
prev_page_no == FIL_NULL
|
||||
? FIL_PAGE_TYPE_ZBLOB
|
||||
: FIL_PAGE_TYPE_ZBLOB2);
|
||||
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;
|
||||
c_stream.avail_out = static_cast<uInt>(
|
||||
payload_size_zip);
|
||||
@@ -7104,7 +7103,7 @@ btr_store_big_rec_extern_fields(
|
||||
ut_ad(blob_page_zip);
|
||||
ut_ad(page_zip_get_size(blob_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));
|
||||
|
||||
if (err == Z_OK && prev_page_no != FIL_NULL) {
|
||||
@@ -7157,7 +7156,7 @@ next_zip_page:
|
||||
}
|
||||
} else {
|
||||
mtr.write<1>(*block, FIL_PAGE_TYPE + 1
|
||||
+ block->frame,
|
||||
+ block->page.frame,
|
||||
FIL_PAGE_TYPE_BLOB);
|
||||
|
||||
if (extern_len > payload_size) {
|
||||
@@ -7169,13 +7168,14 @@ next_zip_page:
|
||||
mtr.memcpy<mtr_t::MAYBE_NOP>(
|
||||
*block,
|
||||
FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE
|
||||
+ block->frame,
|
||||
+ block->page.frame,
|
||||
static_cast<const byte*>
|
||||
(big_rec_vec->fields[i].data)
|
||||
+ big_rec_vec->fields[i].len
|
||||
- extern_len, store_len);
|
||||
mtr.write<4>(*block, BTR_BLOB_HDR_PART_LEN
|
||||
+ FIL_PAGE_DATA + block->frame,
|
||||
+ FIL_PAGE_DATA
|
||||
+ block->page.frame,
|
||||
store_len);
|
||||
compile_time_assert(FIL_NULL == 0xffffffff);
|
||||
mtr.memset(block, BTR_BLOB_HDR_NEXT_PAGE_NO
|
||||
@@ -7259,7 +7259,7 @@ func_exit:
|
||||
@param[in] read true=read, false=purge */
|
||||
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))
|
||||
return;
|
||||
@@ -7710,11 +7710,13 @@ inflate_error:
|
||||
}
|
||||
|
||||
end_of_blob:
|
||||
buf_page_release_zip(bpage);
|
||||
bpage->lock.s_unlock();
|
||||
bpage->unfix();
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
buf_page_release_zip(bpage);
|
||||
bpage->lock.s_unlock();
|
||||
bpage->unfix();
|
||||
|
||||
/* On other BLOB pages except the first
|
||||
the BLOB header always is at the page header: */
|
||||
|
@@ -476,7 +476,7 @@ btr_defragment_n_pages(
|
||||
/* It doesn't make sense to call this function with n_pages = 1. */
|
||||
ut_ad(n_pages > 1);
|
||||
|
||||
if (!page_is_leaf(block->frame)) {
|
||||
if (!page_is_leaf(block->page.frame)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@@ -112,8 +112,9 @@ btr_pcur_store_position(
|
||||
page_cursor = btr_pcur_get_page_cur(cursor);
|
||||
|
||||
rec = page_cur_get_rec(page_cursor);
|
||||
offs = rec - block->frame;
|
||||
ut_ad(block->page.id().page_no() == page_get_page_no(block->frame));
|
||||
offs = rec - block->page.frame;
|
||||
ut_ad(block->page.id().page_no()
|
||||
== page_get_page_no(block->page.frame));
|
||||
ut_ad(block->page.buf_fix_count());
|
||||
/* For spatial index, when we do positioning on parent
|
||||
buffer if necessary, it might not hold latches, but the
|
||||
@@ -126,13 +127,13 @@ btr_pcur_store_position(
|
||||
|
||||
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
|
||||
we do not store the modify_clock, but always do a search
|
||||
if we restore the cursor position */
|
||||
|
||||
ut_a(!page_has_siblings(block->frame));
|
||||
ut_ad(page_is_leaf(block->frame));
|
||||
ut_a(!page_has_siblings(block->page.frame));
|
||||
ut_ad(page_is_leaf(block->page.frame));
|
||||
ut_ad(block->page.id().page_no() == index->page);
|
||||
|
||||
if (page_rec_is_supremum_low(offs)) {
|
||||
@@ -159,9 +160,9 @@ before_first:
|
||||
#endif
|
||||
ut_ad(index->is_instant()
|
||||
|| block->page.id().page_no() != index->page);
|
||||
ut_ad(page_get_n_recs(block->frame) == 1);
|
||||
ut_ad(page_is_leaf(block->frame));
|
||||
ut_ad(!page_has_prev(block->frame));
|
||||
ut_ad(page_get_n_recs(block->page.frame) == 1);
|
||||
ut_ad(page_is_leaf(block->page.frame));
|
||||
ut_ad(!page_has_prev(block->page.frame));
|
||||
cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
|
||||
return;
|
||||
}
|
||||
@@ -171,7 +172,7 @@ before_first:
|
||||
rec = page_rec_get_next(rec);
|
||||
|
||||
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);
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
goto before_first;
|
||||
|
@@ -409,14 +409,10 @@ static
|
||||
bool
|
||||
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;
|
||||
ut_d(auto state= block->page.state());
|
||||
ut_ad(state == BUF_BLOCK_NOT_USED
|
||||
|| state == BUF_BLOCK_FILE_PAGE
|
||||
|| state == BUF_BLOCK_MEMORY
|
||||
|| state == BUF_BLOCK_REMOVE_HASH);
|
||||
ut_ad(buf_pool.is_uncompressed(block));
|
||||
ut_ad(info->magic_n == BTR_SEARCH_MAGIC_N);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
&& (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) {
|
||||
|
||||
if ((!block->index)
|
||||
|| (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_bytes != block->curr_n_bytes)
|
||||
|| (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)
|
||||
{
|
||||
#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 */
|
||||
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
|
||||
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(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);
|
||||
#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);
|
||||
#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)
|
||||
{
|
||||
#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 */
|
||||
|
||||
if (!btr_search_enabled)
|
||||
@@ -697,9 +693,9 @@ btr_search_update_hash_ref(
|
||||
{
|
||||
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
|
||||
|
||||
ut_ad(block->lock.have_x() || block->lock.have_s());
|
||||
ut_ad(page_align(btr_cur_get_rec(cursor)) == block->frame);
|
||||
ut_ad(page_is_leaf(block->frame));
|
||||
ut_ad(block->page.lock.have_x() || block->page.lock.have_s());
|
||||
ut_ad(page_align(btr_cur_get_rec(cursor)) == block->page.frame);
|
||||
ut_ad(page_is_leaf(block->page.frame));
|
||||
assert_block_ahi_valid(block);
|
||||
|
||||
dict_index_t* index = block->index;
|
||||
@@ -935,15 +931,15 @@ inline void buf_pool_t::clear_hash_index()
|
||||
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
|
||||
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
|
||||
here, because in that case we would have !block->index.
|
||||
|
||||
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
|
||||
block->n_pointers= 0;
|
||||
# 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
|
||||
: (--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);
|
||||
|
||||
buf_block_t *block= &chunk->blocks[offs];
|
||||
/* buf_pool_t::chunk_t::init() invokes buf_block_init() so that
|
||||
block[n].frame == block->frame + n * srv_page_size. Check it. */
|
||||
ut_ad(block->frame == page_align(ptr));
|
||||
block[n].frame == block->page.frame + n * srv_page_size. Check it. */
|
||||
ut_ad(block->page.frame == page_align(ptr));
|
||||
/* Read the state of the block without holding hash_lock.
|
||||
A state transition from BUF_BLOCK_FILE_PAGE to
|
||||
BUF_BLOCK_REMOVE_HASH is possible during this execution. */
|
||||
ut_d(const buf_page_state state = block->page.state());
|
||||
ut_ad(state == BUF_BLOCK_FILE_PAGE || state == BUF_BLOCK_REMOVE_HASH);
|
||||
A state transition to REMOVE_HASH is possible during
|
||||
this execution. */
|
||||
ut_ad(block->page.state() >= buf_page_t::REMOVE_HASH);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
@@ -1093,48 +1090,47 @@ fail:
|
||||
if (!ahi_latch) {
|
||||
buf_pool_t::hash_chain& chain = buf_pool.page_hash.cell_get(
|
||||
block->page.id().fold());
|
||||
bool fail;
|
||||
bool fail, got_latch;
|
||||
{
|
||||
transactional_shared_lock_guard<page_hash_latch> g{
|
||||
buf_pool.page_hash.lock_get(chain)};
|
||||
|
||||
switch (block->page.state()) {
|
||||
case BUF_BLOCK_REMOVE_HASH:
|
||||
const auto state = block->page.state();
|
||||
if (state == buf_page_t::REMOVE_HASH) {
|
||||
/* Another thread is just freeing the block
|
||||
from the LRU list of the buffer pool: do not
|
||||
try to access this page. */
|
||||
goto fail;
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
break;
|
||||
default:
|
||||
}
|
||||
if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED)) {
|
||||
#ifndef NO_ELISION
|
||||
xend();
|
||||
#endif
|
||||
ut_error;
|
||||
}
|
||||
|
||||
block->fix();
|
||||
fail = index != block->index
|
||||
&& 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());
|
||||
block->page.set_accessed();
|
||||
if (!got_latch) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
block->page.fix();
|
||||
block->page.set_accessed();
|
||||
buf_page_make_young_if_needed(&block->page);
|
||||
mtr_memo_type_t fix_type;
|
||||
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;
|
||||
ut_ad(!block->page.is_read_fixed());
|
||||
} else {
|
||||
if (!block->lock.x_lock_try()) {
|
||||
goto got_no_latch;
|
||||
}
|
||||
fix_type = MTR_MEMO_PAGE_X_FIX;
|
||||
ut_ad(!block->page.is_io_fixed());
|
||||
}
|
||||
mtr->memo_push(block, fix_type);
|
||||
|
||||
@@ -1146,16 +1142,15 @@ got_no_latch:
|
||||
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
|
||||
&& index_id == block->index->id)) {
|
||||
ut_a(block->index->freed());
|
||||
goto fail_and_release_page;
|
||||
}
|
||||
|
||||
if (block->page.state() != BUF_BLOCK_FILE_PAGE) {
|
||||
|
||||
ut_ad(block->page.state() == BUF_BLOCK_REMOVE_HASH);
|
||||
if (!block->page.in_file()) {
|
||||
ut_ad(block->page.state() == buf_page_t::REMOVE_HASH);
|
||||
|
||||
fail_and_release_page:
|
||||
if (!ahi_latch) {
|
||||
@@ -1177,7 +1172,7 @@ fail_and_release_page:
|
||||
is positioned on. We cannot look at the next of the previous
|
||||
record to determine if our guess for the cursor position is
|
||||
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)) {
|
||||
goto fail_and_release_page;
|
||||
}
|
||||
@@ -1268,17 +1263,21 @@ retry:
|
||||
return;
|
||||
}
|
||||
|
||||
ut_ad(!block->page.buf_fix_count()
|
||||
|| block->page.state() == BUF_BLOCK_REMOVE_HASH
|
||||
|| block->lock.have_any());
|
||||
ut_ad(page_is_leaf(block->frame));
|
||||
ut_d(const auto state = block->page.state());
|
||||
ut_ad(state == buf_page_t::REMOVE_HASH
|
||||
|| state >= buf_page_t::UNFIXED);
|
||||
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
|
||||
if (!index->table->get_ref_count() && !dict_sys.frozen()).
|
||||
Determine the ahi_slot based on the block contents. */
|
||||
|
||||
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,
|
||||
block->page.id().space());
|
||||
@@ -1322,7 +1321,7 @@ retry:
|
||||
|
||||
ut_a(n_fields > 0 || n_bytes > 0);
|
||||
|
||||
page = block->frame;
|
||||
page = block->page.frame;
|
||||
n_recs = page_get_n_recs(page);
|
||||
|
||||
/* 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 AHI is still valid, page can't be in free state.
|
||||
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) {
|
||||
/* In all our callers, the table handle should
|
||||
@@ -1499,9 +1498,9 @@ btr_search_build_page_hash_index(
|
||||
ut_ad(index);
|
||||
ut_ad(block->page.id().space() == index->table->space_id);
|
||||
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);
|
||||
|
||||
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* block)
|
||||
{
|
||||
ut_ad(block->lock.have_x());
|
||||
ut_ad(new_block->lock.have_x());
|
||||
ut_ad(block->page.lock.have_x());
|
||||
ut_ad(new_block->page.lock.have_x());
|
||||
|
||||
if (!btr_search_enabled) {
|
||||
return;
|
||||
@@ -1804,7 +1803,7 @@ void btr_search_update_hash_on_delete(btr_cur_t *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);
|
||||
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);
|
||||
|
||||
ut_ad(block->lock.have_x());
|
||||
ut_ad(block->page.lock.have_x());
|
||||
|
||||
index = block->index;
|
||||
|
||||
@@ -1962,7 +1961,7 @@ void btr_search_update_hash_on_insert(btr_cur_t *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);
|
||||
|
||||
index = block->index;
|
||||
@@ -2210,9 +2209,7 @@ btr_search_hash_table_validate(ulint hash_table_id)
|
||||
= buf_pool.block_from_ahi((byte*) node->data);
|
||||
index_id_t page_index_id;
|
||||
|
||||
if (UNIV_LIKELY(block->page.state()
|
||||
== BUF_BLOCK_FILE_PAGE)) {
|
||||
|
||||
if (UNIV_LIKELY(block->page.in_file())) {
|
||||
/* The space and offset are only valid
|
||||
for file blocks. It is possible that
|
||||
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
|
||||
buf_LRU_block_remove_hashed_page(). Then it
|
||||
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:
|
||||
ut_ad(!dict_index_is_ibuf(block->index));
|
||||
ut_ad(block->page.id().space()
|
||||
== 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(
|
||||
node->data, block->index, offsets,
|
||||
@@ -2255,8 +2254,6 @@ state_ok:
|
||||
page_index_id);
|
||||
|
||||
if (node->fold != fold) {
|
||||
const page_t* page = block->frame;
|
||||
|
||||
ok = FALSE;
|
||||
|
||||
ib::error() << "Error in an adaptive hash"
|
||||
|
@@ -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
|
||||
by another hash_lock that we are not holding.)
|
||||
|
||||
Finally, assuming that we have correct hash bucket latched, we must
|
||||
validate m_block->state() to ensure that the block is not being freed. */
|
||||
Finally, we must ensure that the block is not being freed. */
|
||||
if (m_block)
|
||||
{
|
||||
auto &cell= buf_pool.page_hash.cell_get(m_page_id.fold());
|
||||
transactional_shared_lock_guard<page_hash_latch> g
|
||||
{buf_pool.page_hash.lock_get(cell)};
|
||||
if (buf_pool.is_uncompressed(m_block) && m_page_id == m_block->page.id() &&
|
||||
m_block->page.state() == BUF_BLOCK_FILE_PAGE)
|
||||
m_block->fix();
|
||||
m_block->page.frame && m_block->page.in_file())
|
||||
m_block->page.fix();
|
||||
else
|
||||
clear();
|
||||
}
|
||||
|
@@ -354,11 +354,11 @@ buf_buddy_block_free(void* buf)
|
||||
ut_a(!ut_align_offset(buf, srv_page_size));
|
||||
|
||||
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),
|
||||
((buf_block_t*) bpage)->frame == buf);
|
||||
bpage->frame == buf);
|
||||
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_d(bpage->in_zip_hash = false);
|
||||
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 */
|
||||
{
|
||||
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(!ut_align_offset(block->frame, srv_page_size));
|
||||
ut_a(block->page.frame);
|
||||
ut_a(!ut_align_offset(block->page.frame, srv_page_size));
|
||||
|
||||
ut_ad(!block->page.in_zip_hash);
|
||||
ut_d(block->page.in_zip_hash = true);
|
||||
@@ -462,8 +462,8 @@ byte *buf_buddy_alloc_low(ulint i, bool *lru)
|
||||
alloc_big:
|
||||
buf_buddy_block_register(block);
|
||||
|
||||
block = (buf_block_t*) buf_buddy_alloc_from(
|
||||
block->frame, i, BUF_BUDDY_SIZES);
|
||||
block = reinterpret_cast<buf_block_t*>(
|
||||
buf_buddy_alloc_from(block->page.frame, i, BUF_BUDDY_SIZES));
|
||||
|
||||
func_exit:
|
||||
buf_pool.buddy_stat[i].used++;
|
||||
@@ -694,7 +694,7 @@ buf_buddy_realloc(void* buf, ulint size)
|
||||
|
||||
block = reinterpret_cast<buf_block_t*>(
|
||||
buf_buddy_alloc_from(
|
||||
block->frame, i, BUF_BUDDY_SIZES));
|
||||
block->page.frame, i, BUF_BUDDY_SIZES));
|
||||
}
|
||||
|
||||
buf_pool.buddy_stat[i].used++;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -86,11 +86,12 @@ start_again:
|
||||
buf_block_t *trx_sys_block= buf_dblwr_trx_sys_get(&mtr);
|
||||
|
||||
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
|
||||
some numbers */
|
||||
init(TRX_SYS_DOUBLEWRITE + trx_sys_block->frame);
|
||||
init(TRX_SYS_DOUBLEWRITE + trx_sys_block->page.frame);
|
||||
mtr.commit();
|
||||
return true;
|
||||
}
|
||||
@@ -121,7 +122,7 @@ too_small:
|
||||
}
|
||||
|
||||
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;
|
||||
i < 2 * size + extent_size / 2; i++)
|
||||
{
|
||||
@@ -149,12 +150,12 @@ too_small:
|
||||
tablespace, then the page has not been written to in
|
||||
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();
|
||||
/* 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
|
||||
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));
|
||||
|
||||
if (i == size / 2)
|
||||
@@ -162,10 +163,10 @@ too_small:
|
||||
ut_a(id.page_no() == size);
|
||||
mtr.write<4>(*trx_sys_block,
|
||||
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,
|
||||
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());
|
||||
}
|
||||
else if (i == size / 2 + size)
|
||||
@@ -173,10 +174,10 @@ too_small:
|
||||
ut_a(id.page_no() == 2 * size);
|
||||
mtr.write<4>(*trx_sys_block,
|
||||
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,
|
||||
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());
|
||||
}
|
||||
else if (i > size / 2)
|
||||
@@ -193,7 +194,7 @@ too_small:
|
||||
mtr.start();
|
||||
trx_sys_block= buf_dblwr_trx_sys_get(&mtr);
|
||||
fseg_header= TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG +
|
||||
trx_sys_block->frame;
|
||||
trx_sys_block->page.frame;
|
||||
}
|
||||
|
||||
prev_page_no= id.page_no();
|
||||
@@ -201,15 +202,16 @@ too_small:
|
||||
|
||||
mtr.write<4>(*trx_sys_block,
|
||||
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,
|
||||
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);
|
||||
|
||||
mtr.write<4>(*trx_sys_block,
|
||||
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();
|
||||
|
||||
/* 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. */
|
||||
static void buf_dblwr_check_block(const buf_page_t *bpage)
|
||||
{
|
||||
ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE);
|
||||
const page_t *page= reinterpret_cast<const buf_block_t*>(bpage)->frame;
|
||||
ut_ad(bpage->in_file());
|
||||
const page_t *page= bpage->frame;
|
||||
ut_ad(page);
|
||||
|
||||
switch (fil_page_get_type(page)) {
|
||||
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));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
const IORequest request(nullptr, fil_system.sys_space->chain.start,
|
||||
IORequest::DBLWR_BATCH);
|
||||
const IORequest request{nullptr, nullptr, fil_system.sys_space->chain.start,
|
||||
IORequest::DBLWR_BATCH};
|
||||
ut_a(fil_system.sys_space->acquire());
|
||||
if (multi_batch)
|
||||
{
|
||||
@@ -614,6 +617,14 @@ bool buf_dblwr_t::flush_buffered_writes(const ulint size)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
ut_ad(bpage->in_file());
|
||||
|
||||
/* We request frame here to get correct buffer in case of
|
||||
encryption and/or page compression */
|
||||
void *frame= buf_page_get_frame(bpage);
|
||||
void *frame= get_frame(e.request);
|
||||
ut_ad(frame);
|
||||
|
||||
auto e_size= e.size;
|
||||
|
||||
@@ -664,7 +674,6 @@ void buf_dblwr_t::flush_buffered_writes_completed(const IORequest &request)
|
||||
}
|
||||
else
|
||||
{
|
||||
ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(!bpage->zip_size());
|
||||
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;
|
||||
|
||||
/* 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,
|
||||
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 */
|
||||
memset_aligned<256>(p + size, 0, srv_page_size - size);
|
||||
/* FIXME: Inform the compiler that "size" and "srv_page_size - size"
|
||||
|
@@ -328,19 +328,18 @@ buf_dump(
|
||||
for (bpage = UT_LIST_GET_FIRST(buf_pool.LRU), j = 0;
|
||||
bpage != NULL && j < n_pages;
|
||||
bpage = UT_LIST_GET_NEXT(LRU, bpage)) {
|
||||
|
||||
ut_a(bpage->in_file());
|
||||
const page_id_t id(bpage->id());
|
||||
const auto status = bpage->state();
|
||||
if (status < buf_page_t::UNFIXED) {
|
||||
ut_a(status >= buf_page_t::FREED);
|
||||
continue;
|
||||
}
|
||||
const page_id_t id{bpage->id()};
|
||||
|
||||
if (id.space() == SRV_TMP_SPACE_ID) {
|
||||
/* Ignore the innodb_temporary tablespace. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bpage->status == buf_page_t::FREED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dump[j++] = id;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
MEM_CHECK_DEFINED(block->page.zip.data
|
||||
? block->page.zip.data : block->frame,
|
||||
? block->page.zip.data : block->page.frame,
|
||||
block->physical_size());
|
||||
UT_LIST_ADD_FIRST(flush_list, &block->page);
|
||||
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; )
|
||||
{
|
||||
ut_d(const auto s= bpage->state());
|
||||
ut_ad(s == BUF_BLOCK_ZIP_PAGE || s == BUF_BLOCK_FILE_PAGE ||
|
||||
s == BUF_BLOCK_REMOVE_HASH);
|
||||
const auto s= bpage->state();
|
||||
ut_ad(s >= buf_page_t::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);
|
||||
|
||||
const page_id_t bpage_id(bpage->id());
|
||||
|
||||
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;
|
||||
else
|
||||
buf_pool.delete_from_flush_list(bpage);
|
||||
@@ -322,42 +322,59 @@ buf_flush_relocate_on_flush_list(
|
||||
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.
|
||||
@param request write request */
|
||||
void buf_page_write_complete(const IORequest &request)
|
||||
{
|
||||
ut_ad(request.is_write());
|
||||
ut_ad(!srv_read_only_mode/* ||
|
||||
request.node->space->purpose == FIL_TYPE_TEMPORARY*/);
|
||||
ut_ad(!srv_read_only_mode);
|
||||
buf_page_t *bpage= request.bpage;
|
||||
ut_ad(bpage);
|
||||
ut_ad(bpage->in_file());
|
||||
/* bpage->io_fix() can only be changed by buf_page_write_complete()
|
||||
and buf_page_read_complete() from BUF_IO_READ or BUF_IO_WRITE */
|
||||
ut_ad(bpage->io_fix() == BUF_IO_WRITE);
|
||||
const auto state= bpage->state();
|
||||
/* io-fix can only be cleared by buf_page_t::write_complete()
|
||||
and buf_page_t::read_complete() */
|
||||
ut_ad(state >= buf_page_t::WRITE_FIX);
|
||||
ut_ad(!buf_dblwr.is_inside(bpage->id()));
|
||||
ut_ad(request.node->space->id == bpage->id().space());
|
||||
|
||||
if (bpage->status == buf_page_t::INIT_ON_FLUSH)
|
||||
bpage->status= buf_page_t::NORMAL;
|
||||
else
|
||||
if (state < buf_page_t::WRITE_FIX_REINIT &&
|
||||
request.node->space->use_doublewrite())
|
||||
{
|
||||
ut_ad(bpage->status == buf_page_t::NORMAL);
|
||||
if (request.node->space->use_doublewrite())
|
||||
{
|
||||
ut_ad(request.node->space != fil_system.temp_space);
|
||||
buf_dblwr.write_completed();
|
||||
}
|
||||
ut_ad(request.node->space != fil_system.temp_space);
|
||||
buf_dblwr.write_completed();
|
||||
}
|
||||
|
||||
if (bpage->slot)
|
||||
{
|
||||
bpage->slot->release();
|
||||
bpage->slot= nullptr;
|
||||
}
|
||||
if (request.slot)
|
||||
request.slot->release();
|
||||
|
||||
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",
|
||||
bpage->id().space(), bpage->id().page_no()));
|
||||
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_assert_not_owner(&buf_pool.flush_list_mutex);
|
||||
buf_pool.stat.n_pages_written++;
|
||||
/* While we do not need any mutex for clearing oldest_modification
|
||||
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);
|
||||
bpage->write_complete(temp);
|
||||
|
||||
if (request.is_LRU())
|
||||
{
|
||||
@@ -437,16 +445,14 @@ buf_flush_init_for_writing(
|
||||
void* page_zip_,
|
||||
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
|
||||
checksum stored already as a part of fil_encrypt_buf() */
|
||||
ut_ad(use_full_checksum);
|
||||
return;
|
||||
}
|
||||
|
||||
ut_ad(block == NULL || block->frame == page);
|
||||
ut_ad(block == NULL || page_zip_ == NULL
|
||||
|| &block->page.zip == page_zip_);
|
||||
ut_ad(!block || block->page.frame == page);
|
||||
ut_ad(page);
|
||||
|
||||
if (page_zip_) {
|
||||
@@ -454,6 +460,7 @@ buf_flush_init_for_writing(
|
||||
ulint size;
|
||||
|
||||
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);
|
||||
|
||||
ut_ad(size);
|
||||
@@ -618,10 +625,11 @@ a page is written to disk.
|
||||
@return page frame to be written to file
|
||||
(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,
|
||||
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(!*slot);
|
||||
|
||||
ut_d(fil_page_type_validate(space, s));
|
||||
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);
|
||||
/* Find free slot from temporary memory array */
|
||||
buf_tmp_buffer_t *slot= buf_pool.io_buf_reserve();
|
||||
ut_a(slot);
|
||||
slot->allocate();
|
||||
slot->out_buf= NULL;
|
||||
bpage->slot= slot;
|
||||
*slot= buf_pool.io_buf_reserve();
|
||||
ut_a(*slot);
|
||||
(*slot)->allocate();
|
||||
|
||||
byte *d= slot->crypt_buf;
|
||||
byte *d= (*slot)->crypt_buf;
|
||||
|
||||
if (!page_compressed)
|
||||
{
|
||||
not_compressed:
|
||||
byte *tmp= space->purpose == FIL_TYPE_TEMPORARY
|
||||
d= space->purpose == FIL_TYPE_TEMPORARY
|
||||
? buf_tmp_page_encrypt(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
|
||||
{
|
||||
ut_ad(space->purpose != FIL_TYPE_TEMPORARY);
|
||||
/* First we compress the page content */
|
||||
buf_tmp_reserve_compression_buf(slot);
|
||||
byte *tmp= slot->comp_buf;
|
||||
buf_tmp_reserve_compression_buf(*slot);
|
||||
byte *tmp= (*slot)->comp_buf;
|
||||
ulint len= fil_page_compress(s, tmp, space->flags,
|
||||
fil_space_get_block_size(space, page_no),
|
||||
encrypted);
|
||||
@@ -729,7 +731,7 @@ not_compressed:
|
||||
ut_d(fil_page_type_validate(space, tmp));
|
||||
|
||||
if (encrypted)
|
||||
tmp = fil_space_encrypt(space, page_no, tmp, d);
|
||||
tmp= fil_space_encrypt(space, page_no, tmp, d);
|
||||
|
||||
if (full_crc32)
|
||||
{
|
||||
@@ -738,26 +740,23 @@ not_compressed:
|
||||
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));
|
||||
(*slot)->out_buf= d;
|
||||
return d;
|
||||
}
|
||||
|
||||
/** Free a page whose underlying file page has been freed. */
|
||||
inline void buf_pool_t::release_freed_page(buf_page_t *bpage)
|
||||
{
|
||||
ut_ad(bpage->in_file());
|
||||
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_assert_owner(&mutex);
|
||||
mysql_mutex_lock(&flush_list_mutex);
|
||||
ut_d(const lsn_t oldest_modification= bpage->oldest_modification();)
|
||||
if (fsp_is_system_temporary(bpage->id().space()))
|
||||
{
|
||||
ut_ad(uncompressed);
|
||||
ut_ad(bpage->frame);
|
||||
ut_ad(oldest_modification == 2);
|
||||
}
|
||||
else
|
||||
@@ -767,166 +766,152 @@ inline void buf_pool_t::release_freed_page(buf_page_t *bpage)
|
||||
}
|
||||
bpage->clear_oldest_modification();
|
||||
mysql_mutex_unlock(&flush_list_mutex);
|
||||
|
||||
if (uncompressed)
|
||||
reinterpret_cast<buf_block_t*>(bpage)->lock.u_unlock(true);
|
||||
bpage->lock.u_unlock(true);
|
||||
|
||||
buf_LRU_free_page(bpage, true);
|
||||
mysql_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
/** Write a flushable page from buf_pool to a file.
|
||||
buf_pool.mutex must be held.
|
||||
@param bpage buffer control block
|
||||
/** 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 */
|
||||
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(bpage->ready_for_flush());
|
||||
ut_ad(in_file());
|
||||
ut_ad(in_LRU_list);
|
||||
ut_ad((space->purpose == FIL_TYPE_TEMPORARY) ==
|
||||
(space == fil_system.temp_space));
|
||||
ut_ad(space->referenced());
|
||||
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)
|
||||
rw_lock= nullptr;
|
||||
else
|
||||
const auto s= state();
|
||||
ut_a(s >= FREED);
|
||||
|
||||
if (s < UNFIXED)
|
||||
{
|
||||
rw_lock= &reinterpret_cast<buf_block_t*>(bpage)->lock;
|
||||
if (!rw_lock->u_lock_try(true))
|
||||
return false;
|
||||
buf_pool.release_freed_page(this);
|
||||
mysql_mutex_unlock(&buf_pool.mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bpage->set_io_fix(BUF_IO_WRITE);
|
||||
/* 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 (s >= READ_FIX || oldest_modification() < 2)
|
||||
{
|
||||
if (lru)
|
||||
buf_pool.n_flush_LRU_++;
|
||||
else
|
||||
buf_pool.n_flush_list_++;
|
||||
buf_flush_page_count++;
|
||||
lock.u_unlock(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex);
|
||||
|
||||
/* We are holding rw_lock = buf_block_t::lock in SX mode except if
|
||||
this is a ROW_FORMAT=COMPRESSED page whose uncompressed page frame
|
||||
has been evicted from the buffer pool.
|
||||
|
||||
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. */
|
||||
/* Apart from the U-lock, this block will also be protected by
|
||||
is_write_fixed() and oldest_modification()>1.
|
||||
Thus, it cannot be relocated or removed. */
|
||||
|
||||
DBUG_PRINT("ib_buf", ("%s %u page %u:%u",
|
||||
lru ? "LRU" : "flush_list",
|
||||
bpage->id().space(), bpage->id().page_no()));
|
||||
ut_ad(bpage->io_fix() == BUF_IO_WRITE);
|
||||
ut_d(const lsn_t oldest_modification= bpage->oldest_modification());
|
||||
id().space(), id().page_no()));
|
||||
ut_d(const auto f=) zip.fix.fetch_add(WRITE_FIX - UNFIXED);
|
||||
ut_ad(f >= UNFIXED);
|
||||
ut_ad(f < READ_FIX);
|
||||
ut_ad(space == fil_system.temp_space
|
||||
? oldest_modification == 2
|
||||
: oldest_modification > 2);
|
||||
ut_ad(bpage->state() ==
|
||||
(rw_lock ? BUF_BLOCK_FILE_PAGE : BUF_BLOCK_ZIP_PAGE));
|
||||
ut_ad(ULINT_UNDEFINED >
|
||||
(lru ? buf_pool.n_flush_LRU_ : buf_pool.n_flush_list_));
|
||||
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);
|
||||
? oldest_modification() == 2
|
||||
: oldest_modification() > 2);
|
||||
if (lru)
|
||||
{
|
||||
ut_ad(buf_pool.n_flush_LRU_ < ULINT_UNDEFINED);
|
||||
buf_pool.n_flush_LRU_++;
|
||||
}
|
||||
else
|
||||
{
|
||||
space->reacquire();
|
||||
ut_ad(status == buf_page_t::NORMAL || status == buf_page_t::INIT_ON_FLUSH);
|
||||
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);
|
||||
ut_ad(buf_pool.n_flush_list_ < ULINT_UNDEFINED);
|
||||
buf_pool.n_flush_list_++;
|
||||
}
|
||||
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. */
|
||||
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,
|
||||
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
|
||||
size, and flushed along with the original page. */
|
||||
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 (!buf_pool.watch_is_sentinel(*bpage) &&
|
||||
bpage->oldest_modification() > 1 &&
|
||||
bpage->ready_for_flush() && buf_flush_page(bpage, lru, space))
|
||||
bpage->oldest_modification() > 1 && bpage->ready_for_flush() &&
|
||||
bpage->flush(lru, space))
|
||||
{
|
||||
++count;
|
||||
continue;
|
||||
@@ -1216,24 +1203,17 @@ static void buf_flush_discard_page(buf_page_t *bpage)
|
||||
ut_ad(bpage->in_file());
|
||||
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);
|
||||
buf_pool.delete_from_flush_list(bpage);
|
||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||
|
||||
if (rw_lock)
|
||||
rw_lock->u_unlock();
|
||||
ut_d(const auto state= bpage->state());
|
||||
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);
|
||||
}
|
||||
@@ -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);
|
||||
const lsn_t oldest_modification= bpage->oldest_modification();
|
||||
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
|
||||
IO-fixed or buffer fixed. */
|
||||
if (state != buf_page_t::FREED &&
|
||||
(state >= buf_page_t::READ_FIX || (~buf_page_t::LRU_MASK & state)))
|
||||
goto must_skip;
|
||||
if (buf_LRU_free_page(bpage, true))
|
||||
++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
|
||||
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:
|
||||
mysql_mutex_lock(&buf_pool.mutex);
|
||||
}
|
||||
else if (buf_flush_page(bpage, true, space))
|
||||
else if (bpage->flush(true, space))
|
||||
{
|
||||
++n->flushed;
|
||||
goto reacquire_mutex;
|
||||
}
|
||||
}
|
||||
else
|
||||
must_skip:
|
||||
/* Can't evict or dispatch this block. Go to previous. */
|
||||
ut_ad(buf_pool.lru_hp.is_hp(prev));
|
||||
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(bpage->in_file());
|
||||
|
||||
if (!bpage->ready_for_flush())
|
||||
goto skip;
|
||||
@@ -1445,7 +1429,7 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn)
|
||||
reacquire_mutex:
|
||||
mysql_mutex_lock(&buf_pool.mutex);
|
||||
}
|
||||
else if (buf_flush_page(bpage, false, space))
|
||||
else if (bpage->flush(false, space))
|
||||
{
|
||||
++count;
|
||||
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; )
|
||||
{
|
||||
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->in_file());
|
||||
|
||||
@@ -1594,7 +1575,7 @@ bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed)
|
||||
acquired= false;
|
||||
goto was_freed;
|
||||
}
|
||||
if (!buf_flush_page(bpage, false, space))
|
||||
if (!bpage->flush(false, space))
|
||||
{
|
||||
may_have_skipped= true;
|
||||
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
|
||||
buf_pool.flush_list_mutex to complete the relocation. */
|
||||
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(s >= buf_page_t::REMOVE_HASH);
|
||||
ut_ad(om == 1 || om > 2);
|
||||
|
||||
bpage = UT_LIST_GET_NEXT(list, bpage);
|
||||
|
@@ -108,7 +108,7 @@ uint buf_LRU_old_threshold_ms;
|
||||
|
||||
/** 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.
|
||||
|
||||
@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
|
||||
|
||||
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
|
||||
@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. */
|
||||
static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id,
|
||||
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) {
|
||||
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->page.in_LRU_list);
|
||||
|
||||
@@ -268,17 +269,6 @@ static bool buf_LRU_free_from_common_LRU_list(ulint limit)
|
||||
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
|
||||
@retval NULL if the free list is empty */
|
||||
buf_block_t* buf_LRU_get_free_only()
|
||||
@@ -306,15 +296,13 @@ buf_block_t* buf_LRU_get_free_only()
|
||||
a free block. */
|
||||
assert_block_ahi_empty(block);
|
||||
|
||||
block->page.set_state(BUF_BLOCK_MEMORY);
|
||||
MEM_MAKE_ADDRESSABLE(block->frame, srv_page_size);
|
||||
block->page.set_state(buf_page_t::MEMORY);
|
||||
MEM_MAKE_ADDRESSABLE(block->page.frame, srv_page_size);
|
||||
break;
|
||||
}
|
||||
|
||||
/* This should be withdrawn */
|
||||
UT_LIST_ADD_LAST(
|
||||
buf_pool.withdraw,
|
||||
&block->page);
|
||||
UT_LIST_ADD_LAST(buf_pool.withdraw, &block->page);
|
||||
ut_d(block->in_withdraw_list = true);
|
||||
|
||||
block = reinterpret_cast<buf_block_t*>(
|
||||
@@ -428,7 +416,7 @@ got_block:
|
||||
if (!have_mutex) {
|
||||
mysql_mutex_unlock(&buf_pool.mutex);
|
||||
}
|
||||
memset(&block->page.zip, 0, sizeof block->page.zip);
|
||||
block->page.zip.clear();
|
||||
return block;
|
||||
}
|
||||
|
||||
@@ -771,6 +759,9 @@ buf_LRU_add_block(
|
||||
/** Move a block to the start of the LRU list. */
|
||||
void buf_page_make_young(buf_page_t *bpage)
|
||||
{
|
||||
if (bpage->is_read_fixed())
|
||||
return;
|
||||
|
||||
ut_ad(bpage->in_file());
|
||||
|
||||
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 */
|
||||
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;
|
||||
|
||||
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. */
|
||||
if (!bpage->can_relocate()) {
|
||||
@@ -839,23 +828,21 @@ bool buf_LRU_free_page(buf_page_t *bpage, bool zip)
|
||||
if (oldest_modification) {
|
||||
goto func_exit;
|
||||
}
|
||||
} else if (oldest_modification
|
||||
&& bpage->state() != BUF_BLOCK_FILE_PAGE) {
|
||||
} else if (oldest_modification && !bpage->frame) {
|
||||
func_exit:
|
||||
hash_lock.unlock();
|
||||
return(false);
|
||||
|
||||
} else if (bpage->state() == BUF_BLOCK_FILE_PAGE) {
|
||||
b = buf_page_alloc_descriptor();
|
||||
} else if (bpage->frame) {
|
||||
b = static_cast<buf_page_t*>(ut_zalloc_nokey(sizeof *b));
|
||||
ut_a(b);
|
||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||
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);
|
||||
ut_ad(bpage->in_file());
|
||||
ut_ad(bpage->in_LRU_list);
|
||||
|
||||
DBUG_PRINT("ib_buf", ("free page %u:%u",
|
||||
id.space(), id.page_no()));
|
||||
@@ -887,9 +874,7 @@ func_exit:
|
||||
buf_LRU_block_remove_hashed(), which
|
||||
invokes buf_LRU_remove_block(). */
|
||||
ut_ad(!bpage->in_LRU_list);
|
||||
|
||||
/* bpage->state was BUF_BLOCK_FILE_PAGE because
|
||||
b != nullptr. The type cast below is thus valid. */
|
||||
ut_ad(bpage->frame);
|
||||
ut_ad(!((buf_block_t*) bpage)->in_unzip_LRU_list);
|
||||
|
||||
/* The fields of bpage were copied to b before
|
||||
@@ -952,13 +937,9 @@ func_exit:
|
||||
|
||||
page_zip_set_size(&bpage->zip, 0);
|
||||
|
||||
/* Prevent buf_page_get_gen() from
|
||||
decompressing the block while we release
|
||||
hash_lock. */
|
||||
b->set_io_fix(BUF_IO_PIN);
|
||||
goto release;
|
||||
b->lock.x_lock();
|
||||
hash_lock.unlock();
|
||||
} else if (!zip) {
|
||||
release:
|
||||
hash_lock.unlock();
|
||||
}
|
||||
|
||||
@@ -974,21 +955,16 @@ release:
|
||||
the contents of the page valid (which it still is) in
|
||||
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);
|
||||
MEM_UNDEFINED(block->frame, srv_page_size);
|
||||
|
||||
if (UNIV_LIKELY_NULL(b)) {
|
||||
ut_ad(b->zip_size());
|
||||
b->io_unfix();
|
||||
}
|
||||
|
||||
MEM_UNDEFINED(block->page.frame, srv_page_size);
|
||||
mysql_mutex_lock(&buf_pool.mutex);
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
if (UNIV_LIKELY_NULL(b)) {
|
||||
ut_ad(b->zip_size());
|
||||
b->io_unfix();
|
||||
b->lock.x_unlock();
|
||||
b->unfix();
|
||||
}
|
||||
|
||||
buf_LRU_block_free_hashed_page(block);
|
||||
@@ -1005,22 +981,22 @@ buf_LRU_block_free_non_file_page(
|
||||
{
|
||||
void* data;
|
||||
|
||||
ut_ad(block->page.state() == BUF_BLOCK_MEMORY);
|
||||
ut_ad(block->page.state() == buf_page_t::MEMORY);
|
||||
assert_block_ahi_empty(block);
|
||||
ut_ad(!block->page.in_free_list);
|
||||
ut_ad(!block->page.oldest_modification());
|
||||
ut_ad(!block->page.in_LRU_list);
|
||||
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 */
|
||||
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,
|
||||
"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);
|
||||
data = block->page.zip.data;
|
||||
|
||||
@@ -1050,7 +1026,7 @@ buf_LRU_block_free_non_file_page(
|
||||
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. */
|
||||
@@ -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.
|
||||
|
||||
If bpage->state() == BUF_BLOCK_ZIP_PAGE && !bpage->oldest_modification(),
|
||||
the object will be freed.
|
||||
If !bpage->frame && !bpage->oldest_modification(), the object will be freed.
|
||||
|
||||
@param bpage buffer block
|
||||
@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,
|
||||
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_a(bpage->io_fix() == BUF_IO_NONE);
|
||||
ut_a(!bpage->buf_fix_count());
|
||||
|
||||
buf_LRU_remove_block(bpage);
|
||||
|
||||
buf_pool.freed_page_clock += 1;
|
||||
|
||||
switch (bpage->state()) {
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
if (UNIV_LIKELY(bpage->frame != nullptr)) {
|
||||
MEM_CHECK_ADDRESSABLE(bpage, sizeof(buf_block_t));
|
||||
MEM_CHECK_ADDRESSABLE(((buf_block_t*) bpage)->frame,
|
||||
srv_page_size);
|
||||
MEM_CHECK_ADDRESSABLE(bpage->frame, srv_page_size);
|
||||
buf_block_modify_clock_inc((buf_block_t*) bpage);
|
||||
if (bpage->zip.data) {
|
||||
const page_t* page = ((buf_block_t*) bpage)->frame;
|
||||
if (UNIV_LIKELY_NULL(bpage->zip.data)) {
|
||||
const page_t* page = bpage->frame;
|
||||
|
||||
ut_a(!zip || !bpage->oldest_modification());
|
||||
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);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
goto evict_zip;
|
||||
}
|
||||
/* fall through */
|
||||
case BUF_BLOCK_ZIP_PAGE:
|
||||
} else {
|
||||
evict_zip:
|
||||
ut_a(!bpage->oldest_modification());
|
||||
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);
|
||||
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()) {
|
||||
case BUF_BLOCK_ZIP_PAGE:
|
||||
if (UNIV_UNLIKELY(!bpage->frame)) {
|
||||
ut_ad(!bpage->in_free_list);
|
||||
ut_ad(!bpage->in_LRU_list);
|
||||
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_pool_mutex_exit_allow();
|
||||
buf_page_free_descriptor(bpage);
|
||||
return(false);
|
||||
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
bpage->lock.free();
|
||||
ut_free(bpage);
|
||||
return false;
|
||||
} else {
|
||||
static_assert(FIL_NULL == 0xffffffffU, "fill pattern");
|
||||
static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
|
||||
memset_aligned<4>(reinterpret_cast<buf_block_t*>(bpage)->frame
|
||||
+ FIL_PAGE_OFFSET, 0xff, 4);
|
||||
memset_aligned<4>(bpage->frame + FIL_PAGE_OFFSET, 0xff, 4);
|
||||
static_assert(FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID % 4 == 2,
|
||||
"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);
|
||||
MEM_UNDEFINED(((buf_block_t*) bpage)->frame, srv_page_size);
|
||||
bpage->set_state(BUF_BLOCK_REMOVE_HASH);
|
||||
MEM_UNDEFINED(bpage->frame, srv_page_size);
|
||||
bpage->set_state(buf_page_t::REMOVE_HASH);
|
||||
|
||||
if (!zip) {
|
||||
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);
|
||||
}
|
||||
|
||||
return(true);
|
||||
|
||||
case BUF_BLOCK_NOT_USED:
|
||||
case BUF_BLOCK_MEMORY:
|
||||
case BUF_BLOCK_REMOVE_HASH:
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
|
||||
ut_error;
|
||||
return(false);
|
||||
}
|
||||
|
||||
/** Release and evict a corrupted page.
|
||||
@param bpage page that was being read */
|
||||
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());
|
||||
page_hash_latch &hash_lock= buf_pool.page_hash.lock_get(chain);
|
||||
|
||||
mysql_mutex_lock(&mutex);
|
||||
hash_lock.lock();
|
||||
|
||||
ut_ad(bpage->io_fix() == BUF_IO_READ);
|
||||
ut_ad(!bpage->oldest_modification());
|
||||
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)
|
||||
reinterpret_cast<buf_block_t*>(bpage)->lock.x_unlock(true);
|
||||
|
||||
while (bpage->buf_fix_count())
|
||||
while (s != buf_page_t::UNFIXED)
|
||||
{
|
||||
ut_ad(s > buf_page_t::UNFIXED);
|
||||
ut_ad(s < buf_page_t::READ_FIX);
|
||||
/* Wait for other threads to release the fix count
|
||||
before releasing the bpage from LRU list. */
|
||||
(void) LF_BACKOFF();
|
||||
s= bpage->state();
|
||||
}
|
||||
|
||||
/* remove from LRU and page_hash */
|
||||
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);
|
||||
}
|
||||
|
||||
#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
|
||||
/** Validate the LRU list. */
|
||||
void buf_LRU_validate()
|
||||
@@ -1389,20 +1363,11 @@ void buf_LRU_validate()
|
||||
for (buf_page_t* bpage = UT_LIST_GET_FIRST(buf_pool.LRU);
|
||||
bpage != NULL;
|
||||
bpage = UT_LIST_GET_NEXT(LRU, bpage)) {
|
||||
|
||||
switch (bpage->state()) {
|
||||
case BUF_BLOCK_NOT_USED:
|
||||
case BUF_BLOCK_MEMORY:
|
||||
case BUF_BLOCK_REMOVE_HASH:
|
||||
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;
|
||||
}
|
||||
ut_ad(bpage->in_file());
|
||||
ut_ad(!bpage->frame
|
||||
|| reinterpret_cast<buf_block_t*>(bpage)
|
||||
->in_unzip_LRU_list
|
||||
== bpage->belongs_to_unzip_LRU());
|
||||
|
||||
if (bpage->is_old()) {
|
||||
const buf_page_t* prev
|
||||
@@ -1428,7 +1393,7 @@ void buf_LRU_validate()
|
||||
bpage != NULL;
|
||||
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();
|
||||
@@ -1464,38 +1429,28 @@ void buf_LRU_print()
|
||||
fputs("old ", stderr);
|
||||
}
|
||||
|
||||
if (const uint32_t buf_fix_count = bpage->buf_fix_count()) {
|
||||
fprintf(stderr, "buffix count %u ", buf_fix_count);
|
||||
}
|
||||
|
||||
if (const auto io_fix = bpage->io_fix()) {
|
||||
fprintf(stderr, "io_fix %d ", io_fix);
|
||||
const unsigned s = bpage->state();
|
||||
if (s > buf_page_t::UNFIXED) {
|
||||
fprintf(stderr, "fix %u ", s - buf_page_t::UNFIXED);
|
||||
} else {
|
||||
ut_ad(s == buf_page_t::UNFIXED
|
||||
|| s == buf_page_t::REMOVE_HASH);
|
||||
}
|
||||
|
||||
if (bpage->oldest_modification()) {
|
||||
fputs("modif. ", stderr);
|
||||
}
|
||||
|
||||
switch (const auto state = bpage->state()) {
|
||||
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;
|
||||
if (const byte* frame = bpage->zip.data) {
|
||||
fprintf(stderr, "\ntype %u size " ULINTPF
|
||||
" index id " IB_ID_FMT "\n",
|
||||
fil_page_get_type(frame),
|
||||
bpage->zip_size(),
|
||||
btr_page_get_index_id(frame));
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "\n!state %d!\n", state);
|
||||
break;
|
||||
} else {
|
||||
fprintf(stderr, "\ntype %u index id " IB_ID_FMT "\n",
|
||||
fil_page_get_type(bpage->frame),
|
||||
btr_page_get_index_id(bpage->frame));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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_a(watch_is_sentinel(*watch));
|
||||
if (watch->buf_fix_count())
|
||||
{
|
||||
page_hash.remove(chain, watch);
|
||||
watch->set_buf_fix_count(0);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
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
|
||||
in buf_page_read_complete() by the io-handler thread. */
|
||||
block->lock.x_lock(true);
|
||||
in buf_page_t::read_complete() by the io-handler thread. */
|
||||
block->page.lock.x_lock(true);
|
||||
}
|
||||
|
||||
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. */
|
||||
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);
|
||||
}
|
||||
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)
|
||||
{
|
||||
/* Preserve the reference count. */
|
||||
auto buf_fix_count= hash_page->buf_fix_count();
|
||||
ut_a(buf_fix_count > 0);
|
||||
block->page.add_buf_fix_count(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);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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_set_size(&bpage->zip, zip_size);
|
||||
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
|
||||
@@ -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
|
||||
buf_pool_t::watch_unset() is executing concurrently,
|
||||
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.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.
|
||||
@@ -315,16 +315,7 @@ nothing_read:
|
||||
"read page " << page_id << " zip_size=" << zip_size
|
||||
<< " unzip=" << unzip << ',' << (sync ? "sync" : "async"));
|
||||
|
||||
void* dst;
|
||||
|
||||
if (zip_size) {
|
||||
dst = bpage->zip.data;
|
||||
} else {
|
||||
ut_a(bpage->state() == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
dst = ((buf_block_t*) bpage)->frame;
|
||||
}
|
||||
|
||||
void* dst = zip_size ? bpage->zip.data : bpage->frame;
|
||||
const ulint len = zip_size ? zip_size : srv_page_size;
|
||||
|
||||
auto fio = space->io(IORequest(sync
|
||||
@@ -347,7 +338,7 @@ nothing_read:
|
||||
thd_wait_end(NULL);
|
||||
|
||||
/* 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();
|
||||
|
||||
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
|
||||
prevent deadlocks. The hash_lock is only protecting the
|
||||
buf_pool.page_hash for page i, not the bpage contents itself. */
|
||||
const byte *f;
|
||||
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;
|
||||
}
|
||||
|
||||
const byte *f= bpage->frame ? bpage->frame : bpage->zip.data;
|
||||
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));
|
||||
if (prev == FIL_NULL || next == FIL_NULL)
|
||||
|
@@ -55,29 +55,29 @@ dict_hdr_get_new_id(
|
||||
|
||||
if (table_id) {
|
||||
id = mach_read_from_8(DICT_HDR + DICT_HDR_TABLE_ID
|
||||
+ dict_hdr->frame);
|
||||
+ dict_hdr->page.frame);
|
||||
id++;
|
||||
mtr.write<8>(*dict_hdr, DICT_HDR + DICT_HDR_TABLE_ID
|
||||
+ dict_hdr->frame, id);
|
||||
+ dict_hdr->page.frame, id);
|
||||
*table_id = id;
|
||||
}
|
||||
|
||||
if (index_id) {
|
||||
id = mach_read_from_8(DICT_HDR + DICT_HDR_INDEX_ID
|
||||
+ dict_hdr->frame);
|
||||
+ dict_hdr->page.frame);
|
||||
id++;
|
||||
mtr.write<8>(*dict_hdr, DICT_HDR + DICT_HDR_INDEX_ID
|
||||
+ dict_hdr->frame, id);
|
||||
+ dict_hdr->page.frame, id);
|
||||
*index_id = id;
|
||||
}
|
||||
|
||||
if (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)) {
|
||||
mtr.write<4>(*dict_hdr,
|
||||
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.start();
|
||||
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)
|
||||
mtr.write<8>(*d, row_id, id);
|
||||
mtr.commit();
|
||||
@@ -119,17 +119,18 @@ static bool dict_hdr_create()
|
||||
|
||||
/* Start counting row, table, index, and tree ids from
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
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. */
|
||||
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);
|
||||
|
||||
/* Create the B-tree roots for the clustered indexes of the basic
|
||||
@@ -145,7 +146,8 @@ failed:
|
||||
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,
|
||||
fil_system.sys_space, DICT_TABLE_IDS_ID,
|
||||
@@ -154,7 +156,7 @@ 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 = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
|
||||
@@ -164,7 +166,7 @@ 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 = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
|
||||
@@ -174,7 +176,8 @@ 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,
|
||||
fil_system.sys_space, DICT_FIELDS_ID,
|
||||
@@ -183,7 +186,8 @@ 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:
|
||||
mtr.commit();
|
||||
return fail;
|
||||
@@ -228,7 +232,7 @@ dict_boot(void)
|
||||
dict_sys.lock(SRW_LOCK_CALL);
|
||||
|
||||
/* 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
|
||||
(dictionary header) when it is divisible by
|
||||
|
@@ -314,11 +314,11 @@ btr_get_size_and_reserved(
|
||||
mtr->x_lock_space(index->table->space);
|
||||
|
||||
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) {
|
||||
n += fseg_n_reserved_pages(*root,
|
||||
PAGE_HEADER + PAGE_BTR_SEG_TOP
|
||||
+ root->frame, &dummy, mtr);
|
||||
+ root->page.frame, &dummy, mtr);
|
||||
*used += dummy;
|
||||
}
|
||||
|
||||
|
@@ -934,7 +934,8 @@ void dict_check_tablespaces_and_store_max_id()
|
||||
mtr.start();
|
||||
uint32_t max_space_id = mach_read_from_4(DICT_HDR_MAX_SPACE_ID
|
||||
+ DICT_HDR
|
||||
+ dict_hdr_get(&mtr)->frame);
|
||||
+ dict_hdr_get(&mtr)
|
||||
->page.frame);
|
||||
mtr.commit();
|
||||
|
||||
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() */
|
||||
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.
|
||||
@return error message
|
||||
@@ -1001,7 +1003,7 @@ err_len:
|
||||
if (table_id) {
|
||||
*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(
|
||||
@@ -1124,7 +1126,8 @@ err_len:
|
||||
}
|
||||
|
||||
/** 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
|
||||
from a SYS_VIRTUAL record
|
||||
@@ -1168,7 +1171,7 @@ err_len:
|
||||
if (table_id != NULL) {
|
||||
*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(
|
||||
@@ -1267,16 +1270,21 @@ dict_load_columns(
|
||||
|
||||
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,
|
||||
&name, rec, &nth_v_col);
|
||||
|
||||
if (err_msg == dict_load_column_del) {
|
||||
if (!err_msg) {
|
||||
} else if (err_msg == dict_load_column_del) {
|
||||
n_skipped++;
|
||||
goto next_rec;
|
||||
} else if (err_msg) {
|
||||
ib::fatal() << err_msg;
|
||||
} else if (err_msg == dict_load_column_none
|
||||
&& 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
|
||||
@@ -1339,7 +1347,6 @@ dict_load_virtual_one_col(
|
||||
btr_pcur_t pcur;
|
||||
dtuple_t* tuple;
|
||||
dfield_t* dfield;
|
||||
const rec_t* rec;
|
||||
byte* buf;
|
||||
ulint i = 0;
|
||||
mtr_t mtr;
|
||||
@@ -1384,28 +1391,26 @@ dict_load_virtual_one_col(
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
|
||||
for (i = 0; i < unsigned{v_col->num_base} + skipped; i++) {
|
||||
const char* err_msg;
|
||||
ulint pos;
|
||||
|
||||
ut_ad(btr_pcur_is_on_user_rec(&pcur));
|
||||
|
||||
rec = btr_pcur_get_rec(&pcur);
|
||||
|
||||
ut_a(btr_pcur_is_on_user_rec(&pcur));
|
||||
|
||||
err_msg = dict_load_virtual_low(table,
|
||||
const char* err_msg
|
||||
= btr_pcur_is_on_user_rec(&pcur)
|
||||
? dict_load_virtual_low(table,
|
||||
&v_col->base_col[i - skipped],
|
||||
NULL,
|
||||
&pos, NULL, rec);
|
||||
&pos, NULL,
|
||||
btr_pcur_get_rec(&pcur))
|
||||
: dict_load_virtual_none;
|
||||
|
||||
if (err_msg) {
|
||||
if (err_msg != dict_load_virtual_del) {
|
||||
ib::fatal() << err_msg;
|
||||
} else {
|
||||
skipped++;
|
||||
}
|
||||
} else {
|
||||
if (!err_msg) {
|
||||
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);
|
||||
@@ -1433,7 +1438,9 @@ dict_load_virtual(
|
||||
}
|
||||
|
||||
/** 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.
|
||||
@return error message
|
||||
@@ -1488,7 +1495,7 @@ err_len:
|
||||
} else {
|
||||
first_field = (index->n_def == 0);
|
||||
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;
|
||||
dtuple_t* tuple;
|
||||
dfield_t* dfield;
|
||||
const rec_t* rec;
|
||||
byte* buf;
|
||||
ulint i;
|
||||
mtr_t mtr;
|
||||
@@ -1596,27 +1602,29 @@ dict_load_fields(
|
||||
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
for (i = 0; i < index->n_fields; i++) {
|
||||
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);
|
||||
|
||||
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) {
|
||||
if (!err_msg) {
|
||||
} else if (err_msg == dict_load_field_del) {
|
||||
/* There could be delete marked records in
|
||||
SYS_FIELDS because SYS_FIELDS.INDEX_ID can be
|
||||
updated by ALTER TABLE ADD INDEX. */
|
||||
|
||||
goto next_rec;
|
||||
} else if (err_msg) {
|
||||
ib::error() << err_msg;
|
||||
} else {
|
||||
if (err_msg != dict_load_field_none
|
||||
|| strstr(index->table->name.m_name,
|
||||
"/" TEMP_FILE_PREFIX_INNODB)) {
|
||||
ib::error() << err_msg << " for index "
|
||||
<< index->name
|
||||
<< " of table "
|
||||
<< index->table->name;
|
||||
}
|
||||
error = DB_CORRUPTION;
|
||||
goto func_exit;
|
||||
}
|
||||
next_rec:
|
||||
|
||||
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() */
|
||||
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() */
|
||||
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() */
|
||||
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.
|
||||
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)) {
|
||||
/* Caller supplied table_id, verify it is the same
|
||||
id as on the index record */
|
||||
return(dict_load_index_id_err);
|
||||
return dict_load_index_none;
|
||||
}
|
||||
|
||||
field = rec_get_nth_field_old(
|
||||
@@ -1858,7 +1866,7 @@ dict_load_indexes(
|
||||
err_msg = dict_load_index_low(buf, heap, rec, TRUE, &index);
|
||||
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
|
||||
the table. */
|
||||
break;
|
||||
@@ -1962,8 +1970,8 @@ corrupted:
|
||||
of the database server */
|
||||
dict_mem_index_free(index);
|
||||
} else {
|
||||
dict_load_fields(index, heap);
|
||||
index->table = table;
|
||||
dict_load_fields(index, heap);
|
||||
|
||||
/* The data dictionary tables should never contain
|
||||
invalid index definitions. If we ignored this error
|
||||
@@ -2360,15 +2368,15 @@ corrupted:
|
||||
page_id, table->space->zip_size(),
|
||||
RW_S_LATCH, &mtr);
|
||||
const bool corrupted = !block
|
||||
|| page_get_space_id(block->frame)
|
||||
|| page_get_space_id(block->page.frame)
|
||||
!= page_id.space()
|
||||
|| page_get_page_no(block->frame)
|
||||
|| page_get_page_no(block->page.frame)
|
||||
!= page_id.page_no()
|
||||
|| (mach_read_from_2(FIL_PAGE_TYPE
|
||||
+ block->frame)
|
||||
+ block->page.frame)
|
||||
!= FIL_PAGE_INDEX
|
||||
&& mach_read_from_2(FIL_PAGE_TYPE
|
||||
+ block->frame)
|
||||
+ block->page.frame)
|
||||
!= FIL_PAGE_TYPE_INSTANT);
|
||||
mtr.commit();
|
||||
if (corrupted) {
|
||||
|
@@ -1442,10 +1442,12 @@ invalid:
|
||||
index->stat_index_size
|
||||
= fseg_n_reserved_pages(*root, PAGE_HEADER
|
||||
+ PAGE_BTR_SEG_LEAF
|
||||
+ root->frame, &size, &mtr)
|
||||
+ root->page.frame, &size,
|
||||
&mtr)
|
||||
+ fseg_n_reserved_pages(*root, PAGE_HEADER
|
||||
+ PAGE_BTR_SEG_TOP
|
||||
+ root->frame, &dummy, &mtr);
|
||||
+ root->page.frame, &dummy,
|
||||
&mtr);
|
||||
|
||||
mtr.commit();
|
||||
|
||||
@@ -2529,17 +2531,19 @@ empty_index:
|
||||
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);
|
||||
ulint dummy, size;
|
||||
result.index_size
|
||||
= fseg_n_reserved_pages(*root, PAGE_HEADER
|
||||
+ PAGE_BTR_SEG_LEAF
|
||||
+ root->frame, &size, &mtr)
|
||||
+ root->page.frame,
|
||||
&size, &mtr)
|
||||
+ fseg_n_reserved_pages(*root, PAGE_HEADER
|
||||
+ PAGE_BTR_SEG_TOP
|
||||
+ root->frame, &dummy, &mtr);
|
||||
+ root->page.frame,
|
||||
&dummy, &mtr);
|
||||
result.n_leaf_pages = size ? size : 1;
|
||||
}
|
||||
|
||||
@@ -2647,7 +2651,7 @@ empty_index:
|
||||
mtr_sx_lock_index(index, &mtr);
|
||||
buf_block_t *root = btr_root_block_get(index, RW_S_LATCH,
|
||||
&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) {
|
||||
/* Just quit if the tree has changed beyond
|
||||
recognition here. The old stats from previous
|
||||
|
@@ -216,7 +216,7 @@ void dict_stats_recalc_pool_del(table_id_t id, bool have_mdl_exclusive)
|
||||
|
||||
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,
|
||||
[&](const recalc &r){return r.id == id;});
|
||||
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;
|
||||
do
|
||||
{
|
||||
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);
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
@@ -379,7 +379,7 @@ void fil_space_crypt_t::write_page0(buf_block_t* block, mtr_t* mtr)
|
||||
{
|
||||
const ulint offset = FSP_HEADER_OFFSET
|
||||
+ 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);
|
||||
|
||||
@@ -628,24 +628,19 @@ byte* fil_space_encrypt(
|
||||
@param[in] crypt_data crypt_data
|
||||
@param[in] tmp_frame Temporary buffer
|
||||
@param[in,out] src_frame Page to decrypt
|
||||
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
|
||||
@return true if page decrypted, false if not.*/
|
||||
static bool fil_space_decrypt_full_crc32(
|
||||
@return DB_SUCCESS or error */
|
||||
static dberr_t fil_space_decrypt_full_crc32(
|
||||
ulint space,
|
||||
fil_space_crypt_t* crypt_data,
|
||||
byte* tmp_frame,
|
||||
byte* src_frame,
|
||||
dberr_t* err)
|
||||
byte* src_frame)
|
||||
{
|
||||
uint key_version = mach_read_from_4(
|
||||
src_frame + FIL_PAGE_FCRC32_KEY_VERSION);
|
||||
lsn_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN);
|
||||
uint offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET);
|
||||
*err = DB_SUCCESS;
|
||||
|
||||
if (key_version == ENCRYPTION_KEY_NOT_ENCRYPTED) {
|
||||
return false;
|
||||
}
|
||||
ut_a(key_version != ENCRYPTION_KEY_NOT_ENCRYPTED);
|
||||
|
||||
ut_ad(crypt_data);
|
||||
ut_ad(crypt_data->is_encrypted());
|
||||
@@ -659,9 +654,7 @@ static bool fil_space_decrypt_full_crc32(
|
||||
bool corrupted = false;
|
||||
uint size = buf_page_full_crc32_size(src_frame, NULL, &corrupted);
|
||||
if (UNIV_UNLIKELY(corrupted)) {
|
||||
fail:
|
||||
*err = DB_DECRYPTION_FAILED;
|
||||
return false;
|
||||
return DB_DECRYPTION_FAILED;
|
||||
}
|
||||
|
||||
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 == -1) {
|
||||
goto fail;
|
||||
return DB_DECRYPTION_FAILED;
|
||||
}
|
||||
|
||||
ib::fatal() << "Unable to decrypt data-block "
|
||||
@@ -690,7 +683,7 @@ fail:
|
||||
|
||||
srv_stats.pages_decrypted.inc();
|
||||
|
||||
return true; /* page was decrypted */
|
||||
return DB_SUCCESS; /* page was decrypted */
|
||||
}
|
||||
|
||||
/** Decrypt a page for non full checksum format.
|
||||
@@ -698,14 +691,12 @@ fail:
|
||||
@param[in] tmp_frame Temporary buffer
|
||||
@param[in] physical_size page size
|
||||
@param[in,out] src_frame Page to decrypt
|
||||
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
|
||||
@return true if page decrypted, false if not.*/
|
||||
static bool fil_space_decrypt_for_non_full_checksum(
|
||||
@return DB_SUCCESS or error */
|
||||
static dberr_t fil_space_decrypt_for_non_full_checksum(
|
||||
fil_space_crypt_t* crypt_data,
|
||||
byte* tmp_frame,
|
||||
ulint physical_size,
|
||||
byte* src_frame,
|
||||
dberr_t* err)
|
||||
byte* src_frame)
|
||||
{
|
||||
uint key_version = mach_read_from_4(
|
||||
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);
|
||||
ib_uint64_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN);
|
||||
|
||||
*err = DB_SUCCESS;
|
||||
|
||||
if (key_version == ENCRYPTION_KEY_NOT_ENCRYPTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ut_a(key_version != ENCRYPTION_KEY_NOT_ENCRYPTED);
|
||||
ut_a(crypt_data != NULL && crypt_data->is_encrypted());
|
||||
|
||||
/* 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 == -1) {
|
||||
*err = DB_DECRYPTION_FAILED;
|
||||
return false;
|
||||
return DB_DECRYPTION_FAILED;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
return true; /* page was decrypted */
|
||||
return DB_SUCCESS; /* page was decrypted */
|
||||
}
|
||||
|
||||
/** Decrypt a page.
|
||||
@@ -788,25 +773,24 @@ static bool fil_space_decrypt_for_non_full_checksum(
|
||||
@param[in] physical_size page size
|
||||
@param[in,out] src_frame Page to decrypt
|
||||
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
|
||||
@return true if page decrypted, false if not.*/
|
||||
bool
|
||||
@return DB_SUCCESS or error */
|
||||
dberr_t
|
||||
fil_space_decrypt(
|
||||
uint32_t space_id,
|
||||
uint32_t fsp_flags,
|
||||
fil_space_crypt_t* crypt_data,
|
||||
byte* tmp_frame,
|
||||
ulint physical_size,
|
||||
byte* src_frame,
|
||||
dberr_t* err)
|
||||
byte* src_frame)
|
||||
{
|
||||
if (fil_space_t::full_crc32(fsp_flags)) {
|
||||
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,
|
||||
physical_size, src_frame,
|
||||
err);
|
||||
physical_size,
|
||||
src_frame);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -822,29 +806,23 @@ fil_space_decrypt(
|
||||
byte* tmp_frame,
|
||||
byte* src_frame)
|
||||
{
|
||||
dberr_t err = DB_SUCCESS;
|
||||
byte* res = NULL;
|
||||
const ulint physical_size = space->physical_size();
|
||||
|
||||
ut_ad(space->crypt_data != NULL && space->crypt_data->is_encrypted());
|
||||
ut_ad(space->referenced());
|
||||
|
||||
bool encrypted = fil_space_decrypt(space->id, space->flags,
|
||||
space->crypt_data,
|
||||
tmp_frame, physical_size,
|
||||
src_frame, &err);
|
||||
|
||||
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;
|
||||
if (DB_SUCCESS != fil_space_decrypt(space->id, space->flags,
|
||||
space->crypt_data,
|
||||
tmp_frame, physical_size,
|
||||
src_frame)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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,
|
||||
BUF_GET_POSSIBLY_FREED,
|
||||
&mtr)) {
|
||||
if (block->page.status == buf_page_t::FREED) {
|
||||
if (block->page.is_freed()) {
|
||||
goto func_exit;
|
||||
}
|
||||
mysql_mutex_lock(&fil_system.mutex);
|
||||
if (!space->crypt_data && !space->is_stopping()) {
|
||||
space->crypt_data = fil_space_read_crypt_data(
|
||||
zip_size, block->frame);
|
||||
zip_size, block->page.frame);
|
||||
}
|
||||
mysql_mutex_unlock(&fil_system.mutex);
|
||||
}
|
||||
@@ -1024,7 +1002,7 @@ func_exit:
|
||||
page_id_t(space->id, 0), space->zip_size(),
|
||||
RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED,
|
||||
&mtr, &err)) {
|
||||
if (block->page.status == buf_page_t::FREED) {
|
||||
if (block->page.is_freed()) {
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@@ -1816,7 +1794,7 @@ fil_crypt_rotate_page(
|
||||
const lsn_t block_lsn = mach_read_from_8(FIL_PAGE_LSN + frame);
|
||||
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
|
||||
failure on recovery.*/
|
||||
} else if (block->page.oldest_modification() > 1) {
|
||||
@@ -1996,7 +1974,7 @@ fil_crypt_flush_space(
|
||||
if (buf_block_t* block = buf_page_get_gen(
|
||||
page_id_t(space->id, 0), space->zip_size(),
|
||||
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);
|
||||
crypt_data->write_page0(block, &mtr);
|
||||
}
|
||||
@@ -2438,11 +2416,14 @@ encrypted, or corrupted.
|
||||
@return true if page is encrypted AND OK, false otherwise */
|
||||
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
|
||||
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) {
|
||||
return true;
|
||||
}
|
||||
|
@@ -2650,7 +2650,7 @@ void fsp_flags_try_adjust(fil_space_t *space, uint32_t flags)
|
||||
if (buf_block_t* b = buf_page_get(
|
||||
page_id_t(space->id, 0), space->zip_size(),
|
||||
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)) {
|
||||
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.write<4,mtr_t::FORCED>(*b,
|
||||
FSP_HEADER_OFFSET + FSP_SPACE_FLAGS
|
||||
+ b->frame, flags);
|
||||
+ b->page.frame, flags);
|
||||
}
|
||||
func_exit:
|
||||
mtr.commit();
|
||||
@@ -2836,7 +2836,7 @@ fail:
|
||||
goto release_sync_write;
|
||||
} else {
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@@ -2892,7 +2892,7 @@ write_completed:
|
||||
files and never issue asynchronous reads of change buffer pages. */
|
||||
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)
|
||||
{
|
||||
|
@@ -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),
|
||||
space->zip_size(), RW_SX_LATCH,
|
||||
nullptr, BUF_GET_POSSIBLY_FREED, mtr);
|
||||
if (!block || block->page.status == buf_page_t::FREED)
|
||||
if (!block || block->page.is_freed())
|
||||
return nullptr;
|
||||
ut_ad(space->id == mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_ID +
|
||||
block->frame));
|
||||
block->page.frame));
|
||||
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 |
|
||||
MTR_MEMO_PAGE_X_FIX));
|
||||
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_FREE_BIT == 0);
|
||||
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(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_SX_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);
|
||||
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 |
|
||||
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_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,
|
||||
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(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
|
||||
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 ioffset= uint16_t(seg_inode - iblock->frame);
|
||||
const uint16_t xoffset= uint16_t(descr - xdes->page.frame + XDES_FLST_NODE);
|
||||
const uint16_t ioffset= uint16_t(seg_inode - iblock->page.frame);
|
||||
|
||||
if (!xdes_get_n_used(descr))
|
||||
{
|
||||
@@ -325,9 +325,9 @@ xdes_get_descriptor_with_space_hdr(
|
||||
| MTR_MEMO_PAGE_X_FIX));
|
||||
/* Read free limit and space size */
|
||||
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
|
||||
+ header->frame);
|
||||
+ header->page.frame);
|
||||
ut_ad(limit == space->free_limit
|
||||
|| (space->free_limit == 0
|
||||
&& (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),
|
||||
zip_size, RW_SX_LATCH, nullptr,
|
||||
BUF_GET_POSSIBLY_FREED, mtr);
|
||||
if (block && block->page.status == buf_page_t::FREED) {
|
||||
if (block && block->page.is_freed()) {
|
||||
block = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -363,7 +363,7 @@ xdes_get_descriptor_with_space_hdr(
|
||||
return block
|
||||
? XDES_ARR_OFFSET + XDES_SIZE
|
||||
* xdes_calc_descriptor_index(zip_size, offset)
|
||||
+ block->frame
|
||||
+ block->page.frame
|
||||
: 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),
|
||||
space->zip_size(), RW_SX_LATCH,
|
||||
nullptr, BUF_GET_POSSIBLY_FREED, mtr);
|
||||
if (!block || block->page.status == buf_page_t::FREED)
|
||||
if (!block || block->page.is_freed())
|
||||
return nullptr;
|
||||
return xdes_get_descriptor_with_space_hdr(block, space, offset, mtr, xdes);
|
||||
}
|
||||
@@ -422,18 +422,18 @@ xdes_get_descriptor_const(
|
||||
nullptr,
|
||||
BUF_GET_POSSIBLY_FREED,
|
||||
mtr)) {
|
||||
if (block->page.status == buf_page_t::FREED) {
|
||||
if (block->page.is_freed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ut_ad(page != 0 || space->free_limit == mach_read_from_4(
|
||||
FSP_FREE_LIMIT + FSP_HEADER_OFFSET
|
||||
+ block->frame));
|
||||
+ block->page.frame));
|
||||
ut_ad(page != 0 || space->size_in_header == mach_read_from_4(
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -473,26 +473,27 @@ static uint32_t xdes_get_offset(const xdes_t *descr)
|
||||
@param[in,out] block buffer pool 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());
|
||||
|
||||
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())
|
||||
memset_aligned<8>(block->frame + FIL_PAGE_PREV, 0xff, 8);
|
||||
mach_write_to_4(block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id.space());
|
||||
memset_aligned<8>(block->page.frame + FIL_PAGE_PREV, 0xff, 8);
|
||||
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))
|
||||
{
|
||||
memset_aligned<UNIV_ZIP_SIZE_MIN>(page_zip->data, 0,
|
||||
page_zip_get_size(page_zip));
|
||||
static_assert(FIL_PAGE_OFFSET == 4, "compatibility");
|
||||
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())
|
||||
memset_aligned<8>(page_zip->data + FIL_PAGE_PREV, 0xff, 8);
|
||||
static_assert(FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID % 4 == 2,
|
||||
"not perfect alignment");
|
||||
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);
|
||||
|
||||
mtr->write<2>(*block, block->frame + FIL_PAGE_TYPE,
|
||||
mtr->write<2>(*block, block->page.frame + FIL_PAGE_TYPE,
|
||||
FIL_PAGE_TYPE_FSP_HDR);
|
||||
|
||||
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
|
||||
+ block->frame));
|
||||
+ block->page.frame));
|
||||
/* recv_sys_t::parse() expects to find a WRITE record that
|
||||
covers all 4 bytes. Therefore, we must specify mtr_t::FORCED
|
||||
in order to avoid optimizing away any unchanged most
|
||||
significant bytes of 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
|
||||
+ block->frame));
|
||||
+ block->page.frame));
|
||||
if (auto f = space->flags & ~FSP_FLAGS_MEM_MASK) {
|
||||
mtr->write<4,mtr_t::FORCED>(*block,
|
||||
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
|
||||
+ block->frame));
|
||||
+ block->page.frame));
|
||||
|
||||
flst_init(block, FSP_HEADER_OFFSET + FSP_FREE, 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_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);
|
||||
|
||||
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_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_a(page_no >= size);
|
||||
@@ -629,7 +632,7 @@ fsp_try_extend_data_file_with_pages(
|
||||
in order to avoid optimizing away any unchanged most
|
||||
significant bytes of 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;
|
||||
|
||||
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
|
||||
+ header->frame);
|
||||
+ header->page.frame);
|
||||
ut_ad(size == space->size_in_header);
|
||||
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
|
||||
significant bytes of 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);
|
||||
}
|
||||
@@ -785,10 +789,9 @@ Any other pages were written with uninitialized bytes in FIL_PAGE_TYPE.
|
||||
ATTRIBUTE_COLD
|
||||
void fil_block_reset_type(const buf_block_t& block, ulint type, mtr_t* mtr)
|
||||
{
|
||||
ib::info()
|
||||
<< "Resetting invalid page " << block.page.id() << " type "
|
||||
<< fil_page_get_type(block.frame) << " to " << type << ".";
|
||||
mtr->write<2>(block, block.frame + FIL_PAGE_TYPE, type);
|
||||
ib::info() << "Resetting invalid page " << block.page.id() << " type "
|
||||
<< fil_page_get_type(block.page.frame) << " to " << type << ".";
|
||||
mtr->write<2>(block, block.page.frame + FIL_PAGE_TYPE, type);
|
||||
}
|
||||
|
||||
/** 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 */
|
||||
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
|
||||
+ header->frame);
|
||||
+ header->page.frame);
|
||||
|
||||
ut_ad(size == space->size_in_header);
|
||||
ut_ad(limit == space->free_limit);
|
||||
@@ -849,7 +852,7 @@ fsp_fill_free_list(
|
||||
|
||||
space->free_limit = i + extent_size;
|
||||
mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_FREE_LIMIT
|
||||
+ header->frame, i + extent_size);
|
||||
+ header->page.frame, i + extent_size);
|
||||
|
||||
if (init_xdes) {
|
||||
|
||||
@@ -868,8 +871,8 @@ fsp_fill_free_list(
|
||||
buf_pool.free_block(f);
|
||||
}
|
||||
fsp_init_file_page(space, block, mtr);
|
||||
mtr->write<2>(*block,
|
||||
FIL_PAGE_TYPE + block->frame,
|
||||
mtr->write<2>(*block, FIL_PAGE_TYPE
|
||||
+ block->page.frame,
|
||||
FIL_PAGE_TYPE_XDES);
|
||||
}
|
||||
|
||||
@@ -884,8 +887,8 @@ fsp_fill_free_list(
|
||||
buf_pool.free_block(f);
|
||||
}
|
||||
fsp_init_file_page(space, block, mtr);
|
||||
mtr->write<2>(*block,
|
||||
block->frame + FIL_PAGE_TYPE,
|
||||
mtr->write<2>(*block, FIL_PAGE_TYPE
|
||||
+ block->page.frame,
|
||||
FIL_PAGE_IBUF_BITMAP);
|
||||
}
|
||||
}
|
||||
@@ -903,7 +906,7 @@ fsp_fill_free_list(
|
||||
}
|
||||
xdes_init(*xdes, descr, mtr);
|
||||
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)) {
|
||||
|
||||
@@ -920,7 +923,7 @@ fsp_fill_free_list(
|
||||
FSP_HEADER_OFFSET + FSP_FREE_FRAG,
|
||||
xdes, xoffset, mtr);
|
||||
byte* n_used = FSP_HEADER_OFFSET + FSP_FRAG_N_USED
|
||||
+ header->frame;
|
||||
+ header->page.frame;
|
||||
mtr->write<4>(*header, n_used,
|
||||
2U + mach_read_from_4(n_used));
|
||||
} else {
|
||||
@@ -974,13 +977,13 @@ fsp_alloc_free_extent(
|
||||
} else {
|
||||
/* Take the first extent in the free list */
|
||||
first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE
|
||||
+ header->frame);
|
||||
+ header->page.frame);
|
||||
|
||||
if (first.page == FIL_NULL) {
|
||||
fsp_fill_free_list(false, space, header, mtr);
|
||||
|
||||
first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE
|
||||
+ header->frame);
|
||||
+ header->page.frame);
|
||||
if (first.page == FIL_NULL) {
|
||||
return nullptr; /* No free extents left */
|
||||
}
|
||||
@@ -996,7 +999,8 @@ fsp_alloc_free_extent(
|
||||
|
||||
flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE, desc_block,
|
||||
static_cast<uint16_t>(
|
||||
descr - desc_block->frame + XDES_FLST_NODE), mtr);
|
||||
descr - desc_block->page.frame + XDES_FLST_NODE),
|
||||
mtr);
|
||||
space->free_len--;
|
||||
*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);
|
||||
|
||||
/* 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;
|
||||
|
||||
if (xdes_is_full(descr)) {
|
||||
/* The fragment is full: move it to another list */
|
||||
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,
|
||||
xdes, xoffset, 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)
|
||||
{
|
||||
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));
|
||||
free_block= block;
|
||||
goto got_free_block;
|
||||
@@ -1119,7 +1124,7 @@ fsp_alloc_free_page(
|
||||
} else {
|
||||
/* Else take the first extent in free_frag list */
|
||||
first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE_FRAG
|
||||
+ block->frame);
|
||||
+ block->page.frame);
|
||||
|
||||
if (first.page == FIL_NULL) {
|
||||
/* There are no partially full fragments: allocate
|
||||
@@ -1139,7 +1144,7 @@ fsp_alloc_free_page(
|
||||
xdes_set_state(*xdes, descr, XDES_FREE_FRAG, mtr);
|
||||
flst_add_last(block, FSP_HEADER_OFFSET + FSP_FREE_FRAG,
|
||||
xdes, static_cast<uint16_t>(
|
||||
descr - xdes->frame
|
||||
descr - xdes->page.frame
|
||||
+ XDES_FLST_NODE), mtr);
|
||||
} else {
|
||||
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 space_size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE
|
||||
+ block->frame);
|
||||
+ block->page.frame);
|
||||
ut_ad(space_size == space->size_in_header
|
||||
|| (space_id == TRX_SYS_SPACE
|
||||
&& 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);
|
||||
|
||||
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);
|
||||
|
||||
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,
|
||||
xdes, xoffset, mtr);
|
||||
mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_FRAG_N_USED
|
||||
+ header->frame,
|
||||
+ header->page.frame,
|
||||
frag_n_used + FSP_EXTENT_SIZE - 1);
|
||||
} else {
|
||||
ut_a(frag_n_used > 0);
|
||||
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)) {
|
||||
@@ -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);
|
||||
|
||||
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);
|
||||
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)
|
||||
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
|
||||
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--;
|
||||
inode += FSEG_INODE_SIZE)
|
||||
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. */
|
||||
if (!flst_get_len(FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE
|
||||
+ header->frame)
|
||||
+ header->page.frame)
|
||||
&& !fsp_alloc_seg_inode_page(space, header, mtr)) {
|
||||
return(NULL);
|
||||
}
|
||||
const page_id_t page_id(
|
||||
space->id,
|
||||
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,
|
||||
nullptr, BUF_GET_POSSIBLY_FREED, mtr);
|
||||
if (!block || block->page.status == buf_page_t::FREED) {
|
||||
if (!block || block->page.is_freed()) {
|
||||
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();
|
||||
|
||||
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));
|
||||
|
||||
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,
|
||||
physical_size)) {
|
||||
/* 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();
|
||||
|
||||
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 */
|
||||
flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL,
|
||||
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);
|
||||
|
||||
if (ULINT_UNDEFINED
|
||||
== fsp_seg_inode_page_find_used(iblock->frame, physical_size)) {
|
||||
if (ULINT_UNDEFINED == fsp_seg_inode_page_find_used(iblock->page.frame,
|
||||
physical_size)) {
|
||||
/* There are no other used headers left on the page: free it */
|
||||
flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE,
|
||||
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 */
|
||||
|
||||
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);
|
||||
mtr->write<8>(*iblock, inode + FSEG_ID, seg_id);
|
||||
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);
|
||||
compile_time_assert(FSEG_FRAG_SLOT_SIZE == 4);
|
||||
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);
|
||||
|
||||
if (!block) {
|
||||
@@ -1769,23 +1778,23 @@ fseg_create(fil_space_t *space, ulint byte_offset, mtr_t *mtr,
|
||||
goto funct_exit;
|
||||
}
|
||||
|
||||
ut_d(const auto x = block->lock.x_lock_count());
|
||||
ut_ad(x || block->lock.not_recursive());
|
||||
ut_d(const auto x = block->page.lock.x_lock_count());
|
||||
ut_ad(x || block->page.lock.not_recursive());
|
||||
ut_ad(x == 1 || space->is_being_truncated);
|
||||
ut_ad(x <= 2);
|
||||
ut_ad(!fil_page_get_type(block->frame));
|
||||
mtr->write<1>(*block, FIL_PAGE_TYPE + 1 + block->frame,
|
||||
ut_ad(!fil_page_get_type(block->page.frame));
|
||||
mtr->write<1>(*block, FIL_PAGE_TYPE + 1 + block->page.frame,
|
||||
FIL_PAGE_TYPE_SYS);
|
||||
}
|
||||
|
||||
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
|
||||
+ 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
|
||||
+ block->frame, space->id);
|
||||
+ block->page.frame, space->id);
|
||||
|
||||
funct_exit:
|
||||
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,
|
||||
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,
|
||||
block.page.id().space(),
|
||||
block.zip_size(), mtr),
|
||||
@@ -1897,9 +1906,9 @@ fseg_fill_free_list(
|
||||
mtr->write<8>(*xdes, descr + XDES_ID, seg_id);
|
||||
|
||||
flst_add_last(iblock,
|
||||
static_cast<uint16_t>(inode - iblock->frame
|
||||
static_cast<uint16_t>(inode - iblock->page.frame
|
||||
+ FSEG_FREE), xdes,
|
||||
static_cast<uint16_t>(descr - xdes->frame
|
||||
static_cast<uint16_t>(descr - xdes->page.frame
|
||||
+ XDES_FLST_NODE), mtr);
|
||||
hint += FSP_EXTENT_SIZE;
|
||||
}
|
||||
@@ -1960,9 +1969,9 @@ fseg_alloc_free_extent(
|
||||
mtr->write<8,mtr_t::MAYBE_NOP>(**xdes, descr + XDES_ID,
|
||||
seg_id);
|
||||
flst_add_last(iblock,
|
||||
static_cast<uint16_t>(inode - iblock->frame
|
||||
static_cast<uint16_t>(inode - iblock->page.frame
|
||||
+ FSEG_FREE), *xdes,
|
||||
static_cast<uint16_t>(descr - (*xdes)->frame
|
||||
static_cast<uint16_t>(descr - (*xdes)->page.frame
|
||||
+ XDES_FLST_NODE), mtr);
|
||||
|
||||
/* 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,
|
||||
seg_id);
|
||||
flst_add_last(iblock,
|
||||
static_cast<uint16_t>(seg_inode - iblock->frame
|
||||
static_cast<uint16_t>(seg_inode
|
||||
- iblock->page.frame
|
||||
+ FSEG_FREE), xdes,
|
||||
static_cast<uint16_t>(ret_descr - xdes->frame
|
||||
static_cast<uint16_t>(ret_descr
|
||||
- xdes->page.frame
|
||||
+ XDES_FLST_NODE), mtr);
|
||||
|
||||
/* Try to fill the segment free list */
|
||||
@@ -2409,7 +2420,7 @@ fsp_reserve_free_extents(
|
||||
}
|
||||
try_again:
|
||||
uint32_t size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE
|
||||
+ header->frame);
|
||||
+ header->page.frame);
|
||||
ut_ad(size == space->size_in_header);
|
||||
|
||||
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
|
||||
+ header->frame);
|
||||
+ header->page.frame);
|
||||
ut_ad(space->free_len == n_free_list_ext);
|
||||
|
||||
uint32_t free_limit = mach_read_from_4(FSP_HEADER_OFFSET
|
||||
+ FSP_FREE_LIMIT
|
||||
+ header->frame);
|
||||
+ header->page.frame);
|
||||
ut_ad(space->free_limit == 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)
|
||||
== FSEG_MAGIC_N_VALUE);
|
||||
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));
|
||||
|
||||
#ifdef BTR_CUR_HASH_ADAPT
|
||||
@@ -2550,7 +2561,8 @@ fseg_free_page_low(
|
||||
}
|
||||
|
||||
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
|
||||
+ i * FSEG_FRAG_SLOT_SIZE, 4, 0xff);
|
||||
break;
|
||||
@@ -2576,8 +2588,9 @@ fseg_free_page_low(
|
||||
|
||||
byte* p_not_full = seg_inode + FSEG_NOT_FULL_N_USED;
|
||||
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 ioffset= uint16_t(seg_inode - iblock->frame);
|
||||
const uint16_t xoffset= uint16_t(descr - xdes->page.frame
|
||||
+ XDES_FLST_NODE);
|
||||
const uint16_t ioffset= uint16_t(seg_inode - iblock->page.frame);
|
||||
|
||||
if (xdes_is_full(descr)) {
|
||||
/* The fragment is full: move it to another list */
|
||||
@@ -2704,8 +2717,9 @@ fseg_free_extent(
|
||||
ut_d(space->modify_check(*mtr));
|
||||
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 ioffset= uint16_t(seg_inode - iblock->frame);
|
||||
const uint16_t xoffset= uint16_t(descr - xdes->page.frame
|
||||
+ XDES_FLST_NODE);
|
||||
const uint16_t ioffset= uint16_t(seg_inode - iblock->page.frame);
|
||||
|
||||
#ifdef BTR_CUR_HASH_ADAPT
|
||||
if (ahi) {
|
||||
|
@@ -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)
|
||||
{
|
||||
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);
|
||||
/* Initialize the other address by (MEMMOVE|0x80,offset,FIL_ADDR_SIZE,source)
|
||||
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 |
|
||||
MTR_MEMO_PAGE_SX_FIX));
|
||||
|
||||
ut_ad(!mach_read_from_4(base->frame + boffset + FLST_LEN));
|
||||
mtr->write<1>(*base, base->frame + boffset + (FLST_LEN + 3), 1U);
|
||||
ut_ad(!mach_read_from_4(base->page.frame + boffset + FLST_LEN));
|
||||
mtr->write<1>(*base, base->page.frame + boffset + (FLST_LEN + 3), 1U);
|
||||
/* 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);
|
||||
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);
|
||||
/* Initialize FLST_LAST by (MEMMOVE|0x80,offset,FIL_ADDR_SIZE,source)
|
||||
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 */
|
||||
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.
|
||||
@@ -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 |
|
||||
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);
|
||||
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);
|
||||
|
||||
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);
|
||||
else
|
||||
{
|
||||
@@ -156,10 +157,10 @@ static void flst_insert_after(buf_block_t *base, uint16_t boffset,
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
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);
|
||||
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);
|
||||
|
||||
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);
|
||||
else
|
||||
{
|
||||
@@ -207,10 +208,10 @@ static void flst_insert_before(buf_block_t *base, uint16_t boffset,
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
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);
|
||||
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;
|
||||
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,
|
||||
RW_SX_LATCH, mtr, &cur);
|
||||
if (c)
|
||||
flst_insert_after(base, boffset, cur,
|
||||
static_cast<uint16_t>(c - cur->frame),
|
||||
static_cast<uint16_t>(c - cur->page.frame),
|
||||
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 |
|
||||
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);
|
||||
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;
|
||||
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,
|
||||
RW_SX_LATCH, mtr, &cur);
|
||||
if (c)
|
||||
flst_insert_before(base, boffset, cur,
|
||||
static_cast<uint16_t>(c - cur->frame),
|
||||
static_cast<uint16_t>(c - cur->page.frame),
|
||||
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 |
|
||||
MTR_MEMO_PAGE_SX_FIX));
|
||||
|
||||
const fil_addr_t prev_addr= flst_get_prev_addr(cur->frame + coffset);
|
||||
const fil_addr_t next_addr= flst_get_next_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->page.frame + coffset);
|
||||
|
||||
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);
|
||||
else
|
||||
{
|
||||
buf_block_t *block= cur;
|
||||
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,
|
||||
RW_SX_LATCH, mtr, &block))
|
||||
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)
|
||||
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);
|
||||
else
|
||||
{
|
||||
buf_block_t *block= cur;
|
||||
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,
|
||||
RW_SX_LATCH, mtr, &block))
|
||||
flst_write_addr(*block, next + FLST_PREV,
|
||||
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);
|
||||
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. */
|
||||
mtr_t mtr2;
|
||||
|
||||
const uint32_t len= flst_get_len(base->frame + boffset);
|
||||
fil_addr_t addr= flst_get_first(base->frame + boffset);
|
||||
const uint32_t len= flst_get_len(base->page.frame + boffset);
|
||||
fil_addr_t addr= flst_get_first(base->page.frame + boffset);
|
||||
|
||||
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);
|
||||
|
||||
addr= flst_get_last(base->frame + boffset);
|
||||
addr= flst_get_last(base->page.frame + boffset);
|
||||
|
||||
for (uint32_t i= len; i--; )
|
||||
{
|
||||
|
@@ -231,7 +231,7 @@ rtr_update_mbr_field(
|
||||
ut_ad(page == buf_block_get_frame(block));
|
||||
|
||||
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;
|
||||
|
||||
if (new_rec) {
|
||||
@@ -590,8 +590,8 @@ rtr_adjust_upper_level(
|
||||
|
||||
page_cursor = btr_cur_get_page_cur(&cursor);
|
||||
|
||||
rtr_update_mbr_field(&cursor, offsets, NULL, block->frame, mbr, NULL,
|
||||
mtr);
|
||||
rtr_update_mbr_field(&cursor, offsets, nullptr, block->page.frame, mbr,
|
||||
nullptr, mtr);
|
||||
|
||||
/* Already updated parent MBR, reset in our path */
|
||||
if (sea_cur->rtr_info) {
|
||||
@@ -605,7 +605,7 @@ rtr_adjust_upper_level(
|
||||
/* Insert the node for the new page. */
|
||||
node_ptr_upper = rtr_index_build_node_ptr(
|
||||
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);
|
||||
|
||||
ulint up_match = 0;
|
||||
@@ -660,15 +660,15 @@ rtr_adjust_upper_level(
|
||||
|
||||
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) {
|
||||
buf_block_t* next_block = btr_block_get(
|
||||
*index, next_page_no, RW_X_LATCH, false, mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(next_block->frame)
|
||||
== page_is_comp(block->frame));
|
||||
ut_a(btr_page_get_prev(next_block->frame)
|
||||
ut_a(page_is_comp(next_block->page.frame)
|
||||
== page_is_comp(block->page.frame));
|
||||
ut_a(btr_page_get_prev(next_block->page.frame)
|
||||
== block->page.id().page_no());
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
@@ -744,8 +744,7 @@ rtr_split_page_move_rec_list(
|
||||
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
|
||||
}
|
||||
|
||||
max_to_move = page_get_n_recs(
|
||||
buf_block_get_frame(block));
|
||||
max_to_move = page_get_n_recs(buf_block_get_frame(block));
|
||||
rec_move = static_cast<rtr_rec_move_t*>(mem_heap_alloc(
|
||||
heap,
|
||||
sizeof (*rec_move) * max_to_move));
|
||||
@@ -979,7 +978,7 @@ func_start:
|
||||
if (page_level && UNIV_LIKELY_NULL(new_page_zip)) {
|
||||
/* ROW_FORMAT=COMPRESSED non-leaf pages are not expected
|
||||
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,
|
||||
page_level, mtr);
|
||||
@@ -1879,7 +1878,7 @@ err_exit:
|
||||
/* Scan records in root page and calculate area. */
|
||||
double area = 0;
|
||||
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);
|
||||
rec = page_rec_get_next_const(rec)) {
|
||||
rtr_mbr_t mbr;
|
||||
|
@@ -260,7 +260,7 @@ rtr_pcur_getnext_from_path(
|
||||
ut_ad(my_latch_mode == BTR_MODIFY_TREE
|
||||
|| my_latch_mode == BTR_CONT_MODIFY_TREE
|
||||
|| !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(
|
||||
page_id_t(index->table->space_id,
|
||||
@@ -395,14 +395,14 @@ rtr_pcur_getnext_from_path(
|
||||
}
|
||||
|
||||
if (rw_latch == RW_NO_LATCH) {
|
||||
block->lock.s_lock();
|
||||
block->page.lock.s_lock();
|
||||
}
|
||||
|
||||
lock_prdt_lock(block, &prdt, index, LOCK_S,
|
||||
LOCK_PREDICATE, btr_cur->rtr_info->thr);
|
||||
|
||||
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,
|
||||
&rtr_info->matches->rtr_match_mutex,
|
||||
nullptr);
|
||||
rtr_info->matches->block.lock.init();
|
||||
rtr_info->matches->block.page.lock.init();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
rtr_info->matches->block.lock.free();
|
||||
rtr_info->matches->block.page.lock.free();
|
||||
|
||||
mysql_mutex_destroy(
|
||||
&rtr_info->matches->rtr_match_mutex);
|
||||
@@ -1387,7 +1387,7 @@ rtr_leaf_push_match_rec(
|
||||
ulint data_len;
|
||||
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));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/** 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] block block to copy */
|
||||
static
|
||||
@@ -1498,8 +1498,9 @@ rtr_copy_buf(
|
||||
from the dummy buf_block_t we create here and because memcpy()ing
|
||||
it generates (valid) compiler warnings that the vtable pointer
|
||||
will be copied. */
|
||||
matches->block.page.lock.free();
|
||||
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;
|
||||
|
||||
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());
|
||||
matches->locked = false;
|
||||
rtr_copy_buf(matches, block);
|
||||
matches->block.frame = matches->bufp;
|
||||
matches->block.page.frame = matches->bufp;
|
||||
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. */
|
||||
memcpy(matches->block.frame, page, page_is_comp(page)
|
||||
? PAGE_NEW_SUPREMUM_END
|
||||
: PAGE_OLD_SUPREMUM_END);
|
||||
memcpy(matches->block.page.frame, page, page_is_comp(page)
|
||||
? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END);
|
||||
matches->used = page_is_comp(page)
|
||||
? PAGE_NEW_SUPREMUM_END
|
||||
: PAGE_OLD_SUPREMUM_END;
|
||||
|
@@ -17509,8 +17509,10 @@ func_exit:
|
||||
if (block != NULL) {
|
||||
ib::info() << "Dirtying page: " << block->page.id();
|
||||
mtr.write<1,mtr_t::FORCED>(*block,
|
||||
block->frame + FIL_PAGE_SPACE_ID,
|
||||
block->frame[FIL_PAGE_SPACE_ID]);
|
||||
block->page.frame
|
||||
+ FIL_PAGE_SPACE_ID,
|
||||
block->page.frame
|
||||
[FIL_PAGE_SPACE_ID]);
|
||||
}
|
||||
mtr.commit();
|
||||
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);
|
||||
block != NULL; ) {
|
||||
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->page.in_LRU_list);
|
||||
|
||||
|
@@ -1914,10 +1914,15 @@ innobase_fts_check_doc_id_col(
|
||||
}
|
||||
|
||||
/** 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 */
|
||||
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);
|
||||
mtr_t mtr;
|
||||
btr_pcur_t pcur;
|
||||
@@ -1955,12 +1960,16 @@ next_page:
|
||||
}
|
||||
|
||||
rec= page_cur_get_rec(cur);
|
||||
if (rec_get_deleted_flag(rec, dict_table_is_comp(table)));
|
||||
else if (!page_rec_is_supremum(rec))
|
||||
if (rec_get_deleted_flag(rec, dict_table_is_comp(table)))
|
||||
{
|
||||
if (ignore_delete_marked)
|
||||
goto scan_leaf;
|
||||
non_empty:
|
||||
mtr.commit();
|
||||
return false;
|
||||
}
|
||||
else if (!page_rec_is_supremum(rec))
|
||||
goto non_empty;
|
||||
else
|
||||
{
|
||||
next_page= true;
|
||||
@@ -5816,8 +5825,8 @@ add_all_virtual:
|
||||
btr_pcur_move_to_next_on_page(&pcur);
|
||||
|
||||
buf_block_t* block = btr_pcur_get_block(&pcur);
|
||||
ut_ad(page_is_leaf(block->frame));
|
||||
ut_ad(!page_has_prev(block->frame));
|
||||
ut_ad(page_is_leaf(block->page.frame));
|
||||
ut_ad(!page_has_prev(block->page.frame));
|
||||
ut_ad(!buf_block_get_page_zip(block));
|
||||
const rec_t* rec = btr_pcur_get_rec(&pcur);
|
||||
que_thr_t* thr = pars_complete_graph_for_exec(
|
||||
@@ -5830,8 +5839,8 @@ add_all_virtual:
|
||||
if (is_root
|
||||
&& !rec_is_alter_metadata(rec, *index)
|
||||
&& !index->table->instant
|
||||
&& !page_has_next(block->frame)
|
||||
&& page_rec_is_last(rec, block->frame)) {
|
||||
&& !page_has_next(block->page.frame)
|
||||
&& page_rec_is_last(rec, block->page.frame)) {
|
||||
goto empty_table;
|
||||
}
|
||||
|
||||
@@ -5843,7 +5852,8 @@ add_all_virtual:
|
||||
buf_block_t* root = btr_root_block_get(index, RW_X_LATCH,
|
||||
&mtr);
|
||||
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);
|
||||
err = DB_CORRUPTION;
|
||||
goto func_exit;
|
||||
@@ -5914,8 +5924,8 @@ add_all_virtual:
|
||||
&& !index->table->instant) {
|
||||
empty_table:
|
||||
/* The table is empty. */
|
||||
ut_ad(fil_page_index_page_check(block->frame));
|
||||
ut_ad(!page_has_siblings(block->frame));
|
||||
ut_ad(fil_page_index_page_check(block->page.frame));
|
||||
ut_ad(!page_has_siblings(block->page.frame));
|
||||
ut_ad(block->page.id().page_no() == index->page);
|
||||
/* MDEV-17383: free metadata BLOBs! */
|
||||
btr_page_empty(block, NULL, index, 0, &mtr);
|
||||
@@ -5933,7 +5943,7 @@ empty_table:
|
||||
mtr.start();
|
||||
index->set_modified(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);
|
||||
goto err_exit;
|
||||
}
|
||||
@@ -6753,6 +6763,7 @@ wrong_column_name:
|
||||
DBUG_ASSERT(num_fts_index <= 1);
|
||||
DBUG_ASSERT(!ctx->online || num_fts_index == 0);
|
||||
DBUG_ASSERT(!ctx->online
|
||||
|| !ha_alter_info->mdl_exclusive_after_prepare
|
||||
|| ctx->add_autoinc == ULINT_UNDEFINED);
|
||||
DBUG_ASSERT(!ctx->online
|
||||
|| !innobase_need_rebuild(ha_alter_info, old_table)
|
||||
@@ -7548,6 +7559,20 @@ ha_innobase::prepare_inplace_alter_table(
|
||||
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;
|
||||
|
||||
/* 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");
|
||||
|
||||
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:
|
||||
DEBUG_SYNC(m_user_thd, "innodb_after_inplace_alter_table");
|
||||
DBUG_RETURN(false);
|
||||
@@ -10467,7 +10494,8 @@ commit_cache_norebuild(
|
||||
space->zip_size(),
|
||||
RW_X_LATCH, &mtr)) {
|
||||
byte* f = FSP_HEADER_OFFSET
|
||||
+ FSP_SPACE_FLAGS + b->frame;
|
||||
+ FSP_SPACE_FLAGS
|
||||
+ b->page.frame;
|
||||
const auto sf = space->flags
|
||||
& ~FSP_FLAGS_MEM_MASK;
|
||||
if (mach_read_from_4(f) != sf) {
|
||||
|
@@ -116,10 +116,8 @@ struct buf_page_info_t{
|
||||
ulint block_id; /*!< Buffer Pool block ID */
|
||||
/** page identifier */
|
||||
page_id_t id;
|
||||
unsigned access_time:32; /*!< Time of first access */
|
||||
unsigned io_fix:2; /*!< type of pending I/O operation */
|
||||
uint32_t fix_count; /*!< Count of how manyfold this block
|
||||
is bufferfixed */
|
||||
uint32_t access_time; /*!< Time of first access */
|
||||
uint32_t state; /*!< buf_page_t::state() */
|
||||
#ifdef BTR_CUR_HASH_ADAPT
|
||||
unsigned hashed:1; /*!< Whether hash index has been
|
||||
built on this page */
|
||||
@@ -130,7 +128,7 @@ struct buf_page_info_t{
|
||||
buf_pool.freed_page_clock */
|
||||
unsigned zip_ssize:PAGE_ZIP_SSIZE_BITS;
|
||||
/*!< 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 num_recs:UNIV_PAGE_SIZE_SHIFT_MAX-2;
|
||||
/*!< Number of records on Page */
|
||||
@@ -3816,12 +3814,11 @@ static const LEX_CSTRING io_values[] =
|
||||
{
|
||||
{ STRING_WITH_LEN("IO_NONE") },
|
||||
{ STRING_WITH_LEN("IO_READ") },
|
||||
{ STRING_WITH_LEN("IO_WRITE") },
|
||||
{ STRING_WITH_LEN("IO_PIN") }
|
||||
{ STRING_WITH_LEN("IO_WRITE") }
|
||||
};
|
||||
|
||||
|
||||
static TypelibBuffer<4> io_values_typelib(io_values);
|
||||
static TypelibBuffer<3> io_values_typelib(io_values);
|
||||
|
||||
namespace Show {
|
||||
/* 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_FIX_COUNT]->store(
|
||||
page_info->fix_count, true));
|
||||
~buf_page_t::LRU_MASK & page_info->state, true));
|
||||
|
||||
#ifdef BTR_CUR_HASH_ADAPT
|
||||
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
|
||||
: 0, true));
|
||||
|
||||
OK(fields[IDX_BUFFER_PAGE_STATE]->store(
|
||||
1 + std::min<unsigned>(page_info->page_state,
|
||||
BUF_BLOCK_FILE_PAGE), true));
|
||||
static_assert(buf_page_t::NOT_USED == 0, "compatibility");
|
||||
static_assert(buf_page_t::MEMORY == 1, "compatibility");
|
||||
static_assert(buf_page_t::REMOVE_HASH == 2, "compatibility");
|
||||
|
||||
OK(fields[IDX_BUFFER_PAGE_IO_FIX]->store(
|
||||
1 + page_info->io_fix, true));
|
||||
OK(fields[IDX_BUFFER_PAGE_STATE]->store(
|
||||
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(
|
||||
page_info->is_old, true));
|
||||
@@ -4106,61 +4118,51 @@ i_s_innodb_buffer_page_get_info(
|
||||
{
|
||||
page_info->block_id = pos;
|
||||
|
||||
compile_time_assert(BUF_BLOCK_NOT_USED == 0);
|
||||
compile_time_assert(BUF_BLOCK_MEMORY == 1);
|
||||
compile_time_assert(BUF_BLOCK_REMOVE_HASH == 2);
|
||||
compile_time_assert(BUF_BLOCK_FILE_PAGE == 3);
|
||||
compile_time_assert(BUF_BLOCK_ZIP_PAGE == 4);
|
||||
static_assert(buf_page_t::NOT_USED == 0, "compatibility");
|
||||
static_assert(buf_page_t::MEMORY == 1, "compatibility");
|
||||
static_assert(buf_page_t::REMOVE_HASH == 2, "compatibility");
|
||||
static_assert(buf_page_t::UNFIXED == 1U << 29, "compatibility");
|
||||
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->page_state= int{state} & 7;
|
||||
page_info->state = bpage->state();
|
||||
|
||||
switch (state) {
|
||||
default:
|
||||
if (page_info->state < buf_page_t::FREED) {
|
||||
page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
|
||||
break;
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
case BUF_BLOCK_ZIP_PAGE:
|
||||
page_info->compressed_only = false;
|
||||
} else {
|
||||
const byte* frame;
|
||||
|
||||
page_info->id = bpage->id();
|
||||
|
||||
page_info->fix_count = bpage->buf_fix_count();
|
||||
|
||||
page_info->oldest_mod = bpage->oldest_modification();
|
||||
|
||||
page_info->access_time = bpage->access_time;
|
||||
|
||||
page_info->zip_ssize = bpage->zip.ssize;
|
||||
|
||||
page_info->io_fix = bpage->io_fix() & 3;
|
||||
|
||||
page_info->is_old = bpage->old;
|
||||
|
||||
page_info->freed_page_clock = bpage->freed_page_clock;
|
||||
|
||||
switch (bpage->io_fix()) {
|
||||
case BUF_IO_NONE:
|
||||
case BUF_IO_WRITE:
|
||||
case BUF_IO_PIN:
|
||||
break;
|
||||
case BUF_IO_READ:
|
||||
if (page_info->state >= buf_page_t::READ_FIX
|
||||
&& page_info->state < buf_page_t::WRITE_FIX) {
|
||||
page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
|
||||
page_info->newest_mod = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == BUF_BLOCK_FILE_PAGE) {
|
||||
const buf_block_t*block;
|
||||
|
||||
block = reinterpret_cast<const buf_block_t*>(bpage);
|
||||
frame = block->frame;
|
||||
page_info->compressed_only = !bpage->frame,
|
||||
frame = bpage->frame;
|
||||
if (UNIV_LIKELY(frame != nullptr)) {
|
||||
#ifdef BTR_CUR_HASH_ADAPT
|
||||
/* Note: this may be a false positive, that
|
||||
is, block->index will not always be set to
|
||||
NULL when the last adaptive hash index
|
||||
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 */
|
||||
} else {
|
||||
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_FIX_COUNT]->store(
|
||||
page_info->fix_count, true));
|
||||
~buf_page_t::LRU_MASK & page_info->state, true));
|
||||
|
||||
#ifdef BTR_CUR_HASH_ADAPT
|
||||
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));
|
||||
|
||||
OK(fields[IDX_BUF_LRU_PAGE_STATE]->store(
|
||||
page_info->page_state == BUF_BLOCK_ZIP_PAGE,
|
||||
true));
|
||||
page_info->compressed_only, true));
|
||||
|
||||
OK(fields[IDX_BUF_LRU_PAGE_IO_FIX]->store(
|
||||
1 + page_info->io_fix, 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_BUF_LRU_PAGE_IO_FIX]->store(io_fix, true));
|
||||
|
||||
OK(fields[IDX_BUF_LRU_PAGE_IS_OLD]->store(
|
||||
page_info->is_old, true));
|
||||
|
@@ -321,7 +321,7 @@ ibuf_header_page_get(
|
||||
page_id_t(IBUF_SPACE_ID, FSP_IBUF_HEADER_PAGE_NO),
|
||||
0, RW_X_LATCH, mtr);
|
||||
|
||||
return block ? block->frame : nullptr;
|
||||
return block ? block->page.frame : nullptr;
|
||||
}
|
||||
|
||||
/** 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),
|
||||
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;
|
||||
}
|
||||
@@ -430,7 +430,7 @@ ibuf_init_at_db_start(void)
|
||||
|
||||
fseg_n_reserved_pages(*header_page,
|
||||
IBUF_HEADER + IBUF_TREE_SEG_HEADER
|
||||
+ header_page->frame, &n_used, &mtr);
|
||||
+ header_page->page.frame, &n_used, &mtr);
|
||||
|
||||
ut_ad(n_used >= 2);
|
||||
|
||||
@@ -613,7 +613,7 @@ ibuf_bitmap_page_set_bits(
|
||||
|
||||
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;
|
||||
|
||||
if (bit == IBUF_BITMAP_FREE) {
|
||||
@@ -687,7 +687,7 @@ ibuf_set_free_bits_low(
|
||||
mtr_t* mtr) /*!< in/out: mtr */
|
||||
{
|
||||
ut_ad(mtr->is_named_space(block->page.id().space()));
|
||||
if (!page_is_leaf(block->frame)) {
|
||||
if (!page_is_leaf(block->page.frame)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -721,7 +721,7 @@ ibuf_set_free_bits_func(
|
||||
#endif /* UNIV_IBUF_DEBUG */
|
||||
ulint val) /*!< in: value to set: < 4 */
|
||||
{
|
||||
if (!page_is_leaf(block->frame)) {
|
||||
if (!page_is_leaf(block->page.frame)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -831,7 +831,7 @@ ibuf_update_free_bits_zip(
|
||||
buf_block_t* block, /*!< in/out: index page */
|
||||
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());
|
||||
|
||||
ulint after = ibuf_index_page_calc_free_zip(block);
|
||||
@@ -956,7 +956,7 @@ ibuf_page_low(
|
||||
&local_mtr, &err);
|
||||
|
||||
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_commit(&local_mtr);
|
||||
@@ -971,7 +971,7 @@ ibuf_page_low(
|
||||
|
||||
ret = ibuf_bitmap_page_get_bits(ibuf_bitmap_get_map_page(
|
||||
page_id, zip_size,
|
||||
mtr)->frame,
|
||||
mtr)->page.frame,
|
||||
page_id, zip_size,
|
||||
IBUF_BITMAP_IBUF, mtr);
|
||||
|
||||
@@ -1814,11 +1814,11 @@ static bool ibuf_add_free_page()
|
||||
return false;
|
||||
}
|
||||
|
||||
ut_ad(block->lock.not_recursive());
|
||||
ut_ad(block->page.lock.not_recursive());
|
||||
ibuf_enter(&mtr);
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
@@ -3297,7 +3297,7 @@ fail_exit:
|
||||
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
|
||||
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,
|
||||
which it cannot do until we have buffered the IBUF_OP_DELETE
|
||||
and done mtr_commit(&mtr) to release the latch. */
|
||||
@@ -3322,7 +3322,7 @@ commit_exit:
|
||||
|
||||
if (op == IBUF_OP_INSERT) {
|
||||
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);
|
||||
|
||||
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
|
||||
break the latching order. */
|
||||
|
||||
root = ibuf_tree_root_get(&mtr)->frame;
|
||||
root = ibuf_tree_root_get(&mtr)->page.frame;
|
||||
|
||||
err = btr_cur_optimistic_insert(
|
||||
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 "
|
||||
<< page_get_max_insert_size(block->frame, 1)
|
||||
<< page_get_max_insert_size(block->page.frame, 1)
|
||||
<< ", dtuple size "
|
||||
<< rec_get_converted_size(index, entry, 0);
|
||||
|
||||
@@ -3653,9 +3653,10 @@ ibuf_insert_to_index_page_low(
|
||||
|
||||
ib::error() << "page " << block->page.id() << ", size "
|
||||
<< block->physical_size() << ", bitmap bits "
|
||||
<< ibuf_bitmap_page_get_bits(bitmap_page->frame,
|
||||
block->page.id(), block->zip_size(),
|
||||
IBUF_BITMAP_FREE, mtr);
|
||||
<< ibuf_bitmap_page_get_bits(
|
||||
bitmap_page->page.frame,
|
||||
block->page.id(), block->zip_size(),
|
||||
IBUF_BITMAP_FREE, mtr);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
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(
|
||||
id, zip_size, &mtr)) {
|
||||
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_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];
|
||||
|
||||
ut_ad(!block || page_id == block->page.id());
|
||||
ut_ad(!block || block->page.state() == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(!block || block->page.status == buf_page_t::NORMAL);
|
||||
ut_ad(!block || block->page.frame);
|
||||
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(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);
|
||||
|
||||
if (bitmap_page
|
||||
&& fil_page_get_type(bitmap_page->frame)
|
||||
&& fil_page_get_type(bitmap_page->page.frame)
|
||||
!= FIL_PAGE_TYPE_ALLOCATED) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
the debug checks. */
|
||||
|
||||
block->lock.claim_ownership();
|
||||
block->page.lock.claim_ownership();
|
||||
|
||||
if (!fil_page_index_page_check(block->frame)
|
||||
|| !page_is_leaf(block->frame)) {
|
||||
if (!fil_page_index_page_check(block->page.frame)
|
||||
|| !page_is_leaf(block->page.frame)) {
|
||||
|
||||
corruption_noticed = true;
|
||||
|
||||
ib::error() << "Corruption in the tablespace. Bitmap"
|
||||
" shows insert buffer records to page "
|
||||
<< 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"
|
||||
" to resolve the problem by skipping the"
|
||||
" insert buffer merge for this page. Please"
|
||||
@@ -4291,8 +4293,8 @@ loop:
|
||||
&pcur, &mtr);
|
||||
|
||||
if (block) {
|
||||
buf_block_buf_fix_inc(block);
|
||||
block->lock.x_lock_recursive();
|
||||
block->page.fix();
|
||||
block->page.lock.x_lock_recursive();
|
||||
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
|
||||
}
|
||||
|
||||
@@ -4351,7 +4353,7 @@ loop:
|
||||
dummy_index->table->space = space;
|
||||
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) {
|
||||
case IBUF_OP_INSERT:
|
||||
@@ -4401,8 +4403,8 @@ loop:
|
||||
ibuf_mtr_start(&mtr);
|
||||
mtr.set_named_space(space);
|
||||
|
||||
buf_block_buf_fix_inc(block);
|
||||
block->lock.x_lock_recursive();
|
||||
block->page.lock.x_lock_recursive();
|
||||
block->fix();
|
||||
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
|
||||
|
||||
if (!ibuf_restore_pos(page_id, search_tuple,
|
||||
@@ -4552,7 +4554,7 @@ ibuf_is_empty(void)
|
||||
|
||||
ut_d(mysql_mutex_lock(&ibuf_mutex));
|
||||
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_d(mysql_mutex_unlock(&ibuf_mutex));
|
||||
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;
|
||||
}
|
||||
|
||||
if (buf_is_zeroes(span<const byte>(bitmap_page->frame,
|
||||
if (buf_is_zeroes(span<const byte>(bitmap_page->page.frame,
|
||||
physical_size))) {
|
||||
/* This means we got all-zero page instead of
|
||||
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);
|
||||
|
||||
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)) {
|
||||
|
||||
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(
|
||||
bitmap_page->frame, cur_page_id, zip_size,
|
||||
bitmap_page->page.frame,
|
||||
cur_page_id, zip_size,
|
||||
IBUF_BITMAP_BUFFERED, &mtr)) {
|
||||
|
||||
ib_errf(trx->mysql_thd,
|
||||
|
@@ -460,9 +460,9 @@ template<bool has_prev= false>
|
||||
inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block,
|
||||
mtr_t *mtr)
|
||||
{
|
||||
ut_ad(block.frame == page_align(rec));
|
||||
ut_ad(!page_is_leaf(block.frame));
|
||||
ut_ad(has_prev == page_has_prev(block.frame));
|
||||
ut_ad(block.page.frame == page_align(rec));
|
||||
ut_ad(!page_is_leaf(block.page.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;
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
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);
|
||||
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) &&
|
||||
UNIV_LIKELY_NULL(block->page.zip.data))
|
||||
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)
|
||||
{
|
||||
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) &&
|
||||
UNIV_LIKELY_NULL(block->page.zip.data))
|
||||
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)
|
||||
{
|
||||
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) &&
|
||||
UNIV_LIKELY_NULL(block->page.zip.data))
|
||||
memcpy_aligned<4>(&block->page.zip.data[field], b, 4);
|
||||
|
@@ -73,36 +73,10 @@ struct btr_latch_leaves_t {
|
||||
#include "que0types.h"
|
||||
#include "row0types.h"
|
||||
|
||||
#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 */
|
||||
/*********************************************************//**
|
||||
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 */
|
||||
#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)
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the compressed page on which the tree cursor is positioned.
|
||||
@return pointer to compressed page, or NULL if the page is not compressed */
|
||||
|
@@ -36,44 +36,6 @@ if (btr_cur_limit_optimistic_insert_debug > 1\
|
||||
# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)
|
||||
#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.
|
||||
@return pointer to compressed page, or NULL if the page is not compressed */
|
||||
|
@@ -335,54 +335,11 @@ btr_pcur_move_to_next_page(
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the
|
||||
last record of the current page */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
#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 */
|
||||
/*********************************************************//**
|
||||
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 */
|
||||
|
||||
#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) btr_pcur_get_block(cursor)->page.frame
|
||||
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is on a user record. */
|
||||
UNIV_INLINE
|
||||
@@ -521,6 +478,25 @@ struct btr_pcur_t{
|
||||
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"
|
||||
|
||||
#endif
|
||||
|
@@ -43,76 +43,6 @@ btr_pcur_get_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.
|
||||
@return number of matched fields at the cursor or to the right if
|
||||
|
@@ -56,7 +56,7 @@ public:
|
||||
buf_block_t *block= m_block;
|
||||
bool res= f(block);
|
||||
if (block)
|
||||
buf_block_buf_fix_dec(block);
|
||||
block->page.unfix();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@@ -73,22 +73,6 @@ extern my_bool buf_disable_resize_buffer_pool_debug; /*!< if TRUE, resizing
|
||||
buffer pool is not allowed. */
|
||||
# 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
|
||||
will be used to print table IO stats */
|
||||
struct buf_pool_info_t
|
||||
@@ -170,12 +154,9 @@ operator<<(
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
# 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.
|
||||
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
|
||||
@return own: the allocated block, state()==MEMORY */
|
||||
inline buf_block_t *buf_block_alloc();
|
||||
/********************************************************************//**
|
||||
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. */
|
||||
#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)
|
||||
/********************************************************************//**
|
||||
This is the general function used to get optimistic access to a database
|
||||
page.
|
||||
@return TRUE if success */
|
||||
ibool
|
||||
buf_page_optimistic_get(
|
||||
/*====================*/
|
||||
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
|
||||
buf_block_t* block, /*!< in: guessed block */
|
||||
ib_uint64_t modify_clock,/*!< in: modify clock value */
|
||||
mtr_t* mtr); /*!< in: mini-transaction */
|
||||
/** Try to acquire a page latch.
|
||||
@param rw_latch RW_S_LATCH or RW_X_LATCH
|
||||
@param block guessed block
|
||||
@param modify_clock expected value of block->modify_clock
|
||||
@param mtr mini-transaction
|
||||
@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,
|
||||
uint64_t modify_clock, mtr_t *mtr);
|
||||
|
||||
/** Try to S-latch a page.
|
||||
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
|
||||
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
|
||||
be implemented at a higher level. In other words, all possible
|
||||
accesses to a given page through this function must be protected by
|
||||
the same set of mutexes or latches.
|
||||
@param[in] page_id page id
|
||||
@param[in] zip_size ROW_FORMAT=COMPRESSED page size
|
||||
@return pointer to the block */
|
||||
buf_page_t* buf_page_get_zip(const page_id_t page_id, ulint zip_size);
|
||||
@param page_id page identifier
|
||||
@param zip_size ROW_FORMAT=COMPRESSED page size in bytes
|
||||
@return pointer to the block, s-latched */
|
||||
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.
|
||||
@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
|
||||
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 =>
|
||||
FILE_PAGE (the other is buf_page_get_gen).
|
||||
of the functions which perform to a block a state transition NOT_USED => LRU
|
||||
(the other is buf_page_get_low()).
|
||||
@param[in,out] space space object
|
||||
@param[in] offset offset of the tablespace
|
||||
@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_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. */
|
||||
void buf_page_make_young(buf_page_t *bpage);
|
||||
/** 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_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 */
|
||||
|
||||
/** Check if a buffer is all zeroes.
|
||||
@@ -514,19 +469,7 @@ void buf_pool_invalidate();
|
||||
--------------------------- LOWER LEVEL ROUTINES -------------------------
|
||||
=========================================================================*/
|
||||
|
||||
#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 */
|
||||
MY_ATTRIBUTE((warn_unused_result));
|
||||
#else /* UNIV_DEBUG */
|
||||
# define buf_block_get_frame(block) (block)->frame
|
||||
#endif /* UNIV_DEBUG */
|
||||
#define buf_block_get_frame(block) (block)->page.frame
|
||||
|
||||
/*********************************************************************//**
|
||||
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
|
||||
counter value in MONITOR_MODULE_BUF_PAGE.
|
||||
@param bpage buffer page whose read or write was completed
|
||||
@param io_type BUF_IO_READ or BUF_IO_WRITE */
|
||||
ATTRIBUTE_COLD __attribute__((nonnull))
|
||||
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);
|
||||
@param read true=read, false=write */
|
||||
ATTRIBUTE_COLD void buf_page_monitor(const buf_page_t &bpage, bool read);
|
||||
|
||||
/** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit,
|
||||
if needed.
|
||||
@@ -618,6 +551,7 @@ class buf_page_t
|
||||
{
|
||||
friend buf_pool_t;
|
||||
friend buf_block_t;
|
||||
|
||||
/** @name General fields */
|
||||
/* @{ */
|
||||
|
||||
@@ -625,10 +559,9 @@ public: // FIXME: fix fil_iterate()
|
||||
/** Page id. Protected by buf_pool.page_hash.lock_get() when
|
||||
the page is in buf_pool.page_hash. */
|
||||
page_id_t id_;
|
||||
/** buf_pool.page_hash link; protected by buf_pool.page_hash.lock_get() */
|
||||
buf_page_t *hash;
|
||||
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
|
||||
oldest modification to this block which has not yet been written
|
||||
to the data file;
|
||||
@@ -639,53 +572,64 @@ private:
|
||||
(because id().space() is the temporary tablespace). */
|
||||
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:
|
||||
/** buf_pool.page_hash link; protected by buf_pool.page_hash.lock_get() */
|
||||
buf_page_t *hash;
|
||||
/* @} */
|
||||
page_zip_des_t zip; /*!< compressed page; zip.data
|
||||
(but not the data it points to) is
|
||||
also protected by buf_pool.mutex;
|
||||
state == BUF_BLOCK_ZIP_PAGE and
|
||||
zip.data == NULL means an active
|
||||
buf_pool.watch */
|
||||
/** state() of unused block (in buf_pool.free list) */
|
||||
static constexpr uint32_t NOT_USED= 0;
|
||||
/** state() of block allocated as general-purpose memory */
|
||||
static constexpr uint32_t MEMORY= 1;
|
||||
/** state() of block that is being freed */
|
||||
static constexpr uint32_t REMOVE_HASH= 2;
|
||||
/** smallest state() of a buffer page that is freed in the tablespace */
|
||||
static constexpr uint32_t FREED= 3;
|
||||
/** 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
|
||||
used for encryption/compression
|
||||
or NULL */
|
||||
/** lock covering the contents of frame */
|
||||
block_lock lock;
|
||||
/** 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
|
||||
/** whether this->list is in buf_pool.zip_hash; protected by buf_pool.mutex */
|
||||
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 */
|
||||
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 */
|
||||
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 */
|
||||
bool in_free_list;
|
||||
#endif /* UNIV_DEBUG */
|
||||
/** list member in one of the lists of buf_pool; protected by
|
||||
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():
|
||||
buf_pool.flush_list (protected by buf_pool.flush_list_mutex)
|
||||
|
||||
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;
|
||||
|
||||
/** @name LRU replacement algorithm fields.
|
||||
@@ -709,7 +653,7 @@ public:
|
||||
0 if the block was never accessed
|
||||
in the buffer pool.
|
||||
|
||||
For state==BUF_BLOCK_MEMORY
|
||||
For state() == MEMORY
|
||||
blocks, this field can be repurposed
|
||||
for something else.
|
||||
|
||||
@@ -717,89 +661,126 @@ public:
|
||||
and bytes allocated for recv_sys.pages,
|
||||
the field is protected by
|
||||
recv_sys_t::mutex. */
|
||||
/** Change buffer entries for the page exist.
|
||||
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)
|
||||
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);
|
||||
}
|
||||
|
||||
/** Initialize some fields */
|
||||
void init()
|
||||
buf_page_t(const buf_page_t &b) :
|
||||
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;
|
||||
buf_fix_count_= 0;
|
||||
old= 0;
|
||||
freed_page_clock= 0;
|
||||
access_time= 0;
|
||||
lock.init();
|
||||
}
|
||||
|
||||
/** Initialize some more fields */
|
||||
void init(uint32_t state, page_id_t id)
|
||||
{
|
||||
ut_ad(state < REMOVE_HASH || state >= UNFIXED);
|
||||
id_= id;
|
||||
zip.fix= state;
|
||||
oldest_modification_= 0;
|
||||
slot= nullptr;
|
||||
ibuf_exist= false;
|
||||
status= NORMAL;
|
||||
lock.init();
|
||||
ut_d(in_zip_hash= false);
|
||||
ut_d(in_free_list= false);
|
||||
ut_d(in_LRU_list= false);
|
||||
ut_d(in_page_hash= false);
|
||||
}
|
||||
|
||||
/** Initialize some more fields */
|
||||
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;
|
||||
old= 0;
|
||||
freed_page_clock= 0;
|
||||
access_time= 0;
|
||||
}
|
||||
|
||||
public:
|
||||
const page_id_t &id() const { return id_; }
|
||||
buf_page_state state() const { return state_; }
|
||||
uint32_t buf_fix_count() const { return buf_fix_count_; }
|
||||
buf_io_fix io_fix() const { return io_fix_; }
|
||||
void io_unfix()
|
||||
uint32_t state() const { return zip.fix; }
|
||||
uint32_t buf_fix_count() const
|
||||
{
|
||||
ut_d(const auto old_io_fix= io_fix());
|
||||
ut_ad(old_io_fix == BUF_IO_READ || old_io_fix == BUF_IO_PIN);
|
||||
io_fix_= BUF_IO_NONE;
|
||||
uint32_t f= state();
|
||||
ut_ad(f >= FREED);
|
||||
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 */
|
||||
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);
|
||||
inline void set_buf_fix_count(uint32_t count);
|
||||
inline void set_state(buf_page_state state);
|
||||
inline void set_io_fix(buf_io_fix io_fix);
|
||||
void set_ibuf_exist()
|
||||
{
|
||||
ut_ad(lock.is_write_locked());
|
||||
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();
|
||||
|
||||
/** @return the log sequence number of the oldest pending modification
|
||||
@@ -819,15 +800,35 @@ public:
|
||||
inline void set_oldest_modification(lsn_t lsn);
|
||||
/** Clear oldest_modification after removing from buf_pool.flush_list */
|
||||
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
|
||||
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. */
|
||||
void set_temp_modified()
|
||||
{
|
||||
ut_ad(fsp_is_system_temporary(id().space()));
|
||||
ut_ad(state() == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(in_file());
|
||||
ut_ad(!oldest_modification());
|
||||
oldest_modification_= 2;
|
||||
}
|
||||
@@ -835,19 +836,35 @@ public:
|
||||
/** Prepare to release a file page to buf_pool.free. */
|
||||
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() */
|
||||
ut_d(oldest_modification_= 0;)
|
||||
set_corrupt_id();
|
||||
ut_d(set_state(BUF_BLOCK_MEMORY));
|
||||
id_= page_id_t(~0ULL);
|
||||
}
|
||||
|
||||
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 count= buf_fix_count_--;
|
||||
ut_ad(count != 0);
|
||||
return count - 1;
|
||||
uint32_t f= zip.fix.fetch_sub(1);
|
||||
ut_ad(f > FREED);
|
||||
ut_ad(!((f ^ (f - 1)) & LRU_MASK));
|
||||
return f - 1;
|
||||
}
|
||||
|
||||
/** @return the physical size, in bytes */
|
||||
@@ -873,27 +890,10 @@ public:
|
||||
}
|
||||
|
||||
/** @return whether the block is mapped to a data file */
|
||||
bool in_file() const
|
||||
{
|
||||
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;
|
||||
}
|
||||
bool in_file() const { return state() >= FREED; }
|
||||
|
||||
/** @return whether the block is modified and ready for flushing */
|
||||
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.
|
||||
The block can be dirty, but it must not be I/O-fixed or bufferfixed. */
|
||||
inline bool can_relocate() const;
|
||||
@@ -925,27 +925,18 @@ struct buf_block_t{
|
||||
be the first field, so that
|
||||
buf_pool.page_hash can point
|
||||
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
|
||||
/** 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 */
|
||||
bool in_withdraw_list;
|
||||
/** 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 */
|
||||
bool in_unzip_LRU_list;
|
||||
#endif
|
||||
UT_LIST_NODE_T(buf_block_t) unzip_LRU;
|
||||
/*!< node of the decompressed LRU list;
|
||||
a block is in the unzip_LRU list
|
||||
if page.state() == BUF_BLOCK_FILE_PAGE
|
||||
and page.zip.data != NULL */
|
||||
/** member of buf_pool.unzip_LRU (if belongs_to_unzip_LRU()) */
|
||||
UT_LIST_NODE_T(buf_block_t) unzip_LRU;
|
||||
/* @} */
|
||||
/** @name Optimistic search field */
|
||||
/* @{ */
|
||||
@@ -984,17 +975,15 @@ struct buf_block_t{
|
||||
These 5 fields may only be modified when:
|
||||
we are holding the appropriate x-latch in btr_search_latches[], and
|
||||
one of the following holds:
|
||||
(1) the block state is BUF_BLOCK_FILE_PAGE, and
|
||||
we are holding an s-latch or x-latch on buf_block_t::lock, or
|
||||
(2) buf_block_t::buf_fix_count == 0, or
|
||||
(3) the block state is BUF_BLOCK_REMOVE_HASH.
|
||||
(1) in_file(), and we are holding lock in any mode, or
|
||||
(2) !is_read_fixed()&&(state()>=UNFIXED||state()==REMOVE_HASH).
|
||||
|
||||
An exception to this is when we init or create a page
|
||||
in the buffer pool in buf0buf.cc.
|
||||
|
||||
Another exception for buf_pool_t::clear_hash_index() is that
|
||||
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
|
||||
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
|
||||
condition whenever any of the following hold:
|
||||
- the btr_search_latches[] s-latch or x-latch is being held, or
|
||||
- the block state is not BUF_BLOCK_FILE_PAGE or BUF_BLOCK_REMOVE_HASH,
|
||||
- the btr_search_sys.partition[].latch is being held, or
|
||||
- state() == NOT_USED || state() == MEMORY,
|
||||
and holding some latch prevents the state from changing to that.
|
||||
|
||||
Some use of assert_block_ahi_empty() or assert_block_ahi_valid()
|
||||
@@ -1018,9 +1007,7 @@ struct buf_block_t{
|
||||
Atomic_counter<ulint>
|
||||
n_pointers; /*!< used in debugging: the number of
|
||||
pointers in the adaptive hash index
|
||||
pointing to this frame;
|
||||
protected by atomic memory access
|
||||
or btr_search_own_all(). */
|
||||
pointing to this frame */
|
||||
# define assert_block_ahi_empty(block) \
|
||||
ut_a((block)->n_pointers == 0)
|
||||
# define assert_block_ahi_empty_on_init(block) do { \
|
||||
@@ -1055,13 +1042,7 @@ struct buf_block_t{
|
||||
# define assert_block_ahi_valid(block) /* nothing */
|
||||
#endif /* BTR_CUR_HASH_ADAPT */
|
||||
void fix() { page.fix(); }
|
||||
uint32_t 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();
|
||||
}
|
||||
uint32_t unfix() { return page.unfix(); }
|
||||
|
||||
/** @return the physical size, in bytes */
|
||||
ulint physical_size() const { return page.physical_size(); }
|
||||
@@ -1073,15 +1054,15 @@ struct buf_block_t{
|
||||
/** Initialize the block.
|
||||
@param page_id page identifier
|
||||
@param zip_size ROW_FORMAT=COMPRESSED page size, or 0
|
||||
@param fix initial buf_fix_count() */
|
||||
void initialise(const page_id_t page_id, ulint zip_size, uint32_t fix= 0);
|
||||
@param state initial state() */
|
||||
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. */
|
||||
/* @{ */
|
||||
#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))
|
||||
/* @} */
|
||||
|
||||
@@ -1277,7 +1258,7 @@ class buf_pool_t
|
||||
size_t mem_size() const { return mem_pfx.m_size; }
|
||||
|
||||
/** 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.
|
||||
@param bytes requested size
|
||||
@@ -1369,7 +1350,7 @@ public:
|
||||
}
|
||||
|
||||
/** 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 */
|
||||
bool will_be_withdrawn(const byte *ptr) const
|
||||
{
|
||||
@@ -1382,8 +1363,8 @@ public:
|
||||
for (const chunk_t *chunk= chunks + n_chunks_new,
|
||||
* const echunk= chunks + n_chunks;
|
||||
chunk != echunk; chunk++)
|
||||
if (ptr >= chunk->blocks->frame &&
|
||||
ptr < (chunk->blocks + chunk->size - 1)->frame + srv_page_size)
|
||||
if (ptr >= chunk->blocks->page.frame &&
|
||||
ptr < (chunk->blocks + chunk->size - 1)->page.frame + srv_page_size)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -1487,17 +1468,11 @@ public:
|
||||
buf_page_t *bpage= page_hash.get(page_id, chain);
|
||||
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->zip.data);
|
||||
if (!allow_watch)
|
||||
bpage= nullptr;
|
||||
}
|
||||
else if (bpage)
|
||||
{
|
||||
ut_ad(page_id == bpage->id());
|
||||
ut_ad(bpage->in_file());
|
||||
}
|
||||
return bpage;
|
||||
}
|
||||
|
||||
@@ -1511,15 +1486,9 @@ public:
|
||||
page_hash.lock_get(page_hash.cell_get(bpage.id().fold())).
|
||||
is_locked());
|
||||
#endif /* SAFE_MUTEX */
|
||||
if (&bpage < &watch[0] || &bpage >= &watch[UT_ARR_SIZE(watch)])
|
||||
{
|
||||
ut_ad(bpage.state() == BUF_BLOCK_ZIP_PAGE
|
||||
? !!bpage.zip.data
|
||||
: bpage.state() == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(bpage.in_file());
|
||||
if (&bpage < &watch[0] || &bpage >= &watch[array_elements(watch)])
|
||||
return false;
|
||||
}
|
||||
|
||||
ut_ad(bpage.state() == BUF_BLOCK_ZIP_PAGE);
|
||||
ut_ad(!bpage.in_zip_hash);
|
||||
ut_ad(!bpage.zip.data);
|
||||
return true;
|
||||
@@ -1819,7 +1788,7 @@ public:
|
||||
}
|
||||
|
||||
// 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
|
||||
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)
|
||||
{
|
||||
ut_ad(bpage->in_page_hash);
|
||||
ut_ad(bpage->in_file());
|
||||
if (bpage->id() == id)
|
||||
return bpage;
|
||||
}
|
||||
@@ -2013,50 +1983,12 @@ inline void page_hash_latch::lock()
|
||||
}
|
||||
#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);
|
||||
buf_fix_count_+= count;
|
||||
}
|
||||
|
||||
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;
|
||||
ut_ad(s <= REMOVE_HASH || s >= UNFIXED);
|
||||
ut_ad(s <= READ_FIX);
|
||||
zip.fix= s;
|
||||
}
|
||||
|
||||
inline void buf_page_t::set_corrupt_id()
|
||||
@@ -2073,17 +2005,12 @@ inline void buf_page_t::set_corrupt_id()
|
||||
default:
|
||||
ut_ad("block is dirty" == 0);
|
||||
}
|
||||
switch (state()) {
|
||||
case BUF_BLOCK_REMOVE_HASH:
|
||||
break;
|
||||
case BUF_BLOCK_ZIP_PAGE:
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
const auto f= state();
|
||||
if (f != REMOVE_HASH)
|
||||
{
|
||||
ut_ad(f >= UNFIXED);
|
||||
ut_ad(buf_pool.page_hash.lock_get(buf_pool.page_hash.cell_get(id_.fold())).
|
||||
is_write_locked());
|
||||
break;
|
||||
case BUF_BLOCK_NOT_USED:
|
||||
case BUF_BLOCK_MEMORY:
|
||||
ut_ad("invalid state" == 0);
|
||||
}
|
||||
#endif
|
||||
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()
|
||||
{
|
||||
mysql_mutex_assert_owner(&buf_pool.flush_list_mutex);
|
||||
ut_d(const auto state= state_);
|
||||
ut_ad(state == BUF_BLOCK_FILE_PAGE || state == BUF_BLOCK_ZIP_PAGE ||
|
||||
state == BUF_BLOCK_REMOVE_HASH);
|
||||
ut_d(const auto s= state());
|
||||
ut_ad(s >= REMOVE_HASH);
|
||||
ut_ad(oldest_modification());
|
||||
ut_ad(!list.prev);
|
||||
ut_ad(!list.next);
|
||||
@@ -2114,36 +2040,15 @@ inline void buf_page_t::clear_oldest_modification()
|
||||
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 */
|
||||
inline bool buf_page_t::ready_for_flush() const
|
||||
{
|
||||
mysql_mutex_assert_owner(&buf_pool.mutex);
|
||||
ut_ad(in_LRU_list);
|
||||
ut_a(in_file());
|
||||
ut_ad(fsp_is_system_temporary(id().space())
|
||||
? oldest_modification() == 2
|
||||
: oldest_modification() > 2);
|
||||
return io_fix_ == BUF_IO_NONE;
|
||||
const auto s= state();
|
||||
ut_a(s >= FREED);
|
||||
ut_ad(!fsp_is_system_temporary(id().space()) || oldest_modification() == 2);
|
||||
return s < READ_FIX;
|
||||
}
|
||||
|
||||
/** @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
|
||||
{
|
||||
mysql_mutex_assert_owner(&buf_pool.mutex);
|
||||
ut_ad(in_file());
|
||||
const auto f= state();
|
||||
ut_ad(f >= FREED);
|
||||
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 */
|
||||
@@ -2214,41 +2121,26 @@ inline void buf_page_t::set_old(bool old)
|
||||
/**********************************************************************
|
||||
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
|
||||
page hash table
|
||||
MEMORY: is not in free list, LRU list, or flush list, nor page
|
||||
hash table
|
||||
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()
|
||||
NOT_USED: is in free list, not LRU, not flush_list, nor page_hash
|
||||
MEMORY: is not in any of free, LRU, flush_list, page_hash
|
||||
in_file(): is not in free list, is in LRU list, id() is defined,
|
||||
is in page_hash (not necessarily if is_read_fixed())
|
||||
|
||||
(1) if buf_fix_count == 0, then
|
||||
is in LRU list, not in free list
|
||||
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
|
||||
is in buf_pool.flush_list, if and only
|
||||
if oldest_modification == 1 || oldest_modification > 2
|
||||
|
||||
(2) if buf_fix_count > 0, then
|
||||
is not in LRU list, not in free list
|
||||
is in flush list,
|
||||
if and only if oldest_modification > 0
|
||||
if io_fix == BUF_IO_READ,
|
||||
is x-locked
|
||||
if io_fix == BUF_IO_WRITE,
|
||||
is s-locked
|
||||
(1) if is_write_fixed(): is u-locked
|
||||
(2) if is_read_fixed(): is x-locked
|
||||
|
||||
State transitions:
|
||||
|
||||
NOT_USED => MEMORY
|
||||
MEMORY => FILE_PAGE
|
||||
MEMORY => NOT_USED
|
||||
FILE_PAGE => NOT_USED NOTE: This transition is allowed if and only if
|
||||
(1) buf_fix_count == 0,
|
||||
(2) oldest_modification == 0, and
|
||||
(3) io_fix == 0.
|
||||
MEMORY => UNFIXED
|
||||
UNFIXED => in_file()
|
||||
in_file() => UNFIXED or FREED
|
||||
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
|
||||
|
@@ -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.
|
||||
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
|
||||
inline buf_block_t *buf_block_alloc()
|
||||
@@ -149,16 +117,11 @@ buf_block_modify_clock_inc(
|
||||
buf_block_t* block) /*!< in: block */
|
||||
{
|
||||
#ifdef SAFE_MUTEX
|
||||
/* No latch is acquired for the shared temporary tablespace. */
|
||||
ut_ad(fsp_is_system_temporary(block->page.id().space())
|
||||
|| (mysql_mutex_is_owner(&buf_pool.mutex)
|
||||
&& !block->page.buf_fix_count())
|
||||
|| block->lock.have_u_or_x());
|
||||
ut_ad((mysql_mutex_is_owner(&buf_pool.mutex)
|
||||
&& !block->page.buf_fix_count())
|
||||
|| block->page.lock.have_u_or_x());
|
||||
#else /* SAFE_MUTEX */
|
||||
/* No latch is acquired for the shared temporary tablespace. */
|
||||
ut_ad(fsp_is_system_temporary(block->page.id().space())
|
||||
|| !block->page.buf_fix_count()
|
||||
|| block->lock.have_u_or_x());
|
||||
ut_ad(!block->page.buf_fix_count() || block->page.lock.have_u_or_x());
|
||||
#endif /* SAFE_MUTEX */
|
||||
assert_block_ahi_valid(block);
|
||||
|
||||
@@ -175,77 +138,10 @@ buf_block_get_modify_clock(
|
||||
/*=======================*/
|
||||
buf_block_t* block) /*!< in: block */
|
||||
{
|
||||
/* No latch is acquired for the shared temporary tablespace. */
|
||||
ut_ad(fsp_is_system_temporary(block->page.id().space())
|
||||
|| block->lock.have_any());
|
||||
ut_ad(block->page.lock.have_any());
|
||||
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,
|
||||
if needed.
|
||||
@param[in] size size in bytes
|
||||
|
@@ -24,12 +24,11 @@ The database buffer pool flush algorithm
|
||||
Created 11/5/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef buf0flu_h
|
||||
#define buf0flu_h
|
||||
#pragma once
|
||||
|
||||
#include "ut0byte.h"
|
||||
#include "log0log.h"
|
||||
#include "buf0types.h"
|
||||
#include "buf0buf.h"
|
||||
|
||||
/** Number of pages flushed. Protected by buf_pool.mutex. */
|
||||
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
|
||||
modified in it. Puts the block to the list of modified blocks, if it 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 first mtr in a
|
||||
set of mtr's */
|
||||
lsn_t end_lsn); /*!< in: end lsn of the last mtr in the
|
||||
set of mtr's */
|
||||
inline void buf_flush_note_modification(buf_block_t *b, lsn_t start, lsn_t end)
|
||||
{
|
||||
ut_ad(!srv_read_only_mode);
|
||||
ut_d(const auto s= b->page.state());
|
||||
ut_ad(s > buf_page_t::FREED);
|
||||
ut_ad(s < buf_page_t::READ_FIX);
|
||||
ut_ad(mach_read_from_8(b->page.frame + FIL_PAGE_LSN) <= end);
|
||||
mach_write_to_8(b->page.frame + FIL_PAGE_LSN, end);
|
||||
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. */
|
||||
ATTRIBUTE_COLD void buf_flush_page_cleaner_init();
|
||||
@@ -149,7 +161,3 @@ void buf_flush_validate();
|
||||
/** Synchronously flush dirty blocks.
|
||||
NOTE: The calling thread is not allowed to hold any buffer page latches! */
|
||||
void buf_flush_sync();
|
||||
|
||||
#include "buf0flu.ic"
|
||||
|
||||
#endif
|
||||
|
@@ -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();
|
||||
}
|
@@ -39,16 +39,6 @@ struct buf_buddy_stat_t;
|
||||
/** A buffer frame. @see page_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
|
||||
setting innodb_checksum_algorithm */
|
||||
enum srv_checksum_algorithm_t {
|
||||
@@ -189,10 +179,8 @@ public:
|
||||
/** Acquire an exclusive lock */
|
||||
inline void lock();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/** @return whether an exclusive lock is being held by any thread */
|
||||
bool is_write_locked() const { return rw_lock::is_write_locked(); }
|
||||
#endif
|
||||
|
||||
/** @return whether any lock is being held by any thread */
|
||||
bool is_locked() const { return rw_lock::is_locked(); }
|
||||
|
@@ -296,17 +296,15 @@ byte* fil_space_encrypt(
|
||||
@param[in] tmp_frame Temporary buffer
|
||||
@param[in] physical_size page size
|
||||
@param[in,out] src_frame Page to decrypt
|
||||
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
|
||||
@return true if page decrypted, false if not.*/
|
||||
bool
|
||||
@return DB_SUCCESS or error */
|
||||
dberr_t
|
||||
fil_space_decrypt(
|
||||
uint32_t space_id,
|
||||
uint32_t fsp_flags,
|
||||
fil_space_crypt_t* crypt_data,
|
||||
byte* tmp_frame,
|
||||
ulint physical_size,
|
||||
byte* src_frame,
|
||||
dberr_t* err);
|
||||
byte* src_frame);
|
||||
|
||||
/******************************************************************
|
||||
Decrypt a page
|
||||
|
@@ -545,9 +545,8 @@ fil_block_check_type(
|
||||
ulint type,
|
||||
mtr_t* mtr)
|
||||
{
|
||||
if (UNIV_UNLIKELY(type != fil_page_get_type(block.frame))) {
|
||||
fil_block_reset_type(block, type, mtr);
|
||||
}
|
||||
if (UNIV_UNLIKELY(type != fil_page_get_type(block.page.frame)))
|
||||
fil_block_reset_type(block, type, mtr);
|
||||
}
|
||||
|
||||
/** Checks if a page address is an extent descriptor page address.
|
||||
|
@@ -61,7 +61,7 @@ fut_get_ptr(
|
||||
rw_latch, nullptr, BUF_GET_POSSIBLY_FREED,
|
||||
mtr);
|
||||
if (!block) {
|
||||
} else if (block->page.status == buf_page_t::FREED) {
|
||||
} else if (block->page.is_freed()) {
|
||||
block = nullptr;
|
||||
} else {
|
||||
ptr = buf_block_get_frame(block) + addr.boffset;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
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 */
|
||||
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_ad(!mach_read_from_2(FLST_FIRST + FIL_ADDR_BYTE + ofs + block->frame));
|
||||
ut_ad(!mach_read_from_2(FLST_LAST + FIL_ADDR_BYTE + ofs + block->frame));
|
||||
ut_d(const page_t *page= block->page.frame);
|
||||
ut_ad(!mach_read_from_2(FLST_LEN + ofs + page));
|
||||
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);
|
||||
mtr->memset(block, FLST_FIRST + FIL_ADDR_PAGE + ofs, 4, 0xff);
|
||||
mtr->memset(block, FLST_LAST + FIL_ADDR_PAGE + ofs, 4, 0xff);
|
||||
|
@@ -37,7 +37,7 @@ lock_get_min_heap_no(
|
||||
/*=================*/
|
||||
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)) {
|
||||
return(rec_get_heap_no_new(
|
||||
@@ -74,6 +74,6 @@ lock_rec_create(
|
||||
btr_assert_not_corrupted(block, index);
|
||||
return lock_rec_create_low(
|
||||
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);
|
||||
}
|
||||
|
@@ -225,7 +225,7 @@ private:
|
||||
public:
|
||||
/** whether we are applying redo log records during crash recovery */
|
||||
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*/
|
||||
bool apply_log_recs;
|
||||
byte* buf; /*!< buffer for parsing log records */
|
||||
|
@@ -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
|
||||
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>
|
||||
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");
|
||||
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 + len <= ulint(srv_page_size));
|
||||
::memset(ofs + b->frame, val, len);
|
||||
::memset(ofs + b->page.frame, val, len);
|
||||
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;
|
||||
while (s < len)
|
||||
{
|
||||
::memcpy(ofs + s + b->frame, str, size);
|
||||
::memcpy(ofs + s + b->page.frame, str, size);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ inline void mtr_t::memcpy(const buf_block_t &b, ulint offset, ulint len)
|
||||
ut_ad(len);
|
||||
ut_ad(offset <= 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.
|
||||
@@ -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,
|
||||
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);
|
||||
const char *s= static_cast<const char*>(str);
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@@ -30,7 +30,8 @@ Created 11/26/1995 Heikki Tuuri
|
||||
@return true if the mtr is dirtying a clean page. */
|
||||
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());
|
||||
return block->page.oldest_modification() <= 1;
|
||||
}
|
||||
@@ -109,7 +110,8 @@ mtr_t::sx_latch_at_savepoint(
|
||||
/* == RW_NO_LATCH */
|
||||
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) {
|
||||
m_made_dirty = is_block_dirtied(block);
|
||||
@@ -142,7 +144,8 @@ mtr_t::x_latch_at_savepoint(
|
||||
/* == RW_NO_LATCH */
|
||||
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) {
|
||||
m_made_dirty = is_block_dirtied(block);
|
||||
@@ -159,15 +162,23 @@ mtr_t::release_block_at_savepoint(
|
||||
ulint savepoint,
|
||||
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);
|
||||
|
||||
reinterpret_cast<buf_block_t*>(block)->unfix();
|
||||
|
||||
slot->object = NULL;
|
||||
switch (slot->type) {
|
||||
case MTR_MEMO_PAGE_S_FIX:
|
||||
block->page.lock.s_unlock();
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@@ -51,6 +51,8 @@ extern bool os_has_said_disk_full;
|
||||
/** File offset in bytes */
|
||||
typedef ib_uint64_t os_offset_t;
|
||||
|
||||
class buf_tmp_buffer_t;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/** We define always WIN_ASYNC_IO, and check at run-time whether
|
||||
@@ -206,11 +208,13 @@ public:
|
||||
PUNCH_RANGE= WRITE_SYNC | 128,
|
||||
};
|
||||
|
||||
constexpr IORequest(buf_page_t *bpage, fil_node_t *node, Type type) :
|
||||
bpage(bpage), node(node), type(type) {}
|
||||
constexpr IORequest(buf_page_t *bpage, buf_tmp_buffer_t *slot,
|
||||
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) :
|
||||
bpage(bpage), type(type) {}
|
||||
constexpr IORequest(Type type= READ_SYNC, buf_page_t *bpage= nullptr,
|
||||
buf_tmp_buffer_t *slot= nullptr) :
|
||||
bpage(bpage), slot(slot), type(type) {}
|
||||
|
||||
bool is_read() const { return (type & READ_SYNC) != 0; }
|
||||
bool is_write() const { return (type & WRITE_SYNC) != 0; }
|
||||
@@ -237,7 +241,10 @@ private:
|
||||
|
||||
public:
|
||||
/** 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 */
|
||||
fil_node_t *const node= nullptr;
|
||||
|
@@ -34,13 +34,7 @@ page_cur_get_page(
|
||||
/*==============*/
|
||||
page_cur_t* cur) /*!< in: page cursor */
|
||||
{
|
||||
ut_ad(cur);
|
||||
|
||||
if (cur->rec) {
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
}
|
||||
|
||||
return(page_align(cur->rec));
|
||||
return page_align(page_cur_get_rec(cur));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
@@ -52,13 +46,9 @@ page_cur_get_block(
|
||||
/*===============*/
|
||||
page_cur_t* cur) /*!< in: page cursor */
|
||||
{
|
||||
ut_ad(cur);
|
||||
|
||||
if (cur->rec) {
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
}
|
||||
|
||||
return(cur->block);
|
||||
ut_ad(cur);
|
||||
ut_ad(!cur->rec || page_align(cur->rec) == cur->block->page.frame);
|
||||
return cur->block;
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
@@ -82,13 +72,9 @@ page_cur_get_rec(
|
||||
/*=============*/
|
||||
page_cur_t* cur) /*!< in: page cursor */
|
||||
{
|
||||
ut_ad(cur);
|
||||
|
||||
if (cur->rec) {
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
}
|
||||
|
||||
return(cur->rec);
|
||||
ut_ad(cur);
|
||||
ut_ad(!cur->rec || page_align(cur->rec) == cur->block->page.frame);
|
||||
return cur->rec;
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
@@ -102,7 +88,7 @@ page_cur_set_before_first(
|
||||
const buf_block_t* block, /*!< in: index page */
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -116,7 +102,7 @@ page_cur_set_after_last(
|
||||
const buf_block_t* block, /*!< in: index page */
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -130,7 +116,7 @@ page_cur_is_before_first(
|
||||
const page_cur_t* cur) /*!< in: cursor */
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -144,7 +130,7 @@ page_cur_is_after_last(
|
||||
const page_cur_t* cur) /*!< in: cursor */
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -160,7 +146,7 @@ page_cur_position(
|
||||
page_cur_t* cur) /*!< out: page cursor */
|
||||
{
|
||||
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->block = (buf_block_t*) block;
|
||||
@@ -273,7 +259,7 @@ page_cur_tuple_insert(
|
||||
index, tuple, n_ext);
|
||||
|
||||
*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,
|
||||
ULINT_UNDEFINED, heap);
|
||||
ut_ad(size == rec_offs_size(*offsets));
|
||||
|
@@ -418,8 +418,8 @@ template<bool compressed>
|
||||
inline void page_rec_set_n_owned(buf_block_t *block, rec_t *rec, ulint n_owned,
|
||||
bool comp, mtr_t *mtr)
|
||||
{
|
||||
ut_ad(block->frame == page_align(rec));
|
||||
ut_ad(comp == (page_is_comp(block->frame) != 0));
|
||||
ut_ad(block->page.frame == page_align(rec));
|
||||
ut_ad(comp == (page_is_comp(block->page.frame) != 0));
|
||||
|
||||
if (page_zip_des_t *page_zip= compressed
|
||||
? buf_block_get_page_zip(block) : nullptr)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user