--- extra/innochecksum.c.orig 2012-10-25 20:26:20.000000000 +0200 +++ extra/innochecksum.c 2012-10-26 02:09:06.000000000 +0200 @@ -32,6 +32,7 @@ #include #include #include +#include /* all of these ripped from InnoDB code from MySQL 4.0.22 */ #define UT_HASH_RANDOM_MASK 1463735687 @@ -44,11 +45,58 @@ #define FIL_PAGE_SPACE_OR_CHKSUM 0 #define UNIV_PAGE_SIZE (2 * 8192) +#define FIL_PAGE_TYPE 24 +#define FIL_PAGE_INDEX 17855 /*!< B-tree node */ +#define FIL_PAGE_UNDO_LOG 2 /*!< Undo log page */ +#define FIL_PAGE_INODE 3 /*!< Index node */ +#define FIL_PAGE_IBUF_FREE_LIST 4 /*!< Insert buffer free list */ +/* File page types introduced in MySQL/InnoDB 5.1.7 */ +#define FIL_PAGE_TYPE_ALLOCATED 0 /*!< Freshly allocated page */ +#define FIL_PAGE_IBUF_BITMAP 5 /*!< Insert buffer bitmap */ +#define FIL_PAGE_TYPE_SYS 6 /*!< System page */ +#define FIL_PAGE_TYPE_TRX_SYS 7 /*!< Transaction system data */ +#define FIL_PAGE_TYPE_FSP_HDR 8 /*!< File space header */ +#define FIL_PAGE_TYPE_XDES 9 /*!< Extent descriptor page */ +#define FIL_PAGE_TYPE_BLOB 10 /*!< Uncompressed BLOB page */ +#define FIL_PAGE_TYPE_ZBLOB 11 /*!< First compressed BLOB page */ +#define FIL_PAGE_TYPE_ZBLOB2 12 /*!< Subsequent compressed BLOB page */ + +#define TRX_UNDO_PAGE_TYPE 0 + +#define TRX_UNDO_INSERT 1 /* contains undo entries for inserts */ +#define TRX_UNDO_UPDATE 2 /* contains undo entries for updates */ + +#define FSEG_PAGE_DATA FIL_PAGE_DATA +#define TRX_UNDO_PAGE_HDR FSEG_PAGE_DATA +#define FIL_ADDR_SIZE 6 +#define FLST_NODE_SIZE (2 * FIL_ADDR_SIZE) +#define TRX_UNDO_PAGE_HDR_SIZE (6 + FLST_NODE_SIZE) +#define TRX_UNDO_SEG_HDR (TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE) + +#define TRX_UNDO_STATE 0 + +#define TRX_UNDO_ACTIVE 1 /* contains an undo log of an active + transaction */ +#define TRX_UNDO_CACHED 2 /* cached for quick reuse */ +#define TRX_UNDO_TO_FREE 3 /* insert undo segment can be freed */ +#define TRX_UNDO_TO_PURGE 4 /* update undo segment will not be + reused: it can be freed in purge when + all undo data in it is removed */ +#define TRX_UNDO_PREPARED 5 /* contains an undo log of an + prepared transaction */ + + /* command line argument to do page checks (that's it) */ /* another argument to specify page ranges... seek to right spot and go from there */ typedef unsigned long int ulint; +unsigned long count_page_undo = 0; +unsigned long count_page_undos[4][7]; +unsigned long count_page_log = 0; +unsigned long count_page_unknown = 0; +unsigned long count_page = 0; + /* innodb function in name; modified slightly to not have the ASM version (lots of #ifs that didn't apply) */ ulint mach_read_from_4(uchar *b) { @@ -59,6 +107,69 @@ ); } +ulint mach_read_from_2 (uchar *b) +{ + return(((ulint)(b[0]) << 8) | (ulint)(b[1])); +} + +ulint fil_page_get_type (uchar* page) +{ + return(mach_read_from_2(page + FIL_PAGE_TYPE)); +} + +void count_page_type (uchar* page) +{ + ulint type; + ulint state; + + count_page++; + + switch (fil_page_get_type(page)) { + case FIL_PAGE_UNDO_LOG: + type = mach_read_from_2(page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE); + state = mach_read_from_2(page + TRX_UNDO_SEG_HDR + TRX_UNDO_STATE); + if ((type < TRX_UNDO_INSERT) || (type > TRX_UNDO_UPDATE)) type = 3; + if ((state < TRX_UNDO_ACTIVE) || (state > TRX_UNDO_PREPARED)) state = 6; + count_page_undos[type][state]++; + count_page_undos[0][state]++; + count_page_undos[type][0]++; + count_page_undos[0][0]++; + break; + case FIL_PAGE_TYPE_FSP_HDR: count_page_log++; break; + default: count_page_unknown++; break; + } +} + +void print_page_types () +{ + static const char* const states[7] = { + "total ", + "active ", + "cached ", + "to free ", + "to purge ", + "prepared ", + "unknown " + }; + int type; + int state; + + printf("pages: % 10lu\n", count_page); + + puts("undo pages: total insert update unknown"); + + for (state = 0; state < 7; state++) { + fputs(states[state], stdout); + for (type = 0; type < 4; type++) + printf("% 10lu%c", count_page_undos[type][state], (type < 3 ? ' ' : '\n')); + } + + printf("redo pages: % 10lu\n" + "unknown pages: % 10lu\n", + count_page_log, + count_page_unknown); +} + ulint ut_fold_ulint_pair( /*===============*/ @@ -254,6 +365,9 @@ /* allocate buffer for reading (so we don't realloc every time) */ p= (uchar *)malloc(UNIV_PAGE_SIZE); + memset(count_page_undos, 0, sizeof(count_page_undos)); + if (verbose) atexit(print_page_types); + /* main checksumming loop */ ct= start_page; lastt= 0; @@ -300,6 +414,8 @@ return 1; } + count_page_type(p); + /* end if this was the last page we were supposed to check */ if (use_end_page && (ct >= end_page)) return 0;