aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-10-12 12:19:32 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2013-10-12 12:28:12 +0300
commitb6678bb65fce1f64e82cc049aae3d7ba6f8aa19c (patch)
tree55c1959713e8f37f5958afb4c0cdb4d751406fe6
parent791cdf412f5fb66a056aa28b27507fdc9af86507 (diff)
downloadvmod-binlog-b6678bb65fce1f64e82cc049aae3d7ba6f8aa19c.tar.gz
vmod-binlog-b6678bb65fce1f64e82cc049aae3d7ba6f8aa19c.tar.bz2
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.
-rw-r--r--src/.gitignore1
-rw-r--r--src/Makefile.am6
-rw-r--r--src/binlog.c161
-rw-r--r--src/binlogcat.c71
-rw-r--r--src/pack.c588
-rw-r--r--src/pack.h47
-rw-r--r--src/vmod-binlog.h21
-rw-r--r--src/vmod.vcc7
-rw-r--r--tests/test01.at9
-rw-r--r--tests/test02.at9
10 files changed, 843 insertions, 77 deletions
diff --git a/src/.gitignore b/src/.gitignore
index 7f6e438..a75fe6d 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1 +1,2 @@
1binlogcat
1vcc_if.c 2vcc_if.c
diff --git a/src/Makefile.am b/src/Makefile.am
index c9daf9a..9ce519f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,3 +19,4 @@ AM_CPPFLAGS = -I$(VARNISHSRC)/include -I$(VARNISHSRC)
19bin_PROGRAMS = binlogcat 19bin_PROGRAMS = binlogcat
20binlogcat_SOURCES = binlogcat.c 20binlogcat_SOURCES = binlogcat.c pack.c
21binlogcat_CFLAGS = $(AM_CFLAGS)
21 22
@@ -29,2 +30,3 @@ libvmod_binlog_la_SOURCES = \
29 binlog.c\ 30 binlog.c\
31 pack.c\
30 vmod-binlog.h\ 32 vmod-binlog.h\
@@ -32,2 +34,4 @@ libvmod_binlog_la_SOURCES = \
32 34
35noinst_HEADERS = pack.h
36
33BUILT_SOURCES = vcc_if.c vcc_if.h 37BUILT_SOURCES = vcc_if.c vcc_if.h
diff --git a/src/binlog.c b/src/binlog.c
index be32e10..6f438a8 100644
--- a/src/binlog.c
+++ b/src/binlog.c
@@ -24,2 +24,3 @@
24#include <syslog.h> 24#include <syslog.h>
25#include <stddef.h>
25#include <stdlib.h> 26#include <stdlib.h>
@@ -31,2 +32,3 @@
31#include "vmod-binlog.h" 32#include "vmod-binlog.h"
33#include "pack.h"
32 34
@@ -38,2 +40,8 @@
38 40
41enum binlog_state {
42 state_init,
43 state_start,
44 state_pack
45};
46
39struct binlog_config { 47struct binlog_config {
@@ -47,6 +55,6 @@ struct binlog_config {
47 int fd; /* current file descriptor */ 55 int fd; /* current file descriptor */
48 union binlog_header *base; /* mmap base */ 56 struct binlog_file_header *base; /* mmap base */
49 struct binlog_record *recbase; /* record base */ 57 char *recbase; /* record base */
50 size_t recnum; /* number of records in recbase */ 58 size_t recnum; /* number of records in recbase */
51 size_t recidx; /* index of the next free entry in recbase */ 59 size_t recsize; /* record size */
52 time_t stoptime; /* when to rotate the current file */ 60 time_t stoptime; /* when to rotate the current file */
@@ -55,2 +63,9 @@ struct binlog_config {
55 int flags; 63 int flags;
64
65 char *dataspec;
66 struct packinst *inst_head;
67 struct packinst *inst_cur;
68 struct packenv *env;
69 enum binlog_state state;
70 time_t timestamp;
56}; 71};
@@ -160,3 +175,4 @@ getinterval(char *p, char **endp)
160void 175void
161vmod_init(struct sess *sp, struct vmod_priv *priv, const char *param) 176vmod_init(struct sess *sp, struct vmod_priv *priv,
177 const char *dir, const char *dataspec, const char *param)
162{ 178{
@@ -164,3 +180,3 @@ vmod_init(struct sess *sp, struct vmod_priv *priv, const char *param)
164 struct stat st; 180 struct stat st;
165 char *dir, *p, *q; 181 char *p, *q;
166 unsigned long n; 182 unsigned long n;
@@ -172,8 +188,3 @@ vmod_init(struct sess *sp, struct vmod_priv *priv, const char *param)
172 } 188 }
173 189
174 dir = findparam(param, "dir");
175 if (!dir) {
176 binlog_error("parameter \"dir\" not set");
177 abort();
178 }
179 if (stat(dir, &st)) { 190 if (stat(dir, &st)) {
@@ -196,4 +207,16 @@ vmod_init(struct sess *sp, struct vmod_priv *priv, const char *param)
196 } 207 }
197 conf->dir = dir; 208 conf->dir = strdup(dir);
209 AN(conf->dir);
198 210
211 conf->inst_head = packcomp(dataspec, &p);
212 if (*p) {
213 binlog_error("cannot compile data format near %s", p);
214 abort();
215 }
216 conf->recsize = packsize(conf->inst_head);
217 conf->env = packenv_create(conf->recsize);
218 conf->recsize += offsetof(struct binlog_record,data);
219 conf->dataspec = strdup(dataspec);
220 AN(conf->dataspec);
221
199 p = findparam(param, "pattern"); 222 p = findparam(param, "pattern");
@@ -369,3 +392,2 @@ reset(struct binlog_config *conf)
369 conf->recnum = 0; 392 conf->recnum = 0;
370 conf->recidx = 0;
371} 393}
@@ -381,2 +403,5 @@ setstoptime(struct binlog_config *conf)
381 403
404#define binlog_recnum(conf) \
405 (((conf)->size - (conf)->base->hdrsize) / (conf)->base->recsize)
406
382static int 407static int
@@ -386,2 +411,3 @@ newfile(struct sess *sp, struct binlog_config *conf)
386 void *base; 411 void *base;
412 size_t n;
387 413
@@ -415,10 +441,14 @@ newfile(struct sess *sp, struct binlog_config *conf)
415 conf->base = base; 441 conf->base = base;
416 memcpy(conf->base->hdr.magic, BINLOG_MAGIC_STR, BINLOG_MAGIC_LEN); 442 memcpy(conf->base->magic, BINLOG_MAGIC_STR, BINLOG_MAGIC_LEN);
417 conf->base->hdr.version = BINLOG_VERSION; 443 conf->base->version = BINLOG_VERSION;
418 conf->base->hdr.recsize = sizeof(struct binlog_record); 444 conf->base->recsize = conf->recsize;
419 conf->base->hdr.recnum = 0; 445 conf->base->recnum = 0;
446 strcpy((char*)(conf->base + 1), conf->dataspec);
420 447
421 conf->recbase = (struct binlog_record *) (conf->base + 1); 448 n = (sizeof(struct binlog_file_header) + strlen(conf->dataspec) +
449 conf->recsize - 1) / conf->recsize;
450 conf->base->hdrsize = n * conf->recsize;
451
452 conf->recbase = (char *) conf->base + conf->base->hdrsize;
422 conf->recnum = binlog_recnum(conf); 453 conf->recnum = binlog_recnum(conf);
423 conf->recidx = 0;
424 454
@@ -431,2 +461,4 @@ closefile(struct sess *sp, struct binlog_config *conf)
431{ 461{
462 size_t size;
463
432 if (conf->fd == -1) 464 if (conf->fd == -1)
@@ -434,4 +466,5 @@ closefile(struct sess *sp, struct binlog_config *conf)
434 debug(conf,1,("closing log file %s",conf->fname)); 466 debug(conf,1,("closing log file %s",conf->fname));
467 size = binlog_size(conf->base);
435 munmap(conf->base, conf->size); 468 munmap(conf->base, conf->size);
436 if (ftruncate(conf->fd, binlog_size(conf))) 469 if (ftruncate(conf->fd, size))
437 binlog_error("error truncating \"%s/%s\": %s", 470 binlog_error("error truncating \"%s/%s\": %s",
@@ -442,6 +475,5 @@ closefile(struct sess *sp, struct binlog_config *conf)
442} 475}
443
444 476
445void 477void
446vmod_append(struct sess *sp, struct vmod_priv *priv, int nid, int aid) 478vmod_start(struct sess *sp, struct vmod_priv *priv)
447{ 479{
@@ -461,2 +493,50 @@ vmod_append(struct sess *sp, struct vmod_priv *priv, int nid, int aid)
461 } 493 }
494
495 packenv_init(conf->env);
496 conf->state = state_start;
497 conf->inst_cur = conf->inst_head;
498 conf->timestamp = ts;
499}
500
501void
502vmod_pack(struct sess *sp, struct vmod_priv *priv, const char *str)
503{
504 struct binlog_config *conf = priv->priv;
505 char *argv[2];
506
507 if (!conf)
508 return;
509
510 switch (conf->state) {
511 case state_start:
512 case state_pack:
513 break;
514 default:
515 binlog_error("pack called in wrong state (%d)", conf->state);
516 return;
517 }
518
519 if (!conf->inst_cur) {
520 binlog_error("format spec exhausted");
521 return;
522 }
523
524 argv[0] = (char*) str;
525 argv[1] = NULL;
526 conf->env->argv = argv;
527 conf->env->argc = 2;
528 conf->env->argi = 0;
529
530 conf->inst_cur = packinnext(conf->inst_cur, conf->env);
531
532 conf->state = state_pack;
533}
534
535void
536vmod_commit(struct sess *sp, struct vmod_priv *priv)
537{
538 struct binlog_config *conf = priv->priv;
539
540 if (!conf)
541 return;
462 if (conf->fd == -1) 542 if (conf->fd == -1)
@@ -464,20 +544,29 @@ vmod_append(struct sess *sp, struct vmod_priv *priv, int nid, int aid)
464 544
545 switch (conf->state) {
546 case state_start:
547 binlog_error("committing empty binlog record");
548 break;
549 case state_pack:
550