director.c revision cdc7ca129c3433d3e4b9d5e90f4c209e4546dfe9
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2010-2017 Dovecot authors, see the included COPYING file */
6215a7ed04836eb66776e92b8686eff09b39a93fTimo Sirainen#define DIRECTOR_RECONNECT_TIMEOUT_MSECS (30*1000)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#define DIRECTOR_USER_MOVE_TIMEOUT_MSECS (30*1000)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#define DIRECTOR_QUICK_RECONNECT_TIMEOUT_MSECS 1000
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#define DIRECTOR_DELAYED_DIR_REMOVE_MSECS (1000*30)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenconst char *user_kill_state_names[USER_KILL_STATE_DELAY+1] = {
ff2f20bbc039ad8e362ead199366e21bc41f18edAki Tuomi "notify-received",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen "waiting-for-notify",
ff2f20bbc039ad8e362ead199366e21bc41f18edAki Tuomi "waiting-for-everyone",
d8702d15ee7721ed1fcfc8f00a589970bd6b3598Timo Sirainenstatic struct log_throttle *user_move_throttle;
d8702d15ee7721ed1fcfc8f00a589970bd6b3598Timo Sirainenstatic struct log_throttle *user_kill_fail_throttle;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic const struct log_throttle_settings director_log_throttle_settings = {
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainendirector_user_kill_finish_delayed(struct director *dir, struct user *user,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic bool director_is_self_ip_set(struct director *dir)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (net_ip_compare(&dir->self_ip, &net_ip4_any))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (net_ip_compare(&dir->self_ip, &net_ip6_any))
325d17cdbb7a338f7c413788f5e8e42d2e80a7f8Timo Sirainenstatic void director_find_self_ip(struct director *dir)
325d17cdbb7a338f7c413788f5e8e42d2e80a7f8Timo Sirainen unsigned int i, count;
325d17cdbb7a338f7c413788f5e8e42d2e80a7f8Timo Sirainen for (i = 0; i < count; i++) {
325d17cdbb7a338f7c413788f5e8e42d2e80a7f8Timo Sirainen i_fatal("director_servers doesn't list ourself");
0b808b62a679c81f59958392507fd0f6b5bd4e34Aki Tuomi dir->self_host = director_host_lookup(dir, &dir->self_ip,
8c79de417ae66b4e54daeb9d998af2ab301151b4Aki Tuomi i_fatal("director_servers doesn't list ourself (%s:%u)",
8c79de417ae66b4e54daeb9d998af2ab301151b4Aki Tuomistatic unsigned int director_find_self_idx(struct director *dir)
8c79de417ae66b4e54daeb9d998af2ab301151b4Aki Tuomi unsigned int i, count;
a8dac1be6a0c3adbbce5887ca395f418194c6c06Aki Tuomi for (i = 0; i < count; i++) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainendirector_has_outgoing_connection(struct director *dir,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (director_connection_get_host(*connp) == host &&
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenint director_connect_host(struct director *dir, struct director_host *host)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (director_has_outgoing_connection(dir, host))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen str_printfa(str, "Connecting to %s:%u (as %s",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen str_printfa(str, ", last network failure %ds ago",
6215a7ed04836eb66776e92b8686eff09b39a93fTimo Sirainen (int)(ioloop_time - host->last_network_failure));
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen str_printfa(str, ", last protocol failure %ds ago",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen (int)(ioloop_time - host->last_protocol_failure));
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen port = dir->test_port != 0 ? dir->test_port : host->port;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen fd = net_connect_ip(&host->ip, port, &dir->self_ip);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("connect(%s) failed: %m", host->name);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* Reset timestamp so that director_connect() won't skip this host
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen while we're still trying to connect to it */
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen (void)director_connection_init_out(dir, fd, host);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainendirector_get_preferred_right_host(struct director *dir)
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainen for (i = 0; i < count; i++) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* self, with some removed hosts */
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic bool director_wait_for_others(struct director *dir)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* don't assume we're alone until we've attempted to connect
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen to others for a while */
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen ioloop_time - dir->ring_first_alone > DIRECTOR_RING_MIN_WAIT_SECS)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* reset all failures and try again */
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen dir->to_reconnect = timeout_add(DIRECTOR_QUICK_RECONNECT_TIMEOUT_MSECS,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* try to connect to first working server on our right side.
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen the left side is supposed to connect to us. */
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen DIRECTOR_RECONNECT_RETRY_SECS > ioloop_time) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* connection failed recently, don't try retrying here */
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen DIRECTOR_PROTOCOL_FAILURE_RETRY_SECS > ioloop_time) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* the director recently sent invalid protocol data,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen don't try retrying yet */
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (director_connect_host(dir, hosts[idx]) == 0) {
7c849dbc7be089175c1a83a84ee7249ed695810dTimo Sirainen /* success */
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainen if (count > 1 && director_wait_for_others(dir))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* we're the only one */
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen i_warning("director: Couldn't connect to right side, "
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen "we must be the only director left");
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen /* since we couldn't connect to it,
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen it must have failed recently */
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen i_warning("director: Assuming %s is dead, disconnecting",
if (minor_version > 0 &&
return TRUE;
return FALSE;
const char *cmd;
unsigned int i, count;
for (i = 0; i < count; ) {
unsigned int i, count;
const char *cmd;
for (i = 0; i < count; ) {
const char *cmd;
i_unreached();
if (result == 0) {
char *data;
data);
const char *error;
const char *const args[] = {
error);
bool skip_delay)
if (skip_delay) {
} else if (self ||
switch (state) {
case IPC_CLIENT_CMD_STATE_OK:
const char *cmd;
unsigned int username_hash,
const char *cmd;
unsigned int username_hash)
unsigned int username_hash)
case USER_KILL_STATE_KILLING:
case USER_KILL_STATE_NONE:
case USER_KILL_STATE_FLUSHING:
case USER_KILL_STATE_DELAY:
unsigned int username_hash)
unsigned int username_hash)
const char *cmd)
struct director *
return dir;
if (!director_debug)
T_BEGIN {
} T_END;
struct director_user_iter {
unsigned int tag_idx;
return iter;
return NULL;
return user;
unsigned int *hash_r)
const char *error;
&error))
return TRUE;
return FALSE;
void directors_init(void)
void directors_deinit(void)