summaryrefslogtreecommitdiff
path: root/storage/innobase/buf/buf0buf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/buf/buf0buf.cc')
-rw-r--r--storage/innobase/buf/buf0buf.cc277
1 files changed, 162 insertions, 115 deletions
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 9c569691ef0..46f7f5a49df 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
@@ -487,6 +487,79 @@ buf_page_is_zeroes(
return(true);
}
+/** Checks if the page is in crc32 checksum format.
+@param[in] read_buf database page
+@param[in] checksum_field1 new checksum field
+@param[in] checksum_field2 old checksum field
+@return true if the page is in crc32 checksum format */
+UNIV_INLINE
+bool
+buf_page_is_checksum_valid_crc32(
+ const byte* read_buf,
+ ulint checksum_field1,
+ ulint checksum_field2)
+{
+ ib_uint32_t crc32 = buf_calc_page_crc32(read_buf);
+
+ return(checksum_field1 == crc32 && checksum_field2 == crc32);
+}
+
+/** Checks if the page is in innodb checksum format.
+@param[in] read_buf database page
+@param[in] checksum_field1 new checksum field
+@param[in] checksum_field2 old checksum field
+@return true if the page is in innodb checksum format */
+UNIV_INLINE
+bool
+buf_page_is_checksum_valid_innodb(
+ const byte* read_buf,
+ ulint checksum_field1,
+ ulint checksum_field2)
+{
+ /* There are 2 valid formulas for
+ checksum_field2 (old checksum field) which algo=innodb could have
+ written to the page:
+
+ 1. Very old versions of InnoDB only stored 8 byte lsn to the
+ start and the end of the page.
+
+ 2. Newer InnoDB versions store the old formula checksum
+ (buf_calc_page_old_checksum()). */
+
+ if (checksum_field2 != mach_read_from_4(read_buf + FIL_PAGE_LSN)
+ && checksum_field2 != buf_calc_page_old_checksum(read_buf)) {
+ return(false);
+ }
+
+ /* old field is fine, check the new field */
+
+ /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
+ (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */
+
+ if (checksum_field1 != 0
+ && checksum_field1 != buf_calc_page_new_checksum(read_buf)) {
+ return(false);
+ }
+
+ return(true);
+}
+
+/** Checks if the page is in none checksum format.
+@param[in] read_buf database page
+@param[in] checksum_field1 new checksum field
+@param[in] checksum_field2 old checksum field
+@return true if the page is in none checksum format */
+UNIV_INLINE
+bool
+buf_page_is_checksum_valid_none(
+ const byte* read_buf,
+ ulint checksum_field1,
+ ulint checksum_field2)
+{
+ return(checksum_field1 == checksum_field2
+ && checksum_field1 == BUF_NO_CHECKSUM_MAGIC);
+}
+
/********************************************************************//**
Checks if a page is corrupt.
@return TRUE if corrupted */
@@ -502,8 +575,6 @@ buf_page_is_corrupted(
{
ulint checksum_field1;
ulint checksum_field2;
- ibool crc32_inited = FALSE;
- ib_uint32_t crc32 = ULINT32_UNDEFINED;
if (!zip_size
&& memcmp(read_buf + FIL_PAGE_LSN + 4,
@@ -583,148 +654,121 @@ buf_page_is_corrupted(
return(FALSE);
}
- switch ((srv_checksum_algorithm_t) srv_checksum_algorithm) {
- case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
-
- crc32 = buf_calc_page_crc32(read_buf);
-
- return(checksum_field1 != crc32 || checksum_field2 != crc32);
-
- case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
-
- return(checksum_field1
- != buf_calc_page_new_checksum(read_buf)
- || checksum_field2
- != buf_calc_page_old_checksum(read_buf));
-
- case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
+ DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", return(TRUE); );
- return(checksum_field1 != BUF_NO_CHECKSUM_MAGIC
- || checksum_field2 != BUF_NO_CHECKSUM_MAGIC);
+ ulint page_no = mach_read_from_4(read_buf + FIL_PAGE_OFFSET);
+ ulint space_id = mach_read_from_4(read_buf + FIL_PAGE_SPACE_ID);
+ const srv_checksum_algorithm_t curr_algo =
+ static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
+ switch (curr_algo) {
case SRV_CHECKSUM_ALGORITHM_CRC32:
- case SRV_CHECKSUM_ALGORITHM_INNODB:
- /* There are 3 valid formulas for
- checksum_field2 (old checksum field):
-
- 1. Very old versions of InnoDB only stored 8 byte lsn to the
- start and the end of the page.
-
- 2. InnoDB versions before MySQL 5.6.3 store the old formula
- checksum (buf_calc_page_old_checksum()).
-
- 3. InnoDB versions 5.6.3 and newer with
- innodb_checksum_algorithm=strict_crc32|crc32 store CRC32. */
-
- /* since innodb_checksum_algorithm is not strict_* allow
- any of the algos to match for the old field */
-
- if (checksum_field2
- != mach_read_from_4(read_buf + FIL_PAGE_LSN)
- && checksum_field2 != BUF_NO_CHECKSUM_MAGIC) {
-
- /* The checksum does not match any of the
- fast to check. First check the selected algorithm
- for writing checksums because we assume that the
- chance of it matching is higher. */
-
- if (srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_CRC32) {
-
- crc32 = buf_calc_page_crc32(read_buf);
- crc32_inited = TRUE;
-
- if (checksum_field2 != crc32
- && checksum_field2
- != buf_calc_page_old_checksum(read_buf)) {
+ case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
- return(TRUE);
- }
- } else {
- ut_ad(srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_INNODB);
+ if (buf_page_is_checksum_valid_crc32(read_buf,
+ checksum_field1, checksum_field2)) {
+ return(FALSE);
+ }
- if (checksum_field2
- != buf_calc_page_old_checksum(read_buf)) {
+ if (buf_page_is_checksum_valid_none(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_NONE,
+ space_id, page_no);
+ }
- crc32 = buf_calc_page_crc32(read_buf);
- crc32_inited = TRUE;
+ return(FALSE);
+ }
- if (checksum_field2 != crc32) {
- return(TRUE);
- }
- }
+ if (buf_page_is_checksum_valid_innodb(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_INNODB,
+ space_id, page_no);
}
- }
- /* old field is fine, check the new field */
+ return(FALSE);
+ }
- /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
- (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */
+ return(TRUE);
- if (checksum_field1 != 0
- && checksum_field1 != BUF_NO_CHECKSUM_MAGIC) {
+ case SRV_CHECKSUM_ALGORITHM_INNODB:
+ case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
- /* The checksum does not match any of the
- fast to check. First check the selected algorithm
- for writing checksums because we assume that the
- chance of it matching is higher. */
+ if (buf_page_is_checksum_valid_innodb(read_buf,
+ checksum_field1, checksum_field2)) {
+ return(FALSE);
+ }
- if (srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_CRC32) {
+ if (buf_page_is_checksum_valid_none(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_NONE,
+ space_id, page_no);
+ }
- if (!crc32_inited) {
- crc32 = buf_calc_page_crc32(read_buf);
- crc32_inited = TRUE;
- }
+ return(FALSE);
+ }
- if (checksum_field1 != crc32
- && checksum_field1
- != buf_calc_page_new_checksum(read_buf)) {
+ if (buf_page_is_checksum_valid_crc32(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_CRC32,
+ space_id, page_no);
+ }
- return(TRUE);
- }
- } else {
- ut_ad(srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_INNODB);
+ return(FALSE);
+ }
- if (checksum_field1
- != buf_calc_page_new_checksum(read_buf)) {
+ return(TRUE);
- if (!crc32_inited) {
- crc32 = buf_calc_page_crc32(
- read_buf);
- crc32_inited = TRUE;
- }
+ case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
- if (checksum_field1 != crc32) {
- return(TRUE);
- }
- }
- }
+ if (buf_page_is_checksum_valid_none(read_buf,
+ checksum_field1, checksum_field2)) {
+ return(FALSE);
}
- /* If CRC32 is stored in at least one of the fields, then the
- other field must also be CRC32 */
- if (crc32_inited
- && ((checksum_field1 == crc32
- && checksum_field2 != crc32)
- || (checksum_field1 != crc32
- && checksum_field2 == crc32))) {
+ if (buf_page_is_checksum_valid_crc32(read_buf,
+ checksum_field1, checksum_field2)) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_CRC32,
+ space_id, page_no);
+ return(FALSE);
+ }
- return(TRUE);
+ if (buf_page_is_checksum_valid_innodb(read_buf,
+ checksum_field1, checksum_field2)) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_INNODB,
+ space_id, page_no);
+ return(FALSE);
}
- break;
+ return(TRUE);
+
case SRV_CHECKSUM_ALGORITHM_NONE:
/* should have returned FALSE earlier */
- ut_error;
+ break;
/* no default so the compiler will emit a warning if new enum
is added and not handled here */
}
- DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", return(TRUE); );
-
+ ut_error;
return(FALSE);
}
@@ -1679,6 +1723,9 @@ page_found:
goto page_found;
}
+ /* The maximum number of purge threads should never exceed
+ BUF_POOL_WATCH_SIZE. So there is no way for purge thread
+ instance to hold a watch when setting another watch. */
for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
bpage = &buf_pool->watch[i];