diff options
Diffstat (limited to 'storage/xtradb/buf/buf0checksum.cc')
-rw-r--r-- | storage/xtradb/buf/buf0checksum.cc | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/storage/xtradb/buf/buf0checksum.cc b/storage/xtradb/buf/buf0checksum.cc index 01b646a78e0..98abba575ef 100644 --- a/storage/xtradb/buf/buf0checksum.cc +++ b/storage/xtradb/buf/buf0checksum.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 2018, 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 @@ -28,6 +29,7 @@ Created Aug 11, 2011 Vasil Dimov #include "ut0crc32.h" /* ut_crc32() */ #include "ut0rnd.h" /* ut_fold_binary() */ #include "buf0types.h" +#include "mach0data.h" #ifndef UNIV_INNOCHECKSUM @@ -154,3 +156,46 @@ buf_checksum_algorithm_name( ut_error; return(NULL); } + +/** Calculates the CRC32 checksum of a page compressed page. The value is +stored to the page when it is written to a file and also checked for +a match when reading from the file. Checksum is calculated from +actual payload of the compressed page and some header fields. + +@param[in] page buffer page (UNIV_PAGE_SIZE bytes) +@return checksum */ +UNIV_INTERN +uint32_t +buf_calc_compressed_crc32( + const byte* page) +{ + /* In page compressed pages compression method is stored to field + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, thus add it to checksum. + In pages first compressed and then encrypted same field + contains key version after compression. */ + + ulint page_type = mach_read_from_2(page + FIL_PAGE_TYPE); + + ulint header_len = page_type == FIL_PAGE_PAGE_COMPRESSED ? + FIL_PAGE_SPACE_ID - FIL_PAGE_OFFSET : + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION - FIL_PAGE_OFFSET; + + const uint32_t c1 = ut_crc32( + page + FIL_PAGE_OFFSET, + header_len); + + /* Calculate checksum from actual payload including stored size + field. In encrypted case add also compression method field. */ + ulint payload_len = mach_read_from_2(page+FIL_PAGE_DATA)+FIL_PAGE_COMPRESSED_SIZE; + + if (page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) { + payload_len += FIL_PAGE_COMPRESSION_METHOD_SIZE; + } + + const uint32_t c2 = ut_crc32( + page + FIL_PAGE_DATA, + payload_len); + + return(c1 ^ c2); +} + |