]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- lru_demote and lruhash_insert_or_retrieve functions for getdns.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 20 Mar 2017 15:25:06 +0000 (15:25 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 20 Mar 2017 15:25:06 +0000 (15:25 +0000)
git-svn-id: file:///svn/unbound/trunk@4068 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
util/storage/lruhash.c
util/storage/lruhash.h

index bb06725a817f0b839f132c213cea596c298fb2a8..5716f1392ae8cb9f96e3f38cb771f95357aaf50d 100644 (file)
@@ -2,6 +2,7 @@
        - #1217. DNSCrypt support, with --enable-dnscrypt, libsodium and then
          enabled in the config file from Manu Bretelle.
        - make depend, autoconf, remove warnings about statement before var.
+       - lru_demote and lruhash_insert_or_retrieve functions for getdns.
 
 17 March 2017: Wouter
        - Patch for view functionality for local-data-ptr from Björn Ketelaars.
index 97e99960562d5adc6018dc6c374c1eecb05150ef..cef9fb0b8b7839c3ac9fbe0946651e800a5e5a6d 100644 (file)
@@ -543,3 +543,89 @@ lruhash_traverse(struct lruhash* h, int wr,
        }
        lock_quick_unlock(&h->lock);
 }
+
+/*
+ * Demote: the opposite of touch, move an entry to the bottom
+ * of the LRU pile.
+ */
+
+void
+lru_demote(struct lruhash* table, struct lruhash_entry* entry)
+{
+       log_assert(table && entry);
+       if (entry == table->lru_end)
+               return; /* nothing to do */
+                               /* remove from current lru position */
+       lru_remove(table, entry);
+       /* add at end */
+       entry->lru_next = NULL;
+       entry->lru_prev = table->lru_end;
+
+       if (table->lru_end == NULL)
+       {
+               table->lru_start = entry;
+       }
+       else
+       {
+               table->lru_end->lru_next = entry;
+       }
+       table->lru_end = entry;
+}
+
+struct lruhash_entry*
+lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
+       struct lruhash_entry* entry, void* data, void* cb_arg)
+{
+       struct lruhash_bin* bin;
+       struct lruhash_entry* found, *reclaimlist = NULL;
+       size_t need_size;
+       fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
+       fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
+       fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
+       fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc));
+       fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc));
+       need_size = table->sizefunc(entry->key, data);
+       if (cb_arg == NULL) cb_arg = table->cb_arg;
+
+       /* find bin */
+       lock_quick_lock(&table->lock);
+       bin = &table->array[hash & table->size_mask];
+       lock_quick_lock(&bin->lock);
+
+       /* see if entry exists already */
+       if ((found = bin_find_entry(table, bin, hash, entry->key)) != NULL) {
+               /* if so: keep the existing data - acquire a writelock */
+               lock_rw_wrlock(&found->lock);
+       }
+       else
+       {
+               /* if not: add to bin */
+               entry->overflow_next = bin->overflow_list;
+               bin->overflow_list = entry;
+               lru_front(table, entry);
+               table->num++;
+               table->space_used += need_size;
+               /* return the entry that was presented, and lock it */
+               found = entry;
+               lock_rw_wrlock(&found->lock);
+       }
+       lock_quick_unlock(&bin->lock);
+       if (table->space_used > table->space_max)
+               reclaim_space(table, &reclaimlist);
+       if (table->num >= table->size)
+               table_grow(table);
+       lock_quick_unlock(&table->lock);
+
+       /* finish reclaim if any (outside of critical region) */
+       while (reclaimlist) {
+               struct lruhash_entry* n = reclaimlist->overflow_next;
+               void* d = reclaimlist->data;
+               (*table->delkeyfunc)(reclaimlist->key, cb_arg);
+               (*table->deldatafunc)(d, cb_arg);
+               reclaimlist = n;
+       }
+
+       /* return the entry that was selected */
+       return found;
+}
+
index c39374082328c3948ae720b090417b122536235d..af06b6229849031ee8806dbc6cd2b68c41ddc08c 100644 (file)
@@ -301,6 +301,38 @@ void lru_touch(struct lruhash* table, struct lruhash_entry* entry);
  */
 void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md);
 
+/************************* getdns functions ************************/
+/*** these are used by getdns only and not by unbound. ***/
+
+/**
+ * Demote entry, so it becomes the least recently used in the LRU list.
+ * Caller must hold hash table lock. The entry must be inserted already.
+ * @param table: hash table.
+ * @param entry: entry to make last in LRU.
+ */
+void lru_demote(struct lruhash* table, struct lruhash_entry* entry);
+
+/**
+ * Insert a new element into the hashtable, or retrieve the corresponding
+ * element of it exits.
+ *
+ * If key is already present data pointer in that entry is kept.
+ * If it is not present, a new entry is created. In that case, 
+ * the space calculation function is called with the key, data.
+ * If necessary the least recently used entries are deleted to make space.
+ * If necessary the hash array is grown up.
+ *
+ * @param table: hash table.
+ * @param hash: hash value. User calculates the hash.
+ * @param entry: identifies the entry.
+ * @param data: the data.
+ * @param cb_override: if not null overrides the cb_arg for the deletefunc.
+ * @return: pointer to the existing entry if the key was already present,
+ *     or to the entry argument if it was not.
+ */
+struct lruhash_entry* lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
+        struct lruhash_entry* entry, void* data, void* cb_arg);
+
 /************************* Internal functions ************************/
 /*** these are only exposed for unit tests. ***/