#include #include #include "user_data.h" #include "util.h" #include "hashtable.h" struct user_data{ i64 userid; int *fds; i64 *last_active; i64 cap,len; }; static struct hashtable *user_hash=NULL; __attribute__((constructor)) static void userdata_constructor() { user_hash = ht_alloc(); } void userdata_register(i64 userid,int fd){ struct user_data *data=ht_find(user_hash, userid); if(data){ debug("userdata_register(%" PRIi64 ", %d) -> new fd",userid,fd); for(i64 i=0;ilen;i++){ if(data->fds[i]==fd){ die("userdata_register(%" PRIi64 ", %d) while pair already existed",userid,fd); } } 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); } data->fds[data->len]=fd; data->last_active[data->len]=make_timestamp(); data->len++; } else { debug("userdata_register(%" PRIi64 ", %d) -> new userid",userid,fd); 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){ debug("userdata_unregister(%" PRIi64 ", %d)",userid,fd); 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;ilen;i++){ if(data->fds[i]==fd)break; } if(i==data->len){ die("userdata_unregister(%" PRIi64 ", %d) while nonexistent",userid,fd); } if(ilen-1){ data->fds[i]=data->fds[data->len-1]; data->last_active[i]=data->last_active[data->len-1]; } data->len--; if(data->len==0){ ht_delete(user_hash,userid); } } void userdata_mark_active(i64 userid,int fd,bool active){ 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;ilen;i++){ if(data->fds[i]==fd)break; } if(i==data->len){ die("userdata_mark_active(%" PRIi64 ", %d, %d) while nonexistent",userid,fd,active); } data->last_active[i]=active?make_timestamp():-1; } bool userdata_is_active(i64 userid){ const struct user_data *data=ht_find(user_hash,userid); if(!data)return false; i64 last=0; 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){ const struct user_data *data=ht_find(user_hash,userid); if(!data){ if(nfds)*nfds=0; return NULL; } assert(data->len!=0); if(nfds)*nfds=data->len; return data->fds; }