if (remote_ring_completed && !conn->dir->ring_handshaked) {
/* clear everything we have and use only what remote sends us */
+ dir_debug("%s: We're joining a ring - replace all hosts",
+ conn->name);
hosts = mail_hosts_get(conn->dir->mail_hosts);
while (array_count(hosts) > 0) {
hostp = array_idx(hosts, 0);
}
} else if (!remote_ring_completed && conn->dir->ring_handshaked) {
/* ignore whatever remote sends */
+ dir_debug("%s: Remote is joining our ring - "
+ "ignore all remote HOSTs", conn->name);
conn->ignore_host_events = TRUE;
+ } else {
+ dir_debug("%s: Merge rings' hosts", conn->name);
}
conn->handshake_sending_hosts = TRUE;
return TRUE;
}
static int
-director_cmd_is_seen(struct director_connection *conn,
- const char *const **_args,
- struct director_host **host_r)
+director_cmd_is_seen_full(struct director_connection *conn,
+ const char *const **_args, unsigned int *seq_r,
+ struct director_host **host_r)
{
const char *const *args = *_args;
struct ip_addr ip;
return -1;
}
*_args = args + 3;
+ *seq_r = seq;
host = director_host_lookup(conn->dir, &ip, port);
if (host == NULL || host->removed) {
return 0;
}
+static int
+director_cmd_is_seen(struct director_connection *conn,
+ const char *const **_args,
+ struct director_host **host_r)
+{
+ unsigned int seq;
+
+ return director_cmd_is_seen_full(conn, _args, &seq, host_r);
+}
+
static bool
director_cmd_user_weak(struct director_connection *conn,
const char *const *args)
const char *const *args)
{
struct director_host *dir_host;
- unsigned int username_hash;
+ unsigned int seq, username_hash;
int ret;
- if ((ret = director_cmd_is_seen(conn, &args, &dir_host)) != 0)
- return ret > 0;
+ if ((ret = director_cmd_is_seen_full(conn, &args, &seq, &dir_host)) < 0)
+ return FALSE;
if (str_array_length(args) != 1 ||
str_to_uint(args[0], &username_hash) < 0) {
return FALSE;
}
+ if (ret > 0) {
+ i_assert(dir_host != NULL);
+ dir_debug("User %u - ignoring already seen USER-KILLED-EVERYWHERE "
+ "with seq=%u <= %s.last_seq=%u", username_hash,
+ seq, dir_host->name, dir_host->last_seq);
+ return TRUE;
+ }
+
director_user_killed_everywhere(conn->dir, conn->host,
dir_host, username_hash);
return TRUE;
t_strdup_printf("%u", user->username_hash), NULL};
user->kill_state = USER_KILL_STATE_FLUSHING;
+ dir_debug("Flushing user %u via %s", user->username_hash,
+ ctx->socket_path);
if ((program_client_create(ctx->socket_path, args, &set, FALSE,
&ctx->pclient, &error)) != 0) {
{
i_assert(user->to_move != NULL);
+ dir_debug("User %u move finished at state=%s", user->username_hash,
+ user_kill_state_names[user->kill_state]);
+
user->kill_state = USER_KILL_STATE_NONE;
timeout_remove(&user->to_move);
username_hash);
ipc_client_cmd(dir->ipc_proxy, cmd,
director_kill_user_callback, ctx);
+ } else {
+ /* User is being moved again before the previous move
+ finished. We'll just continue wherever we left off
+ earlier. */
+ dir_debug("User %u move restarted - previous kill_state=%s",
+ username_hash, user_kill_state_names[user->kill_state]);
}
if (orig_src == NULL) {
struct user *user;
user = user_directory_lookup(dir->users, username_hash);
- if (user == NULL ||
- user->kill_state != USER_KILL_STATE_KILLED_WAITING_FOR_EVERYONE)
+ if (user == NULL) {
+ dir_debug("User %u no longer exists - ignoring USER-KILLED-EVERYWHERE",
+ username_hash);
return;
+ }
+ if (user->kill_state != USER_KILL_STATE_KILLED_WAITING_FOR_EVERYONE) {
+ dir_debug("User %u kill_state=%s - ignoring USER-KILLED-EVERYWHERE",
+ username_hash, user_kill_state_names[user->kill_state]);
+ return;
+ }
director_flush_user(dir, user);
director_send_user_killed_everywhere(dir, src, orig_src, username_hash);