diff options
| author | Tom Smeding <tom.smeding@gmail.com> | 2020-07-04 14:23:02 +0200 | 
|---|---|---|
| committer | Tom Smeding <tom.smeding@gmail.com> | 2020-07-04 14:25:53 +0200 | 
| commit | 191fc6cf55df805d36555a26177da0eac65b6261 (patch) | |
| tree | 41de53261bb36a88c2de5d83cc7f613a3ebea9d3 | |
| parent | 9e509673ef53e9a2aa412c16a9752afed1f98869 (diff) | |
server: Use hashtable implementation for user_data
| -rw-r--r-- | user_data.c | 128 | 
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;  } | 
