SQLite

Check-in [a7f6d19816]
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
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a7f6d19816cbfc50060a9d1c0c402cdd23bd16de
User & Date: drh 2013-01-25 15:09:41.890
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: 4e2bf57549 user: drh tags: trunk)
15:09
Enhance the "showwal" utility program to show checksum failures on frames. (check-in: a7f6d19816 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: f1127e87b9 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to tool/showwal.c.
14
15
16
17
18
19
20



























































21
22
23
24
25
26
27
static int pagesize = 1024;     /* Size of a database page */
static int fd = -1;             /* File descriptor for reading the WAL file */
static int mxFrame = 0;         /* Last frame */
static int perLine = 16;        /* HEX elements to print per line */

typedef long long int i64;      /* Datatype for 64-bit integers */





























































/*
** Convert the var-int format into i64.  Return the number of bytes
** in the var-int.  Write the var-int value into *pVal.
*/
static int decodeVarint(const unsigned char *z, i64 *pVal){
  i64 v = 0;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
static int pagesize = 1024;     /* Size of a database page */
static int fd = -1;             /* File descriptor for reading the WAL file */
static int mxFrame = 0;         /* Last frame */
static int perLine = 16;        /* HEX elements to print per line */

typedef long long int i64;      /* Datatype for 64-bit integers */

/* Information for computing the checksum */
typedef struct Cksum Cksum;
struct Cksum {
  int bSwap;           /* True to do byte swapping on 32-bit words */
  unsigned s0, s1;     /* Current checksum value */
};

/*
** extract a 32-bit big-endian integer
*/
static unsigned int getInt32(const unsigned char *a){
  unsigned int x = (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
  return x;
}

/*
** Swap bytes on a 32-bit unsigned integer
*/
static unsigned int swab32(unsigned int x){
  return (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8)
         + (((x)&0x00FF0000)>>8)  + (((x)&0xFF000000)>>24);
}

/* Extend the checksum.  Reinitialize the checksum if bInit is true.
*/
static void extendCksum(
  Cksum *pCksum,
  unsigned char *aData,
  unsigned int nByte,
  int bInit
){
  unsigned int *a32;
  if( bInit ){
    int a = 0;
    *((char*)&a) = 1;
    if( a==1 ){
      /* Host is little-endian */
      pCksum->bSwap = getInt32(aData)!=0x377f0682;
    }else{
      /* Host is big-endian */
      pCksum->bSwap = getInt32(aData)!=0x377f0683;
    }
    pCksum->s0 = 0;
    pCksum->s1 = 0;
  }
  a32 = (unsigned int*)aData;
  while( nByte>0 ){
    unsigned int x0 = a32[0];
    unsigned int x1 = a32[1];
    if( pCksum->bSwap ){
      x0 = swab32(x0);
      x1 = swab32(x1);
    }
    pCksum->s0 += x0 + pCksum->s1;
    pCksum->s1 += x1 + pCksum->s0;
    nByte -= 8;
    a32 += 2;
  }
}

/*
** Convert the var-int format into i64.  Return the number of bytes
** in the var-int.  Write the var-int value into *pVal.
*/
static int decodeVarint(const unsigned char *z, i64 *pVal){
  i64 v = 0;
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

168
169




170
171
172
173
174
175
176
177


178
179
180
181
182
183
184
185
186
187




188
189
190
191
192
193
194
195
196








197
198
199
200
201
202
203
  print_decode_line(aData,16, 4, 1, "Checksum-1");
  print_decode_line(aData,20, 4, 1, "Checksum-2");
  print_byte_range(iStart+24, pagesize, aData+24, 0);
  free(aData);
}

/*
** extract a 32-bit big-endian integer
*/
static unsigned int getInt32(const unsigned char *a){
  unsigned int x = (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
  return x;
}

/*
** Print an entire page of content as hex
*/
static void print_oneline_frame(int iFrame){
  int iStart;
  unsigned char *aData;

  iStart = 32 + (iFrame-1)*(pagesize+24);
  aData = getContent(iStart, 24);




  fprintf(stdout, "Frame %4d: %6d %6d 0x%08x 0x%08x 0x%08x 0x%08x\n",
          iFrame, 
          getInt32(aData),
          getInt32(aData+4),
          getInt32(aData+8),
          getInt32(aData+12),
          getInt32(aData+16),
          getInt32(aData+20)


  );
  free(aData);
}

/*
** Decode the WAL header.
*/
static void print_wal_header(void){
  unsigned char *aData;
  aData = getContent(0, 32);




  printf("WAL Header:\n");
  print_decode_line(aData, 0, 4,1,"Magic.  0x377f0682 (le) or 0x377f0683 (be)");
  print_decode_line(aData, 4, 4, 0, "File format");
  print_decode_line(aData, 8, 4, 0, "Database page size");
  print_decode_line(aData, 12,4, 0, "Checkpoint sequence number");
  print_decode_line(aData, 16,4, 1, "Salt-1");
  print_decode_line(aData, 20,4, 1, "Salt-2");
  print_decode_line(aData, 24,4, 1, "Checksum-1");
  print_decode_line(aData, 28,4, 1, "Checksum-2");








  free(aData);
}

/*
** Create a description for a single cell.
*/
static int describeCell(unsigned char cType, unsigned char *a, char **pzDesc){







<
<
<
<
<
<
|
<
<

|


>


>
>
>
>
|





<
|
>
>







|


>
>
>
>









>
>
>
>
>
>
>
>







207
208
209
210
211
212
213






214


215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
  print_decode_line(aData,16, 4, 1, "Checksum-1");
  print_decode_line(aData,20, 4, 1, "Checksum-2");
  print_byte_range(iStart+24, pagesize, aData+24, 0);
  free(aData);
}

/*






** Summarize a single frame on a single line.


*/
static void print_oneline_frame(int iFrame, Cksum *pCksum){
  int iStart;
  unsigned char *aData;
  unsigned int s0, s1;
  iStart = 32 + (iFrame-1)*(pagesize+24);
  aData = getContent(iStart, 24);
  extendCksum(pCksum, aData, 8, 0);
  extendCksum(pCksum, getContent(iStart+24, pagesize), pagesize, 0);
  s0 = getInt32(aData+16);
  s1 = getInt32(aData+20);
  fprintf(stdout, "Frame %4d: %6d %6d 0x%08x,%08x 0x%08x,%08x %s\n",
          iFrame, 
          getInt32(aData),
          getInt32(aData+4),
          getInt32(aData+8),
          getInt32(aData+12),

          s0,
          s1,
          (s0==pCksum->s0 && s1==pCksum->s1) ? "cksum-ok" : "cksum-fail"
  );
  free(aData);
}

/*
** Decode the WAL header.
*/
static void print_wal_header(Cksum *pCksum){
  unsigned char *aData;
  aData = getContent(0, 32);
  if( pCksum ){
    extendCksum(pCksum, aData, 24, 1);
    printf("Checksum byte order: %s\n", pCksum->bSwap ? "swapped" : "native");
  }
  printf("WAL Header:\n");
  print_decode_line(aData, 0, 4,1,"Magic.  0x377f0682 (le) or 0x377f0683 (be)");
  print_decode_line(aData, 4, 4, 0, "File format");
  print_decode_line(aData, 8, 4, 0, "Database page size");
  print_decode_line(aData, 12,4, 0, "Checkpoint sequence number");
  print_decode_line(aData, 16,4, 1, "Salt-1");
  print_decode_line(aData, 20,4, 1, "Salt-2");
  print_decode_line(aData, 24,4, 1, "Checksum-1");
  print_decode_line(aData, 28,4, 1, "Checksum-2");
  if( pCksum ){
    if( pCksum->s0!=getInt32(aData+24) ){
      printf("**** cksum-1 mismatch: 0x%08x\n", pCksum->s0);
    }
    if( pCksum->s1!=getInt32(aData+28) ){
      printf("**** cksum-2 mismatch: 0x%08x\n", pCksum->s1);
    }
  }
  free(aData);
}

/*
** Create a description for a single cell.
*/
static int describeCell(unsigned char cType, unsigned char *a, char **pzDesc){
294
295
296
297
298
299
300

301
302


303
304
305
306
307
308
309
310
311
312
313
314
315
316
    printf("file too small to be a WAL\n");
    return 0;
  }
  mxFrame = (sbuf.st_size - 32)/(pagesize + 24);
  printf("Available pages: 1..%d\n", mxFrame);
  if( argc==2 ){
    int i;

    print_wal_header();
    for(i=1; i<=mxFrame; i++) print_oneline_frame(i);


  }else{
    int i;
    for(i=2; i<argc; i++){
      int iStart, iEnd;
      char *zLeft;
      if( strcmp(argv[i], "header")==0 ){
        print_wal_header();
        continue;
      }
      if( !isdigit(argv[i][0]) ){
        fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]);
        continue;
      }
      iStart = strtol(argv[i], &zLeft, 0);







>
|
|
>
>






|







363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
    printf("file too small to be a WAL\n");
    return 0;
  }
  mxFrame = (sbuf.st_size - 32)/(pagesize + 24);
  printf("Available pages: 1..%d\n", mxFrame);
  if( argc==2 ){
    int i;
    Cksum x;
    print_wal_header(&x);
    for(i=1; i<=mxFrame; i++){
      print_oneline_frame(i, &x);
    }
  }else{
    int i;
    for(i=2; i<argc; i++){
      int iStart, iEnd;
      char *zLeft;
      if( strcmp(argv[i], "header")==0 ){
        print_wal_header(0);
        continue;
      }
      if( !isdigit(argv[i][0]) ){
        fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]);
        continue;
      }
      iStart = strtol(argv[i], &zLeft, 0);