aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-10-15 18:38:49 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2013-10-15 18:56:22 +0300
commitef3f928cc712f6774e19f8cb8f880cbeac15e8ff (patch)
tree88f59a4c8d1867bfadb924ee547b4b74a97c5ce0
parentf035194d7d1b6cc0846ad7a5d86e0d6fa9463c67 (diff)
downloadvmod-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.ac1
-rw-r--r--src/binlog.c159
-rw-r--r--src/binlogsel.c235
-rw-r--r--src/vmod-binlog.h18
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])
28AC_GNU_SOURCE 28AC_GNU_SOURCE
29AC_PROG_CC 29AC_PROG_CC
30AC_PROG_CC_STDC 30AC_PROG_CC_STDC
31AM_PROG_CC_C_O
31if test "x$ac_cv_prog_cc_c99" = xno; then 32if 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])
33fi 34fi
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
42enum binlog_state { 43enum binlog_state {
43 state_init, 44 state_init,
@@ -183,6 +184,29 @@ getinterval(char *p, char **endp)
183 } 184 }
184} 185}
185 186
187static 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
200static char *
201getindexpat(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
186void 210void
187vmod_init(struct sess *sp, struct vmod_priv *priv, 211vmod_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
422static int 480static int
481checkheader(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
538static int
423newfile(struct sess *sp, struct binlog_config *conf) 539newfile(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",