}
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;
+}
+
*/
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. ***/