diff options
-rw-r--r-- | extra/innochecksum.cc | 598 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innochecksum.test | 1 | ||||
-rw-r--r-- | mysql-test/suite/innodb/include/innodb-wl6045.inc | 22 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/innodb_zip_innochecksum.result | 91 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/innodb_zip_innochecksum2.result | 160 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/innodb_zip_innochecksum3.result | 227 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb_zip_innochecksum.opt | 4 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb_zip_innochecksum.test | 239 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb_zip_innochecksum2.opt | 4 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb_zip_innochecksum2.test | 118 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb_zip_innochecksum3.opt | 2 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb_zip_innochecksum3.test | 406 | ||||
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 54 | ||||
-rw-r--r-- | storage/innobase/include/page0size.h | 200 | ||||
-rw-r--r-- | storage/innobase/include/univ.i | 8 | ||||
-rw-r--r-- | storage/innobase/page/page0zip.cc | 8 |
16 files changed, 1899 insertions, 243 deletions
diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index e258a8c1d08..7ad71aa8159 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -67,6 +67,7 @@ typedef void fil_space_t; #include "ut0crc32.h" /* ut_crc32_init() */ #include "fsp0pagecompress.h" /* fil_get_compression_alg_name */ #include "fil0crypt.h" /* fil_space_verify_crypt_checksum */ +#include "page0size.h" #include <string.h> @@ -83,9 +84,9 @@ typedef void fil_space_t; /* Global variables */ static bool verbose; static bool just_count; -static ulint start_page; -static ulint end_page; -static ulint do_page; +static unsigned long long start_page; +static unsigned long long end_page; +static unsigned long long do_page; static bool use_end_page; static bool do_one_page; static my_bool do_leaf; @@ -95,8 +96,9 @@ extern ulong srv_checksum_algorithm; static ulong physical_page_size; /* Page size in bytes on disk. */ static ulong logical_page_size; /* Page size when uncompressed. */ ulong srv_page_size; +page_size_t univ_page_size(0, 0, false); /* Current page number (0 based). */ -ulint cur_page_num; +unsigned long long cur_page_num; /* Skip the checksum verification. */ static bool no_check; /* Enabled for strict checksum verification. */ @@ -104,7 +106,7 @@ bool strict_verify = 0; /* Enabled for rewrite checksum. */ static bool do_write; /* Mismatches count allowed (0 by default). */ -static ulint allow_mismatches; +static unsigned long long allow_mismatches=0; static bool page_type_summary; static bool page_type_dump; /* Store filename for page-type-dump option. */ @@ -228,7 +230,7 @@ void print_index_leaf_stats( fprintf(fil_out, "page_no\tdata_size\tn_recs\n"); while (it_page != index.leaves.end()) { const per_page_stats& stat = it_page->second; - fprintf(fil_out, "%llu\t%lu\t%lu\n", it_page->first, stat.data_size, stat.n_recs); + fprintf(fil_out, "%llu\t" ULINTPF "\t" ULINTPF "\n", it_page->first, stat.data_size, stat.n_recs); page_no = stat.right_page_no; it_page = index.leaves.find(page_no); } @@ -264,14 +266,14 @@ void defrag_analysis( } if (index.leaf_pages) { - fprintf(fil_out, "count = %lu free = %lu\n", index.count, index.free_pages); + fprintf(fil_out, "count = " ULINTPF " free = " ULINTPF "\n", index.count, index.free_pages); } if (!n_leaf_pages) { n_leaf_pages = 1; } - fprintf(fil_out, "%llu\t\t%llu\t\t%lu\t\t%lu\t\t%lu\t\t%.2f\t%lu\n", + fprintf(fil_out, "%llu\t\t%llu\t\t" ULINTPF "\t\t" ULINTPF "\t\t" ULINTPF "\t\t%.2f\t" ULINTPF "\n", id, index.leaf_pages, n_leaf_pages, n_merge, n_pages, 1.0 - (double)n_pages / (double)n_leaf_pages, index.max_data_size); } @@ -296,6 +298,31 @@ void print_leaf_stats( } } +/** Get the page size of the filespace from the filespace header. +@param[in] buf buffer used to read the page. +@return page size */ +static +const page_size_t +get_page_size( + byte* buf) +{ + const ulint flags = mach_read_from_4(buf + FIL_PAGE_DATA + + FSP_SPACE_FLAGS); + + const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); + + if (ssize == 0) { + srv_page_size = UNIV_PAGE_SIZE_ORIG; + } else { + srv_page_size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize); + } + + univ_page_size.copy_from( + page_size_t(srv_page_size, srv_page_size, false)); + + return(page_size_t(flags)); +} + #ifdef _WIN32 /***********************************************//* @param [in] error error no. from the getLastError(). @@ -426,7 +453,6 @@ ulong read_file( /** Check if page is corrupted or not. @param[in] buf page frame @param[in] page_size page size -@param[in] zip_size != if page row compressed @param[in] is_encrypted true if page0 contained cryp_data with crypt_scheme encrypted @param[in] is_compressed true if page0 fsp_flags contained @@ -436,8 +462,7 @@ static bool is_page_corrupted( byte* buf, - ulint page_size, - ulint zip_size, + const page_size_t& page_size, bool is_encrypted, bool is_compressed) { @@ -448,7 +473,7 @@ is_page_corrupted( ulint logseq; ulint logseqfield; ulint page_type = mach_read_from_2(buf+FIL_PAGE_TYPE); - ulint key_version = mach_read_from_4(buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); + uint key_version = mach_read_from_4(buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); ulint space_id = mach_read_from_4( buf + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); @@ -462,23 +487,23 @@ is_page_corrupted( return (false); } - if (!zip_size) { + if (page_size.is_compressed()) { /* check the stored log sequence numbers for uncompressed tablespace. */ logseq = mach_read_from_4(buf + FIL_PAGE_LSN + 4); logseqfield = mach_read_from_4( - buf + page_size - - FIL_PAGE_END_LSN_OLD_CHKSUM + 4); + buf + page_size.logical() - + FIL_PAGE_END_LSN_OLD_CHKSUM + 4); if (is_log_enabled) { fprintf(log_file, - "space::%" PRIuMAX " page::%" PRIuMAX + "space::" ULINTPF " page::%llu" "; log sequence number:first = " ULINTPF "; second = " ULINTPF "\n", space_id, cur_page_num, logseq, logseqfield); if (logseq != logseqfield) { fprintf(log_file, - "Fail; space %" PRIuMAX " page %" PRIuMAX + "Fail; space::" ULINTPF " page::%llu" " invalid (fails log " "sequence number check)\n", space_id, cur_page_num); @@ -488,13 +513,23 @@ is_page_corrupted( /* Again we can't trust only FIL_PAGE_FILE_FLUSH_LSN field now repurposed as FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, - we need to check also crypt_data contents. */ + we need to check also crypt_data contents. + + If page is encrypted, use different checksum calculation + as innochecksum can't decrypt pages. Note that some old InnoDB + versions did not initialize FIL_PAGE_FILE_FLUSH_LSN field + so if crypt checksum does not match we verify checksum using + normal method. */ if (is_encrypted && key_version != 0) { is_corrupted = !fil_space_verify_crypt_checksum(buf, - zip_size, NULL, cur_page_num); + page_size.is_compressed() ? page_size.physical() : 0, NULL, cur_page_num); } else { + is_corrupted = true; + } + + if (is_corrupted) { is_corrupted = buf_page_is_corrupted( - true, buf, zip_size, NULL); + true, buf, page_size.is_compressed() ? page_size.physical() : 0, NULL); } return(is_corrupted); @@ -592,7 +627,7 @@ update_checksum( mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum); if (is_log_enabled) { - fprintf(log_file, "page::%" PRIuMAX "; Updated checksum =" + fprintf(log_file, "page::%llu; Updated checksum =" " %u\n", cur_page_num, checksum); } @@ -623,7 +658,7 @@ update_checksum( mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum); if (is_log_enabled) { - fprintf(log_file, "page::%" PRIuMAX "; Updated checksum field1" + fprintf(log_file, "page::%llu; Updated checksum field1" " = %u\n", cur_page_num, checksum); } @@ -637,13 +672,13 @@ update_checksum( FIL_PAGE_END_LSN_OLD_CHKSUM,checksum); if (is_log_enabled) { - fprintf(log_file, "page::%" PRIuMAX "; Updated checksum " + fprintf(log_file, "page::%llu; Updated checksum " "field2 = %u\n", cur_page_num, checksum); } } - func_exit: +func_exit: /* The following code is to check the stored checksum with the calculated checksum. If it matches, then return FALSE to skip the rewrite of checksum, otherwise return TRUE. */ @@ -712,7 +747,7 @@ write_file( if (page_size != fwrite(buf, 1, page_size, file == stdin ? stdout : file)) { - fprintf(stderr, "Failed to write page %" PRIuMAX " to %s: %s\n", + fprintf(stderr, "Failed to write page::%llu to %s: %s\n", cur_page_num, filename, strerror(errno)); return(false); @@ -734,12 +769,16 @@ Parse the page and collect/dump the information about page type @param [in] page buffer page @param [out] xdes extend descriptor page @param [in] file file for diagnosis. +@param [in] page_size page_size +@param [in] is_encrypted tablespace is encrypted */ void parse_page( const byte* page, byte* xdes, - FILE* file) + FILE* file, + const page_size_t& page_size, + bool is_encrypted) { unsigned long long id; ulint undo_page_type; @@ -749,7 +788,7 @@ parse_page( ulint left_page_no; ulint right_page_no; ulint data_bytes; - int is_leaf; + bool is_leaf; int size_range_id; /* Check whether page is doublewrite buffer. */ @@ -761,83 +800,107 @@ parse_page( switch (mach_read_from_2(page + FIL_PAGE_TYPE)) { - case FIL_PAGE_INDEX: + case FIL_PAGE_INDEX: { + uint key_version = mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); page_type.n_fil_page_index++; - id = mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID); - n_recs = page_get_n_recs(page); - page_no = page_get_page_no(page); - left_page_no = mach_read_from_4(page + FIL_PAGE_PREV); - right_page_no = mach_read_from_4(page + FIL_PAGE_NEXT); - data_bytes = page_get_data_size(page); - is_leaf = page_is_leaf(page); - size_range_id = (data_bytes * SIZE_RANGES_FOR_PAGE - + logical_page_size - 1) / - logical_page_size; - if (size_range_id > SIZE_RANGES_FOR_PAGE + 1) { - /* data_bytes is bigger than logical_page_size */ - size_range_id = SIZE_RANGES_FOR_PAGE + 1; - } - if (per_page_details) { - printf("index %llu page %lu leaf %u n_recs %lu data_bytes %lu" - "\n", id, page_no, is_leaf, n_recs, data_bytes); - } - /* update per-index statistics */ - { - if (index_ids.count(id) == 0) { - index_ids[id] = per_index_stats(); - } - std::map<unsigned long long, per_index_stats>::iterator it; - it = index_ids.find(id); - per_index_stats &index = (it->second); - const byte* des = xdes + XDES_ARR_OFFSET - + XDES_SIZE * ((page_no & (physical_page_size - 1)) - / FSP_EXTENT_SIZE); - if (xdes_get_bit(des, XDES_FREE_BIT, - page_no % FSP_EXTENT_SIZE)) { - index.free_pages++; - return; - } - index.pages++; - if (is_leaf) { - index.leaf_pages++; - if (data_bytes > index.max_data_size) { - index.max_data_size = data_bytes; - } - struct per_page_stats pp(n_recs, data_bytes, - left_page_no, right_page_no); - - index.leaves[page_no] = pp; - - if (left_page_no == ULINT32_UNDEFINED) { - index.first_leaf_page = page_no; - index.count++; - } - } - index.total_n_recs += n_recs; - index.total_data_bytes += data_bytes; - index.pages_in_size_range[size_range_id] ++; - } - - if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tIndex page\t\t\t|" - "\tindex id=%llu,", cur_page_num, id); - - fprintf(file, - " page level=" ULINTPF - ", No. of records=" ULINTPF - ", garbage=" ULINTPF ", %s\n", - page_header_get_field(page, PAGE_LEVEL), - page_header_get_field(page, PAGE_N_RECS), - page_header_get_field(page, PAGE_GARBAGE), str); - } - break; + /* If page is encrypted we can't read index header */ + if (!is_encrypted) { + id = mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID); + n_recs = mach_read_from_2(page + PAGE_HEADER + PAGE_N_RECS); + page_no = mach_read_from_4(page + FIL_PAGE_OFFSET); + left_page_no = mach_read_from_4(page + FIL_PAGE_PREV); + right_page_no = mach_read_from_4(page + FIL_PAGE_NEXT); + ulint is_comp = mach_read_from_2(page + PAGE_HEADER + PAGE_N_HEAP) & 0x8000; + ulint level = mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL); + ulint garbage = mach_read_from_2(page + PAGE_HEADER + PAGE_GARBAGE); + + + data_bytes = (ulint)(mach_read_from_2(page + PAGE_HEADER + PAGE_HEAP_TOP) + - (is_comp + ? PAGE_NEW_SUPREMUM_END + : PAGE_OLD_SUPREMUM_END) + - garbage); + + is_leaf = (!*(const uint16*) (page + (PAGE_HEADER + PAGE_LEVEL))); + + if (page_type_dump) { + fprintf(file, "#::%llu\t\t|\t\tIndex page\t\t\t|" + "\tindex id=%llu,", cur_page_num, id); + + fprintf(file, + " page level=" ULINTPF + ", No. of records=" ULINTPF + ", garbage=" ULINTPF ", %s\n", + level, n_recs, garbage, str); + } + + size_range_id = (data_bytes * SIZE_RANGES_FOR_PAGE + + page_size.logical() - 1) / + page_size.logical(); + + if (size_range_id > SIZE_RANGES_FOR_PAGE + 1) { + /* data_bytes is bigger than logical_page_size */ + size_range_id = SIZE_RANGES_FOR_PAGE + 1; + } + + if (per_page_details) { + printf("index id=%llu page " ULINTPF " leaf %d n_recs " ULINTPF " data_bytes " ULINTPF + "\n", id, page_no, is_leaf, n_recs, data_bytes); + } + + /* update per-index statistics */ + { + if (index_ids.count(id) == 0) { + index_ids[id] = per_index_stats(); + } + std::map<unsigned long long, per_index_stats>::iterator it; + it = index_ids.find(id); + per_index_stats &index = (it->second); + const byte* des = xdes + XDES_ARR_OFFSET + + XDES_SIZE * ((page_no & (page_size.physical() - 1)) + / FSP_EXTENT_SIZE); + if (xdes_get_bit(des, XDES_FREE_BIT, + page_no % FSP_EXTENT_SIZE)) { + index.free_pages++; + return; + } + + index.pages++; + + if (is_leaf) { + index.leaf_pages++; + if (data_bytes > index.max_data_size) { + index.max_data_size = data_bytes; + } + struct per_page_stats pp(n_recs, data_bytes, + left_page_no, right_page_no); + + index.leaves[page_no] = pp; + + if (left_page_no == ULINT32_UNDEFINED) { + index.first_leaf_page = page_no; + index.count++; + } + } + + index.total_n_recs += n_recs; + index.total_data_bytes += data_bytes; + index.pages_in_size_range[size_range_id] ++; + } + } else { + fprintf(file, "#::%llu\t\t|\t\tEncrypted Index page\t\t\t|" + "\tkey_version %u,%s\n", cur_page_num, key_version, str); + } + + break; + } case FIL_PAGE_UNDO_LOG: page_type.n_fil_page_undo_log++; undo_page_type = mach_read_from_2(page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE); if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tUndo log page\t\t\t|", + fprintf(file, "#::%llu\t\t|\t\tUndo log page\t\t\t|", cur_page_num); } if (undo_page_type == TRX_UNDO_INSERT) { @@ -911,7 +974,7 @@ parse_page( case FIL_PAGE_INODE: page_type.n_fil_page_inode++; if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tInode page\t\t\t|" + fprintf(file, "#::%llu\t\t|\t\tInode page\t\t\t|" "\t%s\n",cur_page_num, str); } break; @@ -919,7 +982,7 @@ parse_page( case FIL_PAGE_IBUF_FREE_LIST: page_type.n_fil_page_ibuf_free_list++; if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tInsert buffer free list" + fprintf(file, "#::%llu\t\t|\t\tInsert buffer free list" " page\t|\t%s\n", cur_page_num, str); } break; @@ -927,7 +990,7 @@ parse_page( case FIL_PAGE_TYPE_ALLOCATED: page_type.n_fil_page_type_allocated++; if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tFreshly allocated " + fprintf(file, "#::%llu\t\t|\t\tFreshly allocated " "page\t\t|\t%s\n", cur_page_num, str); } break; @@ -935,7 +998,7 @@ parse_page( case FIL_PAGE_IBUF_BITMAP: page_type.n_fil_page_ibuf_bitmap++; if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tInsert Buffer " + fprintf(file, "#::%llu\t\t|\t\tInsert Buffer " "Bitmap\t\t|\t%s\n", cur_page_num, str); } break; @@ -943,7 +1006,7 @@ parse_page( case FIL_PAGE_TYPE_SYS: page_type.n_fil_page_type_sys++; if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tSystem page\t\t\t|" + fprintf(file, "#::%llu\t\t|\t\tSystem page\t\t\t|" "\t%s\n",cur_page_num, str); } break; @@ -951,25 +1014,25 @@ parse_page( case FIL_PAGE_TYPE_TRX_SYS: page_type.n_fil_page_type_trx_sys++; if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tTransaction system " + fprintf(file, "#::%llu\t\t|\t\tTransaction system " "page\t\t|\t%s\n", cur_page_num, str); } break; case FIL_PAGE_TYPE_FSP_HDR: page_type.n_fil_page_type_fsp_hdr++; - memcpy(xdes, page, physical_page_size); + memcpy(xdes, page, page_size.physical()); if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tFile Space " + fprintf(file, "#::%llu\t\t|\t\tFile Space " "Header\t\t|\t%s\n", cur_page_num, str); } break; case FIL_PAGE_TYPE_XDES: page_type.n_fil_page_type_xdes++; - memcpy(xdes, page, physical_page_size); + memcpy(xdes, page, page_size.physical()); if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tExtent descriptor " + fprintf(file, "#::%llu\t\t|\t\tExtent descriptor " "page\t\t|\t%s\n", cur_page_num, str); } break; @@ -977,7 +1040,7 @@ parse_page( case FIL_PAGE_TYPE_BLOB: page_type.n_fil_page_type_blob++; if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tBLOB page\t\t\t|\t%s\n", + fprintf(file, "#::%llu\t\t|\t\tBLOB page\t\t\t|\t%s\n", cur_page_num, str); } break; @@ -985,7 +1048,7 @@ parse_page( case FIL_PAGE_TYPE_ZBLOB: page_type.n_fil_page_type_zblob++; if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tCompressed BLOB " + fprintf(file, "#::%llu\t\t|\t\tCompressed BLOB " "page\t\t|\t%s\n", cur_page_num, str); } break; @@ -993,7 +1056,7 @@ parse_page( case FIL_PAGE_TYPE_ZBLOB2: page_type.n_fil_page_type_zblob2++; if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tSubsequent Compressed " + fprintf(file, "#::%llu\t\t|\t\tSubsequent Compressed " "BLOB page\t|\t%s\n", cur_page_num, str); } break; @@ -1001,7 +1064,7 @@ parse_page( case FIL_PAGE_PAGE_COMPRESSED: page_type.n_fil_page_type_page_compressed++; if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tPage compressed " + fprintf(file, "#::%llu\t\t|\t\tPage compressed " "page\t|\t%s\n", cur_page_num, str); } break; @@ -1009,7 +1072,7 @@ parse_page( case FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED: page_type.n_fil_page_type_page_compressed_encrypted++; if (page_type_dump) { - fprintf(file, "#::%8" PRIuMAX "\t\t|\t\tPage compressed encrypted " + fprintf(file, "#::%llu\t\t|\t\tPage compressed encrypted " "page\t|\t%s\n", cur_page_num, str); } break; @@ -1096,12 +1159,12 @@ print_summary( page_type.n_fil_page_type_blob); fprintf(fil_out, "%8d\tCompressed BLOB page\n", page_type.n_fil_page_type_zblob); - fprintf(fil_out, "%8d\tOther type of page\n", - page_type.n_fil_page_type_other); fprintf(fil_out, "%8d\tPage compressed page\n", page_type.n_fil_page_type_page_compressed); fprintf(fil_out, "%8d\tPage compressed encrypted page\n", page_type.n_fil_page_type_page_compressed_encrypted); + fprintf(fil_out, "%8d\tOther type of page\n", + page_type.n_fil_page_type_other); fprintf(fil_out, "\n===============================================\n"); fprintf(fil_out, "Additional information:\n"); fprintf(fil_out, "Undo page type: %d insert, %d update, %d other\n", @@ -1256,6 +1319,7 @@ innochecksum_get_one_option( break; case 'V': print_version(); + my_end(0); exit(EXIT_SUCCESS); break; case 'C': @@ -1316,27 +1380,35 @@ get_options( char ***argv) { if (handle_options(argc, argv, innochecksum_options, - innochecksum_get_one_option)) + innochecksum_get_one_option)) { + my_end(0); exit(true); + } /* The next arg must be the filename */ if (!*argc) { usage(); + my_end(0); return (true); } return (false); } -/** Check from page 0 if table is encrypted. */ +/** Check from page 0 if table is encrypted. +@param[in] filename Filename +@param[in] page_size page size +@param[in] page Page 0 +@retval true if tablespace is encrypted, false if not +*/ static bool check_encryption( const char* filename, - ulint zip_size, + const page_size_t& page_size, byte * page) { ulint offset = (FSP_HEADER_OFFSET + (XDES_ARR_OFFSET + XDES_SIZE * - (zip_size ? zip_size : UNIV_PAGE_SIZE) / FSP_EXTENT_SIZE)); + (page_size.physical()) / FSP_EXTENT_SIZE)); if (memcmp(page + offset, CRYPT_MAGIC, MAGIC_SZ) != 0) { return false; @@ -1361,16 +1433,95 @@ bool check_encryption( uint key_id = mach_read_from_4 (page + offset + MAGIC_SZ + 2 + iv_length + 4); - if (type == CRYPT_SCHEME_1) { - if (is_log_enabled) { - fprintf(log_file,"Tablespace %s encrypted key_version %u key_id %u\n", - filename, min_key_version, key_id); - } + if (type == CRYPT_SCHEME_1 && is_log_enabled) { + fprintf(log_file,"Tablespace %s encrypted key_version %u key_id %u\n", + filename, min_key_version, key_id); } return (type == CRYPT_SCHEME_1); } +/** +Verify page checksum. +@param[in] buf page to verify +@param[in] page_size page size +@param[in] is_encrypted true if tablespace is encrypted +@param[in] is_compressed true if tablespace is page compressed +@param[in,out] mismatch_count Number of pages failed in checksum verify +@retval 0 if page checksum matches or 1 if it does not match +*/ +static +int verify_checksum( + byte* buf, + const page_size_t& page_size, + bool is_encrypted, + bool is_compressed, + unsigned long long* mismatch_count) +{ + int exit_status = 0; + bool is_corrupted = false; + + is_corrupted = is_page_corrupted( + buf, page_size, is_encrypted, is_compressed); + + if (is_corrupted) { + fprintf(stderr, "Fail: page::%llu invalid\n", + cur_page_num); + + (*mismatch_count)++; + + if (*mismatch_count > allow_mismatches) { + fprintf(stderr, + "Exceeded the " + "maximum allowed " + "checksum mismatch " + "count::%llu current::%llu\n", + *mismatch_count, + allow_mismatches); + + exit_status = 1; + } + } + + return (exit_status); +} + +/** Rewrite page checksum if needed. +@param[in] filename File name +@param[in] fil_in File pointer +@param[in] buf page +@param[in] page_size page size +@param[in] pos File position +@param[in] is_encrypted true if tablespace is encrypted +@param[in] is_compressed true if tablespace is page compressed +@retval 0 if checksum rewrite was successful, 1 if error was detected */ +static +int +rewrite_checksum( + const char* filename, + FILE* fil_in, + byte* buf, + const page_size_t& page_size, + fpos_t* pos, + bool is_encrypted, + bool is_compressed) +{ + int exit_status = 0; + /* Rewrite checksum. Note that for encrypted and + page compressed tables this is not currently supported. */ + if (do_write && + !is_encrypted && + !is_compressed + && !write_file(filename, fil_in, buf, + page_size.is_compressed(), pos, + static_cast<ulong>(page_size.physical()))) { + + exit_status = 1; + } + + return (exit_status); +} + int main( int argc, char **argv) @@ -1380,6 +1531,8 @@ int main( /* our input filename. */ char* filename; /* Buffer to store pages read. */ + byte* buf_ptr = NULL; + byte* xdes_ptr = NULL; byte* buf = NULL; byte* xdes = NULL; /* bytes read count */ @@ -1404,9 +1557,7 @@ int main( off_t offset = 0; /* count the no. of page corrupted. */ - ulint mismatch_count = 0; - /* Variable to ack the page is corrupted or not. */ - bool is_corrupted = false; + unsigned long long mismatch_count = 0; bool partial_page_read = false; /* Enabled when read from stdin is done. */ @@ -1465,16 +1616,16 @@ int main( my_print_variables(innochecksum_options); } - - buf = (byte*) malloc(UNIV_PAGE_SIZE_MAX * 2); - xdes = (byte*)malloc(UNIV_PAGE_SIZE_MAX * 2); + buf_ptr = (byte*) malloc(UNIV_PAGE_SIZE_MAX * 2); + xdes_ptr = (byte*)malloc(UNIV_PAGE_SIZE_MAX * 2); + buf = (byte *) ut_align(buf_ptr, UNIV_PAGE_SIZE_MAX); + xdes = (byte *) ut_align(xdes_ptr, UNIV_PAGE_SIZE_MAX); /* The file name is not optional. */ for (int i = 0; i < argc; ++i) { /* Reset parameters for each file. */ filename = argv[i]; memset(&page_type, 0, sizeof(innodb_page_type)); - is_corrupted = false; partial_page_read = false; skip_page = false; @@ -1526,7 +1677,7 @@ int main( if (bytes != UNIV_ZIP_SIZE_MIN) { fprintf(stderr, "Error: Was not able to read the " "minimum page size "); - fprintf(stderr, "of %d bytes. Bytes read was %lu\n", + fprintf(stderr, "of %d bytes. Bytes read was " ULINTPF "\n", UNIV_ZIP_SIZE_MIN, bytes); exit_status = 1; @@ -1542,23 +1693,23 @@ int main( /* Determine page size, zip_size and page compression from fsp_flags and encryption metadata from page 0 */ + const page_size_t& page_size = get_page_size(buf); ulint flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + buf); - ulint page_size = fsp_flags_get_page_size(flags); - ulint zip_size = fsp_flags_get_zip_size(flags); - logical_page_size = zip_size; - physical_page_size = page_size; - srv_page_size = page_size; + ulint zip_size = page_size.is_compressed() ? page_size.logical() : 0; + logical_page_size = page_size.is_compressed() ? zip_size : 0; + physical_page_size = page_size.physical(); + srv_page_size = page_size.logical(); bool is_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(flags); - if (page_size > UNIV_ZIP_SIZE_MIN) { + if (page_size.physical() > UNIV_ZIP_SIZE_MIN) { /* Read rest of the page 0 to determine crypt_data */ - bytes = ulong(read_file(buf, partial_page_read, page_size, fil_in)); + bytes = ulong(read_file(buf, partial_page_read, page_size.physical(), fil_in)); - if (bytes != page_size) { + if (bytes != page_size.physical()) { fprintf(stderr, "Error: Was not able to read the " "rest of the page "); - fprintf(stderr, "of %lu bytes. Bytes read was %lu\n", - page_size - UNIV_ZIP_SIZE_MIN, bytes); + fprintf(stderr, "of " ULINTPF " bytes. Bytes read was " ULINTPF "\n", + page_size.physical() - UNIV_ZIP_SIZE_MIN, bytes); exit_status = 1; goto my_exit; @@ -1567,9 +1718,52 @@ int main( } /* Now that we have full page 0 in buffer, check encryption */ - bool is_encrypted = check_encryption(filename, zip_size, buf); + bool is_encrypted = check_encryption(filename, page_size, buf); + + /* Verify page 0 contents. Note that we can't allow + checksum mismatch on page 0, because that would mean we + could not trust it content. */ + if (!no_check) { + unsigned long long tmp_allow_mismatches = allow_mismatches; + allow_mismatches = 0; - pages = (ulint) (size / page_size); + exit_status = verify_checksum(buf, page_size, is_encrypted, is_compressed, &mismatch_count); + + if (exit_status) { + fprintf(stderr, "Error: Page 0 checksum mismatch, can't continue. \n"); + goto my_exit; + } + allow_mismatches = tmp_allow_mismatches; + } + + if ((exit_status = rewrite_checksum(filename, fil_in, buf, + page_size, &pos, is_encrypted, is_compressed))) { + goto my_exit; + } + + if (page_type_dump) { + fprintf(fil_page_type, + "\n\nFilename::%s\n", filename); + fprintf(fil_page_type, + "========================================" + "======================================\n"); + fprintf(fil_page_type, + "\tPAGE_NO\t\t|\t\tPAGE_TYPE\t\t" + "\t|\tEXTRA INFO\n"); + fprintf(fil_page_type, + "========================================" + "======================================\n"); + } + + if (per_page_details) { + printf("page %llu ", cur_page_num); + } + + if (page_type_summary || page_type_dump) { + parse_page(buf, xdes, fil_page_type, page_size, is_encrypted); + } + + pages = (ulint) (size / page_size.physical()); if (just_count) { if (read_from_stdin) { @@ -1584,14 +1778,14 @@ int main( "(" ULINTPF " pages)\n", filename, size, pages); if (do_one_page) { fprintf(log_file, "Innochecksum: " - "checking page %" PRIuMAX "\n", + "checking page::%llu;\n", do_page); } } } else { if (is_log_enabled) { fprintf(log_file, "Innochecksum: checking " - "pages in range %" PRIuMAX " to %" PRIuMAX "\n", + "pages in range::%llu to %llu\n", start_page, use_end_page ? end_page : (pages - 1)); } @@ -1606,7 +1800,7 @@ int main( partial_page_read = false; offset = (off_t) start_page - * (off_t) page_size; + * (off_t) page_size.physical(); #ifdef _WIN32 if (_fseeki64(fil_in, offset, SEEK_SET)) { #else @@ -1644,7 +1838,7 @@ int main( bytes = read_file(buf, partial_page_read, static_cast<ulong>( - page_size), + page_size.physical()), fil_in); partial_page_read = false; @@ -1662,28 +1856,14 @@ int main( } } - if (page_type_dump) { - fprintf(fil_page_type, - "\n\nFilename::%s\n", filename); - fprintf(fil_page_type, - "========================================" - "======================================\n"); - fprintf(fil_page_type, - "\tPAGE_NO\t\t|\t\tPAGE_TYPE\t\t" - "\t|\tEXTRA INFO\n"); - fprintf(fil_page_type, - "========================================" - "======================================\n"); - } - /* main checksumming loop */ - cur_page_num = start_page; + cur_page_num = start_page ? start_page : cur_page_num + 1; lastt = 0; while (!feof(fil_in)) { bytes = read_file(buf, partial_page_read, static_cast<ulong>( - page_size), fil_in); + page_size.physical()), fil_in); partial_page_read = false; if (!bytes && feof(fil_in)) { @@ -1692,17 +1872,17 @@ int main( if (ferror(fil_in)) { fprintf(stderr, "Error reading " ULINTPF " bytes", - page_size); + page_size.physical()); perror(" "); exit_status = 1; goto my_exit; } - if (bytes != page_size) { - fprintf(stderr, "Error: bytes read (%lu) " + if (bytes != page_size.physical()) { + fprintf(stderr, "Error: bytes read (" ULINTPF ") " "doesn't match page size (" ULINTPF ")\n", - bytes, page_size); + bytes, page_size.physical()); exit_status = 1; goto my_exit; } @@ -1714,46 +1894,26 @@ int main( skip_page = false; } + ulint cur_page_type = mach_read_from_2(buf+FIL_PAGE_TYPE); + + /* FIXME: Page compressed or Page compressed and encrypted + pages do not contain checksum. */ + if (cur_page_type == FIL_PAGE_PAGE_COMPRESSED || + cur_page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) { + skip_page = true; + } + /* If no-check is enabled, skip the checksum verification.*/ - if (!no_check) { - /* Checksum verification */ - if (!skip_page) { - is_corrupted = is_page_corrupted( - buf, page_size, zip_size, is_encrypted, is_compressed); - - if (is_corrupted) { - fprintf(stderr, "Fail: page " - "%" PRIuMAX " invalid\n", - cur_page_num); - - mismatch_count++; - - if(mismatch_count > allow_mismatches) { - fprintf(stderr, - "Exceeded the " - "maximum allowed " - "checksum mismatch " - "count::%" PRIuMAX "\n", - allow_mismatches); - - exit_status = 1; - goto my_exit; - } - } - } + if (!no_check + && !skip_page + && (exit_status = verify_checksum(buf, page_size, + is_encrypted, is_compressed, &mismatch_count))) { + goto my_exit; } - /* Rewrite checksum. Note that for encrypted and - page compressed tables this is not currently supported. */ - if (do_write && - !is_encrypted && - !is_compressed - && !write_file(filename, fil_in, buf, - zip_size != 0, &pos, - static_cast<ulong>(page_size))) { - - exit_status = 1; + if ((exit_status = rewrite_checksum(filename, fil_in, buf, + page_size, &pos, is_encrypted, is_compressed))) { goto my_exit; } @@ -1763,15 +1923,16 @@ int main( } if (per_page_details) { - printf("page %ld ", cur_page_num); + printf("page %llu ", cur_page_num); } if (page_type_summary || page_type_dump) { - parse_page(buf, xdes, fil_page_type); + parse_page(buf, xdes, fil_page_type, page_size, is_encrypted); } /* do counter increase and progress printing */ cur_page_num++; + if (verbose && !read_from_stdin) { if ((cur_page_num % 64) == 0) { now = time(0); @@ -1780,7 +1941,7 @@ int main( } if (now - lastt >= 1 && is_log_enabled) { - fprintf(log_file, "page %" PRIuMAX " " + fprintf(log_file, "page::%llu " "okay: %.3f%% done\n", (cur_page_num - 1), (float) cur_page_num / pages * 100); @@ -1811,10 +1972,29 @@ int main( fclose(log_file); } + free(buf_ptr); + free(xdes_ptr); + + my_end(exit_status); + DBUG_RETURN(exit_status); + my_exit: - if (buf) { - free(buf); + if (buf_ptr) { + free(buf_ptr); + } + + if (xdes_ptr) { + free(xdes_ptr); + } + + if (!read_from_stdin && fil_in) { + fclose(fil_in); } + + if (log_file) { + fclose(log_file); + } + my_end(exit_status); - exit(exit_status); + DBUG_RETURN(exit_status); } diff --git a/mysql-test/suite/encryption/t/innochecksum.test b/mysql-test/suite/encryption/t/innochecksum.test index 74fe7bcf7a0..f1c1b65d418 100644 --- a/mysql-test/suite/encryption/t/innochecksum.test +++ b/mysql-test/suite/encryption/t/innochecksum.test @@ -7,6 +7,7 @@ # Require InnoDB -- source include/have_innodb.inc -- source include/have_file_key_management_plugin.inc +-- source include/innodb_page_size_small.inc if (!$INNOCHECKSUM) { --echo Need innochecksum binary diff --git a/mysql-test/suite/innodb/include/innodb-wl6045.inc b/mysql-test/suite/innodb/include/innodb-wl6045.inc new file mode 100644 index 00000000000..33a2ecd731f --- /dev/null +++ b/mysql-test/suite/innodb/include/innodb-wl6045.inc @@ -0,0 +1,22 @@ +--echo ===> Testing size=$size +--disable_warnings +--eval CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=$size +--enable_warnings + +insert into t1 values(1,"I"); +insert into t1 values(2,"AM"); +insert into t1 values(3,"COMPRESSED"); + +--source include/shutdown_mysqld.inc + +#STOP; + +--exec $INNOCHECKSUM $MYSQLD_DATADIR/test/t1.ibd +--exec $INNOCHECKSUM --write=crc32 $MYSQLD_DATADIR/test/t1.ibd +--exec $INNOCHECKSUM --strict-check=crc32 $MYSQLD_DATADIR/test/t1.ibd +--exec $INNOCHECKSUM --write=none $MYSQLD_DATADIR/test/t1.ibd +--exec $INNOCHECKSUM --strict-check=none $MYSQLD_DATADIR/test/t1.ibd + +--source include/start_mysqld.inc +select * from t1; +drop table t1; diff --git a/mysql-test/suite/innodb/r/innodb_zip_innochecksum.result b/mysql-test/suite/innodb/r/innodb_zip_innochecksum.result new file mode 100644 index 00000000000..ff1bccfb60c --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_zip_innochecksum.result @@ -0,0 +1,91 @@ +# Set the environmental variables +call mtr.add_suppression("InnoDB: Unable to read tablespace .* page no .* into the buffer pool after 100 attempts"); +call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); +CREATE TABLE tab1(c1 INT PRIMARY KEY,c2 VARCHAR(20)) ENGINE=InnoDB; +CREATE INDEX idx1 ON tab1(c2(10)); +INSERT INTO tab1 VALUES(1, 'Innochecksum InnoDB1'); +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; +insert into t1 values(1,"i"); +insert into t1 values(2,"am"); +insert into t1 values(3,"compressed table"); +# Shutdown the Server +# Server Default checksum = innodb +[1b]: check the innochecksum without --strict-check +[2]: check the innochecksum with full form --strict-check=crc32 +[3]: check the innochecksum with short form -C crc32 +[4]: check the innochecksum with --no-check ignores algorithm check, warning is expected +FOUND /Error: --no-check must be associated with --write option./ in my_restart.err +[5]: check the innochecksum with short form --no-check ignores algorithm check, warning is expected +FOUND /Error: --no-check must be associated with --write option./ in my_restart.err +[6]: check the innochecksum with full form strict-check & no-check , an error is expected +FOUND /Error: --strict-check option cannot be used together with --no-check option./ in my_restart.err +[7]: check the innochecksum with short form strict-check & no-check , an error is expected +FOUND /Error: --strict-check option cannot be used together with --no-check option./ in my_restart.err +[8]: check the innochecksum with short & full form combination +# strict-check & no-check, an error is expected +FOUND /Error: --strict-check option cannot be used together with --no-check option./ in my_restart.err +[9]: check the innochecksum with full form --strict-check=innodb +[10]: check the innochecksum with full form --strict-check=none +# when server Default checksum=crc32 +[11]: check the innochecksum with short form -C innodb +# when server Default checksum=crc32 +[12]: check the innochecksum with short form -C none +# when server Default checksum=crc32 +[13]: check strict-check with invalid values +FOUND /Error while setting value \'strict_innodb\' to \'strict-check\'/ in my_restart.err +FOUND /Error while setting value \'strict_innodb\' to \'strict-check\'/ in my_restart.err +FOUND /Error while setting value \'strict_crc32\' to \'strict-check\'/ in my_restart.err +FOUND /Error while setting value \'strict_crc32\' to \'strict-check\'/ in my_restart.err +FOUND /Error while setting value \'strict_none\' to \'strict-check\'/ in my_restart.err +FOUND /Error while setting value \'strict_none\' to \'strict-check\'/ in my_restart.err +FOUND /Error while setting value \'InnoBD\' to \'strict-check\'/ in my_restart.err +FOUND /Error while setting value \'InnoBD\' to \'strict-check\'/ in my_restart.err +FOUND /Error while setting value \'crc\' to \'strict-check\'/ in my_restart.err +FOUND /Error while setting value \'no\' to \'strict-check\'/ in my_restart.err +[14a]: when server default checksum=crc32 rewrite new checksum=crc32 with innochecksum +# Also check the long form of write option. +[14b]: when server default checksum=crc32 rewrite new checksum=innodb with innochecksum +# Also check the long form of write option. +# start the server with innodb_checksum_algorithm=InnoDB +INSERT INTO tab1 VALUES(2, 'Innochecksum CRC32'); +SELECT c1,c2 FROM tab1 order by c1,c2; +c1 c2 +1 Innochecksum InnoDB1 +2 Innochecksum CRC32 +# Stop the server +[15]: when server default checksum=crc32 rewrite new checksum=none with innochecksum +# Also check the short form of write option. +# Start the server with checksum algorithm=none +INSERT INTO tab1 VALUES(3, 'Innochecksum None'); +SELECT c1,c2 FROM tab1 order by c1,c2; +c1 c2 +1 Innochecksum InnoDB1 +2 Innochecksum CRC32 +3 Innochecksum None +DROP TABLE t1; +# Stop the server +[16]: rewrite into new checksum=crc32 with innochecksum +# Restart the DB server with innodb_checksum_algorithm=crc32 +SELECT * FROM tab1; +c1 c2 +1 Innochecksum InnoDB1 +2 Innochecksum CRC32 +3 Innochecksum None +DELETE FROM tab1 where c1=3; +SELECT c1,c2 FROM tab1 order by c1,c2; +c1 c2 +1 Innochecksum InnoDB1 +2 Innochecksum CRC32 +# Stop server +[17]: rewrite into new checksum=InnoDB +# Restart the DB server with innodb_checksum_algorithm=InnoDB +DELETE FROM tab1 where c1=2; +SELECT * FROM tab1; +c1 c2 +1 Innochecksum InnoDB1 +# Stop server +[18]:check Innochecksum with invalid write options +FOUND /Error while setting value \'strict_crc32\' to \'write\'/ in my_restart.err +FOUND /Error while setting value \'strict_innodb\' to \'write\'/ in my_restart.err +FOUND /Error while setting value \'crc23\' to \'write\'/ in my_restart.err +DROP TABLE tab1; diff --git a/mysql-test/suite/innodb/r/innodb_zip_innochecksum2.result b/mysql-test/suite/innodb/r/innodb_zip_innochecksum2.result new file mode 100644 index 00000000000..582bb42f0cb --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_zip_innochecksum2.result @@ -0,0 +1,160 @@ +SET GLOBAL innodb_compression_level=0; +SELECT @@innodb_compression_level; +@@innodb_compression_level +0 +CREATE TABLE t1 (j LONGBLOB) ENGINE = InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; +INSERT INTO t1 VALUES (repeat('abcdefghijklmnopqrstuvwxyz',200)); +INSERT INTO t1 SELECT * from t1; +INSERT INTO t1 SELECT * from t1; +INSERT INTO t1 SELECT * from t1; +INSERT INTO t1 SELECT * from t1; +INSERT INTO t1 SELECT * from t1; +INSERT INTO t1 SELECT * from t1; +INSERT INTO t1 SELECT * from t1; +INSERT INTO t1 SELECT * from t1; +INSERT INTO t1 SELECT * from t1; +INSERT INTO t1 SELECT * from t1; +# stop the server + +Variables (--variable-name=value) +and boolean options {FALSE|TRUE} Value (after reading options) +--------------------------------- ---------------------------------------- +verbose TRUE +debug FALSE +count FALSE +start-page 0 +end-page 0 +page 0 +strict-check crc32 +no-check FALSE +allow-mismatches 0 +write crc32 +page-type-summary FALSE +page-type-dump MYSQLTEST_VARDIR/tmp/dump.txt +per-page-details FALSE +log (No default value) +leaf FALSE +merge 0 +[1]:# check the both short and long options for "help" +[2]:# Run the innochecksum when file isn't provided. +# It will print the innochecksum usage similar to --help option. +innochecksum Ver #.#.# +Copyright (c) YEAR, YEAR , Oracle, MariaDB Corporation Ab and others. + +InnoDB offline file checksum utility. +Usage: innochecksum [-c] [-s <start page>] [-e <end page>] [-p <page>] [-i] [-v] [-a <allow mismatches>] [-n] [-C <strict-check>] [-w <write>] [-S] [-D <page type dump>] [-l <log>] [-l] [-m <merge pages>] <filename or [-]> + -?, --help Displays this help and exits. + -I, --info Synonym for --help. + -V, --version Displays version information and exits. + -v, --verbose Verbose (prints progress every 5 seconds). + -c, --count Print the count of pages in the file and exits. + -s, --start-page=# Start on this page number (0 based). + -e, --end-page=# End at this page number (0 based). + -p, --page=# Check only this page (0 based). + -C, --strict-check=name + Specify the strict checksum algorithm by the user.. One + of: crc32, crc32, innodb, innodb, none, none + -n, --no-check Ignore the checksum verification. + -a, --allow-mismatches=# + Maximum checksum mismatch allowed. + -w, --write=name Rewrite the checksum algorithm by the user.. One of: + crc32, crc32, innodb, innodb, none, none + -S, --page-type-summary + Display a count of each page type in a tablespace. + -D, --page-type-dump=name + Dump the page type info for each page in a tablespace. + -i, --per-page-details + Print out per-page detail information. + -l, --log=name log output. + -f, --leaf Examine leaf index pages + -m, --merge=# leaf page count if merge given number of consecutive + pages + +Variables (--variable-name=value) +and boolean options {FALSE|TRUE} Value (after reading options) +--------------------------------- ---------------------------------------- +verbose FALSE +count FALSE +start-page 0 +end-page 0 +page 0 +strict-check crc32 +no-check FALSE +allow-mismatches 0 +write crc32 +page-type-summary FALSE +page-type-dump (No default value) +per-page-details FALSE +log (No default value) +leaf FALSE +merge 0 +[3]:# check the both short and long options for "count" and exit +Number of pages:# +Number of pages:# +[4]:# Print the version of innochecksum and exit +innochecksum Ver #.#.## Restart the DB server +DROP TABLE t1; +[5]:# Check the innochecksum for compressed table t1 with different key_block_size +# Test for KEY_BLOCK_SIZE=1 +===> Testing size=1 +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; +insert into t1 values(1,"I"); +insert into t1 values(2,"AM"); +insert into t1 values(3,"COMPRESSED"); +select * from t1; +id msg +1 I +2 AM +3 COMPRESSED +drop table t1; +# Test for KEY_BLOCK_SIZE=2 +===> Testing size=2 +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2; +insert into t1 values(1,"I"); +insert into t1 values(2,"AM"); +insert into t1 values(3,"COMPRESSED"); +select * from t1; +id msg +1 I +2 AM +3 COMPRESSED +drop table t1; +# Test for for KEY_BLOCK_SIZE=4 +===> Testing size=4 +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; +insert into t1 values(1,"I"); +insert into t1 values(2,"AM"); +insert into t1 values(3,"COMPRESSED"); +select * from t1; +id msg +1 I +2 AM +3 COMPRESSED +drop table t1; +set innodb_strict_mode=off; +# Test for for KEY_BLOCK_SIZE=8 +===> Testing size=8 +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; +insert into t1 values(1,"I"); +insert into t1 values(2,"AM"); +insert into t1 values(3,"COMPRESSED"); +select * from t1; +id msg +1 I +2 AM +3 COMPRESSED +drop table t1; +set innodb_strict_mode=off; +# Test for KEY_BLOCK_SIZE=16 +===> Testing size=16 +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=16; +insert into t1 values(1,"I"); +insert into t1 values(2,"AM"); +insert into t1 values(3,"COMPRESSED"); +select * from t1; +id msg +1 I +2 AM +3 COMPRESSED +drop table t1; +# Test[5] completed diff --git a/mysql-test/suite/innodb/r/innodb_zip_innochecksum3.result b/mysql-test/suite/innodb/r/innodb_zip_innochecksum3.result new file mode 100644 index 00000000000..03e8b5df75f --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_zip_innochecksum3.result @@ -0,0 +1,227 @@ +# Set the environmental variables +call mtr.add_suppression("InnoDB: Unable to read tablespace .* page no .* into the buffer pool after 100 attempts"); +call mtr.add_suppression("InnoDB: innodb_checksum_algorithm is set to.*"); +[1]: Further Test are for rewrite checksum (innodb|crc32|none) for all ibd file & start the server. +CREATE TABLE tab1 (pk INTEGER NOT NULL PRIMARY KEY, +linestring_key GEOMETRY NOT NULL, +linestring_nokey GEOMETRY NOT NULL) +ENGINE=InnoDB ; +INSERT INTO tab1 (pk, linestring_key, linestring_nokey) +VALUES (1, ST_GeomFromText('POINT(10 10) '), ST_GeomFromText('POINT(10 10) ')); +CREATE INDEX linestring_index ON tab1(linestring_nokey(5)); +ALTER TABLE tab1 ADD KEY (linestring_key(5)); +# create a compressed table +CREATE TABLE tab2(col_1 CHAR (255) , +col_2 VARCHAR (255), col_3 longtext, +col_4 longtext,col_5 longtext, +col_6 longtext , col_7 int ) +engine = innodb row_format=compressed key_block_size=4; +CREATE INDEX idx1 ON tab2(col_3(10)); +CREATE INDEX idx2 ON tab2(col_4(10)); +CREATE INDEX idx3 ON tab2(col_5(10)); +SET @col_1 = repeat('a', 5); +SET @col_2 = repeat('b', 20); +SET @col_3 = repeat('c', 100); +SET @col_4 = repeat('d', 100); +SET @col_5 = repeat('e', 100); +SET @col_6 = repeat('f', 100); +INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) +VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,5); +INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) +VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,4); +INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) +VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,3); +INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) +VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,2); +INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) +VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,1); +SELECT * FROM tab2 ORDER BY col_7; +# stop the server +[1(a)]: Rewrite into new checksum=InnoDB for all *.ibd file and ibdata1 +: start the server with innodb_checksum_algorithm=strict_innodb +INSERT INTO tab1 (pk, linestring_key, linestring_nokey) +VALUES (2, ST_GeomFromText('LINESTRING(10 10,20 20,30 30)'), ST_GeomFromText('LINESTRING(10 10,20 20,30 30)')); +SET @col_1 = repeat('a', 5); +SET @col_2 = repeat('b', 20); +SET @col_3 = repeat('c', 100); +SET @col_4 = repeat('d', 100); +SET @col_5 = repeat('e', 100); +SET @col_6 = repeat('f', 100); +INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) +VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,6); +SELECT pk,ST_AsText(linestring_key),ST_AsText(linestring_nokey) +FROM tab1 ORDER BY pk; +SELECT * FROM tab2 ORDER BY col_7; +# stop the server +[1(b)]: Rewrite into new checksum=crc32 for all *.ibd file and ibdata1 +# start the server with innodb_checksum_algorithm=strict_crc32 +INSERT INTO tab1 (pk, linestring_key, linestring_nokey) +VALUES (3, ST_GeomFromText('POLYGON((0 0,5 5,10 10,15 15,0 0),(10 10,20 20,30 30,40 40,10 10))'), +ST_GeomFromText('POLYGON((0 0,5 5,10 10,15 15,0 0),(10 10,20 20,30 30,40 40,10 10))')); +SET @col_1 = repeat('g', 5); +SET @col_2 = repeat('h', 20); +SET @col_3 = repeat('i', 100); +SET @col_4 = repeat('j', 100); +SET @col_5 = repeat('k', 100); +SET @col_6 = repeat('l', 100); +INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) +VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,7); +SELECT pk,ST_AsText(linestring_key),ST_AsText(linestring_nokey) +FROM tab1 ORDER BY pk; +SELECT * FROM tab2 ORDER BY col_7; +# stop the server +[1(c)]: Rewrite into new checksum=none for all *.ibd file and ibdata1 +INSERT INTO tab1 (pk, linestring_key, linestring_nokey) +VALUES (4, ST_GeomFromText('MULTIPOINT(0 0,5 5,10 10,20 20) '), ST_GeomFromText('MULTIPOINT(0 0,5 5,10 10,20 20) ')); +SET @col_1 = repeat('m', 5); +SET @col_2 = repeat('n', 20); +SET @col_3 = repeat('o', 100); +SET @col_4 = repeat('p', 100); +SET @col_5 = repeat('q', 100); +SET @col_6 = repeat('r', 100); +INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) +VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,8); +SELECT pk,ST_AsText(linestring_key),ST_AsText(linestring_nokey) +FROM tab1 ORDER BY pk; +SELECT * FROM tab2 ORDER BY col_7; +# stop the server +[2]: Check the page type summary with shortform for tab1.ibd + +File::tab#.ibd +================PAGE TYPE SUMMARY============== +#PAGE_COUNT PAGE_TYPE +=============================================== + # Index page + # Undo log page + # Inode page + # Insert buffer free list page + # Freshly allocated page + # Insert buffer bitmap + # System page + # Transaction system page + # File Space Header + # Extent descriptor page + # BLOB page + # Compressed BLOB page + # Page compressed page + # Page compressed encrypted page + # Other type of page + +=============================================== +Additional information: +Undo page type: # insert, # update, # other +Undo page state: # active, # cached, # to_free, # to_purge, # prepared, # other +index_id #pages #leaf_pages #recs_per_page #bytes_per_page +# # # # # +# # # # # +# # # # # + +index_id page_data_bytes_histgram(empty,...,oversized) +# # # # # # # # # # # # # +# # # # # # # # # # # # # +# # # # # # # # # # # # # +[3]: Check the page type summary with longform for tab1.ibd + +File::tab#.ibd +================PAGE TYPE SUMMARY============== +#PAGE_COUNT PAGE_TYPE +=============================================== + # Index page + # Undo log page + # Inode page + # Insert buffer free list page + # Freshly allocated page + # Insert buffer bitmap + # System page + # Transaction system page + # File Space Header + # Extent descriptor page + # BLOB page + # Compressed BLOB page + # Page compressed page + # Page compressed encrypted page + # Other type of page + +=============================================== +Additional information: +Undo page type: # insert, # update, # other +Undo page state: # active, # cached, # to_free, # to_purge, # prepared, # other +index_id #pages #leaf_pages #recs_per_page #bytes_per_page +# # # # # +# # # # # +# # # # # + +index_id page_data_bytes_histgram(empty,...,oversized) +# # # # # # # # # # # # # +# # # # # # # # # # # # # +# # # # # # # # # # # # # +[4]: Page type dump for with longform for tab1.ibd +# Print the contents stored in dump.txt + + +Filename::tab#.ibd +============================================================================== + PAGE_NO | PAGE_TYPE | EXTRA INFO +============================================================================== +#::# | File Space Header | - +#::# | Insert Buffer Bitmap | - +#::# | Inode page | - +#::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - +#::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - +#::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - +#::# | Freshly allocated page | - +#::# | Freshly allocated page | - +# Variables used by page type dump for ibdata1 + +Variables (--variable-name=value) +and boolean options {FALSE|TRUE} Value (after reading options) +--------------------------------- ---------------------------------------- +verbose TRUE +count FALSE +start-page 0 +end-page 0 +page 0 +strict-check crc32 +no-check FALSE +allow-mismatches 0 +write crc32 +page-type-summary FALSE +page-type-dump MYSQLTEST_VARDIR/tmp/dump.txt +per-page-details FALSE +log (No default value) +leaf FALSE +merge 0 +[5]: Page type dump for with shortform for tab1.ibd + + +Filename::tab#.ibd +============================================================================== + PAGE_NO | PAGE_TYPE | EXTRA INFO +============================================================================== +#::# | File Space Header | - +#::# | Insert Buffer Bitmap | - +#::# | Inode page | - +#::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - +#::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - +#::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - +#::# | Freshly allocated page | - +#::# | Freshly allocated page | - +[6]: check the valid lower bound values for option +# allow-mismatches,page,start-page,end-page +[9]: check the both short and long options "page" and "start-page" when +# seek value is larger than file size. +FOUND /Error: Unable to seek to necessary offset: Invalid argument/ in my_restart.err +FOUND /Error: Unable to seek to necessary offset: Invalid argument/ in my_restart.err +FOUND /Error: Unable to seek to necessary offset: Invalid argument/ in my_restart.err +FOUND /Error: Unable to seek to necessary offset: Invalid argument/ in my_restart.err +[34]: check the invalid upper bound values for options, allow-mismatches, end-page, start-page and page. +# innochecksum will fail with error code: 1 +NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_restart.err +NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_restart.err +NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_restart.err +NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_restart.err +NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_restart.err +NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_restart.err +NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_restart.err +NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_restart.err +DROP TABLE tab1,tab2; diff --git a/mysql-test/suite/innodb/t/innodb_zip_innochecksum.opt b/mysql-test/suite/innodb/t/innodb_zip_innochecksum.opt new file mode 100644 index 00000000000..f8c8c9d247d --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_zip_innochecksum.opt @@ -0,0 +1,4 @@ +--skip-innodb-doublewrite +--innodb-file-per-table +--innodb-file-format=Barracuda + diff --git a/mysql-test/suite/innodb/t/innodb_zip_innochecksum.test b/mysql-test/suite/innodb/t/innodb_zip_innochecksum.test new file mode 100644 index 00000000000..63a4b418677 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_zip_innochecksum.test @@ -0,0 +1,239 @@ +#************************************************************ +# WL6045:Improve Innochecksum +#************************************************************ +--source include/innodb_page_size_small.inc +--source include/no_valgrind_without_big.inc +# Embedded server does not support crashing. +--source include/not_embedded.inc + +# Avoid CrashReporter popup on Mac. +--source include/not_crashrep.inc + +--echo # Set the environmental variables +let MYSQLD_BASEDIR= `SELECT @@basedir`; +let MYSQLD_DATADIR= `SELECT @@datadir`; +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err; +call mtr.add_suppression("InnoDB: Unable to read tablespace .* page no .* into the buffer pool after 100 attempts"); +call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); + +CREATE TABLE tab1(c1 INT PRIMARY KEY,c2 VARCHAR(20)) ENGINE=InnoDB; +CREATE INDEX idx1 ON tab1(c2(10)); +INSERT INTO tab1 VALUES(1, 'Innochecksum InnoDB1'); +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; +insert into t1 values(1,"i"); +insert into t1 values(2,"am"); +insert into t1 values(3,"compressed table"); + +--echo # Shutdown the Server +--source include/shutdown_mysqld.inc +--echo # Server Default checksum = innodb + +# +# Not repeatable with --parallel= >1 +# +#--echo [1a]: check the innochecksum when file doesn't exists +#--error 1 +#--exec $INNOCHECKSUM $MYSQLD_DATADIR/test/aa.ibd 2> $SEARCH_FILE +#let SEARCH_PATTERN= Error: $MYSQLD_DATADIR/test/aa.ibd cannot be found; +#--source include/search_pattern_in_file.inc + +--echo [1b]: check the innochecksum without --strict-check +--exec $INNOCHECKSUM $MYSQLD_DATADIR/test/tab1.ibd + +--echo [2]: check the innochecksum with full form --strict-check=crc32 +--exec $INNOCHECKSUM --strict-check=crc32 $MYSQLD_DATADIR/test/tab1.ibd + +--echo [3]: check the innochecksum with short form -C crc32 +--exec $INNOCHECKSUM -C crc32 $MYSQLD_DATADIR/test/tab1.ibd + +--echo [4]: check the innochecksum with --no-check ignores algorithm check, warning is expected +--error 1 +--exec $INNOCHECKSUM --no-check $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error: --no-check must be associated with --write option.; +--source include/search_pattern_in_file.inc + +--echo [5]: check the innochecksum with short form --no-check ignores algorithm check, warning is expected +--error 1 +--exec $INNOCHECKSUM -n $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error: --no-check must be associated with --write option.; +--source include/search_pattern_in_file.inc + +--echo [6]: check the innochecksum with full form strict-check & no-check , an error is expected +--error 1 +--exec $INNOCHECKSUM --strict-check=innodb --no-check $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error: --strict-check option cannot be used together with --no-check option.; +--source include/search_pattern_in_file.inc + +--echo [7]: check the innochecksum with short form strict-check & no-check , an error is expected +--error 1 +--exec $INNOCHECKSUM -C innodb -n $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error: --strict-check option cannot be used together with --no-check option.; +--source include/search_pattern_in_file.inc + +--echo [8]: check the innochecksum with short & full form combination +--echo # strict-check & no-check, an error is expected +--error 1 +--exec $INNOCHECKSUM --strict-check=innodb -n $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error: --strict-check option cannot be used together with --no-check option.; +--source include/search_pattern_in_file.inc + +--echo [9]: check the innochecksum with full form --strict-check=innodb +# Server Default checksum = crc32 +--exec $INNOCHECKSUM --strict-check=innodb $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE + +--echo [10]: check the innochecksum with full form --strict-check=none +--echo # when server Default checksum=crc32 +--exec $INNOCHECKSUM --strict-check=none $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE + +--echo [11]: check the innochecksum with short form -C innodb +--echo # when server Default checksum=crc32 +--exec $INNOCHECKSUM -C innodb $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE + +--echo [12]: check the innochecksum with short form -C none +--echo # when server Default checksum=crc32 +--exec $INNOCHECKSUM -C none $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE + +--echo [13]: check strict-check with invalid values +--error 1 +--exec $INNOCHECKSUM --strict-check=strict_innodb $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error while setting value \'strict_innodb\' to \'strict-check\'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM -C strict_innodb $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error while setting value \'strict_innodb\' to \'strict-check\'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM --strict-check=strict_crc32 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error while setting value \'strict_crc32\' to \'strict-check\'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM -C strict_crc32 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error while setting value \'strict_crc32\' to \'strict-check\'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM --strict-check=strict_none $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error while setting value \'strict_none\' to \'strict-check\'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM -C strict_none $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error while setting value \'strict_none\' to \'strict-check\'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM --strict-check=InnoBD $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error while setting value \'InnoBD\' to \'strict-check\'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM -C InnoBD $MYSQLD_DATADIR/test/tab1.ibd 2>$SEARCH_FILE +let SEARCH_PATTERN= Error while setting value \'InnoBD\' to \'strict-check\'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM --strict-check=crc $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error while setting value \'crc\' to \'strict-check\'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM --strict-check=no $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error while setting value \'no\' to \'strict-check\'; +--source include/search_pattern_in_file.inc + +--echo [14a]: when server default checksum=crc32 rewrite new checksum=crc32 with innochecksum +--echo # Also check the long form of write option. +--exec $INNOCHECKSUM --strict-check=crc32 --write=crc32 $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM --strict-check=crc32 --write=crc32 $MYSQLD_DATADIR/test/t1.ibd +# Rewrite done, verify with --strict-check=crc32 +--exec $INNOCHECKSUM --strict-check=crc32 $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM --strict-check=crc32 $MYSQLD_DATADIR/test/t1.ibd + +--echo [14b]: when server default checksum=crc32 rewrite new checksum=innodb with innochecksum +--echo # Also check the long form of write option. +--exec $INNOCHECKSUM --no-check --write=innodb $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM --strict-check=crc32 --write=innodb $MYSQLD_DATADIR/test/t1.ibd +# Rewrite done, verify with --strict-check=innodb +--exec $INNOCHECKSUM --strict-check=innodb $MYSQLD_DATADIR/test/tab1.ibd + +--echo # start the server with innodb_checksum_algorithm=InnoDB +--let $restart_parameters= --innodb_checksum_algorithm=innodb +--source include/start_mysqld.inc + +INSERT INTO tab1 VALUES(2, 'Innochecksum CRC32'); +SELECT c1,c2 FROM tab1 order by c1,c2; + +--echo # Stop the server +--source include/shutdown_mysqld.inc + +--echo [15]: when server default checksum=crc32 rewrite new checksum=none with innochecksum +--echo # Also check the short form of write option. +--exec $INNOCHECKSUM --no-check -w none $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM --no-check -w none $MYSQLD_DATADIR/test/t1.ibd +# Rewrite done, verify with --strict-check=none +--exec $INNOCHECKSUM --strict-check=none $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM --strict-check=none $MYSQLD_DATADIR/test/t1.ibd + +--echo # Start the server with checksum algorithm=none +--let $restart_parameters= --innodb_checksum_algorithm=none +--source include/start_mysqld.inc + +INSERT INTO tab1 VALUES(3, 'Innochecksum None'); +SELECT c1,c2 FROM tab1 order by c1,c2; +DROP TABLE t1; + +--echo # Stop the server +--source include/shutdown_mysqld.inc + +--echo [16]: rewrite into new checksum=crc32 with innochecksum +--exec $INNOCHECKSUM --no-check --write=crc32 $MYSQLD_DATADIR/test/tab1.ibd + +--echo # Restart the DB server with innodb_checksum_algorithm=crc32 +--let $restart_parameters= --innodb_checksum_algorithm=crc32 +--source include/start_mysqld.inc + +SELECT * FROM tab1; +DELETE FROM tab1 where c1=3; +SELECT c1,c2 FROM tab1 order by c1,c2; + +--echo # Stop server +--source include/shutdown_mysqld.inc + +--echo [17]: rewrite into new checksum=InnoDB +--exec $INNOCHECKSUM --no-check --write=InnoDB $MYSQLD_DATADIR/test/tab1.ibd + +--echo # Restart the DB server with innodb_checksum_algorithm=InnoDB +--let $restart_parameters= --innodb_checksum_algorithm=innodb +--source include/start_mysqld.inc + +DELETE FROM tab1 where c1=2; +SELECT * FROM tab1; + +--echo # Stop server +--source include/shutdown_mysqld.inc + +--echo [18]:check Innochecksum with invalid write options +--error 1 +--exec $INNOCHECKSUM --no-check --write=strict_crc32 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN=Error while setting value \'strict_crc32\' to \'write\'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM --no-check --write=strict_innodb $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN=Error while setting value \'strict_innodb\' to \'write\'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM --no-check --write=crc23 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN=Error while setting value \'crc23\' to \'write\'; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE + +# Cleanup +--let $restart_parameters= +--source include/start_mysqld.inc + +DROP TABLE tab1; diff --git a/mysql-test/suite/innodb/t/innodb_zip_innochecksum2.opt b/mysql-test/suite/innodb/t/innodb_zip_innochecksum2.opt new file mode 100644 index 00000000000..39d5c6d577c --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_zip_innochecksum2.opt @@ -0,0 +1,4 @@ +--skip-innodb-doublewrite +--innodb-file-per-table +--innodb-file-format=Barracuda +--innodb-change-buffering=none diff --git a/mysql-test/suite/innodb/t/innodb_zip_innochecksum2.test b/mysql-test/suite/innodb/t/innodb_zip_innochecksum2.test new file mode 100644 index 00000000000..330bb81ba75 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_zip_innochecksum2.test @@ -0,0 +1,118 @@ +#************************************************************ +# WL6045:Improve Innochecksum +#************************************************************ +--source include/innodb_page_size_small.inc +--source include/have_debug.inc +--source include/no_valgrind_without_big.inc +# Avoid CrashReporter popup on Mac. +--source include/not_crashrep.inc + +--source include/not_embedded.inc +-- source include/big_test.inc + +--disable_query_log +# This warning occurs due to small buffer pool size(i.e. 8MB). It doesn't occur +# with --mysqld=--innodb_buffer_pool_size=10MB +call mtr.add_suppression("\\[Warning\\] InnoDB: Difficult to find free blocks in the buffer pool.*"); +--enable_query_log +let MYSQLD_BASEDIR= `SELECT @@basedir`; +let MYSQLD_DATADIR= `SELECT @@datadir`; +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err; + +SET GLOBAL innodb_compression_level=0; +SELECT @@innodb_compression_level; + +CREATE TABLE t1 (j LONGBLOB) ENGINE = InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; +INSERT INTO t1 VALUES (repeat('abcdefghijklmnopqrstuvwxyz',200)); +let $i=10; +while ($i > 0) { + INSERT INTO t1 SELECT * from t1; + dec $i; +} + +--echo # stop the server +--source include/shutdown_mysqld.inc + +# Page_type_dump for t1 +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $INNOCHECKSUM -v --page-type-dump $MYSQLTEST_VARDIR/tmp/dump.txt $MYSQLD_DATADIR/test/t1.ibd +--file_exists $MYSQLTEST_VARDIR/tmp/dump.txt +--remove_file $MYSQLTEST_VARDIR/tmp/dump.txt + +--echo [1]:# check the both short and long options for "help" +--exec $INNOCHECKSUM --help $MYSQLD_DATADIR/test/t1.ibd > $MYSQLTEST_VARDIR/tmp/help_output_long.txt +--exec $INNOCHECKSUM -I $MYSQLD_DATADIR/test/t1.ibd > $MYSQLTEST_VARDIR/tmp/help_output_short.txt +--diff_files $MYSQLTEST_VARDIR/tmp/help_output_long.txt $MYSQLTEST_VARDIR/tmp/help_output_short.txt + +--echo [2]:# Run the innochecksum when file isn't provided. +--echo # It will print the innochecksum usage similar to --help option. +--error 1 +--exec $INNOCHECKSUM > $MYSQLTEST_VARDIR/tmp/usage.txt +--diff_files $MYSQLTEST_VARDIR/tmp/help_output_long.txt $MYSQLTEST_VARDIR/tmp/usage.txt +--remove_file $MYSQLTEST_VARDIR/tmp/usage.txt + +perl; +use strict; +use warnings; +use File::Copy; +my $dir = $ENV{'MYSQLTEST_VARDIR'}; +my $file= 'help_output_long.txt'; +# open file in write mode +open IN_FILE,"<", "$dir/tmp/$file" or die $!; +open OUT_FILE, ">", "$dir/tmp/tmpfile" or die $!; +while(<IN_FILE>) { + unless ($_=~ /^debug.*$/ || $_=~ /\-#, \-\-debug.*$/ || $_=~ /http:.*html/) { + $_=~ s/^\S*innochecksum.+Ver.+[0-9]*\.[0-9]*\.[0-9]*.+$/innochecksum Ver #.#.#/g; + $_=~ s/(Copyright\s\(c\))\s([0-9]*),\s([0-9]*)(.*)/$1 YEAR, YEAR $4/g; + $_=~ s/Usage:.*\[-c/Usage: innochecksum [-c/g; + print OUT_FILE $_; + } +} +close(IN_FILE); +close(OUT_FILE); +# move the new content from tmp file to the orginal file. +move ("$dir/tmp/tmpfile", "$dir/tmp/$file"); +EOF + +--cat_file $MYSQLTEST_VARDIR/tmp/help_output_long.txt +--remove_file $MYSQLTEST_VARDIR/tmp/help_output_long.txt +--remove_file $MYSQLTEST_VARDIR/tmp/help_output_short.txt + +--echo [3]:# check the both short and long options for "count" and exit +--replace_regex /[0-9]+/#/ +--exec $INNOCHECKSUM --count $MYSQLD_DATADIR/test/t1.ibd +--replace_regex /[0-9]+/#/ +--exec $INNOCHECKSUM -c $MYSQLD_DATADIR/test/t1.ibd + +--echo [4]:# Print the version of innochecksum and exit +--replace_regex /.*innochecksum.*Ver.*[0-9]*.[0-9]*.[0-9]*.*/innochecksum Ver #.#.#/ +--exec $INNOCHECKSUM -V $MYSQLD_DATADIR/test/t1.ibd + +--echo # Restart the DB server +--source include/start_mysqld.inc + +DROP TABLE t1; + +--echo [5]:# Check the innochecksum for compressed table t1 with different key_block_size +--echo # Test for KEY_BLOCK_SIZE=1 +--let $size=1 +--source ../include/innodb-wl6045.inc + +--echo # Test for KEY_BLOCK_SIZE=2 +--let $size=2 +--source ../include/innodb-wl6045.inc + +--echo # Test for for KEY_BLOCK_SIZE=4 +--let $size=4 +--source ../include/innodb-wl6045.inc + +set innodb_strict_mode=off; +--echo # Test for for KEY_BLOCK_SIZE=8 +--let $size=8 +--source ../include/innodb-wl6045.inc + +set innodb_strict_mode=off; +--echo # Test for KEY_BLOCK_SIZE=16 +--let $size=16 +--source ../include/innodb-wl6045.inc +--echo # Test[5] completed diff --git a/mysql-test/suite/innodb/t/innodb_zip_innochecksum3.opt b/mysql-test/suite/innodb/t/innodb_zip_innochecksum3.opt new file mode 100644 index 00000000000..828a7cd67c8 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_zip_innochecksum3.opt @@ -0,0 +1,2 @@ +--innodb-file-per-table +--innodb-file-format=Barracuda diff --git a/mysql-test/suite/innodb/t/innodb_zip_innochecksum3.test b/mysql-test/suite/innodb/t/innodb_zip_innochecksum3.test new file mode 100644 index 00000000000..dab10dcc997 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_zip_innochecksum3.test @@ -0,0 +1,406 @@ +#************************************************************ +# WL6045:Improve Innochecksum +#************************************************************ +--source include/innodb_page_size_small.inc + +--source include/no_valgrind_without_big.inc + +# Embedded server does not support crashing. +--source include/not_embedded.inc + +# Avoid CrashReporter popup on Mac. +--source include/not_crashrep.inc + +--echo # Set the environmental variables +let MYSQLD_BASEDIR= `SELECT @@basedir`; +let MYSQLD_DATADIR= `SELECT @@datadir`; +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err; + +call mtr.add_suppression("InnoDB: Unable to read tablespace .* page no .* into the buffer pool after 100 attempts"); +call mtr.add_suppression("InnoDB: innodb_checksum_algorithm is set to.*"); + +--echo [1]: Further Test are for rewrite checksum (innodb|crc32|none) for all ibd file & start the server. + +CREATE TABLE tab1 (pk INTEGER NOT NULL PRIMARY KEY, +linestring_key GEOMETRY NOT NULL, +linestring_nokey GEOMETRY NOT NULL) +ENGINE=InnoDB ; + +INSERT INTO tab1 (pk, linestring_key, linestring_nokey) +VALUES (1, ST_GeomFromText('POINT(10 10) '), ST_GeomFromText('POINT(10 10) ')); + +CREATE INDEX linestring_index ON tab1(linestring_nokey(5)); +ALTER TABLE tab1 ADD KEY (linestring_key(5)); + +--echo # create a compressed table +CREATE TABLE tab2(col_1 CHAR (255) , +col_2 VARCHAR (255), col_3 longtext, +col_4 longtext,col_5 longtext, +col_6 longtext , col_7 int ) +engine = innodb row_format=compressed key_block_size=4; + +CREATE INDEX idx1 ON tab2(col_3(10)); +CREATE INDEX idx2 ON tab2(col_4(10)); +CREATE INDEX idx3 ON tab2(col_5(10)); + +# load the with repeat function +SET @col_1 = repeat('a', 5); +SET @col_2 = repeat('b', 20); +SET @col_3 = repeat('c', 100); +SET @col_4 = repeat('d', 100); +SET @col_5 = repeat('e', 100); +SET @col_6 = repeat('f', 100); + +# insert 5 records +let $i = 5; +while ($i) { + eval INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) + VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,$i); + dec $i; +} + +--disable_result_log +SELECT * FROM tab2 ORDER BY col_7; + +--echo # stop the server +--source include/shutdown_mysqld.inc + +--echo [1(a)]: Rewrite into new checksum=InnoDB for all *.ibd file and ibdata1 +--exec $INNOCHECKSUM --write=InnoDB $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM --write=InnoDB $MYSQLD_DATADIR/test/tab2.ibd +--exec $INNOCHECKSUM --write=InnoDB $MYSQLD_DATADIR/ibdata1 +perl; +foreach (glob("$ENV{MYSQLD_DATADIR}/*/*.ibd")) { + system("$ENV{INNOCHECKSUM} --no-check --write=InnoDB $_") +} +EOF + +--echo : start the server with innodb_checksum_algorithm=strict_innodb +--let $restart_parameters= --innodb_checksum_algorithm=strict_innodb +--source include/start_mysqld.inc + +INSERT INTO tab1 (pk, linestring_key, linestring_nokey) +VALUES (2, ST_GeomFromText('LINESTRING(10 10,20 20,30 30)'), ST_GeomFromText('LINESTRING(10 10,20 20,30 30)')); + +# load the with repeat function +SET @col_1 = repeat('a', 5); +SET @col_2 = repeat('b', 20); +SET @col_3 = repeat('c', 100); +SET @col_4 = repeat('d', 100); +SET @col_5 = repeat('e', 100); +SET @col_6 = repeat('f', 100); + +# check the table status is GOOD with DML +let $i = 6; +eval INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) +VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,$i); + +-- disable_result_log +SELECT pk,ST_AsText(linestring_key),ST_AsText(linestring_nokey) +FROM tab1 ORDER BY pk; + +-- disable_result_log +SELECT * FROM tab2 ORDER BY col_7; + +--echo # stop the server +--source include/shutdown_mysqld.inc + +--echo [1(b)]: Rewrite into new checksum=crc32 for all *.ibd file and ibdata1 +--exec $INNOCHECKSUM --write=CRC32 $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM --write=CRC32 $MYSQLD_DATADIR/test/tab2.ibd +--exec $INNOCHECKSUM --write=CRC32 $MYSQLD_DATADIR/ibdata1 +perl; +foreach (glob("$ENV{MYSQLD_DATADIR}/*/*.ibd")) { + system("$ENV{INNOCHECKSUM} --no-check --write=crc32 $_") +} +EOF + +--echo # start the server with innodb_checksum_algorithm=strict_crc32 +--let $restart_parameters= --innodb_checksum_algorithm=strict_crc32 +--source include/start_mysqld.inc + +# check the table status is GOOD with DML +INSERT INTO tab1 (pk, linestring_key, linestring_nokey) +VALUES (3, ST_GeomFromText('POLYGON((0 0,5 5,10 10,15 15,0 0),(10 10,20 20,30 30,40 40,10 10))'), +ST_GeomFromText('POLYGON((0 0,5 5,10 10,15 15,0 0),(10 10,20 20,30 30,40 40,10 10))')); + +# load the with repeat function +SET @col_1 = repeat('g', 5); +SET @col_2 = repeat('h', 20); +SET @col_3 = repeat('i', 100); +SET @col_4 = repeat('j', 100); +SET @col_5 = repeat('k', 100); +SET @col_6 = repeat('l', 100); + +# check the table status is GOOD with DML +let $i = 7; +eval INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) +VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,$i); + +# check the records from table +-- disable_result_log +SELECT pk,ST_AsText(linestring_key),ST_AsText(linestring_nokey) +FROM tab1 ORDER BY pk; + +-- disable_result_log +SELECT * FROM tab2 ORDER BY col_7; + +--echo # stop the server +--source include/shutdown_mysqld.inc + +--echo [1(c)]: Rewrite into new checksum=none for all *.ibd file and ibdata1 +--exec $INNOCHECKSUM --write=none $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM --write=none $MYSQLD_DATADIR/test/tab2.ibd +--exec $INNOCHECKSUM --write=none $MYSQLD_DATADIR/ibdata1 +perl; +foreach (glob("$ENV{MYSQLD_DATADIR}/undo*")) { + system("$ENV{INNOCHECKSUM} --no-check --write=NONE $_") +} +foreach (glob("$ENV{MYSQLD_DATADIR}/*/*.ibd")) { + system("$ENV{INNOCHECKSUM} --no-check --write=NONE $_") +} +EOF + +--let $restart_parameters= --innodb_checksum_algorithm=strict_none +--source include/start_mysqld.inc +--let $restart_parameters= +# check the table status is GOOD with DML +INSERT INTO tab1 (pk, linestring_key, linestring_nokey) +VALUES (4, ST_GeomFromText('MULTIPOINT(0 0,5 5,10 10,20 20) '), ST_GeomFromText('MULTIPOINT(0 0,5 5,10 10,20 20) ')); + +# load the with repeat function +SET @col_1 = repeat('m', 5); +SET @col_2 = repeat('n', 20); +SET @col_3 = repeat('o', 100); +SET @col_4 = repeat('p', 100); +SET @col_5 = repeat('q', 100); +SET @col_6 = repeat('r', 100); + +# check the table status is GOOD with DML +let $i = 8; +eval INSERT INTO tab2(col_1,col_2,col_3,col_4,col_5,col_6,col_7) +VALUES (@col_1,@col_2,@col_3,@col_4,@cl_5,@col_6,$i); + +# check the records from table +-- disable_result_log +SELECT pk,ST_AsText(linestring_key),ST_AsText(linestring_nokey) +FROM tab1 ORDER BY pk; + +--disable_result_log +SELECT * FROM tab2 ORDER BY col_7; +--enable_result_log + +--echo # stop the server +--source include/shutdown_mysqld.inc + +--echo [2]: Check the page type summary with shortform for tab1.ibd +--replace_regex /File.*.ibd/File::tab1.ibd/ /[0-9]+/#/ +--exec $INNOCHECKSUM -S $MYSQLD_DATADIR/test/tab1.ibd 2>$MYSQLTEST_VARDIR/tmp/page_summary_short.txt + +--echo [3]: Check the page type summary with longform for tab1.ibd +--replace_regex /File.*.ibd/File::tab1.ibd/ /[0-9]+/#/ +--exec $INNOCHECKSUM --page-type-summary $MYSQLD_DATADIR/test/tab1.ibd 2>$MYSQLTEST_VARDIR/tmp/page_summary_long.txt + +--remove_file $MYSQLTEST_VARDIR/tmp/page_summary_short.txt +--remove_file $MYSQLTEST_VARDIR/tmp/page_summary_long.txt +--echo [4]: Page type dump for with longform for tab1.ibd +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $INNOCHECKSUM --page-type-dump $MYSQLTEST_VARDIR/tmp/dump.txt $MYSQLD_DATADIR/test/tab1.ibd + +perl; +use strict; +use warnings; +use File::Copy; +my $dir = $ENV{'MYSQLTEST_VARDIR'}; +opendir(DIR, $dir) or die $!; +my $file= 'dump.txt'; +# open file in write mode +open IN_FILE,"<", "$dir/tmp/$file" or die $!; +open OUT_FILE, ">", "$dir/tmp/innochecksum_3_tempfile" or die $!; +while(<IN_FILE>) +{ + # Replace the intergers to # and complete file path to file name only. + $_=~ s/Filename.+/Filename::tab1.ibd/g; + $_=~ s/\d+/#/g; + print OUT_FILE $_; +} +close(IN_FILE); +close(OUT_FILE); +# move the new content from tmp file to the orginal file. +move ("$dir/tmp/innochecksum_3_tempfile", "$dir/tmp/$file"); +closedir(DIR); +EOF + +--echo # Print the contents stored in dump.txt +cat_file $MYSQLTEST_VARDIR/tmp/dump.txt; +--remove_file $MYSQLTEST_VARDIR/tmp/dump.txt + +--echo # Variables used by page type dump for ibdata1 +--exec $INNOCHECKSUM -v --page-type-dump $MYSQLTEST_VARDIR/tmp/dump.txt $MYSQLD_DATADIR/ibdata1 > $MYSQLTEST_VARDIR/tmp/page_verbose_summary.txt + +--file_exists $MYSQLTEST_VARDIR/tmp/dump.txt +--remove_file $MYSQLTEST_VARDIR/tmp/dump.txt + +perl; +use strict; +use warnings; +use File::Copy; +my $dir = $ENV{'MYSQLTEST_VARDIR'}; +opendir(DIR, $dir) or die $!; +my $file= 'page_verbose_summary.txt'; +# open file in write mode +open IN_FILE,"<", "$dir/tmp/$file" or die $!; +open OUT_FILE, ">", "$dir/tmp/innochecksum_3_tempfile" or die $!; +while(<IN_FILE>) +{ + # Replace complete file path to file name only. + $_=~ s/$dir/MYSQLTEST_VARDIR/; + # Remove debug option, which is not in all builds + next if (/debug/); + print OUT_FILE $_; +} +close(IN_FILE); +close(OUT_FILE); +# move the new content from tmp file to the orginal file. +move ("$dir/tmp/innochecksum_3_tempfile", "$dir/tmp/$file"); +closedir(DIR); +EOF + +cat_file $MYSQLTEST_VARDIR/tmp/page_verbose_summary.txt; +--remove_file $MYSQLTEST_VARDIR/tmp/page_verbose_summary.txt + +--echo [5]: Page type dump for with shortform for tab1.ibd +--exec $INNOCHECKSUM -D $MYSQLTEST_VARDIR/tmp/dump.txt $MYSQLD_DATADIR/test/tab1.ibd + +perl; +use strict; +use warnings; +use File::Copy; +my $dir = $ENV{'MYSQLTEST_VARDIR'}; +opendir(DIR, $dir) or die $!; +my $file= 'dump.txt'; +# open file in write mode +open IN_FILE,"<", "$dir/tmp/$file" or die $!; +open OUT_FILE, ">", "$dir/tmp/innochecksum_3_tempfile" or die $!; +while(<IN_FILE>) +{ + # Replace the intergers to # and complete file path to file name only. + $_=~ s/Filename.+/Filename::tab1.ibd/g; + $_=~ s/\d+/#/g; + print OUT_FILE $_; +} +close(IN_FILE); +close(OUT_FILE); +# move the new content from tmp file to the orginal file. +move ("$dir/tmp/innochecksum_3_tempfile", "$dir/tmp/$file"); +closedir(DIR); +EOF + +# Print the contents stored in dump.txt +cat_file $MYSQLTEST_VARDIR/tmp/dump.txt; +--remove_file $MYSQLTEST_VARDIR/tmp/dump.txt + +--echo [6]: check the valid lower bound values for option +--echo # allow-mismatches,page,start-page,end-page +--exec $INNOCHECKSUM --allow-mismatches=0 $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM -a 0 $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM --page=0 $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM -p 0 $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM --start-page=0 $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM -s 0 $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM --end-page=0 $MYSQLD_DATADIR/test/tab1.ibd +--exec $INNOCHECKSUM -e 0 $MYSQLD_DATADIR/test/tab1.ibd + +# +# These produce now errors +# +#--echo [7]: check the negative values for option +#--echo # allow-mismatches,page,start-page,end-page. +#--echo # They will reset to zero for negative values. +#--echo # check the invalid lower bound values +#--exec $INNOCHECKSUM --allow-mismatches=-1 $MYSQLD_DATADIR/test/tab1.ibd +#--exec $INNOCHECKSUM -a -1 $MYSQLD_DATADIR/test/tab1.ibd +#--exec $INNOCHECKSUM --page=-1 $MYSQLD_DATADIR/test/tab1.ibd +#--exec $INNOCHECKSUM -p -1 $MYSQLD_DATADIR/test/tab1.ibd +#--exec $INNOCHECKSUM --start-page=-1 $MYSQLD_DATADIR/test/tab1.ibd +#--exec $INNOCHECKSUM -s -1 $MYSQLD_DATADIR/test/tab1.ibd +#--exec $INNOCHECKSUM --end-page=-1 $MYSQLD_DATADIR/test/tab1.ibd +#--exec $INNOCHECKSUM -e -1 $MYSQLD_DATADIR/test/tab1.ibd +# +#--echo [8]: check the valid upper bound values for +#--echo # both short and long options "allow-mismatches" and "end-page" +# +#--exec $INNOCHECKSUM --allow-mismatches=18446744073709551615 $MYSQLD_DATADIR/test/tab1.ibd +#--exec $INNOCHECKSUM -a 18446744073709551615 $MYSQLD_DATADIR/test/tab1.ibd +#--exec $INNOCHECKSUM --end-page=18446744073709551615 $MYSQLD_DATADIR/test/tab1.ibd +#--exec $INNOCHECKSUM -e 18446744073709551615 $MYSQLD_DATADIR/test/tab1.ibd + +--echo [9]: check the both short and long options "page" and "start-page" when +--echo # seek value is larger than file size. +--error 1 +--exec $INNOCHECKSUM --page=18446744073709551615 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error: Unable to seek to necessary offset: Invalid argument; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM -p 18446744073709551615 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error: Unable to seek to necessary offset: Invalid argument; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM --start-page=18446744073709551615 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error: Unable to seek to necessary offset: Invalid argument; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM -s 18446744073709551615 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Error: Unable to seek to necessary offset: Invalid argument; +--source include/search_pattern_in_file.inc + +--echo [34]: check the invalid upper bound values for options, allow-mismatches, end-page, start-page and page. +--echo # innochecksum will fail with error code: 1 +--error 1 +--exec $INNOCHECKSUM --allow-mismatches=18446744073709551616 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Incorrect unsigned integer value: '18446744073709551616'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM -a 18446744073709551616 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Incorrect unsigned integer value: '18446744073709551616'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM --end-page=18446744073709551616 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Incorrect unsigned integer value: '18446744073709551616'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM -e 18446744073709551616 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Incorrect unsigned integer value: '18446744073709551616'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM --page=18446744073709551616 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Incorrect unsigned integer value: '18446744073709551616'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM -p 18446744073709551616 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Incorrect unsigned integer value: '18446744073709551616'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM --start-page=18446744073709551616 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Incorrect unsigned integer value: '18446744073709551616'; +--source include/search_pattern_in_file.inc + +--error 1 +--exec $INNOCHECKSUM -s 18446744073709551616 $MYSQLD_DATADIR/test/tab1.ibd 2> $SEARCH_FILE +let SEARCH_PATTERN= Incorrect unsigned integer value: '18446744073709551616'; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE + +# Cleanup +--source include/start_mysqld.inc + +DROP TABLE tab1,tab2; diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 50d067b3f85..85d7485678e 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -571,10 +571,10 @@ buf_page_is_checksum_valid_crc32( #ifdef UNIV_INNOCHECKSUM if (log_file && srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) { - fprintf(log_file, "page::%lu;" + fprintf(log_file, "page::%llu;" " crc32 calculated = %u;" - " recorded checksum field1 = %lu recorded" - " checksum field2 =%lu\n", cur_page_num, + " recorded checksum field1 = " ULINTPF " recorded" + " checksum field2 =" ULINTPF "\n", cur_page_num, crc32, checksum_field1, checksum_field2); } #endif /* UNIV_INNOCHECKSUM */ @@ -619,28 +619,28 @@ buf_page_is_checksum_valid_innodb( #ifdef UNIV_INNOCHECKSUM if (log_file && srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB) { - fprintf(log_file, "page::%lu;" + fprintf(log_file, "page::%llu;" " old style: calculated =" - " %lu; recorded = %lu\n", + " " ULINTPF "; recorded = " ULINTPF "\n", cur_page_num, old_checksum, checksum_field2); - fprintf(log_file, "page::%lu;" + fprintf(log_file, "page::%llu;" " new style: calculated =" - " %lu; crc32 = %u; recorded = %lu\n", + " " ULINTPF "; crc32 = %u; recorded = " ULINTPF "\n", cur_page_num, new_checksum, buf_calc_page_crc32(read_buf), checksum_field1); } if (log_file && srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) { - fprintf(log_file, "page::%lu;" + fprintf(log_file, "page::%llu;" " old style: calculated =" - " %lu; recorded checksum = %lu\n", + " " ULINTPF "; recorded checksum = " ULINTPF "\n", cur_page_num, old_checksum, checksum_field2); - fprintf(log_file, "page::%lu;" + fprintf(log_file, "page::%llu;" " new style: calculated =" - " %lu; recorded checksum = %lu\n", + " " ULINTPF "; recorded checksum = " ULINTPF "\n", cur_page_num, new_checksum, checksum_field1); } @@ -701,9 +701,9 @@ buf_page_is_checksum_valid_none( if (log_file && srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_NONE) { fprintf(log_file, - "page::%lu; none checksum: calculated" - " = %lu; recorded checksum_field1 = %lu" - " recorded checksum_field2 = %lu\n", + "page::%llu; none checksum: calculated" + " = " ULINTPF "; recorded checksum_field1 = " ULINTPF + " recorded checksum_field2 = " ULINTPF "\n", cur_page_num, BUF_NO_CHECKSUM_MAGIC, checksum_field1, checksum_field2); } @@ -765,7 +765,7 @@ buf_page_is_corrupted( of page do not match */ #ifndef UNIV_INNOCHECKSUM ib_logf(IB_LOG_LEVEL_INFO, - "Log sequence number at the start %lu and the end %lu do not match.", + "Log sequence number at the start " ULINTPF " and the end " ULINTPF " do not match.", mach_read_from_4(read_buf + FIL_PAGE_LSN + 4), mach_read_from_4(read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)); #endif /* UNIV_INNOCHECKSUM */ @@ -786,7 +786,7 @@ buf_page_is_corrupted( ut_print_timestamp(stderr); fprintf(stderr, - " InnoDB: Error: page %lu log sequence number" + " InnoDB: Error: page " ULINTPF " log sequence number" " " LSN_PF "\n" "InnoDB: is in the future! Current system " "log sequence number " LSN_PF ".\n" @@ -876,13 +876,13 @@ buf_page_is_corrupted( #ifdef UNIV_INNOCHECKSUM if (log_file) { - fprintf(log_file, "page::" ULINTPF ";" + fprintf(log_file, "page::%llu;" " old style: calculated = " ULINTPF ";" " recorded = " ULINTPF "\n", cur_page_num, buf_calc_page_old_checksum(read_buf), checksum_field2); - fprintf(log_file, "page::" ULINTPF ";" + fprintf(log_file, "page::%llu;" " new style: calculated = " ULINTPF ";" " crc32 = %u; recorded = " ULINTPF "\n", cur_page_num, @@ -912,7 +912,7 @@ buf_page_is_corrupted( #ifdef UNIV_INNOCHECKSUM if (log_file) { - fprintf(log_file, "Fail; page " ULINTPF + fprintf(log_file, "Fail; page::%llu;" " invalid (fails crc32 checksum)\n", cur_page_num); } @@ -940,12 +940,12 @@ buf_page_is_corrupted( } #ifdef UNIV_INNOCHECKSUM if (log_file) { - fprintf(log_file, "page::" ULINTPF ";" + fprintf(log_file, "page::%llu;" " old style: calculated = " ULINTPF ";" " recorded = " ULINTPF "\n", cur_page_num, buf_calc_page_old_checksum(read_buf), checksum_field2); - fprintf(log_file, "page::" ULINTPF ";" + fprintf(log_file, "page::%llu;" " new style: calculated = " ULINTPF ";" " crc32 = %u; recorded = " ULINTPF "\n", cur_page_num, @@ -975,7 +975,7 @@ buf_page_is_corrupted( #ifdef UNIV_INNOCHECKSUM if (log_file) { - fprintf(log_file, "Fail; page " ULINTPF + fprintf(log_file, "Fail; page::%llu;" " invalid (fails innodb checksum)\n", cur_page_num); } @@ -1014,7 +1014,7 @@ buf_page_is_corrupted( #ifdef UNIV_INNOCHECKSUM if (log_file) { - fprintf(log_file, "Fail; page " ULINTPF + fprintf(log_file, "Fail; page::%llu;" " invalid (fails none checksum)\n", cur_page_num); } @@ -1060,7 +1060,7 @@ buf_page_print( if (!(flags & BUF_PAGE_PRINT_NO_FULL)) { ut_print_timestamp(stderr); fprintf(stderr, - " InnoDB: Page dump in ascii and hex (%lu bytes):\n", + " InnoDB: Page dump in ascii and hex (" ULINTPF " bytes):\n", size); ut_print_buf(stderr, read_buf, size); fputs("\nInnoDB: End of page dump\n", stderr); @@ -1116,7 +1116,7 @@ buf_page_print( "low 4 bytes of LSN at page end " ULINTPF ", " "page number (if stored to page already) " ULINTPF ", " "space id (if created with >= MySQL-4.1.1 " - "and stored already) %lu\n", + "and stored already) " ULINTPF "\n", mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM), buf_checksum_algorithm_name(SRV_CHECKSUM_ALGORITHM_CRC32), buf_calc_page_crc32(read_buf), @@ -2853,8 +2853,8 @@ buf_block_align_instance( if (block->page.space != space || block->page.offset != offset) { ib_logf(IB_LOG_LEVEL_ERROR, - "Corruption: Block space_id %lu != page space_id %lu or " - "Block offset %lu != page offset %lu", + "Corruption: Block space_id " ULINTPF " != page space_id " ULINTPF " or " + "Block offset " ULINTPF " != page offset " ULINTPF " ", (ulint)block->page.space, space, (ulint)block->page.offset, offset); } diff --git a/storage/innobase/include/page0size.h b/storage/innobase/include/page0size.h new file mode 100644 index 00000000000..b1e1254bfc5 --- /dev/null +++ b/storage/innobase/include/page0size.h @@ -0,0 +1,200 @@ +/***************************************************************************** + +Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 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, Suite 500, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +/**************************************************//** +@file include/page0size.h +A class describing a page size. + +Created Nov 14, 2013 Vasil Dimov +*******************************************************/ + +#ifndef page0size_t +#define page0size_t + +#include "univ.i" +#include "fsp0types.h" + +#define FIELD_REF_SIZE 20 + +/** A BLOB field reference full of zero, for use in assertions and +tests.Initially, BLOB field references are set to zero, in +dtuple_convert_big_rec(). */ +extern const byte field_ref_zero[FIELD_REF_SIZE]; + +#define PAGE_SIZE_T_SIZE_BITS 17 + +/** Page size descriptor. Contains the physical and logical page size, as well +as whether the page is compressed or not. */ +class page_size_t { +public: + /** Constructor from (physical, logical, is_compressed). + @param[in] physical physical (on-disk/zipped) page size + @param[in] logical logical (in-memory/unzipped) page size + @param[in] is_compressed whether the page is compressed */ + page_size_t(ulint physical, ulint logical, bool is_compressed) + { + if (physical == 0) { + physical = UNIV_PAGE_SIZE_ORIG; + } + if (logical == 0) { + logical = UNIV_PAGE_SIZE_ORIG; + } + + m_physical = static_cast<unsigned>(physical); + m_logical = static_cast<unsigned>(logical); + m_is_compressed = static_cast<unsigned>(is_compressed); + + ut_ad(physical <= (1 << PAGE_SIZE_T_SIZE_BITS)); + ut_ad(logical <= (1 << PAGE_SIZE_T_SIZE_BITS)); + + ut_ad(ut_is_2pow(physical)); + ut_ad(ut_is_2pow(logical)); + + ut_ad(logical <= UNIV_PAGE_SIZE_MAX); + ut_ad(logical >= physical); + ut_ad(!is_compressed || physical <= UNIV_ZIP_SIZE_MAX); + } + + /** Constructor from (fsp_flags). + @param[in] fsp_flags filespace flags */ + explicit page_size_t(ulint fsp_flags) + { + ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(fsp_flags); + + /* If the logical page size is zero in fsp_flags, then use the + legacy 16k page size. */ + ssize = (0 == ssize) ? UNIV_PAGE_SSIZE_ORIG : ssize; + + /* Convert from a 'log2 minus 9' to a page size in bytes. */ + const unsigned size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize); + + ut_ad(size <= UNIV_PAGE_SIZE_MAX); + ut_ad(size <= (1 << PAGE_SIZE_T_SIZE_BITS)); + + m_logical = size; + + ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags); + + /* If the fsp_flags have zero in the zip_ssize field, then it means + that the tablespace does not have compressed pages and the physical + page size is the same as the logical page size. */ + if (ssize == 0) { + m_is_compressed = false; + m_physical = m_logical; + } else { + m_is_compressed = true; + + /* Convert from a 'log2 minus 9' to a page size + in bytes. */ + const unsigned phy + = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize); + + ut_ad(phy <= UNIV_ZIP_SIZE_MAX); + ut_ad(phy <= (1 << PAGE_SIZE_T_SIZE_BITS)); + + m_physical = phy; + } + } + + /** Retrieve the physical page size (on-disk). + @return physical page size in bytes */ + inline ulint physical() const + { + ut_ad(m_physical > 0); + + return(m_physical); + } + + /** Retrieve the logical page size (in-memory). + @return logical page size in bytes */ + inline ulint logical() const + { + ut_ad(m_logical > 0); + return(m_logical); + } + + /** Check whether the page is compressed on disk. + @return true if compressed */ + inline bool is_compressed() const + { + return(m_is_compressed); + } + + /** Copy the values from a given page_size_t object. + @param[in] src page size object whose values to fetch */ + inline void copy_from(const page_size_t& src) + { + *this = src; + } + + /** Check if a given page_size_t object is equal to the current one. + @param[in] a page_size_t object to compare + @return true if equal */ + inline bool equals_to(const page_size_t& a) const + { + return(a.physical() == m_physical + && a.logical() == m_logical + && a.is_compressed() == m_is_compressed); + } + +private: + + /* For non compressed tablespaces, physical page size is equal to + the logical page size and the data is stored in buf_page_t::frame + (and is also always equal to univ_page_size (--innodb-page-size=)). + + For compressed tablespaces, physical page size is the compressed + page size as stored on disk and in buf_page_t::zip::data. The logical + page size is the uncompressed page size in memory - the size of + buf_page_t::frame (currently also always equal to univ_page_size + (--innodb-page-size=)). */ + + /** Physical page size. */ + unsigned m_physical:PAGE_SIZE_T_SIZE_BITS; + + /** Logical page size. */ + unsigned m_logical:PAGE_SIZE_T_SIZE_BITS; + + /** Flag designating whether the physical page is compressed, which is + true IFF the whole tablespace where the page belongs is compressed. */ + unsigned m_is_compressed:1; +}; + +#ifndef UNIV_INNOCHECKSUM +/* Overloading the global output operator to conveniently print an object +of type the page_size_t. +@param[in,out] out the output stream +@param[in] obj an object of type page_size_t to be printed +@retval the output stream */ +inline +std::ostream& +operator<<( + std::ostream& out, + const page_size_t& obj) +{ + out << "[page size: physical=" << obj.physical() + << ", logical=" << obj.logical() + << ", compressed=" << obj.is_compressed() << "]"; + return(out); +} +#endif + +extern page_size_t univ_page_size; + +#endif /* page0size_t */ diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index aafb84db6f1..755b10ba65a 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -371,6 +371,8 @@ and 2 bits for flags. This limits the uncompressed page size to 16k. #define UNIV_PAGE_SIZE_SHIFT_DEF 14 /** Original 16k InnoDB Page Size Shift, in case the default changes */ #define UNIV_PAGE_SIZE_SHIFT_ORIG 14 +/** Original 16k InnoDB Page Size as an ssize (log2 - 9) */ +#define UNIV_PAGE_SSIZE_ORIG (UNIV_PAGE_SIZE_SHIFT_ORIG - 9) /** Minimum page size InnoDB currently supports. */ #define UNIV_PAGE_SIZE_MIN (1 << UNIV_PAGE_SIZE_SHIFT_MIN) @@ -483,9 +485,9 @@ typedef unsigned long long int ullint; #endif /* UNIV_HOTBACKUP */ #ifdef UNIV_INNOCHECKSUM -extern bool strict_verify; -extern FILE* log_file; -extern ulint cur_page_num; +extern bool strict_verify; +extern FILE* log_file; +extern unsigned long long cur_page_num; #endif /* UNIV_INNOCHECKSUM */ #ifndef __WIN__ diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 6e26f830fe6..b580ba6d098 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -4950,7 +4950,7 @@ page_zip_verify_checksum( } #ifdef UNIV_INNOCHECKSUM if (log_file) { - fprintf(log_file, "Page::%lu is empty and" + fprintf(log_file, "Page::%llu is empty and" " uncorrupted\n", cur_page_num); } #endif /* UNIV_INNOCHECKSUM */ @@ -4970,7 +4970,7 @@ page_zip_verify_checksum( #ifdef UNIV_INNOCHECKSUM if (log_file) { - fprintf(log_file, "page::%lu;" + fprintf(log_file, "page::%llu;" " %s checksum: calculated = %u;" " recorded = %u\n", cur_page_num, buf_checksum_algorithm_name( @@ -4985,10 +4985,10 @@ page_zip_verify_checksum( data, size, SRV_CHECKSUM_ALGORITHM_CRC32); if (log_file) { - fprintf(log_file, "page::%lu: crc32 checksum:" + fprintf(log_file, "page::%llu: crc32 checksum:" " calculated = %u; recorded = %u\n", cur_page_num, crc32, stored); - fprintf(log_file, "page::%lu: none checksum:" + fprintf(log_file, "page::%llu: none checksum:" " calculated = %lu; recorded = %u\n", cur_page_num, BUF_NO_CHECKSUM_MAGIC, stored); } |