aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2020-07-04 14:23:02 +0200
committerTom Smeding <tom.smeding@gmail.com>2020-07-04 14:25:53 +0200
commit191fc6cf55df805d36555a26177da0eac65b6261 (patch)
tree41de53261bb36a88c2de5d83cc7f613a3ebea9d3
parent9e509673ef53e9a2aa412c16a9752afed1f98869 (diff)
server: Use hashtable implementation for user_data
-rw-r--r--user_data.c128
1 files 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 <assert.h>
#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;i<item->data.len;i++){
- if(item->data.fds[i]==fd){
+ struct user_data *data=ht_find(user_hash, userid);
+ if(data){
+ for(i64 i=0;i<data->len;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;i<item->data.len;i++){
- if(item->data.fds[i]==fd)break;
+ for(i=0;i<data->len;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;i<item->data.len;i++){
- if(item->data.fds[i]==fd)break;
+ for(i=0;i<data->len;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;i<item->data.len;i++){
- if(item->data.last_active[i]>last)last=item->data.last_active[i];
+ for(i64 i=0;i<data->len;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;
}