]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
unit tests for hash table.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 14 Mar 2007 14:30:30 +0000 (14:30 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 14 Mar 2007 14:30:30 +0000 (14:30 +0000)
git-svn-id: file:///svn/unbound/trunk@179 be551aaa-1e26-0410-a405-d3ace91eadb9

Makefile.in
doc/Changelog
testcode/checklocks.c
testcode/unitlruhash.c [new file with mode: 0644]
testcode/unitmain.c
testcode/unitmain.h [new file with mode: 0644]
util/storage/lruhash.c
util/storage/lruhash.h

index 0c095c631624876129bfc422593c83762901e6f5..c7c5e7d6dadaa04b9c9841846e0a362b1b15042c 100644 (file)
@@ -53,7 +53,7 @@ INSTALL=$(srcdir)/install-sh
 COMMON_SRC=$(wildcard services/*.c util/*.c util/data/*.c util/storage/*.c) util/configparser.c util/configlexer.c testcode/checklocks.c
 COMMON_OBJ=$(addprefix $(BUILD),$(COMMON_SRC:.c=.o))
 COMPAT_OBJ=$(addprefix $(BUILD)compat/,$(LIBOBJS))
-UNITTEST_SRC=testcode/unitmain.c $(COMMON_SRC)
+UNITTEST_SRC=$(wildcard testcode/unit*.c) $(COMMON_SRC)
 UNITTEST_OBJ=$(addprefix $(BUILD),$(UNITTEST_SRC:.c=.o)) $(COMPAT_OBJ)
 DAEMON_SRC=$(wildcard daemon/*.c) $(COMMON_SRC)
 DAEMON_OBJ=$(addprefix $(BUILD),$(DAEMON_SRC:.c=.o)) $(COMPAT_OBJ)
index ff622daec7a56c4ca57802003ef0ba56774c261d..1dc4979ee9cf59994e624dce4c61f254e4a4d39b 100644 (file)
@@ -1,6 +1,7 @@
 14 March 2007: Wouter
        - hash table insert (and subroutines) and lookup implemented.
        - hash table remove.
+       - unit tests for hash internal bin, lru functions.
 
 13 March 2007: Wouter
        - lock_unprotect in checklocks.
index dd9f8531d5e09260193e7666f3be5274725efe31..e9b5718723f9c64c9f4e379e9d81172c8ac50d3d 100644 (file)
@@ -66,8 +66,9 @@ static void lock_error(struct checked_lock* lock,
        log_err("lock error (description follows)");
        log_err("Created at %s %s:%d", lock->create_func, 
                lock->create_file, lock->create_line);
-       log_err("Previously %s %s:%d", lock->holder_func, 
-               lock->holder_file, lock->holder_line);
+       if(lock->holder_func && lock->holder_file)
+               log_err("Previously %s %s:%d", lock->holder_func, 
+                       lock->holder_file, lock->holder_line);
        log_err("At %s %s:%d", func, file, line);
        log_err("Error for %s lock: %s",
                (lock->type==check_lock_mutex)?"mutex": (
diff --git a/testcode/unitlruhash.c b/testcode/unitlruhash.c
new file mode 100644 (file)
index 0000000..e1dd946
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * testcode/unitlruhash.c - unit test for lruhash table.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * \file
+ * Tests the locking LRU keeping hash table implementation.
+ */
+
+#include "config.h"
+#include "testcode/unitmain.h"
+#include "util/log.h"
+#include "util/storage/lruhash.h"
+
+/* --- test representation --- */
+/** structure contains test key */
+struct testkey {
+       /** the key id */
+       int id;
+       /** the entry */
+       struct lruhash_entry entry;
+};
+/** structure contains test data */
+struct testdata {
+       /** data value */
+       int data;
+};
+
+/** sizefunc for lruhash */
+static size_t test_sizefunc(void*, void*);
+/** comparefunc for lruhash */
+static int test_compfunc(void*, void*);
+/** delkey for lruhash */
+static void test_delkey(void*, void*);
+/** deldata for lruhash */
+static void test_deldata(void*, void*);
+/* --- end test representation --- */
+
+/** hash func, very bad to improve collisions. */
+static hashvalue_t myhash(int id) {return id & 0x0f;}
+/** allocate new key, fill in hash. */
+static struct testkey* newkey(int id) {
+       struct testkey* k = (struct testkey*)calloc(1, sizeof(struct testkey));
+       k->id = id;
+       k->entry.hash = myhash(id);
+       k->entry.key = k;
+       lock_rw_init(&k->entry.lock);
+       return k;
+}
+/** new data el */
+static struct testdata* newdata(int val) {
+       struct testdata* d = (struct testdata*)calloc(1, 
+               sizeof(struct testdata));
+       d->data = val;
+       return d;
+}
+/** delete key */
+static void delkey(struct testkey* k) {        
+       lock_rw_destroy(&k->entry.lock); free(k);}
+/** delete data */
+static void deldata(struct testdata* d) {free(d);}
+
+/** test bin_find_entry function and bin_overflow_remove */
+static void
+test_bin_find_entry(struct lruhash* table)
+{
+       struct testkey* k = newkey(12);
+       struct testdata* d = newdata(128);
+       struct testkey* k2 = newkey(12 + 1024);
+       struct testkey* k3 = newkey(14);
+       struct testkey* k4 = newkey(12 + 1024*2);
+       hashvalue_t h = myhash(12);
+       struct lruhash_bin bin;
+       bin_init(&bin, 1);
+
+       /* remove from empty list */
+       bin_overflow_remove(&bin, &k->entry);
+
+       /* find in empty list */
+       unit_assert( bin_find_entry(table, &bin, h, k) == NULL );
+
+       /* insert */
+       lock_quick_lock(&bin.lock);
+       bin.overflow_list = &k->entry;
+       lock_quick_unlock(&bin.lock);
+
+       /* find, hash not OK. */
+       unit_assert( bin_find_entry(table, &bin, myhash(13), k) == NULL );
+
+       /* find, hash OK, but cmp not */
+       unit_assert( k->entry.hash == k2->entry.hash );
+       unit_assert( bin_find_entry(table, &bin, h, k2) == NULL );
+
+       /* find, hash OK, and cmp too */
+       unit_assert( bin_find_entry(table, &bin, h, k) == &k->entry );
+
+       /* remove the element */
+       lock_quick_lock(&bin.lock);
+       bin_overflow_remove(&bin, &k->entry);
+       lock_quick_unlock(&bin.lock);
+       unit_assert( bin_find_entry(table, &bin, h, k) == NULL );
+
+       /* prepend two different elements; so the list is long */
+       /* one has the same hash, but different cmp */
+       lock_quick_lock(&bin.lock);
+       unit_assert( k->entry.hash == k4->entry.hash );
+       k4->entry.overflow_next = &k->entry;
+       k3->entry.overflow_next = &k4->entry;
+       bin.overflow_list = &k3->entry;
+       lock_quick_unlock(&bin.lock);
+
+       /* find, hash not OK. */
+       unit_assert( bin_find_entry(table, &bin, myhash(13), k) == NULL );
+
+       /* find, hash OK, but cmp not */
+       unit_assert( k->entry.hash == k2->entry.hash );
+       unit_assert( bin_find_entry(table, &bin, h, k2) == NULL );
+
+       /* find, hash OK, and cmp too */
+       unit_assert( bin_find_entry(table, &bin, h, k) == &k->entry );
+
+       /* remove middle element */
+       unit_assert( bin_find_entry(table, &bin, k4->entry.hash, k4) 
+               == &k4->entry );
+       lock_quick_lock(&bin.lock);
+       bin_overflow_remove(&bin, &k4->entry);
+       lock_quick_unlock(&bin.lock);
+       unit_assert( bin_find_entry(table, &bin, k4->entry.hash, k4) == NULL);
+
+       /* remove last element */
+       lock_quick_lock(&bin.lock);
+       bin_overflow_remove(&bin, &k->entry);
+       lock_quick_unlock(&bin.lock);
+       unit_assert( bin_find_entry(table, &bin, h, k) == NULL );
+
+       lock_quick_destroy(&bin.lock);
+       delkey(k);
+       delkey(k2);
+       delkey(k3);
+       delkey(k4);
+       deldata(d);
+}
+
+/** test lru_front lru_remove */
+static void test_lru(struct lruhash* table)
+{
+       struct testkey* k = newkey(12);
+       struct testkey* k2 = newkey(14);
+       lock_quick_lock(&table->lock);
+
+       unit_assert( table->lru_start == NULL && table->lru_end == NULL);
+       lru_remove(table, &k->entry);
+       unit_assert( table->lru_start == NULL && table->lru_end == NULL);
+
+       /* add one */
+       lru_front(table, &k->entry);
+       unit_assert( table->lru_start == &k->entry && 
+               table->lru_end == &k->entry);
+       /* remove it */
+       lru_remove(table, &k->entry);
+       unit_assert( table->lru_start == NULL && table->lru_end == NULL);
+
+       /* add two */
+       lru_front(table, &k->entry);
+       unit_assert( table->lru_start == &k->entry && 
+               table->lru_end == &k->entry);
+       lru_front(table, &k2->entry);
+       unit_assert( table->lru_start == &k2->entry && 
+               table->lru_end == &k->entry);
+       /* remove first in list */
+       lru_remove(table, &k2->entry);
+       unit_assert( table->lru_start == &k->entry && 
+               table->lru_end == &k->entry);
+       lru_front(table, &k2->entry);
+       unit_assert( table->lru_start == &k2->entry && 
+               table->lru_end == &k->entry);
+       /* remove last in list */
+       lru_remove(table, &k->entry);
+       unit_assert( table->lru_start == &k2->entry && 
+               table->lru_end == &k2->entry);
+
+       /* empty the list */
+       lru_remove(table, &k2->entry);
+       unit_assert( table->lru_start == NULL && table->lru_end == NULL);
+       lock_quick_unlock(&table->lock);
+       delkey(k);
+       delkey(k2);
+}
+
+void lruhash_test()
+{
+       /* start very very small array, so it can do lots of table_grow() */
+       /* also small in size so that reclaim has to be done quickly. */
+       struct lruhash* table = lruhash_create(2, 1024, 
+               test_sizefunc, test_compfunc, test_delkey, test_deldata, NULL);
+       test_bin_find_entry(table);
+       test_lru(table);
+       /* hashtable tests go here */
+       lruhash_delete(table);
+}
+
+static size_t test_sizefunc(void* ATTR_UNUSED(key), void* ATTR_UNUSED(data))
+{
+       return sizeof(struct testkey) + sizeof(struct testdata);
+}
+
+static int test_compfunc(void* key1, void* key2)
+{
+       struct testkey* k1 = (struct testkey*)key1;
+       struct testkey* k2 = (struct testkey*)key2;
+       if(k1->id == k2->id)
+               return 0;
+       if(k1->id > k2->id)
+               return 1;
+       return -1;
+}
+
+static void test_delkey(void* key, void* ATTR_UNUSED(arg))
+{
+       delkey((struct testkey*)key);
+}
+
+static void test_deldata(void* data, void* ATTR_UNUSED(arg))
+{
+       deldata((struct testdata*)data);
+}
index 08401c9ec9f12dbe677a3db9cc6c91cebb461680..c515377161ae5cdd13c687632b43c0b3f4d56aa2 100644 (file)
 
 #include "config.h"
 #include "util/log.h"
+#include "testcode/unitmain.h"
 
 /** number of tests done */
 int testcount = 0;
-/** test bool x, exits on failure, increases testcount. */
-#define unit_assert(x) testcount++; log_assert(x);
 
 #include "util/alloc.h"
 /** test alloc code */
@@ -55,7 +54,6 @@ alloc_test() {
        struct alloc_cache major, minor1, minor2;
        int i;
 
-       checklock_start();
        alloc_init(&major, NULL);
        alloc_init(&minor1, &major);
        alloc_init(&minor2, &major);
@@ -84,7 +82,6 @@ alloc_test() {
        alloc_clear(&minor2);
        unit_assert(major.num_quar == 11);
        alloc_clear(&major);
-       checklock_stop();
 }
 
 #include "util/net_help.h"
@@ -148,9 +145,12 @@ main(int argc, char* argv[])
                return 1;
        }
        printf("Start of %s unit test.\n", PACKAGE_STRING);
+       checklock_start();
        net_test();
        alloc_test();
        msgreply_test();
+       lruhash_test();
+       checklock_stop();
        printf("%d tests succeeded\n", testcount);
        return 0;
 }
diff --git a/testcode/unitmain.h b/testcode/unitmain.h
new file mode 100644 (file)
index 0000000..ae0b370
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * testcode/unitmain.h - unit test main program for unbound.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * \file
+ * Declarations useful for the unit tests.
+ */
+
+#ifndef TESTCODE_UNITMAIN_H
+#define TESTCODE_UNITMAIN_H
+#include "util/log.h"
+
+/** number of tests done */
+extern int testcount;
+/** test bool x, exits on failure, increases testcount. */
+#define unit_assert(x) do {testcount++; log_assert(x);} while(0)
+
+/** unit test lruhashtable implementation */
+void lruhash_test();
+
+#endif /* TESTCODE_UNITMAIN_H */
index e173a5f98a6cefe1ba783d3e7b5c4bd242844bbd..88e473463d9e56437bca1162c9ecad4a33fbd537 100644 (file)
 #include "config.h"
 #include "util/storage/lruhash.h"
 
-/* ------ local helper functions ------------- */
-
-/** init the hash bins for the table. */
-static void bin_init(struct lruhash_bin* array, size_t size);
-
-/** delete the hash bin and entries inside it */
-static void bin_delete(struct lruhash* table, struct lruhash_bin* bin);
-
-/** find entry in hash bin. You must have locked the bin.
- * @param table: hash table with function pointers.
- * @param bin: hash bin to look into.
- * @param hash: hash value to look for.
- * @param key: key to look for.
- * @return: the entry or NULL if not found.
- */
-static struct lruhash_entry* bin_find_entry(struct lruhash* table, 
-       struct lruhash_bin* bin, hashvalue_t hash, void* key);
-
-/**
- * Remove entry from bin overflow chain.
- * You must have locked the bin.
- * @param bin: hash bin to look into.
- * @param entry: entry ptr that needs removal.
- */
-static void bin_overflow_remove(struct lruhash_bin* bin, 
-       struct lruhash_entry* entry);
-
-/**
- * Split hash bin into two new ones. Based on increased size_mask.
- * Caller must hold hash table lock.
- * At the end the routine acquires all hashbin locks (in the old array).
- * This makes it wait for other threads to finish with the bins.
- * So the bins are ready to be deleted after this function.
- * @param table: hash table with function pointers.
- * @param newa: new increased array.
- * @param newmask: new lookup mask.
- */
-static void bin_split(struct lruhash* table, struct lruhash_bin* newa, 
-       int newmask);
-
-/** 
- * Try to make space available by deleting old entries.
- * Assumes that the lock on the hashtable is being held by caller.
- * Caller must not hold bin locks.
- * @param table: hash table.
- * @param list: list of entries that are to be deleted later.
- *     Entries have been removed from the hash table and writelock is held.
- */
-static void reclaim_space(struct lruhash* table, struct lruhash_entry** list);
-
-/**
- * Grow the table lookup array. Becomes twice as large.
- * Caller must hold the hash table lock. Must not hold any bin locks.
- * Tries to grow, on malloc failure, nothing happened.
- * @param table: hash table.
- */
-static void table_grow(struct lruhash* table);
-
-/**
- * Touch entry, so it becomes the most 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 first in LRU.
- */
-static void lru_touch(struct lruhash* table, struct lruhash_entry* entry);
-
-/**
- * Put entry at front of lru. entry must be unlinked from lru.
- * Caller must hold hash table lock.
- * @param table: hash table with lru head and tail.
- * @param entry: entry to make most recently used.
- */
-static void lru_front(struct lruhash* table, struct lruhash_entry* entry);
-
-/**
- * Remove entry from lru list.
- * Caller must hold hash table lock.
- * @param table: hash table with lru head and tail.
- * @param entry: entry to remove from lru.
- */
-static void lru_remove(struct lruhash* table, struct lruhash_entry* entry);
-
-/* ------ end local helper functions --------- */
-
-static void
+void
 bin_init(struct lruhash_bin* array, size_t size)
 {
        size_t i;
@@ -173,7 +89,7 @@ lruhash_create(size_t start_size, size_t maxmem, lruhash_sizefunc_t sizefunc,
        return table;
 }
 
-static void 
+void 
 bin_delete(struct lruhash* table, struct lruhash_bin* bin)
 {
        struct lruhash_entry* p, *np;
@@ -190,7 +106,7 @@ bin_delete(struct lruhash* table, struct lruhash_bin* bin)
        }
 }
 
-static void 
+void 
 bin_split(struct lruhash* table, struct lruhash_bin* newa, 
        int newmask)
 {
@@ -232,7 +148,7 @@ lruhash_delete(struct lruhash* table)
        free(table);
 }
 
-static void 
+void 
 bin_overflow_remove(struct lruhash_bin* bin, struct lruhash_entry* entry)
 {
        struct lruhash_entry* p = bin->overflow_list;
@@ -247,7 +163,7 @@ bin_overflow_remove(struct lruhash_bin* bin, struct lruhash_entry* entry)
        }
 }
 
-static void 
+void 
 reclaim_space(struct lruhash* table, struct lruhash_entry** list)
 {
        struct lruhash_entry* d;
@@ -280,7 +196,7 @@ reclaim_space(struct lruhash* table, struct lruhash_entry** list)
        }
 }
 
-static struct lruhash_entry* 
+struct lruhash_entry* 
 bin_find_entry(struct lruhash* table, 
        struct lruhash_bin* bin, hashvalue_t hash, void* key)
 {
@@ -293,7 +209,7 @@ bin_find_entry(struct lruhash* table,
        return NULL;
 }
 
-static void 
+void 
 table_grow(struct lruhash* table)
 {
        struct lruhash_bin* newa;
@@ -329,7 +245,7 @@ table_grow(struct lruhash* table)
        return;
 }
 
-static void 
+void 
 lru_front(struct lruhash* table, struct lruhash_entry* entry)
 {
        entry->lru_prev = NULL;
@@ -340,7 +256,7 @@ lru_front(struct lruhash* table, struct lruhash_entry* entry)
        table->lru_start = entry;
 }
 
-static void 
+void 
 lru_remove(struct lruhash* table, struct lruhash_entry* entry)
 {
        if(entry->lru_prev)
@@ -351,7 +267,7 @@ lru_remove(struct lruhash* table, struct lruhash_entry* entry)
        else    table->lru_end = entry->lru_prev;
 }
 
-static void 
+void 
 lru_touch(struct lruhash* table, struct lruhash_entry* entry)
 {
        log_assert(table && entry);
index f4397bac70fed94d91c06c20ddbe8379b0d12985..548ca1c9b09bd4c57339d56e92eaabbcb163f701 100644 (file)
@@ -266,6 +266,10 @@ void lruhash_insert(struct lruhash* table, hashvalue_t hash,
 struct lruhash_entry* lruhash_lookup(struct lruhash* table, hashvalue_t hash, 
        void* key, int wr);
 
+
+/************************* Internal functions ************************/
+/*** these are only exposed for unit tests. ***/
+
 /**
  * Remove entry from hashtable. Does nothing if not found in hashtable.
  * Delfunc is called for the entry.
@@ -275,4 +279,85 @@ struct lruhash_entry* lruhash_lookup(struct lruhash* table, hashvalue_t hash,
  */
 void lruhash_remove(struct lruhash* table, hashvalue_t hash, void* key);
 
+/** init the hash bins for the table. */
+void bin_init(struct lruhash_bin* array, size_t size);
+
+/** delete the hash bin and entries inside it */
+void bin_delete(struct lruhash* table, struct lruhash_bin* bin);
+
+/** 
+ * Find entry in hash bin. You must have locked the bin.
+ * @param table: hash table with function pointers.
+ * @param bin: hash bin to look into.
+ * @param hash: hash value to look for.
+ * @param key: key to look for.
+ * @return: the entry or NULL if not found.
+ */
+struct lruhash_entry* bin_find_entry(struct lruhash* table, 
+       struct lruhash_bin* bin, hashvalue_t hash, void* key);
+
+/**
+ * Remove entry from bin overflow chain.
+ * You must have locked the bin.
+ * @param bin: hash bin to look into.
+ * @param entry: entry ptr that needs removal.
+ */
+void bin_overflow_remove(struct lruhash_bin* bin, 
+       struct lruhash_entry* entry);
+
+/**
+ * Split hash bin into two new ones. Based on increased size_mask.
+ * Caller must hold hash table lock.
+ * At the end the routine acquires all hashbin locks (in the old array).
+ * This makes it wait for other threads to finish with the bins.
+ * So the bins are ready to be deleted after this function.
+ * @param table: hash table with function pointers.
+ * @param newa: new increased array.
+ * @param newmask: new lookup mask.
+ */
+void bin_split(struct lruhash* table, struct lruhash_bin* newa, 
+       int newmask);
+
+/** 
+ * Try to make space available by deleting old entries.
+ * Assumes that the lock on the hashtable is being held by caller.
+ * Caller must not hold bin locks.
+ * @param table: hash table.
+ * @param list: list of entries that are to be deleted later.
+ *     Entries have been removed from the hash table and writelock is held.
+ */
+void reclaim_space(struct lruhash* table, struct lruhash_entry** list);
+
+/**
+ * Grow the table lookup array. Becomes twice as large.
+ * Caller must hold the hash table lock. Must not hold any bin locks.
+ * Tries to grow, on malloc failure, nothing happened.
+ * @param table: hash table.
+ */
+void table_grow(struct lruhash* table);
+
+/**
+ * Touch entry, so it becomes the most 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 first in LRU.
+ */
+void lru_touch(struct lruhash* table, struct lruhash_entry* entry);
+
+/**
+ * Put entry at front of lru. entry must be unlinked from lru.
+ * Caller must hold hash table lock.
+ * @param table: hash table with lru head and tail.
+ * @param entry: entry to make most recently used.
+ */
+void lru_front(struct lruhash* table, struct lruhash_entry* entry);
+
+/**
+ * Remove entry from lru list.
+ * Caller must hold hash table lock.
+ * @param table: hash table with lru head and tail.
+ * @param entry: entry to remove from lru.
+ */
+void lru_remove(struct lruhash* table, struct lruhash_entry* entry);
+
 #endif /* UTIL_STORAGE_LRUHASH_H */