aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2014-05-29 12:34:28 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2014-05-29 12:38:57 +0300
commit35e2816614ab2a1aa585b1ae2547683a69ed9d22 (patch)
treebb7c8923c2c5ba311b9f042d7dbb3436f65ff3fa
parentac4200fa46eebfc9227130739ae7f867e3fd0a20 (diff)
downloadvmod-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.c107
-rw-r--r--src/binlogsel.c8
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)

Return to:

Send suggestions and report system problems to the System administrator.