diff options
Diffstat (limited to 'src/binlog.c')
-rw-r--r-- | src/binlog.c | 161 |
1 files changed, 125 insertions, 36 deletions
diff --git a/src/binlog.c b/src/binlog.c index be32e10..6f438a8 100644 --- a/src/binlog.c +++ b/src/binlog.c @@ -23,4 +23,5 @@ #include <errno.h> #include <syslog.h> +#include <stddef.h> #include <stdlib.h> #include <ctype.h> @@ -30,4 +31,5 @@ #include "bin/varnishd/cache.h" #include "vmod-binlog.h" +#include "pack.h" #ifndef O_SEARCH @@ -37,4 +39,10 @@ #define BLF_ROUNDTS 0x01 +enum binlog_state { + state_init, + state_start, + state_pack +}; + struct binlog_config { size_t size; /* maximum file size */ @@ -46,12 +54,19 @@ struct binlog_config { char *fname; /* current file name */ int fd; /* current file descriptor */ - union binlog_header *base; /* mmap base */ - struct binlog_record *recbase; /* record base */ + struct binlog_file_header *base; /* mmap base */ + char *recbase; /* record base */ size_t recnum; /* number of records in recbase */ - size_t recidx; /* index of the next free entry in recbase */ + size_t recsize; /* record size */ time_t stoptime; /* when to rotate the current file */ pthread_mutex_t mutex; int debug; int flags; + + char *dataspec; + struct packinst *inst_head; + struct packinst *inst_cur; + struct packenv *env; + enum binlog_state state; + time_t timestamp; }; @@ -159,9 +174,10 @@ getinterval(char *p, char **endp) void -vmod_init(struct sess *sp, struct vmod_priv *priv, const char *param) +vmod_init(struct sess *sp, struct vmod_priv *priv, + const char *dir, const char *dataspec, const char *param) { struct binlog_config *conf = priv->priv; struct stat st; - char *dir, *p, *q; + char *p, *q; unsigned long n; @@ -171,10 +187,5 @@ vmod_init(struct sess *sp, struct vmod_priv *priv, const char *param) free(p); } - - dir = findparam(param, "dir"); - if (!dir) { - binlog_error("parameter \"dir\" not set"); - abort(); - } + if (stat(dir, &st)) { if (errno == ENOENT) @@ -195,6 +206,18 @@ vmod_init(struct sess *sp, struct vmod_priv *priv, const char *param) abort(); } - conf->dir = dir; + conf->dir = strdup(dir); + AN(conf->dir); + conf->inst_head = packcomp(dataspec, &p); + if (*p) { + binlog_error("cannot compile data format near %s", p); + abort(); + } + conf->recsize = packsize(conf->inst_head); + conf->env = packenv_create(conf->recsize); + conf->recsize += offsetof(struct binlog_record,data); + conf->dataspec = strdup(dataspec); + AN(conf->dataspec); + p = findparam(param, "pattern"); if (!p) { @@ -368,5 +391,4 @@ reset(struct binlog_config *conf) conf->recbase = NULL; conf->recnum = 0; - conf->recidx = 0; } @@ -380,4 +402,7 @@ setstoptime(struct binlog_config *conf) } +#define binlog_recnum(conf) \ + (((conf)->size - (conf)->base->hdrsize) / (conf)->base->recsize) + static int newfile(struct sess *sp, struct binlog_config *conf) @@ -385,4 +410,5 @@ newfile(struct sess *sp, struct binlog_config *conf) int c; void *base; + size_t n; setstoptime(conf); @@ -414,12 +440,16 @@ newfile(struct sess *sp, struct binlog_config *conf) conf->base = base; - memcpy(conf->base->hdr.magic, BINLOG_MAGIC_STR, BINLOG_MAGIC_LEN); - conf->base->hdr.version = BINLOG_VERSION; - conf->base->hdr.recsize = sizeof(struct binlog_record); - conf->base->hdr.recnum = 0; + memcpy(conf->base->magic, BINLOG_MAGIC_STR, BINLOG_MAGIC_LEN); + conf->base->version = BINLOG_VERSION; + conf->base->recsize = conf->recsize; + conf->base->recnum = 0; + strcpy((char*)(conf->base + 1), conf->dataspec); - conf->recbase = (struct binlog_record *) (conf->base + 1); + n = (sizeof(struct binlog_file_header) + strlen(conf->dataspec) + + conf->recsize - 1) / conf->recsize; + conf->base->hdrsize = n * conf->recsize; + + conf->recbase = (char *) conf->base + conf->base->hdrsize; conf->recnum = binlog_recnum(conf); - conf->recidx = 0; debug(conf,1,("created new log file %s",conf->fname)); @@ -430,9 +460,12 @@ static void closefile(struct sess *sp, struct binlog_config *conf) { + size_t size; + if (conf->fd == -1) return; debug(conf,1,("closing log file %s",conf->fname)); + size = binlog_size(conf->base); munmap(conf->base, conf->size); - if (ftruncate(conf->fd, binlog_size(conf))) + if (ftruncate(conf->fd, size)) binlog_error("error truncating \"%s/%s\": %s", conf->dir, conf->fname, strerror(errno)); @@ -441,8 +474,7 @@ closefile(struct sess *sp, struct binlog_config *conf) reset(conf); } - void -vmod_append(struct sess *sp, struct vmod_priv *priv, int nid, int aid) +vmod_start(struct sess *sp, struct vmod_priv *priv) { struct binlog_config *conf = priv->priv; @@ -460,25 +492,82 @@ vmod_append(struct sess *sp, struct vmod_priv *priv, int nid, int aid) AZ(pthread_mutex_unlock(&conf->mutex)); } + + packenv_init(conf->env); + conf->state = state_start; + conf->inst_cur = conf->inst_head; + conf->timestamp = ts; +} + +void +vmod_pack(struct sess *sp, struct vmod_priv *priv, const char *str) +{ + struct binlog_config *conf = priv->priv; + char *argv[2]; + + if (!conf) + return; + + switch (conf->state) { + case state_start: + case state_pack: + break; + default: + binlog_error("pack called in wrong state (%d)", conf->state); + return; + } + + if (!conf->inst_cur) { + binlog_error("format spec exhausted"); + return; + } + + argv[0] = (char*) str; + argv[1] = NULL; + conf->env->argv = argv; + conf->env->argc = 2; + conf->env->argi = 0; + + conf->inst_cur = packinnext(conf->inst_cur, conf->env); + + conf->state = state_pack; +} + +void +vmod_commit(struct sess *sp, struct vmod_priv *priv) +{ + struct binlog_config *conf = priv->priv; + + if (!conf) + return; if (conf->fd == -1) return; + switch (conf->state) { + case state_start: + binlog_error("committing empty binlog record"); + break; + case state_pack: + if (conf->inst_cur) + binlog_error("committing incomplete binlog record"); + break; + default: + binlog_error("pack called in wrong state (%d)", conf->state); + return; + } + AZ(pthread_mutex_lock(&conf->mutex)); - if (conf->recidx == conf->recnum) { + if (conf->base->recnum == conf->recnum) { binlog_error("overflow of %s/%s", conf->dir, conf->fname); } else { - struct binlog_record *p = conf->recbase + conf->recidx++; - p->nid = nid; - p->aid = aid; - p->ts = ts; - conf->base->hdr.recnum++; + struct binlog_record *p = + (struct binlog_record *)(conf->recbase + + conf->base->recnum * + conf->recsize); + p->ts = conf->timestamp; + memcpy(p->data, conf->env->buf_base, conf->env->buf_size); + conf->base->recnum++; } AZ(pthread_mutex_unlock(&conf->mutex)); -} - -void -vmod_sappend(struct sess *sp, struct vmod_priv *priv, const char *nid, - const char *aid) -{ - vmod_append(sp, priv, nid ? atoi(nid): 0, aid ? atoi(aid) : 0); + conf->state = state_init; } @@ -493,5 +582,5 @@ vmod_sync(struct sess *sp, struct vmod_priv *priv) AZ(pthread_mutex_lock(&conf->mutex)); if (conf->base) - msync(conf->base, binlog_size(conf), 0); + msync(conf->base, binlog_size(conf->base), 0); AZ(pthread_mutex_unlock(&conf->mutex)); } |