summaryrefslogtreecommitdiffstats
path: root/cache.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2005-01-21 00:16:08 +0000
committerLennart Poettering <lennart@poettering.net>2005-01-21 00:16:08 +0000
commit0781d5363fb6fd723a2316fc7558aef6439b2f71 (patch)
treef6a942889c55230611d4472c21a7075a7c2fc609 /cache.c
parentd6e2dbabccb08970da991e6d2b0fda7a56d83e6f (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.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/cache.c b/cache.c
new file mode 100644
index 0000000..6a0a874
--- /dev/null
+++ b/cache.c
@@ -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);
+}