From 08119c361d1181b3e8f1abb429236e488a664753 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 13 Aug 2013 15:42:54 -0400 Subject: Imported Upstream version 2.2.1 --- tool/showwal.c | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 264 insertions(+), 29 deletions(-) (limited to 'tool/showwal.c') diff --git a/tool/showwal.c b/tool/showwal.c index ae25a59..2888c10 100644 --- a/tool/showwal.c +++ b/tool/showwal.c @@ -18,6 +18,65 @@ 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 @@ -152,39 +211,46 @@ static void print_frame(int iFrame){ } /* -** 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 +** Summarize a single frame on a single line. */ -static void print_oneline_frame(int iFrame){ +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); - fprintf(stdout, "Frame %4d: %6d %6d 0x%08x 0x%08x 0x%08x 0x%08x\n", + 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), - getInt32(aData+16), - getInt32(aData+20) + s0, + s1, + (s0==pCksum->s0 && s1==pCksum->s1) ? "" : "cksum-fail" ); + + /* Reset the checksum so that a single frame checksum failure will not + ** cause all subsequent frames to also show a failure. */ + pCksum->s0 = s0; + pCksum->s1 = s1; free(aData); } /* ** Decode the WAL header. */ -static void print_wal_header(void){ +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"); @@ -194,60 +260,199 @@ static void print_wal_header(void){ 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); } +/* +** Describe cell content. +*/ +static int describeContent( + unsigned char *a, /* Cell content */ + int nLocal, /* Bytes in a[] */ + char *zDesc /* Write description here */ +){ + int nDesc = 0; + int n, i, j; + i64 x, v; + const unsigned char *pData; + const unsigned char *pLimit; + char sep = ' '; + + pLimit = &a[nLocal]; + n = decodeVarint(a, &x); + pData = &a[x]; + a += n; + i = x - n; + while( i>0 && pData<=pLimit ){ + n = decodeVarint(a, &x); + a += n; + i -= n; + nLocal -= n; + zDesc[0] = sep; + sep = ','; + nDesc++; + zDesc++; + if( x==0 ){ + sprintf(zDesc, "*"); /* NULL is a "*" */ + }else if( x>=1 && x<=6 ){ + v = (signed char)pData[0]; + pData++; + switch( x ){ + case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; + case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; + case 4: v = (v<<8) + pData[0]; pData++; + case 3: v = (v<<8) + pData[0]; pData++; + case 2: v = (v<<8) + pData[0]; pData++; + } + sprintf(zDesc, "%lld", v); + }else if( x==7 ){ + sprintf(zDesc, "real"); + pData += 8; + }else if( x==8 ){ + sprintf(zDesc, "0"); + }else if( x==9 ){ + sprintf(zDesc, "1"); + }else if( x>=12 ){ + int size = (x-12)/2; + if( (x&1)==0 ){ + sprintf(zDesc, "blob(%d)", size); + }else{ + sprintf(zDesc, "txt(%d)", size); + } + pData += size; + } + j = strlen(zDesc); + zDesc += j; + nDesc += j; + } + return nDesc; +} + +/* +** Compute the local payload size given the total payload size and +** the page size. +*/ +static int localPayload(i64 nPayload, char cType){ + int maxLocal; + int minLocal; + int surplus; + int nLocal; + if( cType==13 ){ + /* Table leaf */ + maxLocal = pagesize-35; + minLocal = (pagesize-12)*32/255-23; + }else{ + maxLocal = (pagesize-12)*64/255-23; + minLocal = (pagesize-12)*32/255-23; + } + if( nPayload>maxLocal ){ + surplus = minLocal + (nPayload-minLocal)%(pagesize-4); + if( surplus<=maxLocal ){ + nLocal = surplus; + }else{ + nLocal = minLocal; + } + }else{ + nLocal = nPayload; + } + return nLocal; +} /* ** Create a description for a single cell. +** +** The return value is the local cell size. */ -static int describeCell(unsigned char cType, unsigned char *a, char **pzDesc){ +static int describeCell( + unsigned char cType, /* Page type */ + unsigned char *a, /* Cell content */ + int showCellContent, /* Show cell content if true */ + char **pzDesc /* Store description here */ +){ int i; int nDesc = 0; int n = 0; int leftChild; i64 nPayload; i64 rowid; - static char zDesc[100]; + int nLocal; + static char zDesc[1000]; i = 0; if( cType<=5 ){ leftChild = ((a[0]*256 + a[1])*256 + a[2])*256 + a[3]; a += 4; n += 4; - sprintf(zDesc, "left-child: %d ", leftChild); + sprintf(zDesc, "lx: %d ", leftChild); nDesc = strlen(zDesc); } if( cType!=5 ){ i = decodeVarint(a, &nPayload); a += i; n += i; - sprintf(&zDesc[nDesc], "sz: %lld ", nPayload); + sprintf(&zDesc[nDesc], "n: %lld ", nPayload); nDesc += strlen(&zDesc[nDesc]); + nLocal = localPayload(nPayload, cType); + }else{ + nPayload = nLocal = 0; } if( cType==5 || cType==13 ){ i = decodeVarint(a, &rowid); a += i; n += i; - sprintf(&zDesc[nDesc], "rowid: %lld ", rowid); + sprintf(&zDesc[nDesc], "r: %lld ", rowid); nDesc += strlen(&zDesc[nDesc]); } + if( nLocal0 ){ + printf(" key: lx=left-child n=payload-size r=rowid\n"); + } + if( showMap ){ + zMap = malloc(pagesize); + memset(zMap, '.', pagesize); + memset(zMap, '1', hdrSize); + memset(&zMap[hdrSize], 'H', iCellPtr); + memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell); + } for(i=0; i