From 27835dc50e5d277b30decbf553f25f4df19f7555 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 22 Jan 2013 09:17:54 -0500 Subject: [PATCH] split cookie cache keeping into separate file --- daemon/cookie_cache.c | 80 +++++++++++++++++++++++++++++++++++++++++++ daemon/cookie_cache.h | 25 ++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 daemon/cookie_cache.c create mode 100644 daemon/cookie_cache.h diff --git a/daemon/cookie_cache.c b/daemon/cookie_cache.c new file mode 100644 index 000000000..3d5f3da40 --- /dev/null +++ b/daemon/cookie_cache.c @@ -0,0 +1,80 @@ +#include +#include +#include "cookie_cache.h" +#include "aux.h" +#include "poller.h" + +static const char *cookie_in_use = "MAGIC"; + +static inline void cookie_cache_state_init(struct cookie_cache_state *s) { + s->cookies = g_hash_table_new(g_str_hash, g_str_equal); + s->chunks = g_string_chunk_new(4 * 1024); +} + +void cookie_cache_init(struct cookie_cache *c) { + cookie_cache_state_init(&c->current); + cookie_cache_state_init(&c->old); + c->swap_time = poller_now; + mutex_init(&c->lock); + cond_init(&c->cond); +} + +/* lock must be held */ +static void __cookie_cache_check_swap(struct cookie_cache *c) { + if (poller_now - c->swap_time >= 30) { + g_hash_table_remove_all(c->old.cookies); +#if GLIB_CHECK_VERSION(2,14,0) + g_string_chunk_clear(c->old.chunks); + swap_ptrs(&c->old.chunks, &c->current.chunks); +#else + g_string_chunk_free(c->old.chunks); + c->old.chunks = c->current.chunks; + c->current.chunks = g_string_chunk_new(4 * 1024); +#endif + swap_ptrs(&c->old.cookies, &c->current.cookies); + c->swap_time = poller_now; + } +} + +char *cookie_cache_lookup(struct cookie_cache *c, const char *s) { + char *ret; + + mutex_lock(&c->lock); + + __cookie_cache_check_swap(c); + +restart: + /* XXX better hashing */ + ret = g_hash_table_lookup(c->current.cookies, s); + if (!ret) + ret = g_hash_table_lookup(c->old.cookies, s); + if (ret) { + if (ret == cookie_in_use) { + /* another thread is working on this right now */ + cond_wait(&c->cond, &c->lock); + goto restart; + } + mutex_unlock(&c->lock); + return ret; + } + g_hash_table_replace(c->current.cookies, (void *) s, (void *) cookie_in_use); + mutex_unlock(&c->lock); + return NULL; +} + +void cookie_cache_insert(struct cookie_cache *c, const char *s, const char *r, int len) { + mutex_lock(&c->lock); + g_hash_table_replace(c->current.cookies, g_string_chunk_insert(c->current.chunks, s), + g_string_chunk_insert_len(c->current.chunks, r, (len >= 0) ? len : strlen(r))); + g_hash_table_remove(c->old.cookies, s); + cond_broadcast(&c->cond); + mutex_unlock(&c->lock); +} + +void cookie_cache_remove(struct cookie_cache *c, const char *s) { + mutex_lock(&c->lock); + g_hash_table_remove(c->current.cookies, s); + g_hash_table_remove(c->old.cookies, s); + cond_broadcast(&c->cond); + mutex_unlock(&c->lock); +} diff --git a/daemon/cookie_cache.h b/daemon/cookie_cache.h new file mode 100644 index 000000000..aa1b8d902 --- /dev/null +++ b/daemon/cookie_cache.h @@ -0,0 +1,25 @@ +#ifndef _COOKIE_CACHE_H_ +#define _COOKIE_CACHE_H_ + +#include +#include +#include "aux.h" + +struct cookie_cache_state { + GHashTable *cookies; + GStringChunk *chunks; +}; + +struct cookie_cache { + mutex_t lock; + cond_t cond; + struct cookie_cache_state current, old; + time_t swap_time; +}; + +void cookie_cache_init(struct cookie_cache *); +char *cookie_cache_lookup(struct cookie_cache *, const char *); +void cookie_cache_insert(struct cookie_cache *, const char *, const char *, int); +void cookie_cache_remove(struct cookie_cache *, const char *); + +#endif