-rw-r--r-- | src/.gitignore | 1 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/binlog.c | 161 | ||||
-rw-r--r-- | src/binlogcat.c | 71 | ||||
-rw-r--r-- | src/pack.c | 588 | ||||
-rw-r--r-- | src/pack.h | 47 | ||||
-rw-r--r-- | src/vmod-binlog.h | 21 | ||||
-rw-r--r-- | src/vmod.vcc | 7 | ||||
-rw-r--r-- | tests/test01.at | 9 | ||||
-rw-r--r-- | tests/test02.at | 9 |
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 @@ | |||
1 | binlogcat | ||
1 | vcc_if.c | 2 | vcc_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) | |||
19 | bin_PROGRAMS = binlogcat | 19 | bin_PROGRAMS = binlogcat |
20 | binlogcat_SOURCES = binlogcat.c | 20 | binlogcat_SOURCES = binlogcat.c pack.c |
21 | binlogcat_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 | ||
35 | noinst_HEADERS = pack.h | ||
36 | |||
33 | BUILT_SOURCES = vcc_if.c vcc_if.h | 37 | BUILT_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 | ||
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)); |
diff --git a/src/binlogcat.c b/src/binlogcat.c index 219f78c..ee8837a 100644 --- a/src/binlogcat.c +++ b/src/binlogcat.c | |||
@@ -19,2 +19,3 @@ | |||
19 | #include <unistd.h> | 19 | #include <unistd.h> |
20 | #include <stddef.h> | ||
20 | #include <stdio.h> | 21 | #include <stdio.h> |
@@ -25,2 +26,3 @@ | |||
25 | #include "vmod-binlog.h" | 26 | #include "vmod-binlog.h" |
27 | #include "pack.h" | ||
26 | 28 | ||
@@ -36,4 +38,4 @@ catlog(const char *fname) | |||
36 | FILE *fp; | 38 | FILE *fp; |
37 | union binlog_header header; | 39 | struct binlog_file_header header; |
38 | struct binlog_record rec; | 40 | struct binlog_record *rec; |
39 | char timebuf[128]; | 41 | char timebuf[128]; |
@@ -41,2 +43,7 @@ catlog(const char *fname) | |||
41 | time_t start_ts; | 43 | time_t start_ts; |
44 | char *dataspec; | ||
45 | size_t size; | ||
46 | struct packenv *env; | ||
47 | struct packinst *inst; | ||
48 | char *p; | ||
42 | 49 | ||
@@ -59,3 +66,3 @@ catlog(const char *fname) | |||
59 | 66 | ||
60 | if (memcmp(header.hdr.magic, BINLOG_MAGIC_STR, BINLOG_MAGIC_LEN)) { | 67 | if (memcmp(header.magic, BINLOG_MAGIC_STR, BINLOG_MAGIC_LEN)) { |
61 | fprintf(stderr, "%s: %s is not a binlog file\n", | 68 | fprintf(stderr, "%s: %s is not a binlog file\n", |
@@ -65,3 +72,3 @@ catlog(const char *fname) | |||
65 | 72 | ||
66 | if (header.hdr.version != BINLOG_VERSION) { | 73 | if (header.version != BINLOG_VERSION) { |
67 | fprintf(stderr, "%s: %s: unknown version\n", | 74 | fprintf(stderr, "%s: %s: unknown version\n", |
@@ -71,5 +78,12 @@ catlog(const char *fname) | |||
71 | 78 | ||
72 | if (header.hdr.recsize != sizeof(struct binlog_record)) { | 79 | size = header.hdrsize - sizeof(header); |
73 | fprintf(stderr, "%s: %s: record length mismatch\n", | 80 | dataspec = malloc(size); |
74 | progname, fname); | 81 | if (!dataspec) { |
82 | fprintf(stderr, "%s: not enough memory", progname); | ||
83 | abort(); | ||
84 | } | ||
85 | |||
86 | if (fread(dataspec, size, 1, fp) != 1) { | ||
87 | fprintf(stderr, "%s: error reading header of %s: %s\n", | ||
88 | progname, fname, strerror(errno)); | ||
75 | exit(1); | 89 | exit(1); |
@@ -78,6 +92,24 @@ catlog(const char *fname) | |||
78 | if (verbose_option) | 92 | if (verbose_option) |
79 | printf("# %s; %lu records\n", fname, header.hdr.recnum); | 93 | printf("# %s; format=%s; recsize=%lu; recnum=%lu\n", |
94 | fname, dataspec, header.recsize, header.recnum); | ||
95 | |||
96 | inst = packcomp(dataspec, &p); | ||
97 | if (*p) { | ||
98 | fprintf(stderr, "%s: %s: bad dataspec near %s", | ||
99 | progname, dataspec, p); | ||
100 | exit(1); | ||
101 | } | ||
102 | free(dataspec); | ||
103 | |||
104 | rec = malloc(header.recsize); | ||
105 | if (!rec) { | ||
106 | fprintf(stderr, "%s: not enough memory", progname); | ||
107 | abort(); | ||
108 | } | ||
109 | env = packenv_create(header.recsize - | ||
110 | offsetof(struct binlog_record,data)); | ||
111 | env->fp = stdout; | ||
80 | 112 | ||
81 | for (i = 0; i < header.hdr.recnum; i++) { | 113 | for (i = 0; i < header.recnum; i++) { |
82 | if (fread(&rec, sizeof(rec), 1, fp) != 1) { | 114 | if (fread(rec, header.recsize, 1, fp) != 1) { |
83 | fprintf(stderr, "%s: %s: unexpected eof\n", | 115 | fprintf(stderr, "%s: %s: unexpected eof\n", |
@@ -89,11 +121,22 @@ catlog(const char *fname) | |||
89 | if (i == 0) | 121 | if (i == 0) |
90 | start_ts = rec.ts; | 122 | start_ts = rec->ts; |
91 | rec.ts -= start_ts; | 123 | rec->ts -= start_ts; |
92 | } | 124 | } |
93 | 125 | ||
94 | strftime(timebuf, sizeof timebuf, timefmt, localtime(&rec.ts)); | 126 | strftime(timebuf, sizeof timebuf, timefmt, |
127 | localtime(&rec->ts)); | ||
95 | if (number_option) | 128 | if (number_option) |
96 | printf("%lu ", (unsigned long) i); | 129 | printf("%lu ", (unsigned long) i); |
97 | printf("%s %ld %ld\n", timebuf, rec.nid, rec.aid); | 130 | printf("%s ", timebuf); |
131 | |||
132 | memcpy(env->buf_base, rec->data, env->buf_size); | ||
133 | env->buf_pos = 0; | ||
134 | |||
135 | packout(inst, env); | ||
136 | fputc('\n', stdout); | ||
98 | } | 137 | } |
138 | |||
139 | free(rec); | ||
140 | packenv_free(env); | ||
141 | packfree(inst); | ||
99 | 142 | ||
diff --git a/src/pack.c b/src/pack.c new file mode 100644 index 0000000..a6ee933 --- a/dev/null +++ b/src/pack.c | |||
@@ -0,0 +1,588 @@ | |||
1 | /* This file is part of vmod-binlog | ||
2 | Copyright (C) 2013 Sergey Poznyakoff | ||
3 | |||
4 | Vmod-binlog is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | Vmod-binlog is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with vmod-binlog. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | #include <config.h> | ||
18 | #include <stdint.h> | ||
19 | #include <stdlib.h> | ||
20 | #include <stdio.h> | ||
21 | #include <string.h> | ||
22 | #include <ctype.h> | ||
23 | #include "pack.h" | ||
24 | |||
25 | /* Data format specification is a simplified form of Perl pack() template. | ||
26 | It consists of a series of template letters optionally followed by | ||
27 | numeric repeat count (which may be enclosed in square brackets). The | ||
28 | valid template letters are: | ||
29 | |||
30 | Z A null-terminated (ASCIZ) string of at most N-1 characters, will be | ||
31 | null padded. This letter must be followed by repeat count. | ||
32 | |||
33 | c A signed char (8-bit) value. | ||
34 | C An unsigned char (octet) value. | ||
35 | |||
36 | s A signed short (16-bit) value. | ||
37 | S An unsigned short value. | ||
38 | |||
39 | l A signed long (32-bit) value. | ||
40 | L An unsigned long value. | ||
41 | |||
42 | q A signed quad (64-bit) value. | ||
43 | Q An unsigned quad value. | ||
44 | |||
45 | i A signed integer value. | ||
46 | I A unsigned integer value. | ||
47 | |||
48 | x A null byte (a.k.a ASCII NUL, "\000", chr(0)) | ||
49 | X Back up a byte. | ||
50 | @ Null-fill or truncate to absolute position, counted from the | ||
51 | current position. | ||
52 | . Null-fill or truncate to absolute position specified by | ||
53 | the repeat count. | ||
54 | */ | ||
55 | |||
56 | #define F_REP 0x01 | ||
57 | |||
58 | struct packspec { | ||
59 | int ch; | ||
60 | size_t size; | ||
61 | int flags; | ||
62 | void (*packer)(struct packenv *, struct packspec *, int); | ||
63 | void (*unpacker)(struct packenv *, struct packspec *, int); | ||
64 | }; | ||
65 | |||
66 | struct packinst { | ||
67 | struct packinst *next; | ||
68 | struct packspec *spec; | ||
69 | int rep; | ||
70 | }; | ||
71 | |||
72 | static char * | ||
73 | packenv_get(struct packenv *env) | ||
74 | { | ||
75 | if (env->argi == env->argc) | ||
76 | return NULL; | ||
77 | return env->argv[env->argi++]; | ||
78 | } | ||
79 | |||
80 | static void | ||
81 | printunum(FILE *fp, uintmax_t num) | ||
82 | { | ||
83 | char numbuf[512]; | ||
84 | char *p = numbuf + sizeof(numbuf); | ||
85 | *--p = 0; | ||
86 | do | ||
87 | *--p = num % 10 + '0'; | ||
88 | while (num /= 10); | ||
89 | fputs(p, fp); | ||
90 | } | ||
91 | |||
92 | static void | ||
93 | printsnum(FILE *fp, intmax_t num) | ||
94 | { | ||
95 | if (num < 0) { | ||
96 | fputc('-', fp); | ||
97 | num = - num; | ||
98 | } | ||
99 | printunum(fp, num); | ||
100 | } | ||
101 | |||
102 | static void | ||
103 | Z_packer(struct packenv *env, struct packspec *spec, int rep) | ||
104 | { | ||
105 | if (env->buf_base) { | ||
106 | char *arg = packenv_get(env); | ||
107 | |||
108 | memset(env->buf_base + env->buf_pos, 0, rep); | ||
109 | if (arg) { | ||
110 | size_t len = strlen(arg); | ||
111 | if (len > rep - 1) | ||
112 | len = rep - 1; | ||
113 | memcpy(env->buf_base + env->buf_pos, arg, len); | ||
114 | } | ||
115 | } | ||
116 | env->buf_pos += rep; | ||
117 | } | ||
118 | |||
119 | static void | ||
120 | Z_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
121 | { | ||
122 | fprintf(env->fp, "%-*.*s", rep, rep, env->buf_base + env->buf_pos); | ||
123 | env->buf_pos += rep; | ||
124 | } | ||
125 | |||
126 | static void | ||
127 | c_packer(struct packenv *env, struct packspec *spec, int rep) | ||
128 | { | ||
129 | if (env->buf_base) { | ||
130 | char *arg = packenv_get(env); | ||
131 | if (arg) | ||
132 | env->buf_base[env->buf_pos] = *arg; | ||
133 | } | ||
134 | env->buf_pos++; | ||
135 | } | ||
136 | |||
137 | static void | ||
138 | c_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
139 | { | ||
140 | fprintf(env->fp, "%c", env->buf_base[env->buf_pos++]); | ||
141 | } | ||
142 | |||
143 | static void | ||
144 | s_packer(struct packenv *env, struct packspec *spec, int rep) | ||
145 | { | ||
146 | if (env->buf_base) { | ||
147 | char *arg = packenv_get(env); | ||
148 | if (arg) { | ||
149 | int16_t v = atoi(arg); | ||
150 | memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); | ||
151 | } | ||
152 | } | ||
153 | env->buf_pos += spec->size; | ||
154 | } | ||
155 | |||
156 | static void | ||
157 | s_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
158 | { | ||
159 | printsnum(env->fp, *(int16_t *) (env->buf_base + env->buf_pos)); | ||
160 | env->buf_pos += spec->size; | ||
161 | } | ||
162 | |||
163 | static void | ||
164 | S_packer(struct packenv *env, struct packspec *spec, int rep) | ||
165 | { | ||
166 | if (env->buf_base) { | ||
167 | char *arg = packenv_get(env); | ||
168 | if (arg) { | ||
169 | uint16_t v = atoi(arg); | ||
170 | memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); | ||
171 | } | ||
172 | } | ||
173 | env->buf_pos += spec->size; | ||
174 | } | ||
175 | |||
176 | static void | ||
177 | S_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
178 | { | ||
179 | printunum(env->fp, *(uint16_t *)(env->buf_base + env->buf_pos)); | ||
180 | env->buf_pos += spec->size; | ||
181 | } | ||
182 | |||
183 | static void | ||
184 | l_packer(struct packenv *env, struct packspec *spec, int rep) | ||
185 | { | ||
186 | if (env->buf_base) { | ||
187 | char *arg = packenv_get(env); | ||
188 | if (arg) { | ||
189 | int32_t v = atoi(arg); | ||
190 | memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); | ||
191 | } | ||
192 | } | ||
193 | env->buf_pos += spec->size; | ||
194 | } | ||
195 | |||
196 | static void | ||
197 | l_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
198 | { | ||
199 | printsnum(env->fp, *(int32_t *)(env->buf_base + env->buf_pos)); | ||
200 | env->buf_pos += spec->size; | ||
201 | } | ||
202 | |||
203 | static void | ||
204 | L_packer(struct packenv *env, struct packspec *spec, int rep) | ||
205 | { | ||
206 | if (env->buf_base) { | ||
207 | char *arg = packenv_get(env); | ||
208 | if (arg) { | ||
209 | uint32_t v = atoi(arg); | ||
210 | memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); | ||
211 | } | ||
212 | } | ||
213 | env->buf_pos += spec->size; | ||
214 | } | ||
215 | |||
216 | static void | ||
217 | L_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
218 | { | ||
219 | printunum(env->fp, *(uint32_t *)(env->buf_base + env->buf_pos)); | ||
220 | env->buf_pos += spec->size; | ||
221 | } | ||
222 | |||
223 | static void | ||
224 | q_packer(struct packenv *env, struct packspec *spec, int rep) | ||
225 | { | ||
226 | if (env->buf_base) { | ||
227 | char *arg = packenv_get(env); | ||
228 | if (arg) { | ||
229 | int64_t v = atoi(arg); | ||
230 | memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); | ||
231 | } | ||
232 | } | ||
233 | env->buf_pos += spec->size; | ||
234 | } | ||
235 | |||
236 | static void | ||
237 | q_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
238 | { | ||
239 | printsnum(env->fp, *(int64_t *)(env->buf_base + env->buf_pos)); | ||
240 | env->buf_pos += spec->size; | ||
241 | } | ||
242 | |||
243 | static void | ||
244 | Q_packer(struct packenv *env, struct packspec *spec, int rep) | ||
245 | { | ||
246 | if (env->buf_base) { | ||
247 | char *arg = packenv_get(env); | ||
248 | if (arg) { | ||
249 | uint64_t v = atoi(arg); | ||
250 | memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); | ||
251 | } | ||
252 | } | ||
253 | env->buf_pos += spec->size; | ||
254 | } | ||
255 | |||
256 | static void | ||
257 | Q_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
258 | { | ||
259 | printunum(env->fp, *(uint64_t *)(env->buf_base + env->buf_pos)); | ||
260 | env->buf_pos += spec->size; | ||
261 | } | ||
262 | |||
263 | static void | ||
264 | i_packer(struct packenv *env, struct packspec *spec, int rep) | ||
265 | { | ||
266 | if (env->buf_base) { | ||
267 | char *arg = packenv_get(env); | ||
268 | if (arg) { | ||
269 | int v = atoi(arg); | ||
270 | memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); | ||
271 | } | ||
272 | } | ||
273 | env->buf_pos += spec->size; | ||
274 | } | ||
275 | |||
276 | static void | ||
277 | i_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
278 | { | ||
279 | printsnum(env->fp, *(int *)(env->buf_base + env->buf_pos)); | ||
280 | env->buf_pos += spec->size; | ||
281 | } | ||
282 | |||
283 | static void | ||
284 | I_packer(struct packenv *env, struct packspec *spec, int rep) | ||
285 | { | ||
286 | if (env->buf_base) { | ||
287 | char *arg = packenv_get(env); | ||
288 | if (arg) { | ||
289 | unsigned int v = atoi(arg); | ||
290 | memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); | ||
291 | } | ||
292 | } | ||
293 | env->buf_pos += spec->size; | ||
294 | } | ||
295 | |||
296 | static void | ||
297 | I_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
298 | { | ||
299 | printunum(env->fp, *(unsigned *)(env->buf_base + env->buf_pos)); | ||
300 | env->buf_pos += spec->size; | ||
301 | } | ||
302 | |||
303 | static void | ||
304 | x_packer(struct packenv *env, struct packspec *spec, int rep) | ||
305 | { | ||
306 | if (env->buf_base) | ||
307 | env->buf_base[env->buf_pos] = 0; | ||
308 | env->buf_pos++; | ||
309 | } | ||
310 | |||
311 | static void | ||
312 | x_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
313 | { | ||
314 | fputc(0, env->fp); | ||
315 | } | ||
316 | |||
317 | static void | ||
318 | X_packer(struct packenv *env, struct packspec *spec, int rep) | ||
319 | { | ||
320 | if (env->buf_pos) | ||
321 | --env->buf_pos; | ||
322 | } | ||
323 | |||
324 | static void | ||
325 | at_packer(struct packenv *env, struct packspec *spec, int rep) | ||
326 | { | ||
327 | if (env->buf_base) | ||
328 | memset(env->buf_base + env->buf_pos, 0, rep); | ||
329 | env->buf_pos += rep; | ||
330 | } | ||
331 | |||
332 | static void | ||
333 | at_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
334 | { | ||
335 | env->buf_pos += rep; | ||
336 | } | ||
337 | |||
338 | static void | ||
339 | dot_packer(struct packenv *env, struct packspec *spec, int rep) | ||
340 | { | ||
341 | if (env->buf_base) { | ||
342 | if (rep < env->buf_pos) | ||
343 | memset(env->buf_base + rep, 0, env->buf_pos - rep); | ||
344 | else | ||
345 | memset(env->buf_base + env->buf_pos, 0, | ||
346 | rep - env->buf_pos); | ||
347 | } | ||
348 | env->buf_pos = rep; | ||
349 | } | ||
350 | |||
351 | static void | ||
352 | dot_unpacker(struct packenv *env, struct packspec *spec, int rep) | ||
353 | { | ||
354 | env->buf_pos = rep; | ||
355 | } | ||
356 | |||
357 | static struct packspec packspec[] = { | ||
358 | { 'Z', 1, F_REP, Z_packer, Z_unpacker }, | ||
359 | { 'c', 1, 0, c_packer, c_unpacker }, | ||
360 | { 's', sizeof(int16_t), 0, s_packer, s_unpacker }, | ||
361 | { 'S', sizeof(uint16_t), 0, S_packer, S_unpacker }, | ||
362 | { 'l', sizeof(int32_t), 0, l_packer, l_unpacker }, | ||
363 | { 'L', sizeof(uint32_t), 0, L_packer, L_unpacker }, | ||
364 | { 'q', sizeof(int64_t), 0, q_packer, q_unpacker }, | ||
365 | { 'Q', sizeof(uint64_t), 0, Q_packer, Q_unpacker }, | ||
366 | { 'i', sizeof(int), 0, i_packer, i_unpacker }, | ||
367 | { 'I', sizeof(unsigned), 0, I_packer, I_unpacker }, | ||
368 | /* FIXME: n N v V f d */ | ||
369 | { 'x', 1, 0, x_packer, x_unpacker }, | ||
370 | { 'X', 1, 0, X_packer, X_packer }, | ||
371 | { '@', 0, F_REP, at_packer, at_unpacker }, | ||
372 | { '.', 0, F_REP, dot_packer, dot_unpacker }, | ||
373 | |||
374 | { 0 } | ||
375 | }; | ||
376 | |||
377 | static int | ||
378 | getrep(const char *s, char const **endp, int *rep) | ||
379 | { | ||
380 | int n; | ||
381 | char *p; | ||
382 | |||
383 | if (*s == '[') { | ||
384 | if (s[1]) { | ||
385 | if (isdigit(s[1])) { | ||
386 | n = strtol(s + 1, &p, 10); | ||
387 | if (n <= 0) { | ||
388 | *endp = s; | ||
389 | return -1; | ||
390 | } else if (*p != ']') { | ||
391 | *endp = p; | ||
392 | return -1; | ||
393 | } | ||
394 | *rep = n; | ||
395 | *endp = p + 1; | ||
396 | } else { | ||
397 | *endp = s; | ||
398 | return -1; | ||
399 | } | ||
400 | } else { | ||
401 | *endp = s; | ||
402 | return -1; | ||
403 | } | ||
404 | } else if (isdigit(*s)) { | ||
405 | n = strtol(s, &p, 10); | ||
406 | if (n <= 0) { | ||
407 | *endp = s; | ||
408 | return -1; | ||
409 | } | ||
410 | *rep = n; | ||
411 | *endp = p; | ||
412 | } else { | ||
413 | *rep = 1; | ||
414 | *endp = s; | ||
415 | } | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | struct packinst * | ||
420 | packcomp(const char *s, char **endp) | ||
421 | { | ||
422 | struct packinst *head = NULL, *tail = NULL, *pi; | ||
423 | struct packspec *ps; | ||
424 | int rep; | ||
425 | |||
426 | while (s) { | ||
427 | for (ps = packspec; ps->ch; ps++) | ||
428 | if (ps->ch == *s) | ||
429 | break; | ||
430 | if (!ps->ch) | ||
431 | break; | ||
432 | if (getrep(s + 1, &s, &rep)) | ||
433 | break; | ||
434 | pi = malloc(sizeof(*pi)); | ||
435 | pi->next = NULL; | ||
436 | pi->spec = ps; | ||
437 | pi->rep = rep; | ||
438 | if (tail) | ||
439 | tail->next = pi; | ||
440 | else | ||
441 | head = pi; | ||
442 | tail = pi; | ||
443 | } | ||
444 | if (endp) | ||
445 | *endp = (char*) s; | ||
446 | return head; | ||
447 | } | ||
448 | |||
449 | void | ||
450 | packfree(struct packinst *pi) | ||
451 | { | ||
452 | while (pi) { | ||
453 | struct packinst *next = pi->next; | ||
454 | free(pi); | ||
455 | pi = next; | ||
456 | } | ||
457 | } | ||
458 | |||
459 | void | ||
460 | packin(struct packinst *pi, struct packenv *env) | ||
461 | { | ||
462 | int i; | ||
463 | |||
464 | for (; pi; pi = pi->next) { | ||
465 | if (pi->spec->flags & F_REP) | ||
466 | pi->spec->packer(env, pi->spec, pi->rep); | ||
467 | else | ||
468 | for (i = 0; i < pi->rep; i++) | ||
469 | pi->spec->packer(env, pi->spec, 1); | ||
470 | } | ||
471 | } | ||
472 | |||
473 | struct packinst * | ||
474 | packinnext(struct packinst *pi, struct packenv *env) | ||
475 | { | ||
476 | int i; | ||
477 | |||
478 | if (!pi) | ||
479 | return NULL; | ||
480 | if (pi->spec->flags & F_REP) | ||
481 | pi->spec->packer(env, pi->spec, pi->rep); | ||
482 | else | ||
483 | for (i = 0; i < pi->rep; i++) | ||
484 | pi->spec->packer(env, pi->spec, 1); | ||
485 | return pi->next; | ||
486 | } | ||
487 | |||
488 | void | ||
489 | packout(struct packinst *pi, struct packenv *env) | ||
490 | { | ||
491 | int i; | ||
492 | |||
493 | for (; pi; pi = pi->next) { | ||
494 | if (pi->spec->flags & F_REP) | ||
495 | pi->spec->unpacker(env, pi->spec, pi->rep); | ||
496 | else | ||
497 | for (i = 0; i < pi->rep; i++) | ||
498 | pi->spec->unpacker(env, pi->spec, 1); | ||
499 | if (pi->next) | ||
500 | fputc(' ', env->fp); | ||
501 | } | ||
502 | } | ||
503 | |||
504 | size_t | ||
505 | packsize(struct packinst *pi) | ||
506 | { | ||
507 | struct packenv env; | ||
508 | |||
509 | memset(&env, 0, sizeof env); | ||
510 | packin(pi, &env); | ||
511 | return env.buf_pos; | ||
512 | } | ||
513 | |||
514 | struct packenv * | ||
515 | packenv_create(size_t size) | ||
516 | { | ||
517 | struct packenv *env = calloc(1, sizeof(*env)); | ||
518 | env->buf_base = calloc(1, size); | ||
519 | env->buf_size = size; | ||
520 | return env; | ||
521 | } | ||
522 | |||
523 | void | ||
524 | packenv_free(struct packenv *env) | ||
525 | { | ||
526 | if (!env) | ||
527 | return; | ||
528 | free(env->buf_base); | ||
529 | free(env); | ||
530 | } | ||
531 | |||
532 | void | ||
533 | packenv_init(struct packenv *env) | ||
534 | { | ||
535 | memset(env->buf_base, 0, env->buf_size); | ||
536 | env->buf_pos = 0; | ||
537 | } | ||
538 | |||
539 | #ifdef STANDALONE | ||
540 | #include <unistd.h> | ||
541 | |||
542 | int | ||
543 | main(int argc, char **argv) | ||
544 | { | ||
545 | void (*fn)(struct packinst *pi, struct packenv *env) = packin; | ||
546 | struct packinst *pi; | ||
547 | struct packenv *env; | ||
548 | char *end; | ||
549 | int c; | ||
550 | |||
551 | while ((c = getopt(argc, argv, "d")) != EOF) { | ||
552 | switch (c) { | ||
553 | case 'd': | ||
554 | fn = packout; | ||
555 | break; | ||
556 | default: | ||
557 | exit(1); | ||
558 | } | ||
559 | } | ||
560 | |||
561 | argc -= optind; | ||
562 | argv += optind; | ||
563 | |||
564 | if (argc == 0) | ||
565 | abort(); | ||
566 | |||
567 | pi = packcomp(argv[0], &end); | ||
568 | if (*end) { | ||
569 | fprintf(stderr, "compile error near %s\n", end); | ||
570 | exit(1); | ||
571 | } | ||
572 | env = packenv_create(packsize(pi)); | ||
573 | env->fp = stdout; | ||
574 | env->argv = argv + 1; | ||
575 | env->argc = argc - 1; | ||
576 | |||
577 | if (fn == packout) | ||
578 | fread(env->buf_base, env->buf_size, 1, stdin); | ||
579 | |||
580 | fn(pi, env); | ||
581 | if (fn == packin) { | ||
582 | fwrite(env->buf_base, env->buf_size, 1, stdout); | ||
583 | } | ||
584 | |||
585 | packenv_free(env); | ||
586 | packfree(pi); | ||
587 | } | ||
588 | #endif | ||
diff --git a/src/pack.h b/src/pack.h new file mode 100644 index 0000000..70a2488 --- a/dev/null +++ b/src/pack.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* This file is part of vmod-binlog | ||
2 | Copyright (C) 2013 Sergey Poznyakoff | ||
3 | |||
4 | Vmod-binlog is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | Vmod-binlog is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with vmod-binlog. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | #include <stdio.h> | ||
18 | |||
19 | struct packenv { | ||
20 | char *buf_base; | ||
21 | size_t buf_size; | ||
22 | size_t buf_pos; | ||
23 | char **argv; | ||
24 | int argc; | ||
25 | int argi; | ||
26 | FILE *fp; | ||
27 | }; | ||
28 | |||
29 | struct packinst; | ||
30 | |||
31 | struct packinst *packcomp(const char *s, char **endp); | ||
32 | void packfree(struct packinst *pi); | ||
33 | void packin(struct packinst *pi, struct packenv *env); | ||
34 | void packout(struct packinst *pi, struct packenv *env); | ||
35 | struct packinst *packinnext(struct packinst *pi, struct packenv *env); | ||
36 | |||
37 | size_t packsize(struct packinst *pi); | ||
38 | struct packenv *packenv_create(size_t size); | ||
39 | void packenv_init(struct packenv *env); | ||
40 | void packenv_free(struct packenv *env); | ||
41 | |||
42 | |||
43 | |||
44 | |||
45 | |||
46 | |||
47 | |||
diff --git a/src/vmod-binlog.h b/src/vmod-binlog.h index db6c7f0..06d517d 100644 --- a/src/vmod-binlog.h +++ b/src/vmod-binlog.h | |||
@@ -38,5 +38,4 @@ | |||
38 | struct binlog_record { | 38 | struct binlog_record { |
39 | long nid; /* node ID */ | ||
40 | long aid; /* article ID */ | ||
41 | time_t ts; /* timestamp */ | 39 | time_t ts; /* timestamp */ |
40 | char data[1]; /* payload */ | ||
42 | }; | 41 | }; |
@@ -51,21 +50,9 @@ struct binlog_file_header { | |||
51 | uint32_t version; | 50 | uint32_t version; |
51 | size_t hdrsize; | ||
52 | size_t recsize; | 52 | size_t recsize; |
53 | size_t recnum; | 53 | size_t recnum; |
54 | /*char dataspec[X];*/ | ||
54 | }; | 55 | }; |
55 | 56 | ||
56 | #define BINLOG_HEADER_SIZE \ | 57 | #define binlog_size(hdr) ((hdr)->hdrsize + (hdr)->recnum * (hdr)->recsize) |
57 | ((sizeof(struct binlog_file_header) + sizeof(struct binlog_record) - 1) / \ | ||
58 | sizeof(struct binlog_record)) | ||
59 | |||
60 | union binlog_header { | ||
61 | struct binlog_file_header hdr; | ||
62 | struct binlog_record pad[BINLOG_HEADER_SIZE]; | ||
63 | }; | ||
64 | |||
65 | #define binlog_size(conf) \ | ||
66 | (sizeof(union binlog_header) + \ | ||
67 | (conf)->recidx * sizeof(struct binlog_record)) | ||
68 | #define binlog_recnum(conf) \ | ||
69 | (((conf)->size - sizeof(union binlog_header)) / \ | ||
70 | sizeof(struct binlog_record)) | ||
71 | 58 | ||
diff --git a/src/vmod.vcc b/src/vmod.vcc index def0ec3..45da354 100644 --- a/src/vmod.vcc +++ b/src/vmod.vcc | |||
@@ -2,5 +2,6 @@ Module binlog | |||
2 | Init module_init | 2 | Init module_init |
3 | Function VOID init(PRIV_VCL, STRING) | 3 | Function VOID init(PRIV_VCL, STRING, STRING, STRING) |
4 | Function VOID append(PRIV_VCL, INT, INT) | 4 | Function VOID start(PRIV_VCL) |
5 | Function VOID sappend(PRIV_VCL, STRING, STRING) | 5 | Function VOID commit(PRIV_VCL) |
6 | Function VOID pack(PRIV_VCL, STRING) | ||
6 | Function VOID sync(PRIV_VCL) | 7 | Function VOID sync(PRIV_VCL) |
diff --git a/tests/test01.at b/tests/test01.at index 116c8f1..62eb4fb 100644 --- a/tests/test01.at +++ b/tests/test01.at | |||
@@ -17,3 +17,3 @@ | |||
17 | AT_SETUP([appends]) | 17 | AT_SETUP([appends]) |
18 | AT_KEYWORDS([append]) | 18 | AT_KEYWORDS([test01 append]) |
19 | 19 | ||
@@ -34,3 +34,3 @@ varnish v1 -vcl+backend { | |||
34 | sub vcl_init { | 34 | sub vcl_init { |
35 | binlog.init("dir=$cwd/log;size=1M;pattern=logfile"); | 35 | binlog.init("$cwd/log", "LL", "size=1M;pattern=logfile"); |
36 | } | 36 | } |
@@ -40,3 +40,6 @@ varnish v1 -vcl+backend { | |||
40 | sub vcl_recv { | 40 | sub vcl_recv { |
41 | binlog.sappend(req.http.X-nid, req.http.X-aid); | 41 | binlog.start(); |
42 | binlog.pack(req.http.X-nid); | ||
43 | binlog.pack(req.http.X-aid); | ||
44 | binlog.commit(); | ||
42 | return (lookup); | 45 | return (lookup); |
diff --git a/tests/test02.at b/tests/test02.at index df639a5..459a3cc 100644 --- a/tests/test02.at +++ b/tests/test02.at | |||
@@ -17,3 +17,3 @@ | |||
17 | AT_SETUP([log rotation]) | 17 | AT_SETUP([log rotation]) |
18 | AT_KEYWORDS([rotation]) | 18 | AT_KEYWORDS([test02 rotation]) |
19 | 19 | ||
@@ -34,3 +34,3 @@ varnish v1 -vcl+backend { | |||
34 | sub vcl_init { | 34 | sub vcl_init { |
35 | binlog.init("dir=$cwd/log;size=1M;interval=10;roundts=1;pattern=%S.log"); | 35 | binlog.init("$cwd/log","LL","size=1M;interval=10;roundts=1;pattern=%S.log"); |
36 | } | 36 | } |
@@ -40,3 +40,6 @@ varnish v1 -vcl+backend { | |||
40 | sub vcl_recv { | 40 | sub vcl_recv { |
41 | binlog.sappend(req.http.X-nid, req.http.X-aid); | 41 | binlog.start(); |
42 | binlog.pack(req.http.X-nid); | ||
43 | binlog.pack(req.http.X-aid); | ||
44 | binlog.commit(); | ||
42 | return (lookup); | 45 | return (lookup); |