aboutsummaryrefslogtreecommitdiff
path: root/src/binlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/binlog.c')
-rw-r--r--src/binlog.c161
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
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 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
478void
479vmod_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));

Return to:

Send suggestions and report system problems to the