diff --git a/daemon/cookie_cache.c b/daemon/cookie_cache.c index 1a7aa4d22..4fdbb26e3 100644 --- a/daemon/cookie_cache.c +++ b/daemon/cookie_cache.c @@ -8,11 +8,13 @@ #include "poller.h" #include "str.h" -static const char *cookie_in_use = "MAGIC"; - INLINE void cookie_cache_state_init(struct cookie_cache_state *s) { - s->cookies = g_hash_table_new(str_hash, str_equal); - s->chunks = g_string_chunk_new(4 * 1024); + s->in_use = g_hash_table_new(str_hash, str_equal); + s->cookies = g_hash_table_new_full(str_hash, str_equal, free, free); +} +INLINE void cookie_cache_state_cleanup(struct cookie_cache_state *s) { + g_hash_table_destroy(s->cookies); + g_hash_table_destroy(s->in_use); } void cookie_cache_init(struct cookie_cache *c) { @@ -27,8 +29,6 @@ void cookie_cache_init(struct cookie_cache *c) { static void __cookie_cache_check_swap(struct cookie_cache *c) { if (rtpe_now.tv_sec - c->swap_time >= 30) { g_hash_table_remove_all(c->old.cookies); - g_string_chunk_clear(c->old.chunks); - swap_ptrs(&c->old.chunks, &c->current.chunks); swap_ptrs(&c->old.cookies, &c->current.cookies); c->swap_time = rtpe_now.tv_sec; } @@ -46,24 +46,32 @@ restart: if (!ret) ret = g_hash_table_lookup(c->old.cookies, s); if (ret) { - if (ret == (void *) cookie_in_use) { - /* another thread is working on this right now */ - cond_wait(&c->cond, &c->lock); - goto restart; - } ret = str_dup(ret); mutex_unlock(&c->lock); return ret; } - g_hash_table_replace(c->current.cookies, (void *) s, (void *) cookie_in_use); + + // is it being worked on right now by another thread? + void *p = g_hash_table_lookup(c->current.in_use, s); + if (!p) + p = g_hash_table_lookup(c->old.in_use, s); + if (p) { + cond_wait(&c->cond, &c->lock); + goto restart; + } + + // caller is required to call cookie_cache_insert or cookie_cache_remove + // before `s` runs out of scope + g_hash_table_replace(c->current.in_use, (void *) s, (void *) 0x1); mutex_unlock(&c->lock); return NULL; } void cookie_cache_insert(struct cookie_cache *c, const str *s, const str *r) { mutex_lock(&c->lock); - g_hash_table_replace(c->current.cookies, str_chunk_insert(c->current.chunks, s), - str_chunk_insert(c->current.chunks, r)); + g_hash_table_remove(c->current.in_use, s); + g_hash_table_remove(c->old.in_use, s); + g_hash_table_replace(c->current.cookies, str_dup(s), str_dup(r)); g_hash_table_remove(c->old.cookies, s); cond_broadcast(&c->cond); mutex_unlock(&c->lock); @@ -71,6 +79,8 @@ void cookie_cache_insert(struct cookie_cache *c, const str *s, const str *r) { void cookie_cache_remove(struct cookie_cache *c, const str *s) { mutex_lock(&c->lock); + g_hash_table_remove(c->current.in_use, s); + g_hash_table_remove(c->old.in_use, s); g_hash_table_remove(c->current.cookies, s); g_hash_table_remove(c->old.cookies, s); cond_broadcast(&c->cond); @@ -78,8 +88,6 @@ void cookie_cache_remove(struct cookie_cache *c, const str *s) { } void cookie_cache_cleanup(struct cookie_cache *c) { - g_hash_table_destroy(c->current.cookies); - g_hash_table_destroy(c->old.cookies); - g_string_chunk_free(c->current.chunks); - g_string_chunk_free(c->old.chunks); + cookie_cache_state_cleanup(&c->current); + cookie_cache_state_cleanup(&c->old); } diff --git a/include/cookie_cache.h b/include/cookie_cache.h index cc8d5d37d..ff5a8654f 100644 --- a/include/cookie_cache.h +++ b/include/cookie_cache.h @@ -7,8 +7,8 @@ #include "str.h" struct cookie_cache_state { + GHashTable *in_use; GHashTable *cookies; - GStringChunk *chunks; }; struct cookie_cache {