summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (show whitespace changes)
-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
@@ -25,12 +25,13 @@ AC_LANG(C)
25 25
26AM_INIT_AUTOMAKE([gnu tar-ustar]) 26AM_INIT_AUTOMAKE([gnu tar-ustar])
27 27
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
34AC_PROG_CPP 35AC_PROG_CPP
35AC_PROG_YACC 36AC_PROG_YACC
36AC_PROG_INSTALL 37AC_PROG_INSTALL
diff --git a/src/binlog.c b/src/binlog.c
index 765b945..e7ac7e5 100644
--- a/src/binlog.c
+++ b/src/binlog.c
@@ -35,12 +35,13 @@
35 35
36#ifndef O_SEARCH 36#ifndef O_SEARCH
37# define O_SEARCH 0 37# define O_SEARCH 0
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,
44 state_start, 45 state_start,
45 state_pack 46 state_pack
46}; 47};
@@ -180,20 +181,44 @@ getinterval(char *p, char **endp)
180 return (hours*60 + minutes)*60 + seconds; 181 return (hours*60 + minutes)*60 + seconds;
181 } 182 }
182 p++; 183 p++;
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)
189{ 213{
190 struct binlog_config *conf = priv->priv; 214 struct binlog_config *conf = 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) {
197 conf->debug = atoi(p); 222 conf->debug = atoi(p);
198 free(p); 223 free(p);
199 } 224 }
@@ -235,14 +260,38 @@ vmod_init(struct sess *sp, struct vmod_priv *priv,
235 AN(conf->dataspec); 260 AN(conf->dataspec);
236 261
237 p = findparam(param, "pattern"); 262 p = findparam(param, "pattern");
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) {
246 uintmax_t u; 295 uintmax_t u;
247 296
248 errno = 0; 297 errno = 0;
@@ -303,12 +352,21 @@ vmod_init(struct sess *sp, struct vmod_priv *priv,
303 conf->flags |= BLF_ROUNDTS; 352 conf->flags |= BLF_ROUNDTS;
304 else 353 else
305 conf->flags &= ~BLF_ROUNDTS; 354 conf->flags &= ~BLF_ROUNDTS;
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);
312 pthread_mutex_init(&conf->mutex, NULL); 370 pthread_mutex_init(&conf->mutex, NULL);
313} 371}
314 372
@@ -381,13 +439,13 @@ createfile(struct sess *sp, struct binlog_config *conf)
381 return -1; 439 return -1;
382 if (mkdir_p(conf, fname)) { 440 if (mkdir_p(conf, fname)) {
383 free(fname); 441 free(fname);
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",
391 conf->dir, fname, strerror(errno)); 449 conf->dir, fname, strerror(errno));
392 free(fname); 450 free(fname);
393 } 451 }
@@ -417,25 +475,109 @@ setstoptime(struct binlog_config *conf)
417} 475}
418 476
419#define binlog_recnum(conf) \ 477#define binlog_recnum(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",
569 conf->dir, conf->fname, strerror(errno));
570 /* try to continue anyway */
571 }
572 conf->flags |= BLF_TRUNCATE;
573
433 if (lseek(conf->fd, conf->size, SEEK_SET) == -1) { 574 if (lseek(conf->fd, conf->size, SEEK_SET) == -1) {
434 binlog_error("seek in log file %s/%s failed: %s", 575 binlog_error("seek in log file %s/%s failed: %s",
435 conf->dir, conf->fname, strerror(errno)); 576 conf->dir, conf->fname, strerror(errno));
577 if (!reuse)
436 unlinkat(conf->dd, conf->fname, 0); 578 unlinkat(conf->dd, conf->fname, 0);
437 close(conf->fd); 579 close(conf->fd);
438 free(conf->fname); 580 free(conf->fname);
439 reset(conf); 581 reset(conf);
440 return -1; 582 return -1;
441 } 583 }
@@ -443,34 +585,39 @@ newfile(struct sess *sp, struct binlog_config *conf)
443 write(conf->fd, &c, 1); 585 write(conf->fd, &c, 1);
444 base = mmap((caddr_t)0, conf->size, 586 base = mmap((caddr_t)0, conf->size,
445 PROT_READ|PROT_WRITE, MAP_SHARED, 587 PROT_READ|PROT_WRITE, MAP_SHARED,
446 conf->fd, 0); 588 conf->fd, 0);
447 if (base == MAP_FAILED) { 589 if (base == MAP_FAILED) {
448 binlog_error("mmap: %s", strerror(errno)); 590 binlog_error("mmap: %s", strerror(errno));
591 if (!reuse)
449 unlinkat(conf->dd, conf->fname, 0); 592 unlinkat(conf->dd, conf->fname, 0);
450 close(conf->fd); 593 close(conf->fd);
451 free(conf->fname); 594 free(conf->fname);
452 reset(conf); 595 reset(conf);
453 return -1; 596 return -1;
454 } 597 }
455 598
456 conf->base = base; 599 conf->base = base;
600
601 if (reuse) {
602 debug(conf,1,("reusing log file %s, recnum=%lu",
603 conf->fname, (unsigned long)conf->base->recnum));
604 } else {
605 debug(conf,1,("created new log file %s",conf->fname));
457 memcpy(conf->base->magic, BINLOG_MAGIC_STR, BINLOG_MAGIC_LEN); 606 memcpy(conf->base->magic, BINLOG_MAGIC_STR, BINLOG_MAGIC_LEN);
458 conf->base->version = BINLOG_VERSION; 607 conf->base->version = BINLOG_VERSION;
459 conf->base->recsize = conf->recsize; 608 conf->base->recsize = conf->recsize;
460 conf->base->recnum = 0; 609 conf->base->recnum = 0;
461 strcpy((char*)(conf->base + 1), conf->dataspec); 610 strcpy((char*)(conf->base + 1), conf->dataspec);
462 611
463 n = (sizeof(struct binlog_file_header) + strlen(conf->dataspec) + 612 conf->base->hdrsize = hdrsize;
464 conf->recsize - 1) / conf->recsize; 613 }
465 conf->base->hdrsize = n * conf->recsize;
466 614
467 conf->recbase = (char *) conf->base + conf->base->hdrsize; 615 conf->recbase = (char *) conf->base + conf->base->hdrsize;
468 conf->recnum = binlog_recnum(conf); 616 conf->recnum = binlog_recnum(conf);
469 617
470 debug(conf,1,("created new log file %s",conf->fname));
471 return 0; 618 return 0;
472} 619}
473 620
474static void 621static void
475closefile(struct sess *sp, struct binlog_config *conf) 622closefile(struct sess *sp, struct binlog_config *conf)
476{ 623{
diff --git a/src/binlogsel.c b/src/binlogsel.c
index 62299e5..8f1cfce 100644
--- a/src/binlogsel.c
+++ b/src/binlogsel.c
@@ -35,27 +35,32 @@
35#include "parse-datetime.h" 35#include "parse-datetime.h"
36 36
37char *timefmt = "%c"; 37char *timefmt = "%c";
38int number_option; 38int number_option;
39int verbose_option; 39int verbose_option;
40int timediff_option; 40int timediff_option;
41char *directory;
41char *pattern; 42char *pattern;
43enum binlog_index_type index_type = index_year;
42 44
43#define FROM_TIME 0x01 45#define FROM_TIME 0x01
44#define TO_TIME 0x02 46#define TO_TIME 0x02
45int timemask; 47int timemask;
46time_t from_time, to_time; 48time_t from_time, to_time;
47 49
50static int matchnames(const char *dir, const char *pat, glob_t *gl);
51void selglob(const char *dir, const char *pattern);
52
48void 53void
49help() 54help()
50{ 55{
51 printf("usage: %s [-dhnv] [-t FORMAT] [-F FROMTIME] [-T TOTIME] [-p PATTERN] [-D DIR] [FILE...]\n", progname); 56 printf("usage: %s [-dhnv] [-t FORMAT] [-F FROMTIME] [-T TOTIME] [-p PATTERN] [-D DIR] [FILE...]\n", progname);
52} 57}
53 58
54/* Convert strftime-like pattern into globbing pattern */ 59/* Convert strftime-like pattern into globbing pattern */
55void 60char *
56convpattern(const char *dir) 61convpattern(const char *dir)
57{ 62{
58 char *p, *q; 63 char *p, *q;
59 char *newpat; 64 char *newpat;
60 size_t size = strlen(pattern) + 1; 65 size_t size = strlen(pattern) + 1;
61 66
@@ -70,19 +75,20 @@ convpattern(const char *dir)
70 p += strlen(dir); 75 p += strlen(dir);
71 *p++ = '/'; 76 *p++ = '/';
72 } 77 }
73 78
74 for (q = pattern; *q; ) { 79 for (q = pattern; *q; ) {
75 if (*q == '%') { 80 if (*q == '%') {
81 if (p > newpat && p[-1] != '*')
76 *p++ = '*'; 82 *p++ = '*';
77 q += 2; 83 q += 2;
78 } else 84 } else
79 *p++ = *q++; 85 *p++ = *q++;
80 } 86 }
81 *p = 0; 87 *p = 0;
82 pattern = newpat; 88 return newpat;
83} 89}
84 90
85#define getrec(base, recsize, n) \ 91#define getrec(base, recsize, n) \
86 ((struct binlog_record*)((char *)(base) + (n) * (recsize))) 92 ((struct binlog_record*)((char *)(base) + (n) * (recsize)))
87 93
88int 94int
@@ -330,19 +336,217 @@ void
330selfilelist(char **argv) 336selfilelist(char **argv)
331{ 337{
332 for (;*argv;++argv) 338 for (;*argv;++argv)
333 selfile(*argv); 339 selfile(*argv);
334} 340}
335 341
342static char *
343mkfilename(const char *dir, const char *file)
344{
345 size_t dirlen, size;
346 char *ret;
347
348 dirlen = strlen(dir);
349 while (dirlen > 0 && dir[dirlen-1] == '/')
350 --dirlen;
351 size = dirlen + 1 + strlen(file) + 1;
352 ret = xmalloc(size);
353 memcpy(ret, dir, dirlen);
354 ret[dirlen++] = '/';
355 strcpy(ret + dirlen, file);
356 return ret;
357}
358
359int
360filename_to_int(char *name)
361{
362 char *p = strrchr(name, '/');
363 if (!p)
364 abort();
365 return atoi(p + 1);
366}
367
368void
369selidx_day(const char *dir)
370 {
371 int from_day, to_day;
372 struct tm *tm;
373 glob_t gl;
374 int glinit = 0;
375 char *dirbuf;
376 size_t dirlen;
377
378 if (index_type == index_month) {
379 selglob(dir, BINLOG_GLOB_PATTERN);
380 return;
381 }
382
383 if (timemask & FROM_TIME)
384 from_day = gmtime(&from_time)->tm_mday;
385 else {
386 glinit = matchnames(dir, "[0-9][0-9]", &gl);
387 if (glinit)
388 from_day = filename_to_int(gl.gl_pathv[0]);
389 else {
390 error("no matching files");
391 exit(1);
392 }
393 }
394
395 if (timemask & TO_TIME)
396 to_day = gmtime(&to_time)->tm_mday;
397 else {
398 if (!glinit) {
399 glinit = matchnames(dir, "[0-9][0-9]", &gl);
400 if (!glinit) {
401 error("no matching files");
402 exit(1);
403 }
404 }
405 to_day = filename_to_int(gl.gl_pathv[gl.gl_pathc - 1]);
406 }
407
408 dirlen = strlen(dir) + 4;
409 dirbuf = xmalloc(dirlen);
410 for (;from_day <= to_day; from_day++) {
411 snprintf(dirbuf, dirlen, "%s/%02d", dir, from_day);
412 selglob(dirbuf, BINLOG_GLOB_PATTERN);
413 }
414 free(dirbuf);
415 if (glinit)
416 globfree(&gl);
417}
418
419void
420selidx_month(const char *dir)
421 {
422 int from_month, to_month;
423 struct tm *tm;
424 glob_t gl;
425 int glinit = 0;
426 char *dirbuf;
427 size_t dirlen;
428
429 if (index_type == index_year) {
430 selglob(dir, BINLOG_GLOB_PATTERN);
431 return;
432 }
433
434 if (timemask & FROM_TIME)
435 from_month = 1 + gmtime(&from_time)->tm_mon;
436 else {
437 glinit = matchnames(dir, "[0-9][0-9]", &gl);
438 if (glinit)
439 from_month = filename_to_int(gl.gl_pathv[0]);
440 else {
441 error("no matching files");
442 exit(1);
443 }
444 }
445
446 if (timemask & TO_TIME)
447 to_month = 1 + gmtime(&to_time)->tm_mon;
448 else {
449 if (!glinit) {
450 glinit = matchnames(dir, "[0-9][0-9]", &gl);
451 if (!glinit) {
452 error("no matching files");
453 exit(1);
454 }
455 }
456 to_month = filename_to_int(gl.gl_pathv[gl.gl_pathc - 1]);
457 }
458
459 dirlen = strlen(dir) + 4;
460 dirbuf = xmalloc(dirlen);
461 for (;from_month <= to_month; from_month++) {
462 snprintf(dirbuf, dirlen, "%s/%02d", dir, from_month);
463 selidx_day(dirbuf);
464 }
465 free(dirbuf);
466 if (glinit)
467 globfree(&gl);
468}
469
470void
471selidx_year(const char *dir)
472{
473 int from_year, to_year;
474 struct tm *tm;
475 glob_t gl;
476 int glinit = 0;
477 char *dirbuf;
478 size_t dirlen;
479
480 if (timemask & FROM_TIME)
481 from_year = 1900 + gmtime(&from_time)->tm_year;
482 else {
483 glinit = matchnames(dir, "[0-9][0-9][0-9][0-9]", &gl);
484 if (glinit)
485 from_year = filename_to_int(gl.gl_pathv[0]);
486 else {
487 error("no matching files");
488 exit(1);
489 }
490 }
491
492 if (timemask & TO_TIME)
493 to_year = 1900 + gmtime(&to_time)->tm_year;
494 else {
495 if (!glinit) {
496 glinit = matchnames(dir, "[0-9][0-9][0-9][0-9]", &gl);
497 if (!glinit) {
498 error("no matching files");
499 exit(1);
500 }
501 }
502 to_year = filename_to_int(gl.gl_pathv[gl.gl_pathc - 1]);
503 }
504
505 dirlen = strlen(dir) + 6;
506 dirbuf = xmalloc(dirlen);
507 for (;from_year <= to_year; from_year++) {
508 snprintf(dirbuf, dirlen, "%s/%04d", dir, from_year);
509 selidx_month(dirbuf);
510 }
511 free(dirbuf);
512 if (glinit)
513 globfree(&gl);
514}
515
336int 516int
337globerrfunc (const char *epath, int eerrno) 517globerrfunc (const char *epath, int eerrno)
338{ 518{
339 error("%s: %s", strerror(eerrno)); 519 error("%s: %s", epath, strerror(eerrno));
340 return 0; 520 return 0;
341} 521}
342 522
523static int
524matchnames(const char *dir, const char *pat, glob_t *gl)
525{
526 char *p = mkfilename(dir, pat);
527 int rc = glob(p, GLOB_ERR, globerrfunc, gl);
528 free(p);
529 switch (rc) {
530 case 0:
531 break;
532 case GLOB_NOSPACE:
533 error("out of memory");
534 exit(1);
535
536 case GLOB_ABORTED:
537 error("read error");
538 exit(1);
539
540 case GLOB_NOMATCH:
541 return 0;
542 }
543 return 1;
544}
545
546
343struct logfile { 547struct logfile {
344 char *name; 548 char *name;
345 time_t start; 549 time_t start;
346}; 550};
347 551
348static int 552static int
@@ -355,19 +559,20 @@ tsort(const void *a, const void *b)
355 if (la->start < lb->start) 559 if (la->start < lb->start)
356 return -1; 560 return -1;
357 return 0; 561 return 0;
358} 562}
359 563
360void 564void
361selpattern(void) 565selglob(const char *dir, const char *pattern)
362{ 566{
363 size_t i, j; 567 size_t i, j;
364 glob_t gl; 568 glob_t gl;
365 struct logfile *logfiles; 569 struct logfile *logfiles;
570 char *p = mkfilename(dir, pattern);
366 571
367 switch (glob(pattern, GLOB_ERR|GLOB_NOSORT, globerrfunc, &gl)) { 572 switch (glob(p, GLOB_ERR|GLOB_NOSORT, globerrfunc, &gl)) {
368 case 0: 573 case 0:
369 break; 574 break;
370 case GLOB_NOSPACE: 575 case GLOB_NOSPACE:
371 error("out of memory"); 576 error("out of memory");
372 exit(1); 577 exit(1);
373 578
@@ -376,12 +581,13 @@ selpattern(void)
376 exit(1); 581 exit(1);
377 582
378 case GLOB_NOMATCH: 583 case GLOB_NOMATCH:
379 error("no files matched pattern"); 584 error("no files matched pattern");
380 exit(1); 585 exit(1);
381 } 586 }
587 free(p);
382 588
383 logfiles = xcalloc(gl.gl_pathc, sizeof(*logfiles)); 589 logfiles = xcalloc(gl.gl_pathc, sizeof(*logfiles));
384 590
385 for (i = j = 0; i < gl.gl_pathc; i++) { 591 for (i = j = 0; i < gl.gl_pathc; i++) {
386 time_t t; 592 time_t t;
387 if (checktime(gl.gl_pathv[i], &t) == 0) { 593 if (checktime(gl.gl_pathv[i], &t) == 0) {
@@ -403,16 +609,15 @@ selpattern(void)
403 609
404int 610int
405main(int argc, char **argv) 611main(int argc, char **argv)
406{ 612{
407 int c; 613 int c;
408 struct timespec ts; 614 struct timespec ts;
409 char *directory;
410 615
411 setprogname(argv[0]); 616 setprogname(argv[0]);
412 while ((c = getopt(argc, argv, "D:dF:hp:T:t:nv")) != EOF) 617 while ((c = getopt(argc, argv, "D:dF:hi:p:T:t:nv")) != EOF)
413 switch (c) { 618 switch (c) {
414 case 'D': 619 case 'D':
415 directory = optarg; 620 directory = optarg;
416 break; 621 break;
417 case 'd': 622 case 'd':
418 timediff_option = 1; 623 timediff_option = 1;
@@ -426,12 +631,19 @@ main(int argc, char **argv)
426 from_time = ts.tv_sec; 631 from_time = ts.tv_sec;
427 timemask |= FROM_TIME; 632 timemask |= FROM_TIME;
428 break; 633 break;
429 case 'h': 634 case 'h':
430 help(); 635 help();
431 return 0; 636 return 0;
637 case 'i':
638 index_type = atoi(optarg);
639 if (index_type < 0 || index_type > index_last) {
640 error("invalid index type: %s", optarg);
641 exit(1);
642 }
643 break;
432 case 'p': 644 case 'p':
433 pattern = optarg; 645 pattern = optarg;
434 break; 646 break;
435 case 'T': 647 case 'T':
436 if (!parse_datetime(&ts, optarg, NULL)) { 648 if (!parse_datetime(&ts, optarg, NULL)) {
437 error("invalid timespec: %s", optarg); 649 error("invalid timespec: %s", optarg);
@@ -454,21 +666,20 @@ main(int argc, char **argv)
454 } 666 }
455 667
456 argc -= optind; 668 argc -= optind;
457 argv += optind; 669 argv += optind;
458 670
459 if (argc) { 671 if (argc) {
460 if (pattern) { 672 if (pattern || directory) {
461 error("either files or pattern (-p) must be given, " 673 error("either files or pattern (-p) must be given, "
462 "but not both"); 674 "but not both");
463 exit(1); 675 exit(1);
464 } 676 }
465 selfilelist(argv); 677 selfilelist(argv);
678 } else if (pattern) {
679 selglob(directory, convpattern(pattern));
466 } else { 680 } else {
467 if (!pattern) 681 selidx_year(directory);
468 pattern = BINLOG_PATTERN;
469 convpattern(directory);
470 selpattern();
471 } 682 }
472 exit(0); 683 exit(0);
473} 684}
474 685
diff --git a/src/vmod-binlog.h b/src/vmod-binlog.h
index 06d517d..e39ccea 100644
--- a/src/vmod-binlog.h
+++ b/src/vmod-binlog.h
@@ -21,23 +21,39 @@
21 21
22#ifndef BINLOG_SIZE 22#ifndef BINLOG_SIZE
23# define BINLOG_SIZE (1024*1024*1024) 23# define BINLOG_SIZE (1024*1024*1024)
24#endif 24#endif
25 25
26#ifndef BINLOG_PATTERN 26#ifndef BINLOG_PATTERN
27# define BINLOG_PATTERN "%Y/%m/%d.log" 27# define BINLOG_PATTERN "%Y%m%dT%H%M%S.log"
28#endif
29
30#ifndef BINLOG_GLOB_PATTERN
31# define BINLOG_GLOB_PATTERN "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]T[0-9][0-9][0-9][0-9][0-9][0-9].log"
32#endif
33
34#ifndef BINLOG_INDEX
35# define BINLOG_INDEX "year"
28#endif 36#endif
29 37
30#ifndef BINLOG_INTERVAL 38#ifndef BINLOG_INTERVAL
31# define BINLOG_INTERVAL 86400 39# define BINLOG_INTERVAL 86400
32#endif 40#endif
33 41
34#ifndef BINLOG_UMASK 42#ifndef BINLOG_UMASK
35# define BINLOG_UMASK 0077 43# define BINLOG_UMASK 0077
36#endif 44#endif
37 45
46enum binlog_index_type {
47 index_year,
48 index_month,
49 index_day,
50
51};
52#define index_last index_day
53
38struct binlog_record { 54struct binlog_record {
39 time_t ts; /* timestamp */ 55 time_t ts; /* timestamp */
40 char data[1]; /* payload */ 56 char data[1]; /* payload */
41}; 57};
42 58
43#define BINLOG_MAGIC_STR "NXCBINLOG" 59#define BINLOG_MAGIC_STR "NXCBINLOG"

Return to:

Send suggestions and report system problems to the System administrator.