Optimize lookups by CID and nick.
This used to be a linear search O(n), but is now done as a red-black tree O(log n) instead. These operations can be further opimized with a hash-table which would acheive near constant time lookups.
This commit is contained in:
parent
52211a6bac
commit
cd5c4ee622
|
@ -38,6 +38,11 @@ static void clear_user_list_callback(void* ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int uman_map_compare(const void* a, const void* b)
|
||||||
|
{
|
||||||
|
return strcmp((const char*) a, (const char*) b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct hub_user_manager* uman_init()
|
struct hub_user_manager* uman_init()
|
||||||
{
|
{
|
||||||
|
@ -46,15 +51,10 @@ struct hub_user_manager* uman_init()
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
users->list = list_create();
|
users->list = list_create();
|
||||||
|
users->nickmap = rb_tree_create(uman_map_compare, NULL, NULL);
|
||||||
|
users->cidmap = rb_tree_create(uman_map_compare, NULL, NULL);
|
||||||
users->sids = sid_pool_create(net_get_max_sockets());
|
users->sids = sid_pool_create(net_get_max_sockets());
|
||||||
|
|
||||||
if (!users->list)
|
|
||||||
{
|
|
||||||
list_destroy(users->list);
|
|
||||||
hub_free(users);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,11 +64,18 @@ int uman_shutdown(struct hub_user_manager* users)
|
||||||
if (!users)
|
if (!users)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (users->nickmap)
|
||||||
|
rb_tree_destroy(users->nickmap);
|
||||||
|
|
||||||
|
if (users->cidmap)
|
||||||
|
rb_tree_destroy(users->cidmap);
|
||||||
|
|
||||||
if (users->list)
|
if (users->list)
|
||||||
{
|
{
|
||||||
list_clear(users->list, &clear_user_list_callback);
|
list_clear(users->list, &clear_user_list_callback);
|
||||||
list_destroy(users->list);
|
list_destroy(users->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
sid_pool_destroy(users->sids);
|
sid_pool_destroy(users->sids);
|
||||||
|
|
||||||
hub_free(users);
|
hub_free(users);
|
||||||
|
@ -81,6 +88,9 @@ int uman_add(struct hub_user_manager* users, struct hub_user* user)
|
||||||
if (!users || !user)
|
if (!users || !user)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
rb_tree_insert(users->nickmap, user->id.nick, user);
|
||||||
|
rb_tree_insert(users->cidmap, user->id.cid, user);
|
||||||
|
|
||||||
list_append(users->list, user);
|
list_append(users->list, user);
|
||||||
users->count++;
|
users->count++;
|
||||||
users->count_peak = MAX(users->count, users->count_peak);
|
users->count_peak = MAX(users->count, users->count_peak);
|
||||||
|
@ -96,6 +106,8 @@ int uman_remove(struct hub_user_manager* users, struct hub_user* user)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
list_remove(users->list, user);
|
list_remove(users->list, user);
|
||||||
|
rb_tree_remove(users->nickmap, user->id.nick);
|
||||||
|
rb_tree_remove(users->cidmap, user->id.cid);
|
||||||
|
|
||||||
if (users->count > 0)
|
if (users->count > 0)
|
||||||
{
|
{
|
||||||
|
@ -120,25 +132,15 @@ struct hub_user* uman_get_user_by_sid(struct hub_user_manager* users, sid_t sid)
|
||||||
|
|
||||||
struct hub_user* uman_get_user_by_cid(struct hub_user_manager* users, const char* cid)
|
struct hub_user* uman_get_user_by_cid(struct hub_user_manager* users, const char* cid)
|
||||||
{
|
{
|
||||||
struct hub_user* user;
|
struct hub_user* user = (struct hub_user*) rb_tree_get(users->cidmap, (const void*) cid);
|
||||||
LIST_FOREACH(struct hub_user*, user, users->list,
|
|
||||||
{
|
|
||||||
if (strcmp(user->id.cid, cid) == 0)
|
|
||||||
return user;
|
return user;
|
||||||
});
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, const char* nick)
|
struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, const char* nick)
|
||||||
{
|
{
|
||||||
struct hub_user* user;
|
struct hub_user* user = (struct hub_user*) rb_tree_get(users->nickmap, nick);
|
||||||
LIST_FOREACH(struct hub_user*, user, users->list,
|
|
||||||
{
|
|
||||||
if (strcmp(user->id.nick, nick) == 0)
|
|
||||||
return user;
|
return user;
|
||||||
});
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range)
|
size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range)
|
||||||
|
|
|
@ -24,10 +24,12 @@ struct hub_user_manager
|
||||||
{
|
{
|
||||||
size_t count; /**<< "Number of all fully connected and logged in users" */
|
size_t count; /**<< "Number of all fully connected and logged in users" */
|
||||||
size_t count_peak; /**<< "Peak number of users" */
|
size_t count_peak; /**<< "Peak number of users" */
|
||||||
struct sid_pool* sids;
|
|
||||||
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
|
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
|
||||||
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
|
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
|
||||||
|
struct sid_pool* sids; /**<< "Maps SIDs to users (constant time)" */
|
||||||
struct linked_list* list; /**<< "Contains all logged in users" */
|
struct linked_list* list; /**<< "Contains all logged in users" */
|
||||||
|
struct rb_tree* nickmap; /**<< "Maps nicknames to users (red black tree)" */
|
||||||
|
struct rb_tree* cidmap; /**<< "Maps CIDs to users (red black tree)" */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -69,6 +69,7 @@ extern "C" {
|
||||||
#include "util/misc.h"
|
#include "util/misc.h"
|
||||||
#include "util/tiger.h"
|
#include "util/tiger.h"
|
||||||
#include "util/threads.h"
|
#include "util/threads.h"
|
||||||
|
#include "util/rbtree.h"
|
||||||
|
|
||||||
#include "adc/sid.h"
|
#include "adc/sid.h"
|
||||||
#include "adc/message.h"
|
#include "adc/message.h"
|
||||||
|
|
|
@ -157,7 +157,7 @@ static struct rb_node* rb_tree_insert_r(struct rb_tree* tree, struct rb_node* no
|
||||||
|
|
||||||
struct rb_tree* rb_tree_create(rb_tree_compare compare, rb_tree_alloc a, rb_tree_free f)
|
struct rb_tree* rb_tree_create(rb_tree_compare compare, rb_tree_alloc a, rb_tree_free f)
|
||||||
{
|
{
|
||||||
struct rb_tree* tree = a(sizeof(struct rb_tree));
|
struct rb_tree* tree = a ? a(sizeof(struct rb_tree)) : hub_malloc(sizeof(struct rb_tree));
|
||||||
tree->compare = compare;
|
tree->compare = compare;
|
||||||
tree->alloc = a ? a : hub_malloc;
|
tree->alloc = a ? a : hub_malloc;
|
||||||
tree->free = f ? f : hub_free;
|
tree->free = f ? f : hub_free;
|
||||||
|
|
Loading…
Reference in New Issue