director_user_move_free(user);
}
-static void
-director_kill_user(struct director *dir, struct director_host *src,
- struct user *user, struct mail_tag *tag,
- struct mail_host *old_host)
+void director_kill_user(struct director *dir, struct director_host *src,
+ struct user *user, struct mail_tag *tag,
+ struct mail_host *old_host)
{
struct director_kill_context *ctx;
const char *cmd;
struct director_connection *src_conn,
struct director_host *orig_src,
struct user *user) ATTR_NULL(3);
+void director_kill_user(struct director *dir, struct director_host *src,
+ struct user *user, struct mail_tag *tag,
+ struct mail_host *old_host);
void director_move_user(struct director *dir, struct director_host *src,
struct director_host *orig_src,
unsigned int username_hash, struct mail_host *host)
struct director *dir = cmd->dir;
struct user *user;
struct mail_host *new_host;
+ bool users_killed = FALSE;
if (dir->users_moving_count >= cmd->max_moving_users)
return FALSE;
while ((user = director_iterate_users_next(cmd->iter)) != NULL) {
if (user->host != host)
continue;
+
new_host = mail_host_get_by_hash(dir->mail_hosts,
user->username_hash,
mail_host_get_tag(host));
if (new_host != host) T_BEGIN {
- director_move_user(dir, dir->self_host, NULL,
- user->username_hash, new_host);
+ if (new_host != NULL) {
+ director_move_user(dir, dir->self_host, NULL,
+ user->username_hash, new_host);
+ } else {
+ /* there are no more available backends.
+ kick the user instead. */
+ director_kill_user(dir, dir->self_host, user,
+ user->host->tag, user->host);
+ users_killed = TRUE;
+ }
} T_END;
if (dir->users_moving_count >= cmd->max_moving_users)
break;
}
if (user == NULL)
director_iterate_users_deinit(&cmd->iter);
+ if (users_killed) {
+ /* no more backends. we already sent kills. now remove the
+ users entirely from the host. */
+ director_flush_host(dir, dir->self_host, NULL, host);
+ }
if (dir->right != NULL)
director_connection_uncork(dir->right);
return user == NULL;