diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-05-29 12:34:28 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-05-29 12:38:57 +0300 |
commit | 35e2816614ab2a1aa585b1ae2547683a69ed9d22 (patch) | |
tree | bb7c8923c2c5ba311b9f042d7dbb3436f65ff3fa | |
parent | ac4200fa46eebfc9227130739ae7f867e3fd0a20 (diff) | |
download | vmod-binlog-35e2816614ab2a1aa585b1ae2547683a69ed9d22.tar.gz vmod-binlog-35e2816614ab2a1aa585b1ae2547683a69ed9d22.tar.bz2 |
Use per-thread environment for packet construction.
* src/binlog.c (binlog_config) <inst_cur>
<env,state,timestamp>: Remove.
(binlog_env): New struct.
(thread_once.thread_key): New statics.
(binlog_env_get,binlog_env_init): New functions.
(vmod_init): Don't create env here.
Register make_key.
(vmod_start): Use binlog_env
(vmod_pack): Likewise.
(vmod_commit): Likewise.
* src/binlogsel.c (interval_add): Update timemask if START_TIME
or STOP_TIME are set on tmask.
-rw-r--r-- | src/binlog.c | 107 | ||||
-rw-r--r-- | src/binlogsel.c | 8 |
2 files changed, 85 insertions, 30 deletions
diff --git a/src/binlog.c b/src/binlog.c index bf7fa97..4c3f40e 100644 --- a/src/binlog.c +++ b/src/binlog.c @@ -63,20 +63,22 @@ struct binlog_config { pthread_mutex_t mutex; int debug; /* debug level */ int flags; /* flags (see BLF_* defines above) */ char *format; /* data format specification */ struct packinst *inst_head; /* compiled format */ - struct packinst *inst_cur; /* current instruction */ - struct packenv *env; /* pack environment */ - enum binlog_state state; /* binlog machine state */ - time_t timestamp; /* timestamp for the entry being built */ }; -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - +struct binlog_env { + enum binlog_state state; /* binlog machine state */ + struct binlog_config *conf; + time_t timestamp; /* timestamp for the entry being built */ + struct packinst *inst_cur; /* current instruction */ + struct packenv *env; /* pack environment */ +}; + void binlog_error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsyslog(LOG_DAEMON|LOG_ERR, fmt, ap); @@ -91,12 +93,46 @@ binlog_debug(const char *fmt, ...) vsyslog(LOG_DAEMON|LOG_DEBUG, fmt, ap); va_end(ap); } #define debug(c,l,s) do { if ((c)->debug>=(l)) binlog_debug s; } while(0) +static pthread_once_t thread_once = PTHREAD_ONCE_INIT; +static pthread_key_t thread_key; +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +static struct binlog_env * +binlog_env_get(void) +{ + struct binlog_env *ep = pthread_getspecific(thread_key); + if (!ep) { + ep = malloc(sizeof(*ep)); + AN(ep); + memset(ep, 0, sizeof *ep); + ep->state = state_init; + if (pthread_setspecific(thread_key, ep)) { + binlog_error("cannot set thread-specific data"); + abort(); + } + } + return ep; +} + +void +binlog_env_init(struct binlog_env *ep, struct binlog_config *conf, time_t ts) +{ + if (!ep->env) { + ep->env = packenv_create(packsize(conf->inst_head)); + AN(ep->env); + } + packenv_init(ep->env); + ep->state = state_start; + ep->inst_cur = packinit(conf->inst_head); + ep->timestamp = ts; +} + void packerror(const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -204,12 +240,26 @@ getindexpat(const char *name) for (p = indextab; p->name; p++) if (strcmp(p->name, name) == 0) return p->pat; return NULL; } +static void +env_free(void *f) +{ + struct binlog_env *ep = f; + packenv_free(ep->env); + free(ep); +} + +static void +make_key() +{ + pthread_key_create(&thread_key, env_free); +} + void vmod_init(struct sess *sp, struct vmod_priv *priv, const char *dir, const char *format, const char *param) { struct binlog_config *conf = priv->priv; struct stat st; @@ -249,16 +299,14 @@ vmod_init(struct sess *sp, struct vmod_priv *priv, if (errno == EINVAL) binlog_error("cannot compile data format near %s", p); else binlog_error("%s", strerror(errno)); abort(); } - conf->recsize = packsize(conf->inst_head); - conf->env = packenv_create(conf->recsize); - AN(conf->env); - conf->recsize += offsetof(struct binlog_record,data); + conf->recsize = packsize(conf->inst_head) + + offsetof(struct binlog_record,data); conf->format = strdup(format); AN(conf->format); p = findparam(param, "pattern"); if (!p) { p = strdup(BINLOG_PATTERN); @@ -365,12 +413,14 @@ vmod_init(struct sess *sp, struct vmod_priv *priv, free(p); } conf->fd = -1; conf->base = NULL; conf->stoptime = time(NULL); + + pthread_once(&thread_once, make_key); pthread_mutex_init(&conf->mutex, NULL); } static char * mkfilename(struct sess *sp, struct binlog_config *conf) { @@ -639,12 +689,13 @@ closefile(struct sess *sp, struct binlog_config *conf) void vmod_start(struct sess *sp, struct vmod_priv *priv) { struct binlog_config *conf = priv->priv; time_t ts; + struct binlog_env *ep; if (!conf) return; ts = time(NULL); @@ -652,89 +703,89 @@ vmod_start(struct sess *sp, struct vmod_priv *priv) AZ(pthread_mutex_lock(&conf->mutex)); closefile(sp, conf); newfile(sp, conf); AZ(pthread_mutex_unlock(&conf->mutex)); } - packenv_init(conf->env); - conf->state = state_start; - conf->inst_cur = packinit(conf->inst_head); - conf->timestamp = ts; + ep = binlog_env_get(); + binlog_env_init(ep, conf, ts); } void vmod_pack(struct sess *sp, struct vmod_priv *priv, const char *str) { struct binlog_config *conf = priv->priv; + struct binlog_env *ep = binlog_env_get(); char *argv[2]; if (!conf) return; - switch (conf->state) { + switch (ep->state) { case state_start: case state_pack: break; default: - binlog_error("pack called in wrong state (%d)", conf->state); + binlog_error("pack called in wrong state (%d)", ep->state); return; } - if (!conf->inst_cur) { + if (!ep->inst_cur) { binlog_error("format spec exhausted"); return; } argv[0] = (char*) str; argv[1] = NULL; - conf->env->argv = argv; - conf->env->argc = 2; - conf->env->argi = 0; + ep->env->argv = argv; + ep->env->argc = 2; + ep->env->argi = 0; - conf->inst_cur = packinnext(conf->inst_cur, conf->env); + ep->inst_cur = packinnext(ep->inst_cur, ep->env); - conf->state = state_pack; + ep->state = state_pack; } void vmod_commit(struct sess *sp, struct vmod_priv *priv) { struct binlog_config *conf = priv->priv; + struct binlog_env *ep = binlog_env_get(); if (!conf) return; if (conf->fd == -1) return; - switch (conf->state) { + switch (ep->state) { case state_start: binlog_error("committing empty binlog record"); break; case state_pack: - if (conf->inst_cur) + if (ep->inst_cur) binlog_error("committing incomplete binlog record"); break; default: - binlog_error("pack called in wrong state (%d)", conf->state); + binlog_error("pack called in wrong state (%d)", ep->state); return; } AZ(pthread_mutex_lock(&conf->mutex)); if (conf->base->recnum == conf->recnum) { binlog_error("overflow of %s/%s", conf->dir, conf->fname); } else { struct binlog_record *p = (struct binlog_record *)(conf->recbase + conf->base->recnum * conf->recsize); - p->ts = conf->timestamp; - memcpy(p->data, conf->env->buf_base, conf->env->buf_size); + p->ts = ep->timestamp; + memcpy(p->data, ep->env->buf_base, ep->env->buf_size); conf->base->recnum++; } AZ(pthread_mutex_unlock(&conf->mutex)); - conf->state = state_init; + ep->state = state_init; } void vmod_sync(struct sess *sp, struct vmod_priv *priv) { struct binlog_config *conf = priv->priv; diff --git a/src/binlogsel.c b/src/binlogsel.c index 80f5b83..fad0881 100644 --- a/src/binlogsel.c +++ b/src/binlogsel.c @@ -89,20 +89,24 @@ interval_add(const char *name, int tmask, time_t start, time_t end) interval_tail->next = p; else interval_head = p; interval_tail = p; if (tmask & START_TIME) { - if (!(timemask & START_TIME) || start_time > start) + if (!(timemask & START_TIME) || start_time > start) { start_time = start; + timemask |= START_TIME; + } } else timemask |= CLEAR_START_TIME; if (tmask & STOP_TIME) { - if (!(timemask & STOP_TIME) || to_time < end) + if (!(timemask & STOP_TIME) || to_time < end) { to_time = end; + timemask |= STOP_TIME; + } } else timemask |= CLEAR_STOP_TIME; } void interval_add_str(const char *id, const char *from, const char *to) |