/ Check-in [a7f6d198]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Enhance the "showwal" utility program to show checksum failures on frames.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a7f6d19816cbfc50060a9d1c0c402cdd23bd16de
User & Date: drh 2013-01-25 15:09:41
Context
2013-01-25
15:31
Further improvements to showwal.c: Reset the checksum after each frame so that only individual checksum failures are shown. And only show failures, not correct checksums. check-in: 4e2bf575 user: drh tags: trunk
15:09
Enhance the "showwal" utility program to show checksum failures on frames. check-in: a7f6d198 user: drh tags: trunk
2013-01-23
18:53
Improved parsing of the arguments to the ".backup" command in the command-line shell. check-in: f1127e87 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to tool/showwal.c.

    14     14   static int pagesize = 1024;     /* Size of a database page */
    15     15   static int fd = -1;             /* File descriptor for reading the WAL file */
    16     16   static int mxFrame = 0;         /* Last frame */
    17     17   static int perLine = 16;        /* HEX elements to print per line */
    18     18   
    19     19   typedef long long int i64;      /* Datatype for 64-bit integers */
    20     20   
           21  +/* Information for computing the checksum */
           22  +typedef struct Cksum Cksum;
           23  +struct Cksum {
           24  +  int bSwap;           /* True to do byte swapping on 32-bit words */
           25  +  unsigned s0, s1;     /* Current checksum value */
           26  +};
           27  +
           28  +/*
           29  +** extract a 32-bit big-endian integer
           30  +*/
           31  +static unsigned int getInt32(const unsigned char *a){
           32  +  unsigned int x = (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
           33  +  return x;
           34  +}
           35  +
           36  +/*
           37  +** Swap bytes on a 32-bit unsigned integer
           38  +*/
           39  +static unsigned int swab32(unsigned int x){
           40  +  return (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8)
           41  +         + (((x)&0x00FF0000)>>8)  + (((x)&0xFF000000)>>24);
           42  +}
           43  +
           44  +/* Extend the checksum.  Reinitialize the checksum if bInit is true.
           45  +*/
           46  +static void extendCksum(
           47  +  Cksum *pCksum,
           48  +  unsigned char *aData,
           49  +  unsigned int nByte,
           50  +  int bInit
           51  +){
           52  +  unsigned int *a32;
           53  +  if( bInit ){
           54  +    int a = 0;
           55  +    *((char*)&a) = 1;
           56  +    if( a==1 ){
           57  +      /* Host is little-endian */
           58  +      pCksum->bSwap = getInt32(aData)!=0x377f0682;
           59  +    }else{
           60  +      /* Host is big-endian */
           61  +      pCksum->bSwap = getInt32(aData)!=0x377f0683;
           62  +    }
           63  +    pCksum->s0 = 0;
           64  +    pCksum->s1 = 0;
           65  +  }
           66  +  a32 = (unsigned int*)aData;
           67  +  while( nByte>0 ){
           68  +    unsigned int x0 = a32[0];
           69  +    unsigned int x1 = a32[1];
           70  +    if( pCksum->bSwap ){
           71  +      x0 = swab32(x0);
           72  +      x1 = swab32(x1);
           73  +    }
           74  +    pCksum->s0 += x0 + pCksum->s1;
           75  +    pCksum->s1 += x1 + pCksum->s0;
           76  +    nByte -= 8;
           77  +    a32 += 2;
           78  +  }
           79  +}
    21     80   
    22     81   /*
    23     82   ** Convert the var-int format into i64.  Return the number of bytes
    24     83   ** in the var-int.  Write the var-int value into *pVal.
    25     84   */
    26     85   static int decodeVarint(const unsigned char *z, i64 *pVal){
    27     86     i64 v = 0;
................................................................................
   148    207     print_decode_line(aData,16, 4, 1, "Checksum-1");
   149    208     print_decode_line(aData,20, 4, 1, "Checksum-2");
   150    209     print_byte_range(iStart+24, pagesize, aData+24, 0);
   151    210     free(aData);
   152    211   }
   153    212   
   154    213   /*
   155         -** extract a 32-bit big-endian integer
          214  +** Summarize a single frame on a single line.
   156    215   */
   157         -static unsigned int getInt32(const unsigned char *a){
   158         -  unsigned int x = (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
   159         -  return x;
   160         -}
   161         -
   162         -/*
   163         -** Print an entire page of content as hex
   164         -*/
   165         -static void print_oneline_frame(int iFrame){
          216  +static void print_oneline_frame(int iFrame, Cksum *pCksum){
   166    217     int iStart;
   167    218     unsigned char *aData;
          219  +  unsigned int s0, s1;
   168    220     iStart = 32 + (iFrame-1)*(pagesize+24);
   169    221     aData = getContent(iStart, 24);
   170         -  fprintf(stdout, "Frame %4d: %6d %6d 0x%08x 0x%08x 0x%08x 0x%08x\n",
          222  +  extendCksum(pCksum, aData, 8, 0);
          223  +  extendCksum(pCksum, getContent(iStart+24, pagesize), pagesize, 0);
          224  +  s0 = getInt32(aData+16);
          225  +  s1 = getInt32(aData+20);
          226  +  fprintf(stdout, "Frame %4d: %6d %6d 0x%08x,%08x 0x%08x,%08x %s\n",
   171    227             iFrame, 
   172    228             getInt32(aData),
   173    229             getInt32(aData+4),
   174    230             getInt32(aData+8),
   175    231             getInt32(aData+12),
   176         -          getInt32(aData+16),
   177         -          getInt32(aData+20)
          232  +          s0,
          233  +          s1,
          234  +          (s0==pCksum->s0 && s1==pCksum->s1) ? "cksum-ok" : "cksum-fail"
   178    235     );
   179    236     free(aData);
   180    237   }
   181    238   
   182    239   /*
   183    240   ** Decode the WAL header.
   184    241   */
   185         -static void print_wal_header(void){
          242  +static void print_wal_header(Cksum *pCksum){
   186    243     unsigned char *aData;
   187    244     aData = getContent(0, 32);
          245  +  if( pCksum ){
          246  +    extendCksum(pCksum, aData, 24, 1);
          247  +    printf("Checksum byte order: %s\n", pCksum->bSwap ? "swapped" : "native");
          248  +  }
   188    249     printf("WAL Header:\n");
   189    250     print_decode_line(aData, 0, 4,1,"Magic.  0x377f0682 (le) or 0x377f0683 (be)");
   190    251     print_decode_line(aData, 4, 4, 0, "File format");
   191    252     print_decode_line(aData, 8, 4, 0, "Database page size");
   192    253     print_decode_line(aData, 12,4, 0, "Checkpoint sequence number");
   193    254     print_decode_line(aData, 16,4, 1, "Salt-1");
   194    255     print_decode_line(aData, 20,4, 1, "Salt-2");
   195    256     print_decode_line(aData, 24,4, 1, "Checksum-1");
   196    257     print_decode_line(aData, 28,4, 1, "Checksum-2");
          258  +  if( pCksum ){
          259  +    if( pCksum->s0!=getInt32(aData+24) ){
          260  +      printf("**** cksum-1 mismatch: 0x%08x\n", pCksum->s0);
          261  +    }
          262  +    if( pCksum->s1!=getInt32(aData+28) ){
          263  +      printf("**** cksum-2 mismatch: 0x%08x\n", pCksum->s1);
          264  +    }
          265  +  }
   197    266     free(aData);
   198    267   }
   199    268   
   200    269   /*
   201    270   ** Create a description for a single cell.
   202    271   */
   203    272   static int describeCell(unsigned char cType, unsigned char *a, char **pzDesc){
................................................................................
   294    363       printf("file too small to be a WAL\n");
   295    364       return 0;
   296    365     }
   297    366     mxFrame = (sbuf.st_size - 32)/(pagesize + 24);
   298    367     printf("Available pages: 1..%d\n", mxFrame);
   299    368     if( argc==2 ){
   300    369       int i;
   301         -    print_wal_header();
   302         -    for(i=1; i<=mxFrame; i++) print_oneline_frame(i);
          370  +    Cksum x;
          371  +    print_wal_header(&x);
          372  +    for(i=1; i<=mxFrame; i++){
          373  +      print_oneline_frame(i, &x);
          374  +    }
   303    375     }else{
   304    376       int i;
   305    377       for(i=2; i<argc; i++){
   306    378         int iStart, iEnd;
   307    379         char *zLeft;
   308    380         if( strcmp(argv[i], "header")==0 ){
   309         -        print_wal_header();
          381  +        print_wal_header(0);
   310    382           continue;
   311    383         }
   312    384         if( !isdigit(argv[i][0]) ){
   313    385           fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]);
   314    386           continue;
   315    387         }
   316    388         iStart = strtol(argv[i], &zLeft, 0);