Reindented server/core/hashtable.c

This commit is contained in:
Johan Wikman
2015-11-30 13:35:23 +02:00
parent 26d1cf0c1f
commit 255a5b53c1
2 changed files with 574 additions and 536 deletions

View File

@ -105,8 +105,7 @@ hashtable_alloc(int size, int (*hashfn)(), int (*cmpfn)())
return hashtable_alloc_real(NULL, size, hashfn, cmpfn); return hashtable_alloc_real(NULL, size, hashfn, cmpfn);
} }
HASHTABLE* hashtable_alloc_flat( HASHTABLE* hashtable_alloc_flat(HASHTABLE* target,
HASHTABLE* target,
int size, int size,
int (*hashfn)(), int (*hashfn)(),
int (*cmpfn)()) int (*cmpfn)())
@ -115,8 +114,7 @@ HASHTABLE* hashtable_alloc_flat(
} }
static HASHTABLE * static HASHTABLE *
hashtable_alloc_real( hashtable_alloc_real(HASHTABLE* target,
HASHTABLE* target,
int size, int size,
int (*hashfn)(), int (*hashfn)(),
int (*cmpfn)()) int (*cmpfn)())
@ -126,7 +124,9 @@ hashtable_alloc_real(
if (target == NULL) if (target == NULL)
{ {
if ((rval = malloc(sizeof(HASHTABLE))) == NULL) if ((rval = malloc(sizeof(HASHTABLE))) == NULL)
{
return NULL; return NULL;
}
rval->ht_isflat = false; rval->ht_isflat = false;
} }
else else
@ -168,11 +168,13 @@ hashtable_alloc_real(
void void
hashtable_free(HASHTABLE *table) hashtable_free(HASHTABLE *table)
{ {
int i; int i;
HASHENTRIES *entry, *ptr; HASHENTRIES *entry, *ptr;
if(table == NULL) if (table == NULL)
{
return; return;
}
hashtable_write_lock(table); hashtable_write_lock(table);
for (i = 0; i < table->hashsize; i++) for (i = 0; i < table->hashsize; i++)
@ -208,21 +210,28 @@ HASHENTRIES *entry, *ptr;
* @param vfreefn The free function for the value * @param vfreefn The free function for the value
*/ */
void void
hashtable_memory_fns( hashtable_memory_fns(HASHTABLE *table,
HASHTABLE *table,
HASHMEMORYFN kcopyfn, HASHMEMORYFN kcopyfn,
HASHMEMORYFN vcopyfn, HASHMEMORYFN vcopyfn,
HASHMEMORYFN kfreefn, HASHMEMORYFN kfreefn,
HASHMEMORYFN vfreefn) HASHMEMORYFN vfreefn)
{ {
if (kcopyfn != NULL) if (kcopyfn != NULL)
{
table->kcopyfn = kcopyfn; table->kcopyfn = kcopyfn;
}
if (vcopyfn != NULL) if (vcopyfn != NULL)
{
table->vcopyfn = vcopyfn; table->vcopyfn = vcopyfn;
}
if (kfreefn != NULL) if (kfreefn != NULL)
{
table->kfreefn = kfreefn; table->kfreefn = kfreefn;
}
if (vfreefn != NULL) if (vfreefn != NULL)
{
table->vfreefn = vfreefn; table->vfreefn = vfreefn;
}
} }
/** /**
@ -240,11 +249,16 @@ hashtable_add(HASHTABLE *table, void *key, void *value)
HASHENTRIES *entry; HASHENTRIES *entry;
if (table == NULL || key == NULL || value == NULL) if (table == NULL || key == NULL || value == NULL)
{
return 0; return 0;
}
if (table->hashsize <= 0) { if (table->hashsize <= 0)
{
return 0; return 0;
} else { }
else
{
hashkey = table->hashfn(key) % table->hashsize; hashkey = table->hashfn(key) % table->hashsize;
} }
hashtable_write_lock(table); hashtable_write_lock(table);
@ -272,7 +286,8 @@ hashtable_add(HASHTABLE *table, void *key, void *value)
ptr->key = table->kcopyfn(key); ptr->key = table->kcopyfn(key);
/* check succesfull key copy */ /* check succesfull key copy */
if ( ptr->key == NULL) { if (ptr->key == NULL)
{
free(ptr); free(ptr);
hashtable_write_unlock(table); hashtable_write_unlock(table);
@ -283,7 +298,8 @@ hashtable_add(HASHTABLE *table, void *key, void *value)
ptr->value = table->vcopyfn(value); ptr->value = table->vcopyfn(value);
/* check succesfull value copy */ /* check succesfull value copy */
if ( ptr->value == NULL) { if (ptr->value == NULL)
{
/* remove the key ! */ /* remove the key ! */
table->kfreefn(ptr->key); table->kfreefn(ptr->key);
free(ptr); free(ptr);
@ -313,11 +329,13 @@ hashtable_add(HASHTABLE *table, void *key, void *value)
int int
hashtable_delete(HASHTABLE *table, void *key) hashtable_delete(HASHTABLE *table, void *key)
{ {
unsigned int hashkey; unsigned int hashkey;
HASHENTRIES *entry, *ptr; HASHENTRIES *entry, *ptr;
if(table == NULL || key == NULL) if (table == NULL || key == NULL)
{
return 0; return 0;
}
hashkey = table->hashfn(key) % table->hashsize; hashkey = table->hashfn(key) % table->hashsize;
hashtable_write_lock(table); hashtable_write_lock(table);
@ -340,10 +358,13 @@ HASHENTRIES *entry, *ptr;
table->kfreefn(entry->key); table->kfreefn(entry->key);
table->vfreefn(entry->value); table->vfreefn(entry->value);
if (entry->next != NULL) { if (entry->next != NULL)
{
entry->key = entry->next->key; entry->key = entry->next->key;
entry->value = entry->next->value; entry->value = entry->next->value;
} else { }
else
{
entry->key = NULL; entry->key = NULL;
entry->value = NULL; entry->value = NULL;
} }
@ -353,7 +374,9 @@ HASHENTRIES *entry, *ptr;
{ {
ptr = table->entries[hashkey % table->hashsize]; ptr = table->entries[hashkey % table->hashsize];
while (ptr && ptr->next != entry) while (ptr && ptr->next != entry)
{
ptr = ptr->next; ptr = ptr->next;
}
if (ptr == NULL) if (ptr == NULL)
{ {
hashtable_write_unlock(table); hashtable_write_unlock(table);
@ -380,11 +403,13 @@ HASHENTRIES *entry, *ptr;
void * void *
hashtable_fetch(HASHTABLE *table, void *key) hashtable_fetch(HASHTABLE *table, void *key)
{ {
unsigned int hashkey; unsigned int hashkey;
HASHENTRIES *entry; HASHENTRIES *entry;
if(table == NULL || key == NULL || 0 == table->hashsize) if (table == NULL || key == NULL || 0 == table->hashsize)
{
return NULL; return NULL;
}
hashkey = table->hashfn(key) % table->hashsize; hashkey = table->hashfn(key) % table->hashsize;
hashtable_read_lock(table); hashtable_read_lock(table);
@ -413,11 +438,13 @@ HASHENTRIES *entry;
void void
hashtable_stats(HASHTABLE *table) hashtable_stats(HASHTABLE *table)
{ {
int total, longest, i, j; int total, longest, i, j;
HASHENTRIES *entries; HASHENTRIES *entries;
if(table == NULL) if (table == NULL)
{
return; return;
}
printf("Hashtable: %p, size %d\n", table, table->hashsize); printf("Hashtable: %p, size %d\n", table, table->hashsize);
total = 0; total = 0;
@ -462,8 +489,7 @@ HASHENTRIES *entries;
* *
* *
*/ */
void hashtable_get_stats( void hashtable_get_stats(void* table,
void* table,
int* hashsize, int* hashsize,
int* nelems, int* nelems,
int* longest) int* longest)
@ -493,7 +519,8 @@ void hashtable_get_stats(
entries = entries->next; entries = entries->next;
} }
*nelems += j; *nelems += j;
if (j > *longest) { if (j > *longest)
{
*longest = j; *longest = j;
} }
} }
@ -529,7 +556,9 @@ hashtable_read_lock(HASHTABLE *table)
{ {
spinlock_release(&table->spin); spinlock_release(&table->spin);
while (table->writelock) while (table->writelock)
{
; ;
}
spinlock_acquire(&table->spin); spinlock_acquire(&table->spin);
} }
atomic_add(&table->n_readers, 1); atomic_add(&table->n_readers, 1);
@ -568,16 +597,22 @@ hashtable_read_unlock(HASHTABLE *table)
static void static void
hashtable_write_lock(HASHTABLE *table) hashtable_write_lock(HASHTABLE *table)
{ {
int available; int available;
spinlock_acquire(&table->spin); spinlock_acquire(&table->spin);
do { do
{
while (table->n_readers) while (table->n_readers)
{
; ;
}
available = atomic_add(&table->writelock, 1); available = atomic_add(&table->writelock, 1);
if (available != 0) if (available != 0)
{
atomic_add(&table->writelock, -1); atomic_add(&table->writelock, -1);
} while (available != 0); }
}
while (available != 0);
spinlock_release(&table->spin); spinlock_release(&table->spin);
} }
@ -601,7 +636,7 @@ hashtable_write_unlock(HASHTABLE *table)
HASHITERATOR * HASHITERATOR *
hashtable_iterator(HASHTABLE *table) hashtable_iterator(HASHTABLE *table)
{ {
HASHITERATOR *rval; HASHITERATOR *rval;
if ((rval = (HASHITERATOR *)malloc(sizeof(HASHITERATOR))) != NULL) if ((rval = (HASHITERATOR *)malloc(sizeof(HASHITERATOR))) != NULL)
{ {
@ -621,11 +656,13 @@ HASHITERATOR *rval;
void * void *
hashtable_next(HASHITERATOR *iter) hashtable_next(HASHITERATOR *iter)
{ {
int i; int i;
HASHENTRIES *entries; HASHENTRIES *entries;
if(iter == NULL) if (iter == NULL)
{
return NULL; return NULL;
}
iter->depth++; iter->depth++;
while (iter->chain < iter->table->hashsize) while (iter->chain < iter->table->hashsize)
@ -678,9 +715,9 @@ hashtable_save(HASHTABLE *table, char *filename,
int (*keywrite)(int, void*), int (*keywrite)(int, void*),
int (*valuewrite)(int, void*)) int (*valuewrite)(int, void*))
{ {
int fd, rval = 0; int fd, rval = 0;
HASHITERATOR *iter; HASHITERATOR *iter;
void *key, *value; void *key, *value;
if ((fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) if ((fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1)
{ {
@ -714,7 +751,7 @@ void *key, *value;
} }
/* Now go back and write the count of entries */ /* Now go back and write the count of entries */
if(lseek(fd, 7L, SEEK_SET) != -1) if (lseek(fd, 7L, SEEK_SET) != -1)
{ {
write(fd, &rval, sizeof(rval)); write(fd, &rval, sizeof(rval));
} }
@ -738,9 +775,9 @@ hashtable_load(HASHTABLE *table, char *filename,
void *(*keyread)(int), void *(*keyread)(int),
void *(*valueread)(int)) void *(*valueread)(int))
{ {
int fd, count, rval = 0; int fd, count, rval = 0;
void *key, *value; void *key, *value;
char buf[40]; char buf[40];
if ((fd = open(filename, O_RDONLY)) == -1) if ((fd = open(filename, O_RDONLY)) == -1)
{ {

View File

@ -44,7 +44,8 @@
* A NULL value for key indicates an empty entry. * A NULL value for key indicates an empty entry.
* The next pointer is the overflow chain for this hashentry. * The next pointer is the overflow chain for this hashentry.
*/ */
typedef struct hashentry { typedef struct hashentry
{
void *key; /**< The value of the key or NULL if empty entry */ void *key; /**< The value of the key or NULL if empty entry */
void *value; /**< The value associated with key */ void *value; /**< The value associated with key */
struct hashentry *next; /**< The overflow chain */ struct hashentry *next; /**< The overflow chain */
@ -54,9 +55,9 @@ typedef struct hashentry {
* HASHTABLE iterator - used to walk the hashtable in a thread safe * HASHTABLE iterator - used to walk the hashtable in a thread safe
* way * way
*/ */
typedef struct hashiterator { typedef struct hashiterator
struct hashtable {
*table; /**< The hashtable the iterator refers to */ struct hashtable *table; /**< The hashtable the iterator refers to */
int chain; /**< The current chain we are walking */ int chain; /**< The current chain we are walking */
int depth; /**< The current depth down the chain */ int depth; /**< The current depth down the chain */
} HASHITERATOR; } HASHITERATOR;
@ -69,7 +70,8 @@ typedef void *(*HASHMEMORYFN)(void *);
/** /**
* The general purpose hashtable struct. * The general purpose hashtable struct.
*/ */
typedef struct hashtable { typedef struct hashtable
{
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
skygw_chk_t ht_chk_top; skygw_chk_t ht_chk_top;
#endif #endif
@ -85,7 +87,7 @@ typedef struct hashtable {
int n_readers; /**< Number of clients reading the table */ int n_readers; /**< Number of clients reading the table */
int writelock; /**< The table is locked by a writer */ int writelock; /**< The table is locked by a writer */
bool ht_isflat; /**< Indicates whether hashtable is in stack or heap */ bool ht_isflat; /**< Indicates whether hashtable is in stack or heap */
int n_elements; /*< Number of added elements */ int n_elements; /**< Number of added elements */
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
skygw_chk_t ht_chk_tail; skygw_chk_t ht_chk_tail;
#endif #endif
@ -96,24 +98,23 @@ HASHTABLE *hashtable_alloc_flat(HASHTABLE* target,
int size, int size,
int (*hashfn)(), int (*hashfn)(),
int (*cmpfn)()); int (*cmpfn)());
/**< Allocate a hashtable */ /**< Allocate a hashtable */
extern void hashtable_memory_fns(HASHTABLE *table, extern void hashtable_memory_fns(HASHTABLE *table,
HASHMEMORYFN kcopyfn, HASHMEMORYFN kcopyfn,
HASHMEMORYFN vcopyfn, HASHMEMORYFN vcopyfn,
HASHMEMORYFN kfreefn, HASHMEMORYFN kfreefn,
HASHMEMORYFN vfreefn); HASHMEMORYFN vfreefn);
/**< Provide an interface to control key/value memory /**< Provide an interface to control key/value memory
* manipulation * manipulation
*/ */
extern void hashtable_free(HASHTABLE *); /**< Free a hashtable */ extern void hashtable_free(HASHTABLE *); /**< Free a hashtable */
extern int hashtable_add(HASHTABLE *, void *, void *); /**< Add an entry */ extern int hashtable_add(HASHTABLE *, void *, void *); /**< Add an entry */
extern int hashtable_delete(HASHTABLE *, void *); extern int hashtable_delete(HASHTABLE *, void *);
/**< Delete an entry table */ /**< Delete an entry table */
extern void *hashtable_fetch(HASHTABLE *, void *); extern void *hashtable_fetch(HASHTABLE *, void *);
/**< Fetch the data for a given key */ /**< Fetch the data for a given key */
extern void hashtable_stats(HASHTABLE *); /**< Print statisitics */ extern void hashtable_stats(HASHTABLE *); /**< Print statisitics */
void hashtable_get_stats( void hashtable_get_stats(void* hashtable,
void* hashtable,
int* hashsize, int* hashsize,
int* nelems, int* nelems,
int* longest); int* longest);
@ -127,9 +128,9 @@ extern int hashtable_load(HASHTABLE *,
void *(*valueread)(int)); void *(*valueread)(int));
extern HASHITERATOR *hashtable_iterator(HASHTABLE *); extern HASHITERATOR *hashtable_iterator(HASHTABLE *);
/**< Allocate an iterator on the hashtable */ /**< Allocate an iterator on the hashtable */
extern void *hashtable_next(HASHITERATOR *); extern void *hashtable_next(HASHITERATOR *);
/**< Return the key of the hash table iterator */ /**< Return the key of the hash table iterator */
extern void hashtable_iterator_free(HASHITERATOR *); extern void hashtable_iterator_free(HASHITERATOR *);
extern int hashtable_size(HASHTABLE *table); extern int hashtable_size(HASHTABLE *table);
#endif #endif