159 lines
4.2 KiB
C
159 lines
4.2 KiB
C
/*
|
|
** A utility for printing content from the wal-index or "shm" file.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <assert.h>
|
|
|
|
#define ISDIGIT(X) isdigit((unsigned char)(X))
|
|
#define ISPRINT(X) isprint((unsigned char)(X))
|
|
|
|
#if !defined(_MSC_VER)
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#else
|
|
#include <io.h>
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static int fd = -1; /* The open SHM file */
|
|
|
|
/* Report an out-of-memory error and die.
|
|
*/
|
|
static void out_of_memory(void){
|
|
fprintf(stderr,"Out of memory...\n");
|
|
exit(1);
|
|
}
|
|
|
|
/*
|
|
** Read content from the file.
|
|
**
|
|
** Space to hold the content is obtained from malloc() and needs to be
|
|
** freed by the caller.
|
|
*/
|
|
static unsigned char *getContent(int ofst, int nByte){
|
|
unsigned char *aData;
|
|
aData = malloc(nByte);
|
|
if( aData==0 ) out_of_memory();
|
|
lseek(fd, ofst, SEEK_SET);
|
|
read(fd, aData, nByte);
|
|
return aData;
|
|
}
|
|
|
|
/*
|
|
** Flags values
|
|
*/
|
|
#define FG_HEX 1 /* Show as hex */
|
|
#define FG_NBO 2 /* Native byte order */
|
|
#define FG_PGSZ 4 /* Show as page-size */
|
|
|
|
/* Print a line of decode output showing a 4-byte integer.
|
|
*/
|
|
static void print_decode_line(
|
|
unsigned char *aData, /* Content being decoded */
|
|
int ofst, int nByte, /* Start and size of decode */
|
|
unsigned flg, /* Display flags */
|
|
const char *zMsg /* Message to append */
|
|
){
|
|
int i, j;
|
|
int val = aData[ofst];
|
|
char zBuf[100];
|
|
sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]);
|
|
i = (int)strlen(zBuf);
|
|
for(j=1; j<4; j++){
|
|
if( j>=nByte ){
|
|
sprintf(&zBuf[i], " ");
|
|
}else{
|
|
sprintf(&zBuf[i], " %02x", aData[ofst+j]);
|
|
val = val*256 + aData[ofst+j];
|
|
}
|
|
i += (int)strlen(&zBuf[i]);
|
|
}
|
|
if( nByte==8 ){
|
|
for(j=4; j<8; j++){
|
|
sprintf(&zBuf[i], " %02x", aData[ofst+j]);
|
|
i += (int)strlen(&zBuf[i]);
|
|
}
|
|
}
|
|
if( flg & FG_NBO ){
|
|
assert( nByte==4 );
|
|
memcpy(&val, aData+ofst, 4);
|
|
}
|
|
sprintf(&zBuf[i], " ");
|
|
i += 12;
|
|
if( flg & FG_PGSZ ){
|
|
unsigned short sz;
|
|
memcpy(&sz, aData+ofst, 2);
|
|
sprintf(&zBuf[i], " %9d", sz==1 ? 65536 : sz);
|
|
}else if( flg & FG_HEX ){
|
|
sprintf(&zBuf[i], " 0x%08x", val);
|
|
}else if( nByte<8 ){
|
|
sprintf(&zBuf[i], " %9d", val);
|
|
}
|
|
printf("%s %s\n", zBuf, zMsg);
|
|
}
|
|
|
|
/*
|
|
** Print an instance of the WalIndexHdr object. ix is either 0 or 1
|
|
** to select which header to print.
|
|
*/
|
|
static void print_index_hdr(unsigned char *aData, int ix){
|
|
int i;
|
|
assert( ix==0 || ix==1 );
|
|
i = ix ? 48 : 0;
|
|
print_decode_line(aData, 0+i, 4, FG_NBO, "Wal-index version");
|
|
print_decode_line(aData, 4+i, 4, 0, "unused padding");
|
|
print_decode_line(aData, 8+i, 4, FG_NBO, "transaction counter");
|
|
print_decode_line(aData,12+i, 1, 0, "1 when initialized");
|
|
print_decode_line(aData,13+i, 1, 0, "true if WAL cksums are bigendian");
|
|
print_decode_line(aData,14+i, 2, FG_PGSZ, "database page size");
|
|
print_decode_line(aData,16+i, 4, FG_NBO, "mxFrame");
|
|
print_decode_line(aData,20+i, 4, FG_NBO, "Size of database in pages");
|
|
print_decode_line(aData,24+i, 8, 0, "Cksum of last frame in -wal");
|
|
print_decode_line(aData,32+i, 8, 0, "Salt values from the -wal");
|
|
print_decode_line(aData,40+i, 8, 0, "Cksum over all prior fields");
|
|
}
|
|
|
|
/*
|
|
** Print the WalCkptInfo object
|
|
*/
|
|
static void print_ckpt_info(unsigned char *aData){
|
|
const int i = 96;
|
|
int j;
|
|
print_decode_line(aData, 0+i, 4, FG_NBO, "nBackfill");
|
|
for(j=0; j<5; j++){
|
|
char zLabel[100];
|
|
sprintf(zLabel, "aReadMark[%d]", j);
|
|
print_decode_line(aData, 4*j+4+i, 4, FG_NBO, zLabel);
|
|
}
|
|
print_decode_line(aData,24+i, 8, 0, "aLock");
|
|
print_decode_line(aData,32+i, 4, FG_NBO, "nBackfillAttempted");
|
|
print_decode_line(aData,36+i, 4, FG_NBO, "notUsed0");
|
|
}
|
|
|
|
|
|
int main(int argc, char **argv){
|
|
unsigned char *aData;
|
|
if( argc<2 ){
|
|
fprintf(stderr,"Usage: %s FILENAME\n", argv[0]);
|
|
exit(1);
|
|
}
|
|
fd = open(argv[1], O_RDONLY);
|
|
if( fd<0 ){
|
|
fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
|
|
exit(1);
|
|
}
|
|
aData = getContent(0, 136);
|
|
print_index_hdr(aData, 0);
|
|
print_index_hdr(aData, 1);
|
|
print_ckpt_info(aData);
|
|
free(aData);
|
|
close(fd);
|
|
return 0;
|
|
}
|