1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
#include <string.h>
#include <assert.h>
#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){
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(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 {
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 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<data->len;i++){
if(data->fds[i]==fd)break;
}
if(i==data->len){
die("userdata_unregister(%" PRIi64 ", %d) while nonexistent",userid,fd);
}
if(i<data->len-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;i<data->len;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;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){
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;
}
|