Implementation of the users table and a generic hashtable mechanism
This commit is contained in:
@ -408,7 +408,7 @@ users.o: users.c /usr/include/stdlib.h /usr/include/features.h \
|
|||||||
/usr/include/bits/sigset.h /usr/include/bits/time.h \
|
/usr/include/bits/sigset.h /usr/include/bits/time.h \
|
||||||
/usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
|
/usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
|
||||||
/usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
|
/usr/include/alloca.h /usr/include/string.h /usr/include/xlocale.h \
|
||||||
../include/users.h ../include/hashtable.h
|
../include/users.h ../include/hashtable.h ../include/atomic.h
|
||||||
hashtable.o: hashtable.c /usr/include/stdlib.h /usr/include/features.h \
|
hashtable.o: hashtable.c /usr/include/stdlib.h /usr/include/features.h \
|
||||||
/usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
|
/usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
|
||||||
/usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
|
/usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
|
||||||
|
197
core/hashtable.c
197
core/hashtable.c
@ -31,9 +31,22 @@
|
|||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special null function used as default memory allfunctions in the hashtable
|
||||||
|
* implementation. This avoids havign to special case the code that manipulates
|
||||||
|
* the keys and values
|
||||||
|
*
|
||||||
|
* @param data The data pointer
|
||||||
|
* @return Return the value we were called with
|
||||||
|
*/
|
||||||
|
static void *
|
||||||
|
nullfn(void *data)
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate a new users table
|
* Allocate a new hash table
|
||||||
*
|
*
|
||||||
* @param size The size of the hash table
|
* @param size The size of the hash table
|
||||||
* @param hashfn The user supplied hash function
|
* @param hashfn The user supplied hash function
|
||||||
@ -50,6 +63,8 @@ HASHTABLE *rval;
|
|||||||
rval->hashsize = size;
|
rval->hashsize = size;
|
||||||
rval->hashfn = hashfn;
|
rval->hashfn = hashfn;
|
||||||
rval->cmpfn = cmpfn;
|
rval->cmpfn = cmpfn;
|
||||||
|
rval->copyfn = nullfn;
|
||||||
|
rval->freefn = nullfn;
|
||||||
if ((rval->entries = calloc(size, sizeof(HASHENTRIES))) == NULL)
|
if ((rval->entries = calloc(size, sizeof(HASHENTRIES))) == NULL)
|
||||||
{
|
{
|
||||||
free(rval);
|
free(rval);
|
||||||
@ -60,3 +75,183 @@ HASHTABLE *rval;
|
|||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete an entire hash table
|
||||||
|
*
|
||||||
|
* @param table The hash table to delete
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
hashtable_free(HASHTABLE *table)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
HASHENTRIES *entry, *ptr;
|
||||||
|
|
||||||
|
for (i = 0; i < table->hashsize; i++)
|
||||||
|
{
|
||||||
|
entry = table->entries[i];
|
||||||
|
if (entry->key)
|
||||||
|
{
|
||||||
|
table->freefn(entry->key);
|
||||||
|
table->freefn(entry->value);
|
||||||
|
}
|
||||||
|
entry = entry->next;
|
||||||
|
while (entry)
|
||||||
|
{
|
||||||
|
ptr = entry->next;
|
||||||
|
table->freefn(entry->key);
|
||||||
|
table->freefn(entry->value);
|
||||||
|
free(entry);
|
||||||
|
entry = ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(table->entries);
|
||||||
|
free(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide memory management functions to the hash table. This allows
|
||||||
|
* function pointers to be registered that can make copies of the
|
||||||
|
* key and value.
|
||||||
|
*
|
||||||
|
* @param table The hash table
|
||||||
|
* @param copyfn The copy function
|
||||||
|
* @param freefn The free function
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
hashtable_memory_fns(HASHTABLE *table, HASHMEMORYFN copyfn, HASHMEMORYFN freefn)
|
||||||
|
{
|
||||||
|
table->copyfn = copyfn;
|
||||||
|
table->freefn = freefn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an item to the hash table.
|
||||||
|
*
|
||||||
|
* @param table The hash table to which to add the item
|
||||||
|
* @param key The key of the item
|
||||||
|
* @param value The value for the item
|
||||||
|
* @return Return the number of items added
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
hashtable_add(HASHTABLE *table, void *key, void *value)
|
||||||
|
{
|
||||||
|
int hashkey = table->hashfn(key);
|
||||||
|
HASHENTRIES *entry;
|
||||||
|
|
||||||
|
entry = table->entries[hashkey % table->hashsize];
|
||||||
|
while (entry->next && entry->key && table->cmpfn(key, entry->key) != 0)
|
||||||
|
{
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
if (entry->key == NULL)
|
||||||
|
{
|
||||||
|
/* Entry is empty - special case for first insert */
|
||||||
|
entry->key = table->copyfn(key);
|
||||||
|
entry->value = table->copyfn(value);
|
||||||
|
}
|
||||||
|
else if (table->cmpfn(key, entry->key) == 0)
|
||||||
|
{
|
||||||
|
/* Duplicate key value */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HASHENTRIES *ptr = (HASHENTRIES *)malloc(sizeof(HASHENTRIES));
|
||||||
|
if (ptr == NULL)
|
||||||
|
return 0;
|
||||||
|
ptr->key = table->copyfn(key);
|
||||||
|
ptr->value = table->copyfn(value);
|
||||||
|
ptr->next = NULL;
|
||||||
|
entry->next = ptr;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete an item from the hash table that has a given key
|
||||||
|
*
|
||||||
|
* @param table The hash table to delete from
|
||||||
|
* @param key The key value of the item to remove
|
||||||
|
* @return Return the number of items deleted
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
hashtable_delete(HASHTABLE *table, void *key)
|
||||||
|
{
|
||||||
|
int hashkey = table->hashfn(key);
|
||||||
|
HASHENTRIES *entry, *ptr;
|
||||||
|
|
||||||
|
entry = table->entries[hashkey % table->hashsize];
|
||||||
|
while (entry && entry->key && table->cmpfn(key, entry->key) != 0)
|
||||||
|
{
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
if (entry == NULL || entry->key == NULL)
|
||||||
|
{
|
||||||
|
/* Not found */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry == table->entries[hashkey % table->hashsize])
|
||||||
|
{
|
||||||
|
/* We are removing from the special first entry */
|
||||||
|
if (entry->next)
|
||||||
|
{
|
||||||
|
table->freefn(entry->key);
|
||||||
|
table->freefn(entry->value);
|
||||||
|
entry->key = entry->next->key;
|
||||||
|
entry->value = entry->next->value;
|
||||||
|
ptr = entry->next;
|
||||||
|
entry->next = ptr->next;
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
table->freefn(entry->key);
|
||||||
|
table->freefn(entry->value);
|
||||||
|
entry->key = NULL;
|
||||||
|
entry->value = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptr = table->entries[hashkey % table->hashsize];
|
||||||
|
while (ptr && ptr->next != entry)
|
||||||
|
ptr = ptr->next;
|
||||||
|
if (ptr == NULL)
|
||||||
|
return 0; /* This should never happen */
|
||||||
|
ptr->next = entry->next;
|
||||||
|
table->freefn(entry->key);
|
||||||
|
table->freefn(entry->value);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch an item with a given key value from the hash table
|
||||||
|
*
|
||||||
|
* @param table The hash table
|
||||||
|
* @param key The key value
|
||||||
|
* @return The item or NULL if the item was not found
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
hashtable_fetch(HASHTABLE *table, void *key)
|
||||||
|
{
|
||||||
|
int hashkey = table->hashfn(key);
|
||||||
|
HASHENTRIES *entry;
|
||||||
|
|
||||||
|
entry = table->entries[hashkey % table->hashsize];
|
||||||
|
while (entry && entry->key && table->cmpfn(key, entry->key) != 0)
|
||||||
|
{
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
if (entry == NULL || entry->key == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return entry->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ SERVICE *service;
|
|||||||
service->state = SERVICE_STATE_ALLOC;
|
service->state = SERVICE_STATE_ALLOC;
|
||||||
service->credentials.name = NULL;
|
service->credentials.name = NULL;
|
||||||
service->credentials.authdata = NULL;
|
service->credentials.authdata = NULL;
|
||||||
service->users = NULL;
|
service->users = users_alloc();
|
||||||
|
|
||||||
spinlock_acquire(&service_spin);
|
spinlock_acquire(&service_spin);
|
||||||
service->next = allServices;
|
service->next = allServices;
|
||||||
|
67
core/users.c
67
core/users.c
@ -18,6 +18,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <users.h>
|
#include <users.h>
|
||||||
|
#include <atomic.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file users.c User table maintenance routines
|
* @file users.c User table maintenance routines
|
||||||
@ -40,7 +41,7 @@
|
|||||||
static int
|
static int
|
||||||
user_hash(char *key)
|
user_hash(char *key)
|
||||||
{
|
{
|
||||||
return (*key + *(key + 1)) % 52;
|
return (*key + *(key + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,6 +63,70 @@ USERS *rval;
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hashtable_memory_fns(rval->data, (HASHMEMORYFN)strdup, (HASHMEMORYFN)free);
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the users table
|
||||||
|
*
|
||||||
|
* @param users The users table to remove
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
users_free(USERS *users)
|
||||||
|
{
|
||||||
|
hashtable_free(users->data);
|
||||||
|
free(users);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new user to the user table. The user name must be unique
|
||||||
|
*
|
||||||
|
* @param users The users table
|
||||||
|
* @param user The user name
|
||||||
|
* @param auth The authentication data
|
||||||
|
* @return The number of users added to the table
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
users_add(USERS *users, char *user, char *auth)
|
||||||
|
{
|
||||||
|
int add;
|
||||||
|
|
||||||
|
atomic_add(&users->stats.n_adds, 1);
|
||||||
|
add = hashtable_add(users->data, user, auth);
|
||||||
|
atomic_add(&users->stats.n_entries, add);
|
||||||
|
return add;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a user from the user table.
|
||||||
|
*
|
||||||
|
* @param users The users table
|
||||||
|
* @param user The user name
|
||||||
|
* @return The number of users deleted from the table
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
users_delete(USERS *users, char *user)
|
||||||
|
{
|
||||||
|
int del;
|
||||||
|
|
||||||
|
atomic_add(&users->stats.n_deletes, 1);
|
||||||
|
del = hashtable_delete(users->data, user);
|
||||||
|
atomic_add(&users->stats.n_entries, del * -1);
|
||||||
|
return del;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the authentication data for a particular user from the users table
|
||||||
|
*
|
||||||
|
* @param users The users table
|
||||||
|
* @param user The user name
|
||||||
|
* @return The authentication data or NULL on error
|
||||||
|
*/
|
||||||
|
char
|
||||||
|
*users_fetch(USERS *users, char *user)
|
||||||
|
{
|
||||||
|
atomic_add(&users->stats.n_fetches, 1);
|
||||||
|
return hashtable_fetch(users->data, user);
|
||||||
|
}
|
||||||
|
@ -38,25 +38,38 @@
|
|||||||
* 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 */
|
||||||
} HASHENTRIES;
|
} HASHENTRIES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type definition for the memory allocation functions
|
||||||
|
*/
|
||||||
|
typedef void *(*HASHMEMORYFN)(void *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The general purpose hashtable struct.
|
* The general purpose hashtable struct.
|
||||||
*/
|
*/
|
||||||
typedef struct hashtable {
|
typedef struct hashtable {
|
||||||
int hashsize; /**< The number of HASHENTRIES */
|
int hashsize; /**< The number of HASHENTRIES */
|
||||||
HASHENTRIES *entries; /**< The entries themselves */
|
HASHENTRIES **entries; /**< The entries themselves */
|
||||||
int (*hashfn)(void *); /**< The hash function */
|
int (*hashfn)(void *); /**< The hash function */
|
||||||
int (*cmpfn)(void *, void *); /**< The key comparison function */
|
int (*cmpfn)(void *, void *); /**< The key comparison function */
|
||||||
|
HASHMEMORYFN copyfn; /**< Optional copy function */
|
||||||
|
HASHMEMORYFN freefn; /**< Optional free function */
|
||||||
} HASHTABLE;
|
} HASHTABLE;
|
||||||
|
|
||||||
extern HASHTABLE *hashtable_alloc(int, int (*hashfn)(),
|
extern HASHTABLE *hashtable_alloc(int, int (*hashfn)(), int (*cmpfn)());
|
||||||
int (*cmpfn)()); /**< Allocate a hashtable */
|
/**< Allocate a hashtable */
|
||||||
|
extern void hashtable_memory_fns(HASHTABLE *, HASHMEMORYFN, HASHMEMORYFN);
|
||||||
|
/**< Provide an interface to control key/value memory
|
||||||
|
* manipulation
|
||||||
|
*/
|
||||||
extern void hashtable_free(HASHTABLE *); /**< Free a hashtable */
|
extern void hashtable_free(HASHTABLE *); /**< Free a hashtable */
|
||||||
extern int hashtable_add(HASHTABLE *, char *, void *); /**< Add an entry */
|
extern int hashtable_add(HASHTABLE *, void *, void *); /**< Add an entry */
|
||||||
extern int hashtable_delete(HASHTABLE *, char *); /**< Delete an entry table */
|
extern int hashtable_delete(HASHTABLE *, void *);
|
||||||
extern void *hashtable_fetch(HASHTABLE *, char *); /**< Fetch the data for a given key */
|
/**< Delete an entry table */
|
||||||
|
extern void *hashtable_fetch(HASHTABLE *, void *);
|
||||||
|
/**< Fetch the data for a given key */
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,12 +31,26 @@
|
|||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The users table statistics structure
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int n_entries; /**< The number of entries */
|
||||||
|
int n_adds; /**< The number of inserts */
|
||||||
|
int n_deletes; /**< The number of deletes */
|
||||||
|
int n_fetches; /**< The number of fetchs */
|
||||||
|
} USERS_STATS;
|
||||||
|
/**
|
||||||
|
* The user table, this contains the username and authentication data required
|
||||||
|
* for the authentication implementation within the gateway.
|
||||||
|
*/
|
||||||
typedef struct users {
|
typedef struct users {
|
||||||
HASHTABLE *data;
|
HASHTABLE *data; /**< The hashtable containing the actual data */
|
||||||
|
USERS_STATS stats; /**< The statistics for the users table */
|
||||||
} USERS;
|
} USERS;
|
||||||
|
|
||||||
extern USERS *users_alloc(); /**< Allocate a users table */
|
extern USERS *users_alloc(); /**< Allocate a users table */
|
||||||
extern users_free(USERS *); /**< Free a users table */
|
extern void users_free(USERS *); /**< Free a users table */
|
||||||
extern int users_add(USERS *, char *, char *); /**< Add a user to the users table */
|
extern int users_add(USERS *, char *, char *); /**< Add a user to the users table */
|
||||||
extern int users_delete(USERS *, char *); /**< Delete a user from the users table */
|
extern int users_delete(USERS *, char *); /**< Delete a user from the users table */
|
||||||
extern char *users_fetch(USERS *, char *); /**< Fetch the authentication data for a user */
|
extern char *users_fetch(USERS *, char *); /**< Fetch the authentication data for a user */
|
||||||
|
Reference in New Issue
Block a user