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);
|
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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user