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 /src/binlogsel.c | |
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.
Diffstat (limited to 'src/binlogsel.c')
-rw-r--r-- | src/binlogsel.c | 245 |
1 files changed, 228 insertions, 17 deletions
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 @@ #include "parse-datetime.h" char *timefmt = "%c"; int number_option; int verbose_option; int timediff_option; +char *directory; char *pattern; +enum binlog_index_type index_type = index_year; #define FROM_TIME 0x01 #define TO_TIME 0x02 int timemask; time_t from_time, to_time; +static int matchnames(const char *dir, const char *pat, glob_t *gl); +void selglob(const char *dir, const char *pattern); + void help() { printf("usage: %s [-dhnv] [-t FORMAT] [-F FROMTIME] [-T TOTIME] [-p PATTERN] [-D DIR] [FILE...]\n", progname); } - + /* Convert strftime-like pattern into globbing pattern */ -void +char * convpattern(const char *dir) { char *p, *q; char *newpat; size_t size = strlen(pattern) + 1; @@ -70,19 +75,20 @@ convpattern(const char *dir) p += strlen(dir); *p++ = '/'; } for (q = pattern; *q; ) { if (*q == '%') { - *p++ = '*'; + if (p > newpat && p[-1] != '*') + *p++ = '*'; q += 2; } else *p++ = *q++; } *p = 0; - pattern = newpat; + return newpat; } #define getrec(base, recsize, n) \ ((struct binlog_record*)((char *)(base) + (n) * (recsize))) int @@ -329,20 +335,218 @@ selfile(char *name) void selfilelist(char **argv) { for (;*argv;++argv) selfile(*argv); } + +static char * +mkfilename(const char *dir, const char *file) +{ + size_t dirlen, size; + char *ret; + + dirlen = strlen(dir); + while (dirlen > 0 && dir[dirlen-1] == '/') + --dirlen; + size = dirlen + 1 + strlen(file) + 1; + ret = xmalloc(size); + memcpy(ret, dir, dirlen); + ret[dirlen++] = '/'; + strcpy(ret + dirlen, file); + return ret; +} + +int +filename_to_int(char *name) +{ + char *p = strrchr(name, '/'); + if (!p) + abort(); + return atoi(p + 1); +} + +void +selidx_day(const char *dir) +{ + int from_day, to_day; + struct tm *tm; + glob_t gl; + int glinit = 0; + char *dirbuf; + size_t dirlen; + + if (index_type == index_month) { + selglob(dir, BINLOG_GLOB_PATTERN); + return; + } + + if (timemask & FROM_TIME) + from_day = gmtime(&from_time)->tm_mday; + else { + glinit = matchnames(dir, "[0-9][0-9]", &gl); + if (glinit) + from_day = filename_to_int(gl.gl_pathv[0]); + else { + error("no matching files"); + exit(1); + } + } + + if (timemask & TO_TIME) + to_day = gmtime(&to_time)->tm_mday; + else { + if (!glinit) { + glinit = matchnames(dir, "[0-9][0-9]", &gl); + if (!glinit) { + error("no matching files"); + exit(1); + } + } + to_day = filename_to_int(gl.gl_pathv[gl.gl_pathc - 1]); + } + + dirlen = strlen(dir) + 4; + dirbuf = xmalloc(dirlen); + for (;from_day <= to_day; from_day++) { + snprintf(dirbuf, dirlen, "%s/%02d", dir, from_day); + selglob(dirbuf, BINLOG_GLOB_PATTERN); + } + free(dirbuf); + if (glinit) + globfree(&gl); +} + +void +selidx_month(const char *dir) +{ + int from_month, to_month; + struct tm *tm; + glob_t gl; + int glinit = 0; + char *dirbuf; + size_t dirlen; + + if (index_type == index_year) { + selglob(dir, BINLOG_GLOB_PATTERN); + return; + } + + if (timemask & FROM_TIME) + from_month = 1 + gmtime(&from_time)->tm_mon; + else { + glinit = matchnames(dir, "[0-9][0-9]", &gl); + if (glinit) + from_month = filename_to_int(gl.gl_pathv[0]); + else { + error("no matching files"); + exit(1); + } + } + + if (timemask & TO_TIME) + to_month = 1 + gmtime(&to_time)->tm_mon; + else { + if (!glinit) { + glinit = matchnames(dir, "[0-9][0-9]", &gl); + if (!glinit) { + error("no matching files"); + exit(1); + } + } + to_month = filename_to_int(gl.gl_pathv[gl.gl_pathc - 1]); + } + + dirlen = strlen(dir) + 4; + dirbuf = xmalloc(dirlen); + for (;from_month <= to_month; from_month++) { + snprintf(dirbuf, dirlen, "%s/%02d", dir, from_month); + selidx_day(dirbuf); + } + free(dirbuf); + if (glinit) + globfree(&gl); +} + +void +selidx_year(const char *dir) +{ + int from_year, to_year; + struct tm *tm; + glob_t gl; + int glinit = 0; + char *dirbuf; + size_t dirlen; + + if (timemask & FROM_TIME) + from_year = 1900 + gmtime(&from_time)->tm_year; + else { + glinit = matchnames(dir, "[0-9][0-9][0-9][0-9]", &gl); + if (glinit) + from_year = filename_to_int(gl.gl_pathv[0]); + else { + error("no matching files"); + exit(1); + } + } + if (timemask & TO_TIME) + to_year = 1900 + gmtime(&to_time)->tm_year; + else { + if (!glinit) { + glinit = matchnames(dir, "[0-9][0-9][0-9][0-9]", &gl); + if (!glinit) { + error("no matching files"); + exit(1); + } + } + to_year = filename_to_int(gl.gl_pathv[gl.gl_pathc - 1]); + } + + dirlen = strlen(dir) + 6; + dirbuf = xmalloc(dirlen); + for (;from_year <= to_year; from_year++) { + snprintf(dirbuf, dirlen, "%s/%04d", dir, from_year); + selidx_month(dirbuf); + } + free(dirbuf); + if (glinit) + globfree(&gl); +} + int globerrfunc (const char *epath, int eerrno) { - error("%s: %s", strerror(eerrno)); + error("%s: %s", epath, strerror(eerrno)); return 0; } +static int +matchnames(const char *dir, const char *pat, glob_t *gl) +{ + char *p = mkfilename(dir, pat); + int rc = glob(p, GLOB_ERR, globerrfunc, gl); + free(p); + switch (rc) { + case 0: + break; + case GLOB_NOSPACE: + error("out of memory"); + exit(1); + + case GLOB_ABORTED: + error("read error"); + exit(1); + + case GLOB_NOMATCH: + return 0; + } + return 1; +} + + struct logfile { char *name; time_t start; }; static int @@ -355,19 +559,20 @@ tsort(const void *a, const void *b) if (la->start < lb->start) return -1; return 0; } void -selpattern(void) +selglob(const char *dir, const char *pattern) { size_t i, j; glob_t gl; struct logfile *logfiles; - - switch (glob(pattern, GLOB_ERR|GLOB_NOSORT, globerrfunc, &gl)) { + char *p = mkfilename(dir, pattern); + + switch (glob(p, GLOB_ERR|GLOB_NOSORT, globerrfunc, &gl)) { case 0: break; case GLOB_NOSPACE: error("out of memory"); exit(1); @@ -376,13 +581,14 @@ selpattern(void) exit(1); case GLOB_NOMATCH: error("no files matched pattern"); exit(1); } - + free(p); + logfiles = xcalloc(gl.gl_pathc, sizeof(*logfiles)); for (i = j = 0; i < gl.gl_pathc; i++) { time_t t; if (checktime(gl.gl_pathv[i], &t) == 0) { logfiles[j].name = gl.gl_pathv[i]; @@ -397,22 +603,21 @@ selpattern(void) for (i = 0; i < j; i++) selfile(logfiles[i].name); free(logfiles); globfree(&gl); } - + int main(int argc, char **argv) { int c; struct timespec ts; - char *directory; setprogname(argv[0]); - while ((c = getopt(argc, argv, "D:dF:hp:T:t:nv")) != EOF) + while ((c = getopt(argc, argv, "D:dF:hi:p:T:t:nv")) != EOF) switch (c) { case 'D': directory = optarg; break; case 'd': timediff_option = 1; @@ -426,12 +631,19 @@ main(int argc, char **argv) from_time = ts.tv_sec; timemask |= FROM_TIME; break; case 'h': help(); return 0; + case 'i': + index_type = atoi(optarg); + if (index_type < 0 || index_type > index_last) { + error("invalid index type: %s", optarg); + exit(1); + } + break; case 'p': pattern = optarg; break; case 'T': if (!parse_datetime(&ts, optarg, NULL)) { error("invalid timespec: %s", optarg); @@ -454,21 +666,20 @@ main(int argc, char **argv) } argc -= optind; argv += optind; if (argc) { - if (pattern) { + if (pattern || directory) { error("either files or pattern (-p) must be given, " "but not both"); exit(1); } selfilelist(argv); + } else if (pattern) { + selglob(directory, convpattern(pattern)); } else { - if (!pattern) - pattern = BINLOG_PATTERN; - convpattern(directory); - selpattern(); + selidx_year(directory); } exit(0); } |