diff --git a/core/adminusers.c b/core/adminusers.c index ec3cb796b..c824e8b35 100644 --- a/core/adminusers.c +++ b/core/adminusers.c @@ -185,3 +185,14 @@ admin_test_user(char *user) return 0; return users_fetch(users, user) != NULL; } + +/** + * Print the statistics and user names of the administration users + * + * @param dcb A DCB to send the output to + */ +void +dcb_PrintAdminUsers(DCB *dcb) +{ + dcb_usersPrint(dcb, users); +} diff --git a/core/hashtable.c b/core/hashtable.c index a2e8bf873..cc20a1a27 100644 --- a/core/hashtable.c +++ b/core/hashtable.c @@ -51,6 +51,7 @@ * * Date Who Description * 23/06/13 Mark Riddoch Initial implementation + * 23/07/13 Mark Riddoch Addition of hashtable iterator * * @endverbatim */ @@ -437,3 +438,68 @@ hashtable_write_unlock(HASHTABLE *table) { atomic_add(&table->writelock, -1); } + +/** + * Create an iterator on a hash table + * + * @param table The table to ceate an iterator on + * @return An iterator to use in future calls + */ +HASHITERATOR * +hashtable_iterator(HASHTABLE *table) +{ +HASHITERATOR *rval; + + if ((rval = (HASHITERATOR *)malloc(sizeof(HASHITERATOR))) != NULL) + { + rval->table = table; + rval->chain = 0; + rval->depth = -1; + } + return rval; +} + +/** + * Return the next key for a hashtable iterator + * + * @param iter The hashtable iterator + * @return The next key value or NULL + */ +void * +hashtable_next(HASHITERATOR *iter) +{ +int i; +HASHENTRIES *entries; + + iter->depth++; + while (iter->chain < iter->table->hashsize) + { + if ((entries = iter->table->entries[iter->chain]) != NULL) + { + i = 0; + hashtable_read_lock(iter->table); + while (entries && i < iter->depth) + { + entries = entries->next; + i++; + } + hashtable_read_unlock(iter->table); + if (entries) + return entries->key; + } + iter->depth = 0; + iter->chain++; + } + return NULL; +} + +/** + * Free a hashtable iterator + * + * @param iter The iterator to free + */ +void +hashtable_iterator_free(HASHITERATOR *iter) +{ + free(iter); +} diff --git a/core/users.c b/core/users.c index 427ad743a..a836f6ad2 100644 --- a/core/users.c +++ b/core/users.c @@ -170,6 +170,20 @@ usersPrint(USERS *users) void dcb_usersPrint(DCB *dcb, USERS *users) { +HASHITERATOR *iter; +char *sep, *user; + dcb_printf(dcb, "Users table data\n"); dcb_hashtable_stats(dcb, users->data); + if ((iter = hashtable_iterator(users->data)) != NULL) + { + dcb_printf(dcb, "User names: "); + sep = ""; + while ((user = hashtable_next(iter)) != NULL) + { + dcb_printf(dcb, "%s%s", sep, user); + sep = ", "; + } + dcb_printf(dcb, "\n"); + } } diff --git a/include/adminusers.h b/include/adminusers.h index 1d38e24cb..16c61c26d 100644 --- a/include/adminusers.h +++ b/include/adminusers.h @@ -34,5 +34,7 @@ extern int admin_verify(char *, char *); extern char *admin_add_user(char *, char *); extern int admin_test_user(char *); +extern void dcb_PrintAdminUsers(DCB *dcb); + #endif diff --git a/include/hashtable.h b/include/hashtable.h index 5a571bb3b..be7075c2c 100644 --- a/include/hashtable.h +++ b/include/hashtable.h @@ -27,6 +27,7 @@ * * Date Who Description * 23/06/13 Mark Riddoch Initial implementation + * 23/07/13 Mark Riddoch Addition of iterator mechanism * * @endverbatim */ @@ -46,6 +47,17 @@ typedef struct hashentry { struct hashentry *next; /**< The overflow chain */ } HASHENTRIES; +/** + * HASHTABLE iterator - used to walk the hashtable in a thread safe + * way + */ +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; + /** * The type definition for the memory allocation functions */ @@ -80,4 +92,9 @@ extern void *hashtable_fetch(HASHTABLE *, void *); /**< Fetch the data for a given key */ extern void hashtable_stats(HASHTABLE *); /**< Print statisitics */ extern void dcb_hashtable_stats(DCB *, HASHTABLE *); /**< Print statisitics */ +extern HASHITERATOR *hashtable_iterator(HASHTABLE *); + /**< Allocate an iterator on the hashtable */ +extern void *hashtable_next(HASHITERATOR *); + /**< Return the key of the hash table iterator */ +extern void hashtable_iterator_free(HASHITERATOR *); #endif diff --git a/modules/routing/debugcmd.c b/modules/routing/debugcmd.c index fb2ee398e..de460c0d5 100644 --- a/modules/routing/debugcmd.c +++ b/modules/routing/debugcmd.c @@ -75,6 +75,7 @@ struct subcommand { int arg_types[3]; }; +static void telnetdShowUsers(DCB *); /** * The subcommands of the show command */ @@ -97,7 +98,9 @@ struct subcommand showoptions[] = { {ARG_TYPE_ADDRESS, 0, 0} }, { "epoll", 0, dprintPollStats, "Show the poll statistics", {0, 0, 0} }, - { "users", 1, dcb_usersPrint, "Show statistics for a users table", + { "dbusers", 1, dcb_usersPrint, "Show statistics and user names for a service's user table", + {ARG_TYPE_ADDRESS, 0, 0} }, + { "users", 0, telnetdShowUsers, "Show statistics and user names for the debug interface", {ARG_TYPE_ADDRESS, 0, 0} }, { NULL, 0, NULL, NULL, {0, 0, 0} } @@ -503,3 +506,15 @@ char *err; else dcb_printf(dcb, "Failed to add new user. %s\n", err); } + +/** + * Print the adminsitration users + * + * @param dcb The DCB to print the user data to + */ +static void +telnetdShowUsers(DCB *dcb) +{ + dcb_printf(dcb, "Administration interface users:\n"); + dcb_PrintAdminUsers(dcb); +}