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 | |||
@@ -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 | ||
41 | enum binlog_state { | ||
42 | state_init, | ||
43 | state_start, | ||
44 | state_pack | ||
45 | }; | ||
46 | |||
39 | struct binlog_config { | 47 | struct 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) | |||
160 | void | 175 | void |
161 | vmod_init(struct sess *sp, struct vmod_priv *priv, const char *param) | 176 | vmod_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 | |||
382 | static int | 407 | static 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 | ||
445 | void | 477 | void |
446 | vmod_append(struct sess *sp, struct vmod_priv *priv, int nid, int aid) | 478 | vmod_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 | |||
501 | void | ||
502 | vmod_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 | |||
535 | void | ||
536 | vmod_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 | if (conf->inst_cur) | ||
551 | binlog_error("committing incomplete binlog record"); | ||
552 | break; | ||
553 | default: | ||
554 | binlog_error("pack called in wrong state (%d)", conf->state); | ||
555 | return; | ||
556 | } | ||
557 | |||
465 | AZ(pthread_mutex_lock(&conf->mutex)); | 558 | AZ(pthread_mutex_lock(&conf->mutex)); |
466 | if (conf->recidx == conf->recnum) { | 559 | if (conf->base->recnum == conf->recnum) { |
467 | binlog_error("overflow of %s/%s", conf->dir, conf->fname); | 560 | binlog_error("overflow of %s/%s", conf->dir, conf->fname); |
468 | } else { | 561 | } else { |
469 | struct binlog_record *p = conf->recbase + conf->recidx++; | 562 | struct binlog_record *p = |
470 | p->nid = nid; | 563 | (struct binlog_record *)(conf->recbase + |
471 | p->aid = aid; | 564 | conf->base->recnum * |
472 | p->ts = ts; | 565 | conf->recsize); |
473 | conf->base->hdr.recnum++; | 566 | p->ts = conf->timestamp; |
567 | memcpy(p->data, conf->env->buf_base, conf->env->buf_size); | ||
568 | conf->base->recnum++; | ||
474 | } | 569 | } |
475 | AZ(pthread_mutex_unlock(&conf->mutex)); | 570 | AZ(pthread_mutex_unlock(&conf->mutex)); |
476 | } | 571 | conf->state = state_init; |
477 | |||
478 | void | ||
479 | vmod_sappend(struct sess *sp, struct vmod_priv *priv, const char *nid, | ||
480 | const char *aid) | ||
481 | { | ||
482 | vmod_append(sp, priv, nid ? atoi(nid): 0, aid ? atoi(aid) : 0); | ||
483 | } | 572 | } |
@@ -494,3 +583,3 @@ vmod_sync(struct sess *sp, struct vmod_priv *priv) | |||
494 | if (conf->base) | 583 | if (conf->base) |
495 | msync(conf->base, binlog_size(conf), 0); | 584 | msync(conf->base, binlog_size(conf->base), 0); |
496 | AZ(pthread_mutex_unlock(&conf->mutex)); | 585 | AZ(pthread_mutex_unlock(&conf->mutex)); |