26
director_request_get_timeout_error(struct director_request *request)
28
string_t *str = t_str_new(128);
32
str_printfa(str, "Timeout - queued for %u secs (",
33
(unsigned int)(ioloop_time - request->create_time));
35
if (request->dir->ring_last_sync_time == 0)
36
str_append(str, "Ring has never been synced");
38
secs = ioloop_time - request->dir->ring_last_sync_time;
39
if (request->dir->ring_synced)
40
str_printfa(str, "Ring synced for %u secs", secs);
42
str_printfa(str, "Ring not synced for %u secs", secs);
45
user = user_directory_lookup(request->dir->users,
46
request->username_hash);
49
str_append(str, ", weak user");
50
str_printfa(str, ", user refreshed %u secs ago",
51
(unsigned int)(ioloop_time - user->timestamp));
53
str_append_c(str, ')');
24
57
static void director_request_timeout(struct director *dir)
26
59
struct director_request **requestp, *request;
28
62
while (array_count(&dir->pending_requests) > 0) {
29
63
requestp = array_idx_modifiable(&dir->pending_requests, 0);
36
70
array_delete(&dir->pending_requests, 0, 1);
37
request->callback(NULL, request->context);
71
errormsg = director_request_get_timeout_error(request);
73
request->callback(NULL, errormsg, request->context);
46
83
director_request_callback *callback, void *context)
48
85
struct director_request *request;
49
unsigned int username_hash = user_directory_get_username_hash(username);
86
unsigned int username_hash =
87
user_directory_get_username_hash(dir->users, username);
51
89
request = i_new(struct director_request, 1);
52
90
request->dir = dir;
89
127
ring_noconn_warning, dir);
130
static bool director_request_existing(struct director *dir, struct user *user)
132
struct mail_host *host;
134
if (user->kill_state != USER_KILL_STATE_NONE) {
135
/* delay processing this user's connections until
136
its existing connections have been killed */
140
/* wait for user to become non-weak */
143
if (!user_directory_user_is_near_expiring(dir->users, user))
146
/* user is close to being expired. another director may have
147
already expired it. */
148
host = mail_host_get_by_hash(dir->mail_hosts, user->username_hash);
149
if (!dir->ring_synced) {
150
/* try again later once ring is synced */
153
if (user->host == host) {
154
/* doesn't matter, other directors would
155
assign the user the same way regardless */
159
/* We have to worry about two separate timepoints in here:
161
a) some directors think the user isn't expiring, and
162
others think the user is near expiring
164
b) some directors think the user is near expiring, and
165
others think the user has already expired
167
What we don't have to worry about is:
169
!c) some directors think the user isn't expiring, and
170
others think the user has already expired
172
If !c) happens, the user might get redirected to different backends.
173
We'll use a large enough timeout between a) and b) states, so that
174
!c) should never happen.
176
So what we'll do here is:
178
1. Send a USER-WEAK notification to all directors with the new host.
179
2. Each director receiving USER-WEAK refreshes the user's timestamp
180
and host, but marks the user as being weak.
181
3. Once USER-WEAK has reached all directors, a real USER update is
182
sent, which removes the weak-flag.
183
4. If a director ever receives a USER update for a weak user, the
184
USER update overrides the host and removes the weak-flag.
185
5. Director doesn't let any weak user log in, until the weak-flag
188
if (dir->ring_min_version < DIRECTOR_VERSION_WEAK_USERS) {
189
/* weak users not supported by ring currently */
193
director_update_user_weak(dir, dir->self_host, NULL, user);
92
198
bool director_request_continue(struct director_request *request)
94
200
struct director *dir = request->dir;
104
210
user = user_directory_lookup(dir->users, request->username_hash);
105
211
if (user != NULL) {
106
if (user->kill_state != USER_KILL_STATE_NONE) {
107
/* delay processing this user's connections until
108
its existing connections have been killed */
212
if (!director_request_existing(dir, user))
111
214
user_directory_refresh(dir->users, user);
113
216
if (!dir->ring_synced) {