From 191fc6cf55df805d36555a26177da0eac65b6261 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Sat, 4 Jul 2020 14:23:02 +0200 Subject: server: Use hashtable implementation for user_data --- user_data.c | 128 ++++++++++++++++++++++++------------------------------------ 1 file changed, 50 insertions(+), 78 deletions(-) diff --git a/user_data.c b/user_data.c index f92d4d4..6b9b041 100644 --- a/user_data.c +++ b/user_data.c @@ -2,6 +2,7 @@ #include #include "user_data.h" #include "util.h" +#include "hashtable.h" struct user_data{ @@ -12,124 +13,95 @@ struct user_data{ i64 cap,len; }; -struct hash_item{ - struct user_data data; - struct hash_item *next; -}; - -#define USER_HASH_SIZE (16) -static struct hash_item *user_hash[USER_HASH_SIZE]; +static struct hashtable *user_hash=NULL; - -static struct hash_item* find_userdata(i64 userid){ - struct hash_item *item=user_hash[userid%USER_HASH_SIZE]; - while(item&&item->data.userid!=userid)item=item->next; - return item; -} - -static void remove_userdata(i64 userid){ - struct hash_item *item=user_hash[userid%USER_HASH_SIZE]; - assert(item); - if(item->data.userid==userid){ - user_hash[userid%USER_HASH_SIZE]=item->next; - free(item->data.fds); - free(item); - return; - } - struct hash_item *parent=NULL; - while(item->data.userid!=userid){ - parent=item; - item=item->next; - assert(item); - } - parent->next=item->next; - free(item->data.fds); - free(item); +__attribute__((constructor)) +static void userdata_constructor() { + user_hash = ht_alloc(); } void userdata_register(i64 userid,int fd){ - struct hash_item *item=find_userdata(userid); - if(item){ - for(i64 i=0;idata.len;i++){ - if(item->data.fds[i]==fd){ + struct user_data *data=ht_find(user_hash, userid); + if(data){ + for(i64 i=0;ilen;i++){ + if(data->fds[i]==fd){ die("userdata_register(%" PRIi64 ", %d) while pair already existed",userid,fd); } } - if(item->data.len==item->data.cap){ - item->data.cap*=2; - item->data.fds=realloc(item->data.fds,item->data.cap,int); - item->data.last_active=realloc(item->data.last_active,item->data.cap,i64); + if(data->len==data->cap){ + data->cap*=2; + data->fds=realloc(data->fds,data->cap,int); + data->last_active=realloc(data->last_active,data->cap,i64); } - item->data.fds[item->data.len]=fd; - item->data.last_active[item->data.len]=make_timestamp(); - item->data.len++; + data->fds[data->len]=fd; + data->last_active[data->len]=make_timestamp(); + data->len++; } else { - item=malloc(1,struct hash_item); - item->data.userid=userid; - item->data.cap=2; - item->data.len=1; - item->data.fds=malloc(item->data.cap,int); - item->data.fds[0]=fd; - item->data.last_active=malloc(item->data.cap,i64); - item->data.last_active[0]=make_timestamp(); - item->next=user_hash[userid%USER_HASH_SIZE]; - user_hash[userid%USER_HASH_SIZE]=item; + data=malloc(1, struct user_data); + data->userid=userid; + data->cap=2; + data->len=1; + data->fds=malloc(data->cap,int); + data->fds[0]=fd; + data->last_active=malloc(data->cap,i64); + data->last_active[0]=make_timestamp(); + ht_insert(user_hash,userid,data); } } void userdata_unregister(i64 userid,int fd){ - struct hash_item *item=find_userdata(userid); - if(!item){ + struct user_data *data=ht_find(user_hash,userid); + if(!data){ die("userdata_unregister(%" PRIi64 ", %d) while nonexistent",userid,fd); } i64 i; - for(i=0;idata.len;i++){ - if(item->data.fds[i]==fd)break; + for(i=0;ilen;i++){ + if(data->fds[i]==fd)break; } - if(i==item->data.len){ + if(i==data->len){ die("userdata_unregister(%" PRIi64 ", %d) while nonexistent",userid,fd); } - memmove(item->data.fds+i,item->data.fds+i+1,item->data.len-i-1); - memmove(item->data.last_active+i,item->data.last_active+i+1,item->data.len-i-1); - item->data.len--; - if(item->data.len==0){ - remove_userdata(userid); + memmove(data->fds+i,data->fds+i+1,data->len-i-1); + memmove(data->last_active+i,data->last_active+i+1,data->len-i-1); + data->len--; + if(data->len==0){ + ht_delete(user_hash,userid); } } void userdata_mark_active(i64 userid,int fd,bool active){ - struct hash_item *item=find_userdata(userid); - if(!item){ + struct user_data *data=ht_find(user_hash,userid); + if(!data){ die("userdata_mark_active(%" PRIi64 ", %d, %d) with nonexistent userid",userid,fd,active); } i64 i; - for(i=0;idata.len;i++){ - if(item->data.fds[i]==fd)break; + for(i=0;ilen;i++){ + if(data->fds[i]==fd)break; } - if(i==item->data.len){ + if(i==data->len){ die("userdata_mark_active(%" PRIi64 ", %d, %d) while nonexistent",userid,fd,active); } - item->data.last_active[i]=active?make_timestamp():-1; + data->last_active[i]=active?make_timestamp():-1; } bool userdata_is_active(i64 userid){ - struct hash_item *item=find_userdata(userid); - if(!item)return false; + const struct user_data *data=ht_find(user_hash,userid); + if(!data)return false; i64 last=0; - for(i64 i=0;idata.len;i++){ - if(item->data.last_active[i]>last)last=item->data.last_active[i]; + for(i64 i=0;ilen;i++){ + if(data->last_active[i]>last)last=data->last_active[i]; } return make_timestamp()-last<2*60*1000*1000; } const int* userdata_online(i64 userid,i64 *nfds){ - struct hash_item *item=find_userdata(userid); - if(!item){ + const struct user_data *data=ht_find(user_hash,userid); + if(!data){ if(nfds)*nfds=0; return NULL; } - assert(item->data.len!=0); - if(nfds)*nfds=item->data.len; - return item->data.fds; + assert(data->len!=0); + if(nfds)*nfds=data->len; + return data->fds; } -- cgit v1.2.3-70-g09d2