Reindented server/core/hashtable.c
This commit is contained in:
@ -105,8 +105,7 @@ hashtable_alloc(int size, int (*hashfn)(), int (*cmpfn)())
|
||||
return hashtable_alloc_real(NULL, size, hashfn, cmpfn);
|
||||
}
|
||||
|
||||
HASHTABLE* hashtable_alloc_flat(
|
||||
HASHTABLE* target,
|
||||
HASHTABLE* hashtable_alloc_flat(HASHTABLE* target,
|
||||
int size,
|
||||
int (*hashfn)(),
|
||||
int (*cmpfn)())
|
||||
@ -115,8 +114,7 @@ HASHTABLE* hashtable_alloc_flat(
|
||||
}
|
||||
|
||||
static HASHTABLE *
|
||||
hashtable_alloc_real(
|
||||
HASHTABLE* target,
|
||||
hashtable_alloc_real(HASHTABLE* target,
|
||||
int size,
|
||||
int (*hashfn)(),
|
||||
int (*cmpfn)())
|
||||
@ -126,7 +124,9 @@ hashtable_alloc_real(
|
||||
if (target == NULL)
|
||||
{
|
||||
if ((rval = malloc(sizeof(HASHTABLE))) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
rval->ht_isflat = false;
|
||||
}
|
||||
else
|
||||
@ -168,11 +168,13 @@ hashtable_alloc_real(
|
||||
void
|
||||
hashtable_free(HASHTABLE *table)
|
||||
{
|
||||
int i;
|
||||
HASHENTRIES *entry, *ptr;
|
||||
int i;
|
||||
HASHENTRIES *entry, *ptr;
|
||||
|
||||
if(table == NULL)
|
||||
if (table == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hashtable_write_lock(table);
|
||||
for (i = 0; i < table->hashsize; i++)
|
||||
@ -208,21 +210,28 @@ HASHENTRIES *entry, *ptr;
|
||||
* @param vfreefn The free function for the value
|
||||
*/
|
||||
void
|
||||
hashtable_memory_fns(
|
||||
HASHTABLE *table,
|
||||
hashtable_memory_fns(HASHTABLE *table,
|
||||
HASHMEMORYFN kcopyfn,
|
||||
HASHMEMORYFN vcopyfn,
|
||||
HASHMEMORYFN kfreefn,
|
||||
HASHMEMORYFN vfreefn)
|
||||
{
|
||||
if (kcopyfn != NULL)
|
||||
{
|
||||
table->kcopyfn = kcopyfn;
|
||||
}
|
||||
if (vcopyfn != NULL)
|
||||
{
|
||||
table->vcopyfn = vcopyfn;
|
||||
}
|
||||
if (kfreefn != NULL)
|
||||
{
|
||||
table->kfreefn = kfreefn;
|
||||
}
|
||||
if (vfreefn != NULL)
|
||||
{
|
||||
table->vfreefn = vfreefn;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,11 +249,16 @@ hashtable_add(HASHTABLE *table, void *key, void *value)
|
||||
HASHENTRIES *entry;
|
||||
|
||||
if (table == NULL || key == NULL || value == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (table->hashsize <= 0) {
|
||||
if (table->hashsize <= 0)
|
||||
{
|
||||
return 0;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
hashkey = table->hashfn(key) % table->hashsize;
|
||||
}
|
||||
hashtable_write_lock(table);
|
||||
@ -272,7 +286,8 @@ hashtable_add(HASHTABLE *table, void *key, void *value)
|
||||
ptr->key = table->kcopyfn(key);
|
||||
|
||||
/* check succesfull key copy */
|
||||
if ( ptr->key == NULL) {
|
||||
if (ptr->key == NULL)
|
||||
{
|
||||
free(ptr);
|
||||
hashtable_write_unlock(table);
|
||||
|
||||
@ -283,7 +298,8 @@ hashtable_add(HASHTABLE *table, void *key, void *value)
|
||||
ptr->value = table->vcopyfn(value);
|
||||
|
||||
/* check succesfull value copy */
|
||||
if ( ptr->value == NULL) {
|
||||
if (ptr->value == NULL)
|
||||
{
|
||||
/* remove the key ! */
|
||||
table->kfreefn(ptr->key);
|
||||
free(ptr);
|
||||
@ -313,11 +329,13 @@ hashtable_add(HASHTABLE *table, void *key, void *value)
|
||||
int
|
||||
hashtable_delete(HASHTABLE *table, void *key)
|
||||
{
|
||||
unsigned int hashkey;
|
||||
HASHENTRIES *entry, *ptr;
|
||||
unsigned int hashkey;
|
||||
HASHENTRIES *entry, *ptr;
|
||||
|
||||
if(table == NULL || key == NULL)
|
||||
if (table == NULL || key == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
hashkey = table->hashfn(key) % table->hashsize;
|
||||
hashtable_write_lock(table);
|
||||
@ -340,10 +358,13 @@ HASHENTRIES *entry, *ptr;
|
||||
table->kfreefn(entry->key);
|
||||
table->vfreefn(entry->value);
|
||||
|
||||
if (entry->next != NULL) {
|
||||
if (entry->next != NULL)
|
||||
{
|
||||
entry->key = entry->next->key;
|
||||
entry->value = entry->next->value;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->key = NULL;
|
||||
entry->value = NULL;
|
||||
}
|
||||
@ -353,7 +374,9 @@ HASHENTRIES *entry, *ptr;
|
||||
{
|
||||
ptr = table->entries[hashkey % table->hashsize];
|
||||
while (ptr && ptr->next != entry)
|
||||
{
|
||||
ptr = ptr->next;
|
||||
}
|
||||
if (ptr == NULL)
|
||||
{
|
||||
hashtable_write_unlock(table);
|
||||
@ -380,11 +403,13 @@ HASHENTRIES *entry, *ptr;
|
||||
void *
|
||||
hashtable_fetch(HASHTABLE *table, void *key)
|
||||
{
|
||||
unsigned int hashkey;
|
||||
HASHENTRIES *entry;
|
||||
unsigned int hashkey;
|
||||
HASHENTRIES *entry;
|
||||
|
||||
if(table == NULL || key == NULL || 0 == table->hashsize)
|
||||
if (table == NULL || key == NULL || 0 == table->hashsize)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hashkey = table->hashfn(key) % table->hashsize;
|
||||
hashtable_read_lock(table);
|
||||
@ -413,11 +438,13 @@ HASHENTRIES *entry;
|
||||
void
|
||||
hashtable_stats(HASHTABLE *table)
|
||||
{
|
||||
int total, longest, i, j;
|
||||
HASHENTRIES *entries;
|
||||
int total, longest, i, j;
|
||||
HASHENTRIES *entries;
|
||||
|
||||
if(table == NULL)
|
||||
if (table == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Hashtable: %p, size %d\n", table, table->hashsize);
|
||||
total = 0;
|
||||
@ -462,8 +489,7 @@ HASHENTRIES *entries;
|
||||
*
|
||||
*
|
||||
*/
|
||||
void hashtable_get_stats(
|
||||
void* table,
|
||||
void hashtable_get_stats(void* table,
|
||||
int* hashsize,
|
||||
int* nelems,
|
||||
int* longest)
|
||||
@ -493,7 +519,8 @@ void hashtable_get_stats(
|
||||
entries = entries->next;
|
||||
}
|
||||
*nelems += j;
|
||||
if (j > *longest) {
|
||||
if (j > *longest)
|
||||
{
|
||||
*longest = j;
|
||||
}
|
||||
}
|
||||
@ -529,7 +556,9 @@ hashtable_read_lock(HASHTABLE *table)
|
||||
{
|
||||
spinlock_release(&table->spin);
|
||||
while (table->writelock)
|
||||
{
|
||||
;
|
||||
}
|
||||
spinlock_acquire(&table->spin);
|
||||
}
|
||||
atomic_add(&table->n_readers, 1);
|
||||
@ -568,16 +597,22 @@ hashtable_read_unlock(HASHTABLE *table)
|
||||
static void
|
||||
hashtable_write_lock(HASHTABLE *table)
|
||||
{
|
||||
int available;
|
||||
int available;
|
||||
|
||||
spinlock_acquire(&table->spin);
|
||||
do {
|
||||
do
|
||||
{
|
||||
while (table->n_readers)
|
||||
{
|
||||
;
|
||||
}
|
||||
available = atomic_add(&table->writelock, 1);
|
||||
if (available != 0)
|
||||
{
|
||||
atomic_add(&table->writelock, -1);
|
||||
} while (available != 0);
|
||||
}
|
||||
}
|
||||
while (available != 0);
|
||||
spinlock_release(&table->spin);
|
||||
}
|
||||
|
||||
@ -601,7 +636,7 @@ hashtable_write_unlock(HASHTABLE *table)
|
||||
HASHITERATOR *
|
||||
hashtable_iterator(HASHTABLE *table)
|
||||
{
|
||||
HASHITERATOR *rval;
|
||||
HASHITERATOR *rval;
|
||||
|
||||
if ((rval = (HASHITERATOR *)malloc(sizeof(HASHITERATOR))) != NULL)
|
||||
{
|
||||
@ -621,11 +656,13 @@ HASHITERATOR *rval;
|
||||
void *
|
||||
hashtable_next(HASHITERATOR *iter)
|
||||
{
|
||||
int i;
|
||||
HASHENTRIES *entries;
|
||||
int i;
|
||||
HASHENTRIES *entries;
|
||||
|
||||
if(iter == NULL)
|
||||
if (iter == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
iter->depth++;
|
||||
while (iter->chain < iter->table->hashsize)
|
||||
@ -678,9 +715,9 @@ hashtable_save(HASHTABLE *table, char *filename,
|
||||
int (*keywrite)(int, void*),
|
||||
int (*valuewrite)(int, void*))
|
||||
{
|
||||
int fd, rval = 0;
|
||||
HASHITERATOR *iter;
|
||||
void *key, *value;
|
||||
int fd, rval = 0;
|
||||
HASHITERATOR *iter;
|
||||
void *key, *value;
|
||||
|
||||
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 */
|
||||
if(lseek(fd, 7L, SEEK_SET) != -1)
|
||||
if (lseek(fd, 7L, SEEK_SET) != -1)
|
||||
{
|
||||
write(fd, &rval, sizeof(rval));
|
||||
}
|
||||
@ -738,9 +775,9 @@ hashtable_load(HASHTABLE *table, char *filename,
|
||||
void *(*keyread)(int),
|
||||
void *(*valueread)(int))
|
||||
{
|
||||
int fd, count, rval = 0;
|
||||
void *key, *value;
|
||||
char buf[40];
|
||||
int fd, count, rval = 0;
|
||||
void *key, *value;
|
||||
char buf[40];
|
||||
|
||||
if ((fd = open(filename, O_RDONLY)) == -1)
|
||||
{
|
||||
|
@ -44,7 +44,8 @@
|
||||
* A NULL value for key indicates an empty entry.
|
||||
* 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 *value; /**< The value associated with key */
|
||||
struct hashentry *next; /**< The overflow chain */
|
||||
@ -54,9 +55,9 @@ typedef struct hashentry {
|
||||
* HASHTABLE iterator - used to walk the hashtable in a thread safe
|
||||
* way
|
||||
*/
|
||||
typedef struct hashiterator {
|
||||
struct hashtable
|
||||
*table; /**< The hashtable the iterator refers to */
|
||||
typedef struct hashiterator
|
||||
{
|
||||
struct hashtable *table; /**< The hashtable the iterator refers to */
|
||||
int chain; /**< The current chain we are walking */
|
||||
int depth; /**< The current depth down the chain */
|
||||
} HASHITERATOR;
|
||||
@ -69,7 +70,8 @@ typedef void *(*HASHMEMORYFN)(void *);
|
||||
/**
|
||||
* The general purpose hashtable struct.
|
||||
*/
|
||||
typedef struct hashtable {
|
||||
typedef struct hashtable
|
||||
{
|
||||
#if defined(SS_DEBUG)
|
||||
skygw_chk_t ht_chk_top;
|
||||
#endif
|
||||
@ -85,7 +87,7 @@ typedef struct hashtable {
|
||||
int n_readers; /**< Number of clients reading the table */
|
||||
int writelock; /**< The table is locked by a writer */
|
||||
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)
|
||||
skygw_chk_t ht_chk_tail;
|
||||
#endif
|
||||
@ -96,24 +98,23 @@ HASHTABLE *hashtable_alloc_flat(HASHTABLE* target,
|
||||
int size,
|
||||
int (*hashfn)(),
|
||||
int (*cmpfn)());
|
||||
/**< Allocate a hashtable */
|
||||
/**< Allocate a hashtable */
|
||||
extern void hashtable_memory_fns(HASHTABLE *table,
|
||||
HASHMEMORYFN kcopyfn,
|
||||
HASHMEMORYFN vcopyfn,
|
||||
HASHMEMORYFN kfreefn,
|
||||
HASHMEMORYFN vfreefn);
|
||||
/**< Provide an interface to control key/value memory
|
||||
/**< Provide an interface to control key/value memory
|
||||
* manipulation
|
||||
*/
|
||||
extern void hashtable_free(HASHTABLE *); /**< Free a hashtable */
|
||||
extern int hashtable_add(HASHTABLE *, void *, void *); /**< Add an entry */
|
||||
extern int hashtable_delete(HASHTABLE *, void *);
|
||||
/**< Delete an entry table */
|
||||
/**< Delete an entry table */
|
||||
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 */
|
||||
void hashtable_get_stats(
|
||||
void* hashtable,
|
||||
void hashtable_get_stats(void* hashtable,
|
||||
int* hashsize,
|
||||
int* nelems,
|
||||
int* longest);
|
||||
@ -127,9 +128,9 @@ extern int hashtable_load(HASHTABLE *,
|
||||
void *(*valueread)(int));
|
||||
|
||||
extern HASHITERATOR *hashtable_iterator(HASHTABLE *);
|
||||
/**< Allocate an iterator on the hashtable */
|
||||
/**< Allocate an iterator on the hashtable */
|
||||
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 int hashtable_size(HASHTABLE *table);
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user