aboutsummaryrefslogtreecommitdiff
path: root/src/binlogsel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/binlogsel.c')
-rw-r--r--src/binlogsel.c202
1 files changed, 183 insertions, 19 deletions
diff --git a/src/binlogsel.c b/src/binlogsel.c
index 5238215..10630e6 100644
--- a/src/binlogsel.c
+++ b/src/binlogsel.c
@@ -28,6 +28,7 @@
#include <time.h>
#include <string.h>
#include <glob.h>
+#include <ltdl.h>
#include "vmod-binlog.h"
#include "pack.h"
#include "err.h"
@@ -42,6 +43,14 @@ char *directory;
char *pattern;
enum binlog_index_type index_type = index_year;
+char *module_name;
+char *module_args;
+void (*module_init)(char *, void (*)(const char *, const char *, const char *));
+int (*module_open)(const char *, size_t, const char *);
+void (*module_close)(void);
+void (*module_done)(void);
+void (*module_record)(const char *, time_t, void *);
+
/* Time mask flags indicate which timestamp is set. */
#define START_TIME 0x01 /* start time is set */
#define STOP_TIME 0x02 /* stop time is set */
@@ -96,22 +105,65 @@ interval_add(const char *name, int tmask, time_t start, time_t end)
}
void
+interval_add_str(const char *id, const char *from, const char *to)
+{
+ struct timespec ts;
+ time_t start, end;
+ int tmask = 0;
+
+ if (from) {
+ if (!parse_datetime(&ts, from, NULL)) {
+ error("invalid timespec: %s", from);
+ exit(1);
+ }
+ start = ts.tv_sec;
+ tmask |= START_TIME;
+ }
+
+ if (to) {
+ if (!parse_datetime(&ts, to, NULL)) {
+ error("invalid timespec: %s", to);
+ exit(1);
+ }
+ end = ts.tv_sec;
+ tmask |= STOP_TIME;
+ }
+
+ if (tmask)
+ interval_add(id, tmask, start, end);
+}
+
+
+void
help()
{
- printf("usage: %s [-dhnVv] [-t FORMAT] [-F TIME] [-T TIME] [-p PATTERN] [-D DIR] [-i 0|1|2] [FILE...]\n", progname);
+ printf("usage: %s [OPTIONS] [FILE...]\n", progname);
printf("Select records from binary logs\n");
- printf("\nOptions are:\n\n");
+ printf("\nOPTIONS are:\n\n");
+ printf("File selection:\n");
printf(" -D DIR log file storage directory\n");
printf(" -i 0|1|2 select directory indexing level\n");
+ printf(" -p PATTERN select files matching PATTERN\n");
+ printf("\n");
+ printf("Time intervals:\n");
+ printf(" -I TAG set tag for the subsequent -F and -T option pair\n");
printf(" -F TIME print records starting from TIME\n");
printf(" -T TIME print records starting up to TIME\n");
- printf(" -p PATTERN select files matching PATTERN\n");
printf("\n");
+ printf("Loadable module control\n");
+ printf(" -L DIR append DIR to the loadable module search path\n");
+ printf(" -P DIR add DIR to the loadable module search path before\n");
+ printf(" the default module directory\n");
+ printf(" -m 'MODULE[ ARGS]'\n");
+ printf(" load given MODULE\n");
+ printf("\n");
+ printf("Output control:\n");
printf(" -d print timestamps relative to first record in the file\n");
printf(" -n output record numbers\n");
printf(" -v print information about each file\n");
printf(" -t FMT format timestamps according to FMT\n");
printf("\n");
+ printf("Informational options:\n");
printf(" -h print this help summary\n");
printf(" -V show program version\n");
printf("\n");
@@ -208,6 +260,7 @@ selmem(const char *name, void *base)
char timebuf[128];
char *format;
struct interval *ip;
+ size_t datasize;
hdr = base;
@@ -228,6 +281,13 @@ selmem(const char *name, void *base)
name, format, (unsigned long) hdr->recsize,
(unsigned long) hdr->recnum);
+ datasize = hdr->recsize - offsetof(struct binlog_record,data);
+
+ if (module_open && module_open(name, datasize, format)) {
+ error("%s: rejected by module %s", name, module_name);
+ return;
+ }
+
inst = packcomp(format, &p);
if (!inst) {
if (errno == EINVAL) {
@@ -240,8 +300,7 @@ selmem(const char *name, void *base)
return;
}
- env = packenv_create(hdr->recsize -
- offsetof(struct binlog_record,data));
+ env = packenv_create(datasize);
env->fp = stdout;
base = (char*)base + hdr->hdrsize;
@@ -286,18 +345,25 @@ selmem(const char *name, void *base)
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);
+ if (module_record)
+ module_record(ip->name, rec->ts, env->buf_base);
+ else {
+ 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);
+ }
}
}
+
+ if (module_close)
+ module_close();
}
static int
@@ -679,6 +745,78 @@ selglob(const char *dir, const char *pattern)
globfree(&gl);
}
+#define LP_PREPEND 0
+#define LP_APPEND 1
+
+struct libdir {
+ struct libdir *next;
+ struct libdir *prev;
+ const char *dir;
+};
+
+struct libdir *libdir_head, *libdir_mid, *libdir_tail;
+
+void
+add_load_path(const char *dir, int where)
+{
+ struct libdir *ld = xmalloc(sizeof(ld[0]));
+ ld->dir = dir;
+ if (!libdir_mid) {
+ ld->next = ld->prev = NULL;
+ libdir_mid = libdir_head = libdir_tail = ld;
+ } else if (where == LP_PREPEND) {
+ ld->next = libdir_mid;
+ ld->prev = libdir_mid->prev;
+ if (ld->prev)
+ ld->prev->next = libdir_mid;
+ else
+ libdir_head = ld;
+ libdir_mid->prev = ld;
+ } else /* if (where == LT_APPEND) */ {
+ ld->next = NULL;
+ ld->prev = libdir_tail;
+ libdir_tail->next = ld;
+ libdir_tail = ld;
+ }
+}
+
+void
+loader_init(void)
+{
+ struct libdir *ld;
+ lt_dlhandle handle = NULL;
+ lt_dladvise advise = NULL;
+
+ if (!module_name)
+ return;
+
+ lt_dlinit();
+ for (ld = libdir_head; ld; ld = ld->next)
+ lt_dladdsearchdir(ld->dir);
+
+ if (!lt_dladvise_init(&advise) && !lt_dladvise_ext(&advise)
+ && !lt_dladvise_global(&advise))
+ handle = lt_dlopenadvise(module_name, advise);
+ lt_dladvise_destroy(&advise);
+
+ if (!handle) {
+ error("cannot load module %s: %s", module_name,
+ lt_dlerror());
+ exit(1);
+ }
+
+ module_record = lt_dlsym(handle, "record");
+ if (!module_record) {
+ error("%s: faulty module: function record() not defined",
+ module_name);
+ exit(1);
+ }
+ module_init = lt_dlsym(handle, "init");
+ module_open = lt_dlsym(handle, "open");
+ module_close = lt_dlsym(handle, "close");
+ module_done = lt_dlsym(handle, "done");
+}
+
int
main(int argc, char **argv)
{
@@ -687,9 +825,11 @@ main(int argc, char **argv)
const char *id;
int tmask = 0;
time_t start, stop;
+ char *p;
setprogname(argv[0]);
- while ((c = getopt(argc, argv, "D:dF:hi:I:p:T:t:nV")) != EOF)
+ add_load_path(BINLOGSEL_MODDIR, LP_APPEND);
+ while ((c = getopt(argc, argv, "D:dF:hi:I:L:m:p:P:T:t:nV")) != EOF)
switch (c) {
case 'D':
directory = optarg;
@@ -722,6 +862,23 @@ main(int argc, char **argv)
exit(1);
}
break;
+ case 'L':
+ add_load_path(optarg, LP_APPEND);
+ break;
+ case 'm':
+ p = strchr(optarg, ' ');
+ if (p) {
+ *p++ = 0;
+ while (*p == ' ')
+ p++;
+ if (*p)
+ module_args = p;
+ }
+ module_name = optarg;
+ break;
+ case 'P':
+ add_load_path(optarg, LP_PREPEND);
+ break;
case 'p':
pattern = optarg;
break;
@@ -752,13 +909,18 @@ main(int argc, char **argv)
if (tmask)
interval_add(id, tmask, start, stop);
+ argc -= optind;
+ argv += optind;
+
+ loader_init();
+
+ if (module_init)
+ module_init(module_args, interval_add_str);
+
if (timemask & CLEAR_START_TIME)
timemask &= ~START_TIME;
if (timemask & CLEAR_STOP_TIME)
timemask &= ~STOP_TIME;
-
- argc -= optind;
- argv += optind;
if (argc) {
if (pattern) {
@@ -772,6 +934,8 @@ main(int argc, char **argv)
} else {
selidx_year(directory);
}
+ if (module_done)
+ module_done();
exit(0);
}

Return to:

Send suggestions and report system problems to the System administrator.