diff options
author | Lennart Poettering <lennart@poettering.net> | 2005-01-21 00:16:08 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2005-01-21 00:16:08 +0000 |
commit | 0781d5363fb6fd723a2316fc7558aef6439b2f71 (patch) | |
tree | f6a942889c55230611d4472c21a7075a7c2fc609 /cache.c | |
parent | d6e2dbabccb08970da991e6d2b0fda7a56d83e6f (diff) |
massive work
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@8 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe
Diffstat (limited to 'cache.c')
-rw-r--r-- | cache.c | 149 |
1 files changed, 149 insertions, 0 deletions
@@ -0,0 +1,149 @@ +#include <string.h> + +#include "cache.h" + +static void remove_entry(flxCache *c, flxCacheEntry *e, gboolean remove_from_hash_table) { + g_assert(c); + g_assert(e); + + if (remove_from_hash_table) { + flxCacheEntry *t; + t = g_hash_table_lookup(c->hash_table, &e->record->key); + FLX_LLIST_REMOVE(flxCacheEntry, by_name, t, e); + if (t) + g_hash_table_replace(c->hash_table, &t->record->key, t); + else + g_hash_table_remove(c->hash_table, &e->record->key); + } + + flx_record_unref(e->record); + g_free(e); +} + +flxCache *flx_cache_new(flxServer *server, flxInterface *iface) { + flxCache *c; + g_assert(server); + + c = g_new(flxCache, 1); + c->server = server; + c->interface = iface; + c->hash_table = g_hash_table_new((GHashFunc) flx_key_hash, (GEqualFunc) flx_key_equal); + + return c; +} + +gboolean remove_func(gpointer key, gpointer value, gpointer user_data) { + flxCacheEntry *e, *next; + + for (e = value; e; e = next) { + next = e->by_name_next; + remove_entry(user_data, e, FALSE); + } + + return TRUE; +} + +void flx_cache_free(flxCache *c) { + g_assert(c); + + g_hash_table_foreach_remove(c->hash_table, remove_func, c); + g_hash_table_destroy(c->hash_table); + + g_free(c); +} + +flxCacheEntry *flx_cache_lookup_key(flxCache *c, flxKey *k) { + g_assert(c); + g_assert(k); + + return g_hash_table_lookup(c->hash_table, k); +} + +flxCacheEntry *flx_cache_lookup_record(flxCache *c, flxRecord *r) { + flxCacheEntry *e; + g_assert(c); + g_assert(r); + + for (e = flx_cache_lookup_key(c, r->key); e; e = e->by_name_next) + if (e->record->size == r->size && !memcmp(e->record->data, r->data, r->size)) + return e; + + return NULL; +} + +flxCacheEntry *flx_cache_update(flxCache *c, flxRecord *r, gboolean unique, const flxAddress *a) { + flxCacheEntry *e, *t; + + g_assert(c); + g_assert(r); + + if ((t = e = flx_cache_lookup_key(c, r->key))) { + + if (unique) { + flxCacheEntry *n; + /* Drop all entries but the first which we replace */ + + while (e->by_name_next) + remove_entry(c, e->by_name_next, TRUE); + + g_free(e->record->data); + e->record->data = g_memdup(r->data, r->size); + e->record->size = r->size; + e->record->ttl = r->ttl; + + } else { + /* Look for exactly the same entry */ + + for (; e; e = e->by_name_next) { + if (e->record->size == r->size && + !memcmp(e->record->data, r->data, r->size)) { + + /* We found it, so let's update the TTL */ + e->record->ttl = r->ttl; + break; + } + } + } + } + + if (!e) { + /* No entry found, therefore we create a new one */ + + e = g_new(flxCacheEntry, 1); + e->node = NULL; + + e->record = flx_record_ref(r); + FLX_LLIST_PREPEND(flxCacheEntry, by_name, t, e); + g_hash_table_replace(c->hash_table, e->record->key, e); + } + + e->origin = *a; + + g_get_current_time(&e->timestamp); + e->expiry = e->timestamp; + g_time_val_add(&e->expiry, e->record->ttl * 1000000); + + e->state = FLX_CACHE_VALID; + + return e; +} + +void flx_cache_drop_key(flxCache *c, flxKey *k) { + flxCacheEntry *e; + + g_assert(c); + g_assert(k); + + while ((e = flx_cache_lookup_key(c, k))) + remove_entry(c, e, TRUE); +} + +void flx_cache_drop_record(flxCache *c, flxRecord *r) { + flxCacheEntry *e; + + g_assert(c); + g_assert(r); + + if ((e = flx_cache_lookup_record(c, r))) + remove_entry(c, e, TRUE); +} |