drh | 666fb69 | 2017-10-30 23:25:06 +0000 | [diff] [blame] | 1 | /* |
| 2 | ** A utility for printing content from the wal-index or "shm" file. |
| 3 | */ |
| 4 | #include <stdio.h> |
| 5 | #include <ctype.h> |
| 6 | #include <sys/types.h> |
| 7 | #include <sys/stat.h> |
| 8 | #include <fcntl.h> |
| 9 | #include <assert.h> |
| 10 | |
| 11 | #define ISDIGIT(X) isdigit((unsigned char)(X)) |
| 12 | #define ISPRINT(X) isprint((unsigned char)(X)) |
| 13 | |
| 14 | #if !defined(_MSC_VER) |
| 15 | #include <unistd.h> |
| 16 | #include <sys/types.h> |
| 17 | #else |
| 18 | #include <io.h> |
| 19 | #endif |
| 20 | |
| 21 | #include <stdlib.h> |
| 22 | #include <string.h> |
| 23 | |
| 24 | static int fd = -1; /* The open SHM file */ |
| 25 | |
| 26 | /* Report an out-of-memory error and die. |
| 27 | */ |
| 28 | static void out_of_memory(void){ |
| 29 | fprintf(stderr,"Out of memory...\n"); |
| 30 | exit(1); |
| 31 | } |
| 32 | |
| 33 | /* |
| 34 | ** Read content from the file. |
| 35 | ** |
| 36 | ** Space to hold the content is obtained from malloc() and needs to be |
| 37 | ** freed by the caller. |
| 38 | */ |
| 39 | static unsigned char *getContent(int ofst, int nByte){ |
| 40 | unsigned char *aData; |
| 41 | aData = malloc(nByte); |
| 42 | if( aData==0 ) out_of_memory(); |
| 43 | lseek(fd, ofst, SEEK_SET); |
| 44 | read(fd, aData, nByte); |
| 45 | return aData; |
| 46 | } |
| 47 | |
| 48 | /* |
| 49 | ** Flags values |
| 50 | */ |
| 51 | #define FG_HEX 1 /* Show as hex */ |
| 52 | #define FG_NBO 2 /* Native byte order */ |
| 53 | #define FG_PGSZ 4 /* Show as page-size */ |
| 54 | |
| 55 | /* Print a line of decode output showing a 4-byte integer. |
| 56 | */ |
| 57 | static void print_decode_line( |
| 58 | unsigned char *aData, /* Content being decoded */ |
| 59 | int ofst, int nByte, /* Start and size of decode */ |
| 60 | unsigned flg, /* Display flags */ |
| 61 | const char *zMsg /* Message to append */ |
| 62 | ){ |
| 63 | int i, j; |
| 64 | int val = aData[ofst]; |
| 65 | char zBuf[100]; |
| 66 | sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]); |
| 67 | i = (int)strlen(zBuf); |
| 68 | for(j=1; j<4; j++){ |
| 69 | if( j>=nByte ){ |
| 70 | sprintf(&zBuf[i], " "); |
| 71 | }else{ |
| 72 | sprintf(&zBuf[i], " %02x", aData[ofst+j]); |
| 73 | val = val*256 + aData[ofst+j]; |
| 74 | } |
| 75 | i += (int)strlen(&zBuf[i]); |
| 76 | } |
| 77 | if( nByte==8 ){ |
| 78 | for(j=4; j<8; j++){ |
| 79 | sprintf(&zBuf[i], " %02x", aData[ofst+j]); |
| 80 | i += (int)strlen(&zBuf[i]); |
| 81 | } |
| 82 | } |
| 83 | if( flg & FG_NBO ){ |
| 84 | assert( nByte==4 ); |
| 85 | memcpy(&val, aData+ofst, 4); |
| 86 | } |
| 87 | sprintf(&zBuf[i], " "); |
| 88 | i += 12; |
| 89 | if( flg & FG_PGSZ ){ |
| 90 | unsigned short sz; |
| 91 | memcpy(&sz, aData+ofst, 2); |
| 92 | sprintf(&zBuf[i], " %9d", sz==1 ? 65536 : sz); |
| 93 | }else if( flg & FG_HEX ){ |
| 94 | sprintf(&zBuf[i], " 0x%08x", val); |
| 95 | }else if( nByte<8 ){ |
| 96 | sprintf(&zBuf[i], " %9d", val); |
| 97 | } |
| 98 | printf("%s %s\n", zBuf, zMsg); |
| 99 | } |
| 100 | |
| 101 | /* |
| 102 | ** Print an instance of the WalIndexHdr object. ix is either 0 or 1 |
| 103 | ** to select which header to print. |
| 104 | */ |
| 105 | static void print_index_hdr(unsigned char *aData, int ix){ |
| 106 | int i; |
| 107 | assert( ix==0 || ix==1 ); |
| 108 | i = ix ? 48 : 0; |
| 109 | print_decode_line(aData, 0+i, 4, FG_NBO, "Wal-index version"); |
| 110 | print_decode_line(aData, 4+i, 4, 0, "unused padding"); |
| 111 | print_decode_line(aData, 8+i, 4, FG_NBO, "transaction counter"); |
| 112 | print_decode_line(aData,12+i, 1, 0, "1 when initialized"); |
| 113 | print_decode_line(aData,13+i, 1, 0, "true if WAL cksums are bigendian"); |
| 114 | print_decode_line(aData,14+i, 2, FG_PGSZ, "database page size"); |
| 115 | print_decode_line(aData,16+i, 4, FG_NBO, "mxFrame"); |
| 116 | print_decode_line(aData,20+i, 4, FG_NBO, "Size of database in pages"); |
| 117 | print_decode_line(aData,24+i, 8, 0, "Cksum of last frame in -wal"); |
| 118 | print_decode_line(aData,32+i, 8, 0, "Salt values from the -wal"); |
| 119 | print_decode_line(aData,40+i, 8, 0, "Cksum over all prior fields"); |
| 120 | } |
| 121 | |
| 122 | /* |
| 123 | ** Print the WalCkptInfo object |
| 124 | */ |
| 125 | static void print_ckpt_info(unsigned char *aData){ |
| 126 | const int i = 96; |
| 127 | int j; |
| 128 | print_decode_line(aData, 0+i, 4, FG_NBO, "nBackfill"); |
| 129 | for(j=0; j<5; j++){ |
| 130 | char zLabel[100]; |
| 131 | sprintf(zLabel, "aReadMark[%d]", j); |
| 132 | print_decode_line(aData, 4*j+4+i, 4, FG_NBO, zLabel); |
| 133 | } |
| 134 | print_decode_line(aData,24+i, 8, 0, "aLock"); |
| 135 | print_decode_line(aData,32+i, 4, FG_NBO, "nBackfillAttempted"); |
| 136 | print_decode_line(aData,36+i, 4, FG_NBO, "notUsed0"); |
| 137 | } |
| 138 | |
| 139 | |
| 140 | int main(int argc, char **argv){ |
| 141 | unsigned char *aData; |
| 142 | if( argc<2 ){ |
| 143 | fprintf(stderr,"Usage: %s FILENAME\n", argv[0]); |
| 144 | exit(1); |
| 145 | } |
| 146 | fd = open(argv[1], O_RDONLY); |
| 147 | if( fd<0 ){ |
| 148 | fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]); |
| 149 | exit(1); |
| 150 | } |
| 151 | aData = getContent(0, 136); |
| 152 | print_index_hdr(aData, 0); |
| 153 | print_index_hdr(aData, 1); |
| 154 | print_ckpt_info(aData); |
| 155 | free(aData); |
| 156 | close(fd); |
| 157 | return 0; |
| 158 | } |