Commit 8369e7de authored by jimw@mysql.com's avatar jimw@mysql.com

Merge bk-internal:/home/bk/mysql-5.0

into  mysql.com:/home/jimw/my/mysql-5.0-clean
parents a60ed0b7 1313a30c
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
Published with a permission. Published with a permission.
*/ */
// needed to have access to 64 bit file functions /* needed to have access to 64 bit file functions */
#define _LARGEFILE_SOURCE #define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
// all of these ripped from InnoDB code from MySQL 4.0.22 /* all of these ripped from InnoDB code from MySQL 4.0.22 */
#define UT_HASH_RANDOM_MASK 1463735687 #define UT_HASH_RANDOM_MASK 1463735687
#define UT_HASH_RANDOM_MASK2 1653893711 #define UT_HASH_RANDOM_MASK2 1653893711
#define FIL_PAGE_LSN 16 #define FIL_PAGE_LSN 16
...@@ -46,18 +46,19 @@ ...@@ -46,18 +46,19 @@
#define FIL_PAGE_SPACE_OR_CHKSUM 0 #define FIL_PAGE_SPACE_OR_CHKSUM 0
#define UNIV_PAGE_SIZE (2 * 8192) #define UNIV_PAGE_SIZE (2 * 8192)
// command line argument to do page checks (that's it) /* command line argument to do page checks (that's it) */
// another argument to specify page ranges... seek to right spot and go from there /* another argument to specify page ranges... seek to right spot and go from there */
typedef unsigned long int ulint; typedef unsigned long int ulint;
typedef unsigned char byte; typedef unsigned char byte;
/* innodb function in name; modified slightly to not have the ASM version (lots of #ifs that didn't apply) */ /* innodb function in name; modified slightly to not have the ASM version (lots of #ifs that didn't apply) */
ulint mach_read_from_4(byte *b) { ulint mach_read_from_4(byte *b)
return( ((ulint)(b[0]) << 24) {
+ ((ulint)(b[1]) << 16) return( ((ulint)(b[0]) << 24)
+ ((ulint)(b[2]) << 8) + ((ulint)(b[1]) << 16)
+ (ulint)(b[3]) + ((ulint)(b[2]) << 8)
+ (ulint)(b[3])
); );
} }
...@@ -80,12 +81,13 @@ ut_fold_binary( ...@@ -80,12 +81,13 @@ ut_fold_binary(
ulint len) /* in: length */ ulint len) /* in: length */
{ {
ulint i; ulint i;
ulint fold = 0; ulint fold= 0;
for (i = 0; i < len; i++) { for (i= 0; i < len; i++)
fold = ut_fold_ulint_pair(fold, (ulint)(*str)); {
fold= ut_fold_ulint_pair(fold, (ulint)(*str));
str++; str++;
} }
return(fold); return(fold);
...@@ -106,12 +108,12 @@ buf_calc_page_new_checksum( ...@@ -106,12 +108,12 @@ buf_calc_page_new_checksum(
checksum is stored, and also the last 8 bytes of page because checksum is stored, and also the last 8 bytes of page because
there we store the old formula checksum. */ there we store the old formula checksum. */
checksum = ut_fold_binary(page + FIL_PAGE_OFFSET, checksum= ut_fold_binary(page + FIL_PAGE_OFFSET,
FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET) FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
+ ut_fold_binary(page + FIL_PAGE_DATA, + ut_fold_binary(page + FIL_PAGE_DATA,
UNIV_PAGE_SIZE - FIL_PAGE_DATA UNIV_PAGE_SIZE - FIL_PAGE_DATA
- FIL_PAGE_END_LSN_OLD_CHKSUM); - FIL_PAGE_END_LSN_OLD_CHKSUM);
checksum = checksum & 0xFFFFFFFF; checksum= checksum & 0xFFFFFFFF;
return(checksum); return(checksum);
} }
...@@ -124,183 +126,203 @@ buf_calc_page_old_checksum( ...@@ -124,183 +126,203 @@ buf_calc_page_old_checksum(
{ {
ulint checksum; ulint checksum;
checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN); checksum= ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
checksum = checksum & 0xFFFFFFFF; checksum= checksum & 0xFFFFFFFF;
return(checksum); return(checksum);
} }
int main(int argc, char **argv) { int main(int argc, char **argv)
FILE *f; // our input file {
byte *p; // storage of pages read FILE *f; /* our input file */
int bytes; // bytes read count byte *p; /* storage of pages read */
ulint ct; // current page number (0 based) int bytes; /* bytes read count */
int now; // current time ulint ct; /* current page number (0 based) */
int lastt; // last time int now; /* current time */
ulint oldcsum, oldcsumfield, csum, csumfield, logseq, logseqfield; // ulints for checksum storage int lastt; /* last time */
struct stat st; // for stat, if you couldn't guess ulint oldcsum, oldcsumfield, csum, csumfield, logseq, logseqfield; /* ulints for checksum storage */
unsigned long long int size; // size of file (has to be 64 bits) struct stat st; /* for stat, if you couldn't guess */
ulint pages; // number of pages in file unsigned long long int size; /* size of file (has to be 64 bits) */
ulint start_page = 0, end_page = 0, use_end_page = 0; // for starting and ending at certain pages ulint pages; /* number of pages in file */
off_t offset = 0; ulint start_page= 0, end_page= 0, use_end_page= 0; /* for starting and ending at certain pages */
int just_count = 0; // if true, just print page count off_t offset= 0;
int verbose = 0; int just_count= 0; /* if true, just print page count */
int debug = 0; int verbose= 0;
int c; int debug= 0;
int fd; int c;
int fd;
// remove arguments
while ((c = getopt(argc, argv, "cvds:e:p:")) != -1) { /* remove arguments */
switch (c) { while ((c= getopt(argc, argv, "cvds:e:p:")) != -1)
case 'v': {
verbose = 1; switch (c)
break; {
case 'c': case 'v':
just_count = 1; verbose= 1;
break; break;
case 's': case 'c':
start_page = atoi(optarg); just_count= 1;
break; break;
case 'e': case 's':
end_page = atoi(optarg); start_page= atoi(optarg);
use_end_page = 1; break;
break; case 'e':
case 'p': end_page= atoi(optarg);
start_page = atoi(optarg); use_end_page= 1;
end_page = atoi(optarg); break;
use_end_page = 1; case 'p':
break; start_page= atoi(optarg);
case 'd': end_page= atoi(optarg);
debug = 1; use_end_page= 1;
break; break;
case ':': case 'd':
fprintf(stderr, "option -%c requires an argument\n", optopt); debug= 1;
return 1; break;
break; case ':':
case '?': fprintf(stderr, "option -%c requires an argument\n", optopt);
fprintf(stderr, "unrecognized option: -%c\n", optopt); return 1;
return 1; break;
break; case '?':
} fprintf(stderr, "unrecognized option: -%c\n", optopt);
return 1;
break;
} }
}
// debug implies verbose...
if (debug) verbose = 1; /* debug implies verbose... */
if (debug) verbose= 1;
// make sure we have the right arguments
if (optind >= argc) { /* make sure we have the right arguments */
printf("InnoDB offline file checksum utility.\n"); if (optind >= argc)
printf("usage: %s [-c] [-s <start page>] [-e <end page>] [-p <page>] [-v] [-d] <filename>\n", argv[0]); {
printf("\t-c\tprint the count of pages in the file\n"); printf("InnoDB offline file checksum utility.\n");
printf("\t-s n\tstart on this page number (0 based)\n"); printf("usage: %s [-c] [-s <start page>] [-e <end page>] [-p <page>] [-v] [-d] <filename>\n", argv[0]);
printf("\t-e n\tend at this page number (0 based)\n"); printf("\t-c\tprint the count of pages in the file\n");
printf("\t-p n\tcheck only this page (0 based)\n"); printf("\t-s n\tstart on this page number (0 based)\n");
printf("\t-v\tverbose (prints progress every 5 seconds)\n"); printf("\t-e n\tend at this page number (0 based)\n");
printf("\t-d\tdebug mode (prints checksums for each page)\n"); printf("\t-p n\tcheck only this page (0 based)\n");
return 1; printf("\t-v\tverbose (prints progress every 5 seconds)\n");
printf("\t-d\tdebug mode (prints checksums for each page)\n");
return 1;
}
/* stat the file to get size and page count */
if (stat(argv[optind], &st))
{
perror("error statting file");
return 1;
}
size= st.st_size;
pages= size / UNIV_PAGE_SIZE;
if (just_count)
{
printf("%lu\n", pages);
return 0;
}
else if (verbose)
{
printf("file %s= %llu bytes (%lu pages)...\n", argv[1], size, pages);
printf("checking pages in range %lu to %lu\n", start_page, use_end_page ? end_page : (pages - 1));
}
/* open the file for reading */
f= fopen(argv[optind], "r");
if (!f)
{
perror("error opening file");
return 1;
}
/* seek to the necessary position */
if (start_page)
{
fd= fileno(f);
if (!fd)
{
perror("unable to obtain file descriptor number");
return 1;
} }
// stat the file to get size and page count offset= (off_t)start_page * (off_t)UNIV_PAGE_SIZE;
if (stat(argv[optind], &st)) {
perror("error statting file"); if (lseek(fd, offset, SEEK_SET) != offset)
return 1; {
perror("unable to seek to necessary offset");
return 1;
} }
size = st.st_size; }
pages = size / UNIV_PAGE_SIZE;
if (just_count) { /* allocate buffer for reading (so we don't realloc every time) */
printf("%lu\n", pages); p= (byte *)malloc(UNIV_PAGE_SIZE);
return 0;
} else if (verbose) { /* main checksumming loop */
printf("file %s = %llu bytes (%lu pages)...\n", argv[1], size, pages); ct= start_page;
printf("checking pages in range %lu to %lu\n", start_page, use_end_page ? end_page : (pages - 1)); lastt= 0;
while (!feof(f))
{
bytes= fread(p, 1, UNIV_PAGE_SIZE, f);
if (!bytes && feof(f)) return 0;
if (bytes != UNIV_PAGE_SIZE)
{
fprintf(stderr, "bytes read (%d) doesn't match universal page size (%d)\n", bytes, UNIV_PAGE_SIZE);
return 1;
} }
// open the file for reading /* check the "stored log sequence numbers" */
f = fopen(argv[optind], "r"); logseq= mach_read_from_4(p + FIL_PAGE_LSN + 4);
if (!f) { logseqfield= mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + 4);
perror("error opening file"); if (debug)
return 1; printf("page %lu: log sequence number: first = %lu; second = %lu\n", ct, logseq, logseqfield);
if (logseq != logseqfield)
{
fprintf(stderr, "page %lu invalid (fails log sequence number check)\n", ct);
return 1;
} }
// seek to the necessary position /* check old method of checksumming */
if (start_page) { oldcsum= buf_calc_page_old_checksum(p);
fd = fileno(f); oldcsumfield= mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
if (!fd) { if (debug)
perror("unable to obtain file descriptor number"); printf("page %lu: old style: calculated = %lu; recorded = %lu\n", ct, oldcsum, oldcsumfield);
return 1; if (oldcsumfield != mach_read_from_4(p + FIL_PAGE_LSN) && oldcsumfield != oldcsum)
} {
fprintf(stderr, "page %lu invalid (fails old style checksum)\n", ct);
offset = (off_t)start_page * (off_t)UNIV_PAGE_SIZE; return 1;
if (lseek(fd, offset, SEEK_SET) != offset) {
perror("unable to seek to necessary offset");
return 1;
}
} }
// allocate buffer for reading (so we don't realloc every time) /* now check the new method */
p = (byte *)malloc(UNIV_PAGE_SIZE); csum= buf_calc_page_new_checksum(p);
csumfield= mach_read_from_4(p + FIL_PAGE_SPACE_OR_CHKSUM);
// main checksumming loop if (debug)
ct = start_page; printf("page %lu: new style: calculated = %lu; recorded = %lu\n", ct, csum, csumfield);
lastt = 0; if (csumfield != 0 && csum != csumfield)
while (!feof(f)) { {
bytes = fread(p, 1, UNIV_PAGE_SIZE, f); fprintf(stderr, "page %lu invalid (fails new style checksum)\n", ct);
if (!bytes && feof(f)) return 0; return 1;
if (bytes != UNIV_PAGE_SIZE) { }
fprintf(stderr, "bytes read (%d) doesn't match universal page size (%d)\n", bytes, UNIV_PAGE_SIZE);
return 1;
}
// check the "stored log sequence numbers"
logseq = mach_read_from_4(p + FIL_PAGE_LSN + 4);
logseqfield = mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + 4);
if (debug)
printf("page %lu: log sequence number: first = %lu; second = %lu\n", ct, logseq, logseqfield);
if (logseq != logseqfield) {
fprintf(stderr, "page %lu invalid (fails log sequence number check)\n", ct);
return 1;
}
// check old method of checksumming
oldcsum = buf_calc_page_old_checksum(p);
oldcsumfield = mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
if (debug)
printf("page %lu: old style: calculated = %lu; recorded = %lu\n", ct, oldcsum, oldcsumfield);
if (oldcsumfield != mach_read_from_4(p + FIL_PAGE_LSN) && oldcsumfield != oldcsum) {
fprintf(stderr, "page %lu invalid (fails old style checksum)\n", ct);
return 1;
}
// now check the new method
csum = buf_calc_page_new_checksum(p);
csumfield = mach_read_from_4(p + FIL_PAGE_SPACE_OR_CHKSUM);
if (debug)
printf("page %lu: new style: calculated = %lu; recorded = %lu\n", ct, csum, csumfield);
if (csumfield != 0 && csum != csumfield) {
fprintf(stderr, "page %lu invalid (fails new style checksum)\n", ct);
return 1;
}
// end if this was the last page we were supposed to check /* end if this was the last page we were supposed to check */
if (use_end_page && (ct >= end_page)) if (use_end_page && (ct >= end_page))
return 0; return 0;
// do counter increase and progress printing /* do counter increase and progress printing */
ct++; ct++;
if (verbose) { if (verbose)
if (ct % 64 == 0) { {
now = time(0); if (ct % 64 == 0)
if (!lastt) lastt = now; {
if (now - lastt >= 1) { now= time(0);
printf("page %lu okay: %.3f%% done\n", (ct - 1), (float) ct / pages * 100); if (!lastt) lastt= now;
lastt = now; if (now - lastt >= 1)
} {
} printf("page %lu okay: %.3f%% done\n", (ct - 1), (float) ct / pages * 100);
lastt= now;
} }
}
} }
return 0; }
return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment