From b6678bb65fce1f64e82cc049aae3d7ba6f8aa19c Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sat, 12 Oct 2013 12:19:32 +0300 Subject: Rewrite using opaque record data. Records can carry arbitrary data, whose format is defined using teplate strings similar to those of Perl's pack() function. The teplate string is stored in the logfile header and is used by binlogcat to render a human-readable representation. * src/.gitignore: New file. * pack.c: New file. * pack.h: New file. * src/Makefile.am: Add pack.c, pack.h * src/binlog.c: Rewrite. Use pack routines to construct each record. * src/binlogcat.c: Likewise. Use packout to unpack each record. * src/vmod-binlog.h (struct binlog_record): Remove nid,aid. (struct binlog_file_header): Add hdrsize. (BINLOG_HEADER_SIZE,union binlog_header): Remove (binlog_recnum): Remove. (binlog_size): Rewrite. * src/vmod.vcc (append,sappend): Remove. (init): Change signature. (start,commit,pack): New functions. * tests/test01.at: Rewrite. * tests/test02.at: Rewrite. --- src/binlogcat.c | 71 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 14 deletions(-) (limited to 'src/binlogcat.c') diff --git a/src/binlogcat.c b/src/binlogcat.c index 219f78c..ee8837a 100644 --- a/src/binlogcat.c +++ b/src/binlogcat.c @@ -17,12 +17,14 @@ #include #include +#include #include #include #include #include #include #include "vmod-binlog.h" +#include "pack.h" char *progname; char *timefmt = "%c"; @@ -34,11 +36,16 @@ void catlog(const char *fname) { FILE *fp; - union binlog_header header; - struct binlog_record rec; + struct binlog_file_header header; + struct binlog_record *rec; char timebuf[128]; size_t i; time_t start_ts; + char *dataspec; + size_t size; + struct packenv *env; + struct packinst *inst; + char *p; if (strcmp(fname, "-") == 0) fp = stdin; @@ -57,29 +64,54 @@ catlog(const char *fname) exit(1); } - if (memcmp(header.hdr.magic, BINLOG_MAGIC_STR, BINLOG_MAGIC_LEN)) { + if (memcmp(header.magic, BINLOG_MAGIC_STR, BINLOG_MAGIC_LEN)) { fprintf(stderr, "%s: %s is not a binlog file\n", progname, fname); exit(1); } - if (header.hdr.version != BINLOG_VERSION) { + if (header.version != BINLOG_VERSION) { fprintf(stderr, "%s: %s: unknown version\n", progname, fname); exit(1); } - if (header.hdr.recsize != sizeof(struct binlog_record)) { - fprintf(stderr, "%s: %s: record length mismatch\n", - progname, fname); + size = header.hdrsize - sizeof(header); + dataspec = malloc(size); + if (!dataspec) { + fprintf(stderr, "%s: not enough memory", progname); + abort(); + } + + if (fread(dataspec, size, 1, fp) != 1) { + fprintf(stderr, "%s: error reading header of %s: %s\n", + progname, fname, strerror(errno)); exit(1); } if (verbose_option) - printf("# %s; %lu records\n", fname, header.hdr.recnum); + printf("# %s; format=%s; recsize=%lu; recnum=%lu\n", + fname, dataspec, header.recsize, header.recnum); + + inst = packcomp(dataspec, &p); + if (*p) { + fprintf(stderr, "%s: %s: bad dataspec near %s", + progname, dataspec, p); + exit(1); + } + free(dataspec); + + rec = malloc(header.recsize); + if (!rec) { + fprintf(stderr, "%s: not enough memory", progname); + abort(); + } + env = packenv_create(header.recsize - + offsetof(struct binlog_record,data)); + env->fp = stdout; - for (i = 0; i < header.hdr.recnum; i++) { - if (fread(&rec, sizeof(rec), 1, fp) != 1) { + for (i = 0; i < header.recnum; i++) { + if (fread(rec, header.recsize, 1, fp) != 1) { fprintf(stderr, "%s: %s: unexpected eof\n", progname, fname); break; @@ -87,15 +119,26 @@ catlog(const char *fname) if (timediff_option) { if (i == 0) - start_ts = rec.ts; - rec.ts -= start_ts; + start_ts = rec->ts; + rec->ts -= start_ts; } - strftime(timebuf, sizeof timebuf, timefmt, localtime(&rec.ts)); + strftime(timebuf, sizeof timebuf, timefmt, + localtime(&rec->ts)); if (number_option) printf("%lu ", (unsigned long) i); - printf("%s %ld %ld\n", timebuf, rec.nid, rec.aid); + printf("%s ", timebuf); + + memcpy(env->buf_base, rec->data, env->buf_size); + env->buf_pos = 0; + + packout(inst, env); + fputc('\n', stdout); } + + free(rec); + packenv_free(env); + packfree(inst); fclose(fp); } -- cgit v1.2.1