diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-10-15 18:38:49 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-10-15 18:56:22 +0300 |
commit | ef3f928cc712f6774e19f8cb8f880cbeac15e8ff (patch) | |
tree | 88f59a4c8d1867bfadb924ee547b4b74a97c5ce0 | |
parent | f035194d7d1b6cc0846ad7a5d86e0d6fa9463c67 (diff) | |
download | vmod-binlog-ef3f928cc712f6774e19f8cb8f880cbeac15e8ff.tar.gz vmod-binlog-ef3f928cc712f6774e19f8cb8f880cbeac15e8ff.tar.bz2 |
Change default log naming.
* configure.ac: Call AM_PROG_CC_C_O
* src/binlog.c (BLF_TRUNCATE): New flag.
(vmod_init): Change pattern initialization.
New parameter "reuselog".
(createfile): Remove O_TRUNC.
(checkheader): New function.
(newfile): Reuse existing file, if it is the first file
to be opened after varnish startup and its header matches
exactly our data.
* src/binlogsel.c: Use indexed directory structure to speed up
searches.
* src/vmod-binlog.h (BINLOG_PATTERN): Change pattern.
(BINLOG_GLOB_PATTERN,BINLOG_INDEX): New defines.
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/binlog.c | 159 | ||||
-rw-r--r-- | src/binlogsel.c | 235 | ||||
-rw-r--r-- | src/vmod-binlog.h | 18 |
4 files changed, 394 insertions, 19 deletions
diff --git a/configure.ac b/configure.ac index 2bb8f38..56e0411 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -28,6 +28,7 @@ AM_INIT_AUTOMAKE([gnu tar-ustar]) | |||
28 | AC_GNU_SOURCE | 28 | AC_GNU_SOURCE |
29 | AC_PROG_CC | 29 | AC_PROG_CC |
30 | AC_PROG_CC_STDC | 30 | AC_PROG_CC_STDC |
31 | AM_PROG_CC_C_O | ||
31 | if test "x$ac_cv_prog_cc_c99" = xno; then | 32 | if test "x$ac_cv_prog_cc_c99" = xno; then |
32 | AC_MSG_ERROR([could not find a C99 compatible compiler]) | 33 | AC_MSG_ERROR([could not find a C99 compatible compiler]) |
33 | fi | 34 | fi |
diff --git a/src/binlog.c b/src/binlog.c index 765b945..e7ac7e5 100644 --- a/src/binlog.c +++ b/src/binlog.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | #define BLF_ROUNDTS 0x01 | 40 | #define BLF_ROUNDTS 0x01 |
41 | #define BLF_TRUNCATE 0x02 | ||
41 | 42 | ||
42 | enum binlog_state { | 43 | enum binlog_state { |
43 | state_init, | 44 | state_init, |
@@ -183,6 +184,29 @@ getinterval(char *p, char **endp) | |||
183 | } | 184 | } |
184 | } | 185 | } |
185 | 186 | ||
187 | static struct indexdef { | ||
188 | char *name; | ||
189 | char *pat; | ||
190 | } indextab[] = { | ||
191 | { "year", "%Y" }, | ||
192 | { "0", "%Y" }, | ||
193 | { "month", "%Y/%m" }, | ||
194 | { "1", "%Y/%m" }, | ||
195 | { "day", "%Y/%m/%d" }, | ||
196 | { "2", "%Y/%m/%d" }, | ||
197 | { NULL } | ||
198 | }; | ||
199 | |||
200 | static char * | ||
201 | getindexpat(const char *name) | ||
202 | { | ||
203 | struct indexdef *p; | ||
204 | for (p = indextab; p->name; p++) | ||
205 | if (strcmp(p->name, name) == 0) | ||
206 | return p->pat; | ||
207 | return NULL; | ||
208 | } | ||
209 | |||
186 | void | 210 | void |
187 | vmod_init(struct sess *sp, struct vmod_priv *priv, | 211 | vmod_init(struct sess *sp, struct vmod_priv *priv, |
188 | const char *dir, const char *dataspec, const char *param) | 212 | const char *dir, const char *dataspec, const char *param) |
@@ -191,6 +215,7 @@ vmod_init(struct sess *sp, struct vmod_priv *priv, | |||
191 | struct stat st; | 215 | struct stat st; |
192 | char *p, *q; | 216 | char *p, *q; |
193 | unsigned long n; | 217 | unsigned long n; |
218 | int user_pattern = 0; | ||
194 | 219 | ||
195 | p = findparam(param, "debug"); | 220 | p = findparam(param, "debug"); |
196 | if (p) { | 221 | if (p) { |
@@ -238,8 +263,32 @@ vmod_init(struct sess *sp, struct vmod_priv *priv, | |||
238 | if (!p) { | 263 | if (!p) { |
239 | p = strdup(BINLOG_PATTERN); | 264 | p = strdup(BINLOG_PATTERN); |
240 | AN(p); | 265 | AN(p); |
266 | } else | ||
267 | user_pattern = 1; | ||
268 | conf->pattern = p; | ||
269 | |||
270 | p = findparam(param, "index"); | ||
271 | if (p) { | ||
272 | q = getindexpat(p); | ||
273 | if (!q) { | ||
274 | binlog_error("invalid index type"); | ||
275 | abort(); | ||
241 | } | 276 | } |
277 | } else if (!user_pattern) { | ||
278 | q = getindexpat(BINLOG_INDEX); | ||
279 | AN(q); | ||
280 | } else | ||
281 | q = NULL; | ||
282 | |||
283 | if (q) { | ||
284 | p = malloc(strlen(q) + strlen(conf->pattern) + 2); | ||
285 | AN(p); | ||
286 | strcpy(p, q); | ||
287 | strcat(p, "/"); | ||
288 | strcat(p, conf->pattern); | ||
289 | free(conf->pattern); | ||
242 | conf->pattern = p; | 290 | conf->pattern = p; |
291 | } | ||
243 | 292 | ||
244 | p = findparam(param, "size"); | 293 | p = findparam(param, "size"); |
245 | if (p) { | 294 | if (p) { |
@@ -306,6 +355,15 @@ vmod_init(struct sess *sp, struct vmod_priv *priv, | |||
306 | free(p); | 355 | free(p); |
307 | } | 356 | } |
308 | 357 | ||
358 | p = findparam(param, "reuselog"); | ||
359 | if (p) { | ||
360 | if (atoi(p)) | ||
361 | conf->flags &= ~BLF_TRUNCATE; | ||
362 | else | ||
363 | conf->flags |= BLF_TRUNCATE; | ||
364 | free(p); | ||
365 | } | ||
366 | |||
309 | conf->fd = -1; | 367 | conf->fd = -1; |
310 | conf->base = NULL; | 368 | conf->base = NULL; |
311 | conf->stoptime = time(NULL); | 369 | conf->stoptime = time(NULL); |
@@ -384,7 +442,7 @@ createfile(struct sess *sp, struct binlog_config *conf) | |||
384 | return -1; | 442 | return -1; |
385 | } | 443 | } |
386 | 444 | ||
387 | fd = openat(conf->dd, fname, O_CREAT|O_RDWR|O_TRUNC, | 445 | fd = openat(conf->dd, fname, O_CREAT|O_RDWR, |
388 | 0666 & ~conf->umask); | 446 | 0666 & ~conf->umask); |
389 | if (fd == -1) { | 447 | if (fd == -1) { |
390 | binlog_error("cannot create log file %s/%s: %s", | 448 | binlog_error("cannot create log file %s/%s: %s", |
@@ -420,19 +478,103 @@ setstoptime(struct binlog_config *conf) | |||
420 | (((conf)->size - (conf)->base->hdrsize) / (conf)->base->recsize) | 478 | (((conf)->size - (conf)->base->hdrsize) / (conf)->base->recsize) |
421 | 479 | ||
422 | static int | 480 | static int |
481 | checkheader(struct binlog_config *conf, size_t hdrsize) | ||
482 | { | ||
483 | struct binlog_file_header header; | ||
484 | int c; | ||
485 | ssize_t rc; | ||
486 | char *p; | ||
487 | |||
488 | rc = read(conf->fd, &header, sizeof(header)); | ||
489 | if (rc == -1) { | ||
490 | binlog_error("error reading header of %s/%s: %s", | ||
491 | conf->dir, conf->fname, strerror(errno)); | ||
492 | return -1; | ||
493 | } else if (rc != sizeof(header)) { | ||
494 | binlog_error("error reading header of %s/%s: %s", | ||
495 | conf->dir, conf->fname, "hit eof"); | ||
496 | return -1; | ||
497 | } | ||
498 | |||
499 | if (memcmp(header.magic, BINLOG_MAGIC_STR, BINLOG_MAGIC_LEN)) { | ||
500 | binlog_error("%s/%s is not a binlog file", | ||
501 | conf->dir, conf->fname); | ||
502 | return -1; | ||
503 | } | ||
504 | |||
505 | if (header.version != BINLOG_VERSION) { | ||
506 | binlog_error("%s/%s: unknown version", conf->dir, conf->fname); | ||
507 | return -1; | ||
508 | } | ||
509 | |||
510 | if (header.hdrsize != hdrsize) { | ||
511 | debug(conf,1,("%s/%s: header size mismatch", | ||
512 | conf->dir, conf->fname)); | ||
513 | return 1; | ||
514 | } | ||
515 | if (header.recsize != conf->recsize) { | ||
516 | debug(conf,1,("%s/%s: record size mismatch", | ||
517 | conf->dir, conf->fname)); | ||
518 | return 1; | ||
519 | } | ||
520 | |||
521 | p = conf->dataspec; | ||
522 | while (*p) { | ||
523 | if (read(conf->fd, &c, 1) != 1 || c != *p) { | ||
524 | debug(conf,1,("%s/%s: dataspec mismatch near %s: %c", | ||
525 | conf->dir, conf->fname, p, c)); | ||
526 | return 1; | ||
527 | } | ||
528 | ++p; | ||
529 | } | ||
530 | if (read(conf->fd, &c, 1) != 1 || c != 0) { | ||
531 | debug(conf,1,("%s/%s: dataspec mismatch at the end: %c", | ||
532 | conf->dir, conf->fname, c)); | ||
533 | return 1; | ||
534 | } | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int | ||
423 | newfile(struct sess *sp, struct binlog_config *conf) | 539 | newfile(struct sess *sp, struct binlog_config *conf) |
424 | { | 540 | { |
425 | int c; | 541 | int c; |
426 | void *base; | 542 | void *base; |
427 | size_t n; | 543 | size_t hdrsize; |
544 | struct stat st; | ||
545 | int reuse = 0; | ||
428 | 546 | ||
429 | setstoptime(conf); | 547 | setstoptime(conf); |
430 | 548 | ||
431 | if (createfile(sp, conf)) | 549 | if (createfile(sp, conf)) |
432 | return -1; | 550 | return -1; |
551 | |||
552 | hdrsize = ((sizeof(struct binlog_file_header) + | ||
553 | strlen(conf->dataspec) + | ||
554 | conf->recsize - 1) / conf->recsize) * conf->recsize; | ||
555 | |||
556 | if (fstat(conf->fd, &st) == 0) { | ||
557 | /* File already exists */ | ||
558 | if (st.st_size > 0 && | ||
559 | !(conf->flags & BLF_TRUNCATE) && | ||
560 | checkheader(conf, hdrsize) == 0) { | ||
561 | reuse = 1; | ||
562 | } else { | ||
563 | binlog_error("truncating existing file %s/%s", | ||
564 | conf->dir, conf->fname); | ||
565 | ftruncate(conf->fd, 0); | ||
566 | } | ||
567 | } else { | ||
568 | binlog_error("can't stat %s/%s: %s", | ||