mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-01-02 21:09:35 -05:00
unit tests for hash table.
git-svn-id: file:///svn/unbound/trunk@179 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
06b25ffa5a
commit
af41706579
8 changed files with 414 additions and 101 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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": (
|
||||
|
|
|
|||
257
testcode/unitlruhash.c
Normal file
257
testcode/unitlruhash.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -41,11 +41,10 @@
|
|||
|
||||
#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;
|
||||
}
|
||||
|
|
|
|||
53
testcode/unitmain.h
Normal file
53
testcode/unitmain.h
Normal file
|
|
@ -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 */
|
||||
|
|
@ -43,91 +43,7 @@
|
|||
#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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in a new issue