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
|
#ifndef USER_DIRECTORY_H
#define USER_DIRECTORY_H
struct director;
#define USER_IS_BEING_KILLED(user) \
((user)->kill_ctx != NULL)
struct user {
/* Approximately sorted by time (except during handshaking).
The sorting order may be constantly wrong a few seconds here and
there. */
struct user *prev, *next;
/* first 32 bits of MD5(username). collisions are quite unlikely, but
even if they happen it doesn't matter - the users are just
redirected to same server */
unsigned int username_hash;
unsigned int timestamp;
struct mail_host *host;
/* If non-NULL, don't allow new connections until all
directors have killed the user's connections. */
struct director_kill_context *kill_ctx;
/* TRUE, if the user's timestamp was close to being expired and we're
now doing a ring-wide sync for this user to make sure we don't
assign conflicting hosts to it */
bool weak:1;
};
typedef void user_free_hook_t(struct user *);
/* Create a new directory. Users are dropped if their time gets older
than timeout_secs. */
struct user_directory *
user_directory_init(struct director *director, unsigned int timeout_secs,
user_free_hook_t *user_free_hook);
void user_directory_deinit(struct user_directory **dir);
/* Returns the number of users currently in directory. */
unsigned int user_directory_count(struct user_directory *dir);
/* Look up username from directory. Returns NULL if not found. */
struct user *user_directory_lookup(struct user_directory *dir,
unsigned int username_hash);
/* Add a user to directory and return it. */
struct user *
user_directory_add(struct user_directory *dir, unsigned int username_hash,
struct mail_host *host, time_t timestamp);
/* Refresh user's timestamp */
void user_directory_refresh(struct user_directory *dir, struct user *user);
/* Remove all users that have pointers to given host */
void user_directory_remove_host(struct user_directory *dir,
struct mail_host *host);
/* Sort users based on the timestamp. This is called only after updating
timestamps based on remote director's user list after handshake. */
void user_directory_sort(struct user_directory *dir);
bool user_directory_user_is_recently_updated(struct user_directory *dir,
struct user *user);
bool user_directory_user_is_near_expiring(struct user_directory *dir,
struct user *user);
/* Iterate through users in the directory. It's safe to modify user directory
while iterators are running. The removed users will just be skipped over.
Users that are refreshed (= moved to end of list) may be processed twice.
Using iter_until_current_tail=TRUE causes the iterator to not iterate
through any users that were added/refreshed since the iteration began.
Note that this may skip some users entirely. */
struct user_directory_iter *
user_directory_iter_init(struct user_directory *dir,
bool iter_until_current_tail);
struct user *user_directory_iter_next(struct user_directory_iter *iter);
void user_directory_iter_deinit(struct user_directory_iter **iter);
#endif
|