diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-10-17 10:21:56 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-10-17 10:21:56 +0300 |
commit | aad0ead6ae1bb56953642eac584d9a5f1dc6d72e (patch) | |
tree | fb943138c9612c0036860e9991420a1ea5433c05 | |
parent | 57d1cbccf5bfb96831501519825e462580b0affe (diff) | |
download | vmod-binlog-aad0ead6ae1bb56953642eac584d9a5f1dc6d72e.tar.gz vmod-binlog-aad0ead6ae1bb56953642eac584d9a5f1dc6d72e.tar.bz2 |
Add multiple interval support to binlogsel.
* src/binlogsel.c (FROM_TIME,TO_TIME): Rename to
START_TIME, STOP_TIME.
(from_time,to_time): Rename to start_time,to_time.
(CLEAR_START_TIME,CLEAR_STOP_TIME): New macros.
(interval): New struct.
(interval_head, interval_tail): New variables.
(interval_add): New function.
(selmem): Iterate over available intervals and output records for
those that match the time limits.
(main): New option -I.
Build interval list from multiple -I,-F,-T options.
-rw-r--r-- | src/binlogsel.c | 138 |
1 files changed, 105 insertions, 33 deletions
diff --git a/src/binlogsel.c b/src/binlogsel.c index 550724c..5238215 100644 --- a/src/binlogsel.c +++ b/src/binlogsel.c @@ -42,14 +42,59 @@ char *directory; char *pattern; enum binlog_index_type index_type = index_year; -#define FROM_TIME 0x01 -#define TO_TIME 0x02 +/* Time mask flags indicate which timestamp is set. */ +#define START_TIME 0x01 /* start time is set */ +#define STOP_TIME 0x02 /* stop time is set */ +/* The two flags below are valid only for global timemask. They + are set when building interval list and are then used in main to + reset the START_TIME and STOP_TIME bits. */ +#define CLEAR_START_TIME 0x04 /* Reset start time */ +#define CLEAR_STOP_TIME 0x08 /* Reset stop time */ + int timemask; -time_t from_time, to_time; +time_t start_time, to_time; static int matchnames(const char *dir, const char *pat, glob_t *gl); void selglob(const char *dir, const char *pattern); +struct interval { + struct interval *next; + const char *name; + int timemask; + time_t start; + time_t end; +}; + +static struct interval *interval_head, *interval_tail; + +void +interval_add(const char *name, int tmask, time_t start, time_t end) +{ + struct interval *p = xmalloc(sizeof(*p)); + p->next = NULL; + p->name = name; + p->timemask = tmask; + p->start = start; + p->end = end; + if (interval_tail) + interval_tail->next = p; + else + interval_head = p; + interval_tail = p; + + if (tmask & START_TIME) { + if (!(timemask & START_TIME) || start_time > start) + start_time = start; + } else + timemask |= CLEAR_START_TIME; + + if (tmask & STOP_TIME) { + if (!(timemask & STOP_TIME) || to_time < end) + to_time = end; + } else + timemask |= CLEAR_STOP_TIME; +} + void help() { @@ -162,6 +207,7 @@ selmem(const char *name, void *base) time_t start_ts; char timebuf[128]; char *format; + struct interval *ip; hdr = base; @@ -200,20 +246,20 @@ selmem(const char *name, void *base) base = (char*)base + hdr->hdrsize; - if (timemask & FROM_TIME) { + if (timemask & START_TIME) { switch (searchts(base, hdr->recsize, 0, hdr->recnum - 1, - from_time, &start)) { + start_time, &start)) { case 0: break; case -1: for (; start < hdr->recnum; start++) { - if (getrec(base, hdr->recsize, start)->ts > from_time) + if (getrec(base, hdr->recsize, start)->ts > start_time) break; } break; case 1: for (; start + 1 >= 0; start--) { - if (from_time < getrec(base, hdr->recsize, start)->ts) + if (start_time < getrec(base, hdr->recsize, start)->ts) break; } ++start; @@ -224,7 +270,7 @@ selmem(const char *name, void *base) for (i = 0; start < hdr->recnum; i++, start++) { rec = getrec(base, hdr->recsize, start); - if ((timemask & TO_TIME) && rec->ts > to_time) + if ((timemask & STOP_TIME) && rec->ts > to_time) break; if (timediff_option) { @@ -234,14 +280,23 @@ selmem(const char *name, void *base) } strftime(timebuf, sizeof timebuf, timefmt, localtime(&rec->ts)); - if (number_option) - printf("%lu ", (unsigned long) start); - printf("%s ", timebuf); memcpy(env->buf_base, rec->data, env->buf_size); - env->buf_pos = 0; - - packout(inst, env); - fputc('\n', stdout); + for (ip = interval_head; ip; ip = ip->next) { + if ((ip->timemask & START_TIME) && ip->start > rec->ts) + continue; + if ((ip->timemask & STOP_TIME) && ip->end < rec->ts) + continue; + if (ip->name) + printf("%s ", ip->name); + else if (ip == interval_head && ip->next) + printf("default "); + if (number_option) + printf("%lu ", (unsigned long) start); + printf("%s ", timebuf); + env->buf_pos = 0; + packout(inst, env); + fputc('\n', stdout); + } } } @@ -291,15 +346,15 @@ fchecktime(FILE *fp, const char *fname, time_t *ts) } end = rec.ts; - if ((timemask & TO_TIME) && header.recnum > 1) { + if ((timemask & STOP_TIME) && header.recnum > 1) { if (to_time < start) return 1; - if (timemask & FROM_TIME) { - if (from_time > end) + if (timemask & START_TIME) { + if (start_time > end) return 1; } - } else if ((timemask & FROM_TIME) && from_time > end) + } else if ((timemask & START_TIME) && start_time > end) return 1; *ts = start; @@ -399,8 +454,8 @@ selidx_day(const char *dir) return; } - if (timemask & FROM_TIME) - from_day = gmtime(&from_time)->tm_mday; + if (timemask & START_TIME) + from_day = gmtime(&start_time)->tm_mday; else { glinit = matchnames(dir, "[0-9][0-9]", &gl); if (glinit) @@ -411,7 +466,7 @@ selidx_day(const char *dir) } } - if (timemask & TO_TIME) + if (timemask & STOP_TIME) to_day = gmtime(&to_time)->tm_mday; else { if (!glinit) { @@ -449,8 +504,8 @@ selidx_month(const char *dir) return; } - if (timemask & FROM_TIME) - from_month = 1 + gmtime(&from_time)->tm_mon; + if (timemask & START_TIME) + from_month = 1 + gmtime(&start_time)->tm_mon; else { glinit = matchnames(dir, "[0-9][0-9]", &gl); if (glinit) @@ -461,7 +516,7 @@ selidx_month(const char *dir) } } - if (timemask & TO_TIME) + if (timemask & STOP_TIME) to_month = 1 + gmtime(&to_time)->tm_mon; else { if (!glinit) { @@ -494,8 +549,8 @@ selidx_year(const char *dir) char *dirbuf; size_t dirlen; - if (timemask & FROM_TIME) - from_year = 1900 + gmtime(&from_time)->tm_year; + if (timemask & START_TIME) + from_year = 1900 + gmtime(&start_time)->tm_year; else { glinit = matchnames(dir, "[0-9][0-9][0-9][0-9]", &gl); if (glinit) @@ -506,7 +561,7 @@ selidx_year(const char *dir) } } - if (timemask & TO_TIME) + if (timemask & STOP_TIME) to_year = 1900 + gmtime(&to_time)->tm_year; else { if (!glinit) { @@ -629,9 +684,12 @@ main(int argc, char **argv) { int c; struct timespec ts; + const char *id; + int tmask = 0; + time_t start, stop; setprogname(argv[0]); - while ((c = getopt(argc, argv, "D:dF:hi:p:T:t:nV")) != EOF) + while ((c = getopt(argc, argv, "D:dF:hi:I:p:T:t:nV")) != EOF) switch (c) { case 'D': directory = optarg; @@ -645,12 +703,18 @@ main(int argc, char **argv) error("invalid timespec: %s", optarg); exit(1); } - from_time = ts.tv_sec; - timemask |= FROM_TIME; + start = ts.tv_sec; + tmask |= START_TIME; break; case 'h': help(); return 0; + case 'I': + if (tmask) + interval_add(id, tmask, start, stop); + tmask = 0; + id = optarg; + break; case 'i': index_type = atoi(optarg); if (index_type < 0 || index_type > index_last) { @@ -666,8 +730,8 @@ main(int argc, char **argv) error("invalid timespec: %s", optarg); exit(1); } - to_time = ts.tv_sec; - timemask |= TO_TIME; + stop = ts.tv_sec; + tmask |= STOP_TIME; break; case 't': timefmt = optarg; @@ -685,6 +749,14 @@ main(int argc, char **argv) exit(1); } + if (tmask) + interval_add(id, tmask, start, stop); + + if (timemask & CLEAR_START_TIME) + timemask &= ~START_TIME; + if (timemask & CLEAR_STOP_TIME) + timemask &= ~STOP_TIME; + argc -= optind; argv += optind; |