summaryrefslogtreecommitdiff
path: root/storage/xtradb/buf/buf0checksum.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/xtradb/buf/buf0checksum.cc')
-rw-r--r--storage/xtradb/buf/buf0checksum.cc45
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);
+}
+