SQLite
Check-in [a7f6d19816]
Not logged in
Overview
SHA1 Hash:a7f6d19816cbfc50060a9d1c0c402cdd23bd16de
Date: 2013-01-25 15:09:41
User: drh
Comment:Enhance the "showwal" utility program to show checksum failures on frames.
Tags And Properties
Changes
hide diffs unified diffs patch

Changes to tool/showwal.c

14 static int pagesize = 1024; /* Size of a database page */ 14 static int pagesize = 1024; /* Size of a database page */ 15 static int fd = -1; /* File descriptor for reading the WAL file */ 15 static int fd = -1; /* File descriptor for reading the WAL file */ 16 static int mxFrame = 0; /* Last frame */ 16 static int mxFrame = 0; /* Last frame */ 17 static int perLine = 16; /* HEX elements to print per line */ 17 static int perLine = 16; /* HEX elements to print per line */ 18 18 19 typedef long long int i64; /* Datatype for 64-bit integers */ 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 ** Convert the var-int format into i64. Return the number of bytes 82 ** Convert the var-int format into i64. Return the number of bytes 24 ** in the var-int. Write the var-int value into *pVal. 83 ** in the var-int. Write the var-int value into *pVal. 25 */ 84 */ 26 static int decodeVarint(const unsigned char *z, i64 *pVal){ 85 static int decodeVarint(const unsigned char *z, i64 *pVal){ 27 i64 v = 0; 86 i64 v = 0; ................................................................................................................................................................................ 148 print_decode_line(aData,16, 4, 1, "Checksum-1"); 207 print_decode_line(aData,16, 4, 1, "Checksum-1"); 149 print_decode_line(aData,20, 4, 1, "Checksum-2"); 208 print_decode_line(aData,20, 4, 1, "Checksum-2"); 150 print_byte_range(iStart+24, pagesize, aData+24, 0); 209 print_byte_range(iStart+24, pagesize, aData+24, 0); 151 free(aData); 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 int iStart; 217 int iStart; 167 unsigned char *aData; 218 unsigned char *aData; > 219 unsigned int s0, s1; 168 iStart = 32 + (iFrame-1)*(pagesize+24); 220 iStart = 32 + (iFrame-1)*(pagesize+24); 169 aData = getContent(iStart, 24); 221 aData = getContent(iStart, 24); > 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); 170 fprintf(stdout, "Frame %4d: %6d %6d 0x%08x 0x%08x 0x%08x 0x%08x\n", | 226 fprintf(stdout, "Frame %4d: %6d %6d 0x%08x,%08x 0x%08x,%08x %s\n", 171 iFrame, 227 iFrame, 172 getInt32(aData), 228 getInt32(aData), 173 getInt32(aData+4), 229 getInt32(aData+4), 174 getInt32(aData+8), 230 getInt32(aData+8), 175 getInt32(aData+12), 231 getInt32(aData+12), 176 getInt32(aData+16), | 232 s0, 177 getInt32(aData+20) | 233 s1, > 234 (s0==pCksum->s0 && s1==pCksum->s1) ? "cksum-ok" : "cksum-fail" 178 ); 235 ); 179 free(aData); 236 free(aData); 180 } 237 } 181 238 182 /* 239 /* 183 ** Decode the WAL header. 240 ** Decode the WAL header. 184 */ 241 */ 185 static void print_wal_header(void){ | 242 static void print_wal_header(Cksum *pCksum){ 186 unsigned char *aData; 243 unsigned char *aData; 187 aData = getContent(0, 32); 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 printf("WAL Header:\n"); 249 printf("WAL Header:\n"); 189 print_decode_line(aData, 0, 4,1,"Magic. 0x377f0682 (le) or 0x377f0683 (be)"); 250 print_decode_line(aData, 0, 4,1,"Magic. 0x377f0682 (le) or 0x377f0683 (be)"); 190 print_decode_line(aData, 4, 4, 0, "File format"); 251 print_decode_line(aData, 4, 4, 0, "File format"); 191 print_decode_line(aData, 8, 4, 0, "Database page size"); 252 print_decode_line(aData, 8, 4, 0, "Database page size"); 192 print_decode_line(aData, 12,4, 0, "Checkpoint sequence number"); 253 print_decode_line(aData, 12,4, 0, "Checkpoint sequence number"); 193 print_decode_line(aData, 16,4, 1, "Salt-1"); 254 print_decode_line(aData, 16,4, 1, "Salt-1"); 194 print_decode_line(aData, 20,4, 1, "Salt-2"); 255 print_decode_line(aData, 20,4, 1, "Salt-2"); 195 print_decode_line(aData, 24,4, 1, "Checksum-1"); 256 print_decode_line(aData, 24,4, 1, "Checksum-1"); 196 print_decode_line(aData, 28,4, 1, "Checksum-2"); 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 free(aData); 266 free(aData); 198 } 267 } 199 268 200 /* 269 /* 201 ** Create a description for a single cell. 270 ** Create a description for a single cell. 202 */ 271 */ 203 static int describeCell(unsigned char cType, unsigned char *a, char **pzDesc){ 272 static int describeCell(unsigned char cType, unsigned char *a, char **pzDesc){ ................................................................................................................................................................................ 294 printf("file too small to be a WAL\n"); 363 printf("file too small to be a WAL\n"); 295 return 0; 364 return 0; 296 } 365 } 297 mxFrame = (sbuf.st_size - 32)/(pagesize + 24); 366 mxFrame = (sbuf.st_size - 32)/(pagesize + 24); 298 printf("Available pages: 1..%d\n", mxFrame); 367 printf("Available pages: 1..%d\n", mxFrame); 299 if( argc==2 ){ 368 if( argc==2 ){ 300 int i; 369 int i; > 370 Cksum x; 301 print_wal_header(); | 371 print_wal_header(&x); 302 for(i=1; i<=mxFrame; i++) print_oneline_frame(i); | 372 for(i=1; i<=mxFrame; i++){ > 373 print_oneline_frame(i, &x); > 374 } 303 }else{ 375 }else{ 304 int i; 376 int i; 305 for(i=2; i<argc; i++){ 377 for(i=2; i<argc; i++){ 306 int iStart, iEnd; 378 int iStart, iEnd; 307 char *zLeft; 379 char *zLeft; 308 if( strcmp(argv[i], "header")==0 ){ 380 if( strcmp(argv[i], "header")==0 ){ 309 print_wal_header(); | 381 print_wal_header(0); 310 continue; 382 continue; 311 } 383 } 312 if( !isdigit(argv[i][0]) ){ 384 if( !isdigit(argv[i][0]) ){ 313 fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]); 385 fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]); 314 continue; 386 continue; 315 } 387 } 316 iStart = strtol(argv[i], &zLeft, 0); 388 iStart = strtol(argv[i], &zLeft, 0);