director.c revision b6b9c99fefbbc662bd9a0006566133c4480bf0e8
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "lib.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "ioloop.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "array.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "str.h"
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen#include "ipc-client.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "user-directory.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "mail-host.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "director-host.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "director-connection.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "director.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen#define DIRECTOR_IPC_PROXY_PATH "ipc"
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
4fe3f07477bae6da3fb8d8fa9bab10ab82ada2bdTimo Sirainen#define DIRECTOR_RECONNECT_RETRY_SECS 60
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen#define DIRECTOR_RECONNECT_TIMEOUT_MSECS (30*1000)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen#define DIRECTOR_USER_MOVE_TIMEOUT_MSECS (30*1000)
5411e6f71afb0f753cdf831f4da4ee73e928796eTimo Sirainen#define DIRECTOR_USER_MOVE_FINISH_DELAY_MSECS (2*1000)
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen#define DIRECTOR_SYNC_TIMEOUT_MSECS (15*1000)
4fe3f07477bae6da3fb8d8fa9bab10ab82ada2bdTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic bool director_is_self_ip_set(struct director *dir)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct ip_addr ip;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen net_get_ip_any4(&ip);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (net_ip_compare(&dir->self_ip, &ip))
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return FALSE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen net_get_ip_any6(&ip);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (net_ip_compare(&dir->self_ip, &ip))
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return FALSE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void director_find_self_ip(struct director *dir)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director_host *const *hosts;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int i, count;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen hosts = array_get(&dir->dir_hosts, &count);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (i = 0; i < count; i++) {
a356c4736fe6041142c6096045bc00c15a80af4eTimo Sirainen if (net_try_bind(&hosts[i]->ip) == 0) {
a356c4736fe6041142c6096045bc00c15a80af4eTimo Sirainen dir->self_ip = hosts[i]->ip;
a356c4736fe6041142c6096045bc00c15a80af4eTimo Sirainen return;
a356c4736fe6041142c6096045bc00c15a80af4eTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
a356c4736fe6041142c6096045bc00c15a80af4eTimo Sirainen i_fatal("director_servers doesn't list ourself");
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
c4900d31385344bfadaee53a897daeafdb3063d8Timo Sirainenvoid director_find_self(struct director *dir)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (dir->self_host != NULL)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
34a45b80c8ed18861c6e343fe40adbe360fc6badTimo Sirainen if (!director_is_self_ip_set(dir))
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_find_self_ip(dir);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dir->self_host = director_host_lookup(dir, &dir->self_ip,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dir->self_port);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (dir->self_host == NULL) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_fatal("director_servers doesn't list ourself (%s:%u)",
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen net_ip2addr(&dir->self_ip), dir->self_port);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dir->self_host->self = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic unsigned int director_find_self_idx(struct director *dir)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director_host *const *hosts;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int i, count;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_assert(dir->self_host != NULL);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen hosts = array_get(&dir->dir_hosts, &count);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (i = 0; i < count; i++) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (hosts[i] == dir->self_host)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return i;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_unreached();
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenint director_connect_host(struct director *dir, struct director_host *host)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen unsigned int port;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen int fd;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (director_connection_find_outgoing(dir, host) != NULL)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return 0;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen if (dir->debug) {
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen i_debug("Connecting to %s:%u",
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen net_ip2addr(&host->ip), host->port);
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen }
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen port = dir->test_port != 0 ? dir->test_port : host->port;
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen fd = net_connect_ip(&host->ip, port, &dir->self_ip);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (fd == -1) {
4fe3f07477bae6da3fb8d8fa9bab10ab82ada2bdTimo Sirainen host->last_failed = ioloop_time;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_error("connect(%s) failed: %m", host->name);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
4c20178a7f70bfe43d252e50796013aac1d8c74aTimo Sirainen /* Reset timestamp so that director_connect() won't skip this host
4c20178a7f70bfe43d252e50796013aac1d8c74aTimo Sirainen while we're still trying to connect to it */
4c20178a7f70bfe43d252e50796013aac1d8c74aTimo Sirainen host->last_failed = 0;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_connection_init_out(dir, fd, host);
4fe3f07477bae6da3fb8d8fa9bab10ab82ada2bdTimo Sirainen return 0;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainenstatic struct director_host *
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainendirector_get_preferred_right_host(struct director *dir)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct director_host *const *hosts;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen unsigned int count, self_idx;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen hosts = array_get(&dir->dir_hosts, &count);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (count == 1)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return NULL;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen self_idx = director_find_self_idx(dir);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return hosts[(self_idx + 1) % count];
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen}
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid director_connect(struct director *dir)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director_host *const *hosts;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int i, count, self_idx;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen self_idx = director_find_self_idx(dir);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* try to connect to first working server on our right side.
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen the left side is supposed to connect to us. */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen hosts = array_get(&dir->dir_hosts, &count);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (i = 1; i < count; i++) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int idx = (self_idx + i) % count;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainen if (hosts[idx]->last_failed +
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainen DIRECTOR_RECONNECT_RETRY_SECS > ioloop_time) {
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainen /* failed recently, don't try retrying here */
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainen continue;
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainen }
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainen
4fe3f07477bae6da3fb8d8fa9bab10ab82ada2bdTimo Sirainen if (director_connect_host(dir, hosts[idx]) == 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen break;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (i == count) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* we're the only one */
4e43828ef88183a0750a8a374b6ba4ecf227c58fTimo Sirainen if (dir->debug) {
4e43828ef88183a0750a8a374b6ba4ecf227c58fTimo Sirainen i_debug("director: Couldn't connect to right side, "
4e43828ef88183a0750a8a374b6ba4ecf227c58fTimo Sirainen "we must be the only director left");
4e43828ef88183a0750a8a374b6ba4ecf227c58fTimo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->left != NULL) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen /* since we couldn't connect to it,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen it must have failed recently */
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_connection_deinit(&dir->left);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen dir->ring_min_version = DIRECTOR_VERSION_MINOR;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (!dir->ring_handshaked)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_set_ring_handshaked(dir);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen else
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_set_ring_synced(dir);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainenvoid director_set_ring_handshaked(struct director *dir)
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen i_assert(!dir->ring_handshaked);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->to_handshake_warning != NULL)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen timeout_remove(&dir->to_handshake_warning);
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen if (dir->ring_handshake_warning_sent) {
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen i_warning("Directors have been connected, "
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen "continuing delayed requests");
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen dir->ring_handshake_warning_sent = FALSE;
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen }
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen if (dir->debug)
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen i_debug("Director ring handshaked");
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen dir->ring_handshaked = TRUE;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_set_ring_synced(dir);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen}
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainenstatic void director_reconnect_timeout(struct director *dir)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct director_host *cur_host, *preferred_host =
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_get_preferred_right_host(dir);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen cur_host = dir->right == NULL ? NULL :
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_connection_get_host(dir->right);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (cur_host != preferred_host)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen (void)director_connect_host(dir, preferred_host);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen else {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen /* the connection hasn't finished sync yet.
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen keep this timeout for now. */
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen}
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainenvoid director_set_ring_synced(struct director *dir)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct director_host *host;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen i_assert(!dir->ring_synced);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen i_assert((dir->left != NULL && dir->right != NULL) ||
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen (dir->left == NULL && dir->right == NULL));
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->to_handshake_warning != NULL)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen timeout_remove(&dir->to_handshake_warning);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->ring_handshake_warning_sent) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen i_warning("Ring is synced, continuing delayed requests");
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen dir->ring_handshake_warning_sent = FALSE;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen host = dir->right == NULL ? NULL :
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_connection_get_host(dir->right);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (host != director_get_preferred_right_host(dir)) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen /* try to reconnect to preferred host later */
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->to_reconnect == NULL) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen dir->to_reconnect =
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen timeout_add(DIRECTOR_RECONNECT_TIMEOUT_MSECS,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_reconnect_timeout, dir);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen } else {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->to_reconnect != NULL)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen timeout_remove(&dir->to_reconnect);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen if (dir->to_sync != NULL)
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen timeout_remove(&dir->to_sync);
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen dir->ring_synced = TRUE;
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen dir->ring_last_sync_time = ioloop_time;
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen director_set_state_changed(dir);
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen}
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainenvoid director_sync_send(struct director *dir, struct director_host *host,
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen uint32_t seq, unsigned int minor_version)
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen{
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen string_t *str = t_str_new(128);
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen str_printfa(str, "SYNC\t%s\t%u\t%u",
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen net_ip2addr(&host->ip), host->port, seq);
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen if (minor_version > 0) {
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen /* only minor_version>0 supports this parameter */
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen str_printfa(str, "\t%u", minor_version);
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen }
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen str_append_c(str, '\n');
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen director_connection_send(dir->right, str_c(str));
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen}
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainenbool director_resend_sync(struct director *dir)
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen{
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen if (!dir->ring_synced && dir->left != NULL && dir->right != NULL) {
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen /* send a new SYNC in case the previous one got dropped */
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen director_sync_send(dir, dir->self_host, dir->sync_seq,
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen DIRECTOR_VERSION_MINOR);
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen if (dir->to_sync != NULL)
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen timeout_reset(dir->to_sync);
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen return TRUE;
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen }
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen return FALSE;
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen}
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainenstatic void director_sync_timeout(struct director *dir)
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen{
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen i_assert(!dir->ring_synced);
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen if (director_resend_sync(dir))
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen i_error("Ring SYNC appears to have got lost, resending");
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen}
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainenvoid director_set_ring_unsynced(struct director *dir)
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen{
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen if (dir->ring_synced) {
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen dir->ring_synced = FALSE;
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen dir->ring_last_sync_time = ioloop_time;
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen }
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen if (dir->to_sync == NULL) {
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen dir->to_sync = timeout_add(DIRECTOR_SYNC_TIMEOUT_MSECS,
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen director_sync_timeout, dir);
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen } else {
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen timeout_reset(dir->to_sync);
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen }
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen}
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainenstatic void director_sync(struct director *dir)
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->sync_frozen) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen dir->sync_pending = TRUE;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->right == NULL) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen i_assert(!dir->ring_synced ||
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen (dir->left == NULL && dir->right == NULL));
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen /* we're synced again when we receive this SYNC back */
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen dir->sync_seq++;
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen director_set_ring_unsynced(dir);
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen if (dir->debug) {
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen i_debug("Ring is desynced (seq=%u, sending SYNC to %s)",
883c882ede03123e771e5f1cd1d4fbdbddafd6c2Timo Sirainen dir->sync_seq, dir->right == NULL ? "(nowhere)" :
883c882ede03123e771e5f1cd1d4fbdbddafd6c2Timo Sirainen director_connection_get_name(dir->right));
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen }
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->left != NULL)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_connection_wait_sync(dir->left);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_connection_wait_sync(dir->right);
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen director_sync_send(dir, dir->self_host, dir->sync_seq,
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen DIRECTOR_VERSION_MINOR);
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen}
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainenvoid director_sync_freeze(struct director *dir)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen i_assert(!dir->sync_frozen);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen i_assert(!dir->sync_pending);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->left != NULL)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_connection_cork(dir->left);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->right != NULL)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_connection_cork(dir->right);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen dir->sync_frozen = TRUE;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen}
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainenvoid director_sync_thaw(struct director *dir)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen i_assert(dir->sync_frozen);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen dir->sync_frozen = FALSE;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->sync_pending) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen dir->sync_pending = FALSE;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_sync(dir);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->left != NULL)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_connection_uncork(dir->left);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->right != NULL)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_connection_uncork(dir->right);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen}
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid director_update_host(struct director *dir, struct director_host *src,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct director_host *orig_src,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct mail_host *host)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen /* update state in case this is the first mail host being added */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_set_state_changed(dir);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (orig_src == NULL) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen orig_src = dir->self_host;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen orig_src->last_seq++;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_update_send(dir, src, t_strdup_printf(
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen "HOST\t%s\t%u\t%u\t%s\t%u\n",
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen net_ip2addr(&orig_src->ip), orig_src->port, orig_src->last_seq,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen net_ip2addr(&host->ip), host->vhost_count));
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen director_sync(dir);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid director_remove_host(struct director *dir, struct director_host *src,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct director_host *orig_src,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct mail_host *host)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (src != NULL) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (orig_src == NULL) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen orig_src = dir->self_host;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen orig_src->last_seq++;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen director_update_send(dir, src, t_strdup_printf(
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen "HOST-REMOVE\t%s\t%u\t%u\t%s\n",
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen net_ip2addr(&orig_src->ip), orig_src->port,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen orig_src->last_seq, net_ip2addr(&host->ip)));
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen user_directory_remove_host(dir->users, host);
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen mail_host_remove(dir->mail_hosts, host);
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen director_sync(dir);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainenvoid director_flush_host(struct director *dir, struct director_host *src,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct director_host *orig_src,
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen struct mail_host *host)
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (orig_src == NULL) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen orig_src = dir->self_host;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen orig_src->last_seq++;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen director_update_send(dir, src, t_strdup_printf(
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen "HOST-FLUSH\t%s\t%u\t%u\t%s\n",
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen net_ip2addr(&orig_src->ip), orig_src->port, orig_src->last_seq,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen net_ip2addr(&host->ip)));
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen user_directory_remove_host(dir->users, host);
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen director_sync(dir);
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen}
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid director_update_user(struct director *dir, struct director_host *src,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct user *user)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen i_assert(src != NULL);
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen i_assert(!user->weak);
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen director_update_send(dir, src, t_strdup_printf("USER\t%u\t%s\n",
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen user->username_hash, net_ip2addr(&user->host->ip)));
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen}
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainenvoid director_update_user_weak(struct director *dir, struct director_host *src,
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen struct director_host *orig_src,
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen struct user *user)
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen{
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen i_assert(src != NULL);
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen i_assert(user->weak);
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen if (orig_src == NULL) {
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen orig_src = dir->self_host;
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen orig_src->last_seq++;
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen }
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_update_send(dir, src, t_strdup_printf(
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen "USER-WEAK\t%s\t%u\t%u\t%u\t%s\n",
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen net_ip2addr(&orig_src->ip), orig_src->port, orig_src->last_seq,
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen user->username_hash, net_ip2addr(&user->host->ip)));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenstruct director_user_kill_finish_ctx {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct director *dir;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct user *user;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen};
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenstatic void
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainendirector_user_kill_finish_delayed_to(struct director_user_kill_finish_ctx *ctx)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen i_assert(ctx->user->kill_state == USER_KILL_STATE_DELAY);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ctx->user->kill_state = USER_KILL_STATE_NONE;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen timeout_remove(&ctx->user->to_move);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ctx->dir->state_change_callback(ctx->dir);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen i_free(ctx);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen}
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenstatic void
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainendirector_user_kill_finish_delayed(struct director *dir, struct user *user)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct director_user_kill_finish_ctx *ctx;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ctx = i_new(struct director_user_kill_finish_ctx, 1);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ctx->dir = dir;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ctx->user = user;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->kill_state = USER_KILL_STATE_DELAY;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen timeout_remove(&user->to_move);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->to_move = timeout_add(DIRECTOR_USER_MOVE_FINISH_DELAY_MSECS,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_user_kill_finish_delayed_to, ctx);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen}
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenstruct director_kill_context {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct director *dir;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen unsigned int username_hash;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen bool self;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen};
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenstatic void
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainendirector_finish_user_kill(struct director *dir, struct user *user, bool self)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (dir->right == NULL || dir->right == dir->left) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen /* we're alone */
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_user_kill_finish_delayed(dir, user);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen } else if (self ||
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->kill_state == USER_KILL_STATE_KILLING_NOTIFY_RECEIVED) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_connection_send(dir->right, t_strdup_printf(
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen "USER-KILLED\t%u\n", user->username_hash));
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->kill_state = USER_KILL_STATE_KILLED_WAITING_FOR_EVERYONE;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen } else {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen i_assert(user->kill_state == USER_KILL_STATE_KILLING);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->kill_state = USER_KILL_STATE_KILLED_WAITING_FOR_NOTIFY;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen}
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenstatic void director_kill_user_callback(enum ipc_client_cmd_state state,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen const char *data, void *context)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct director_kill_context *ctx = context;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct user *user;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen switch (state) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen case IPC_CLIENT_CMD_STATE_REPLY:
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen return;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen case IPC_CLIENT_CMD_STATE_OK:
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen break;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen case IPC_CLIENT_CMD_STATE_ERROR:
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen i_error("Failed to kill user %u connections: %s",
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ctx->username_hash, data);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen /* we can't really do anything but continue anyway */
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen break;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user = user_directory_lookup(ctx->dir->users, ctx->username_hash);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (user == NULL || user->kill_state == USER_KILL_STATE_NONE)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen return;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_finish_user_kill(ctx->dir, user, ctx->self);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen}
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenstatic void director_user_move_timeout(struct user *user)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen i_error("Finishing user %u move timed out, "
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen "its state may now be inconsistent", user->username_hash);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->kill_state = USER_KILL_STATE_NONE;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen timeout_remove(&user->to_move);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen}
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenvoid director_move_user(struct director *dir, struct director_host *src,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct director_host *orig_src,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen unsigned int username_hash, struct mail_host *host)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct user *user;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen const char *cmd;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct director_kill_context *ctx;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen /* 1. move this user's host, and set its "killing" flag to delay all of
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen its future connections until all directors have killed the
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen connections and notified us about it.
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen 2. tell the other directors about the move
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen 3. once user kill callback is called, tell the other directors
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen with USER-KILLED that we're done killing the user.
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen 4. when some director gets a duplicate USER-KILLED, it's
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen responsible for notifying all directors that user is completely
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen killed.
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen 5. after receiving USER-KILLED-EVERYWHERE notification,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen new connections are again allowed for the user.
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen */
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user = user_directory_lookup(dir->users, username_hash);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (user == NULL) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user = user_directory_add(dir->users, username_hash,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen host, ioloop_time);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen } else {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (user->host == host) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen /* user is already in this host */
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen return;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->host->user_count--;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->host = host;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->host->user_count++;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->timestamp = ioloop_time;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (user->kill_state == USER_KILL_STATE_NONE) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ctx = i_new(struct director_kill_context, 1);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ctx->dir = dir;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ctx->username_hash = username_hash;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ctx->self = src->self;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->to_move = timeout_add(DIRECTOR_USER_MOVE_TIMEOUT_MSECS,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_user_move_timeout, user);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->kill_state = USER_KILL_STATE_KILLING;
ac1118842c3d80285e32d2cd53bda3e95e5be217Timo Sirainen cmd = t_strdup_printf("proxy\t*\tKICK-DIRECTOR-HASH\t%u",
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen username_hash);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ipc_client_cmd(dir->ipc_proxy, cmd,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_kill_user_callback, ctx);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (orig_src == NULL) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen orig_src = dir->self_host;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen orig_src->last_seq++;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_update_send(dir, src, t_strdup_printf(
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen "USER-MOVE\t%s\t%u\t%u\t%u\t%s\n",
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen net_ip2addr(&orig_src->ip), orig_src->port, orig_src->last_seq,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->username_hash, net_ip2addr(&user->host->ip)));
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen}
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenvoid director_user_killed(struct director *dir, unsigned int username_hash)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct user *user;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user = user_directory_lookup(dir->users, username_hash);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (user == NULL)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen return;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen switch (user->kill_state) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen case USER_KILL_STATE_KILLING:
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->kill_state = USER_KILL_STATE_KILLING_NOTIFY_RECEIVED;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen break;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen case USER_KILL_STATE_KILLED_WAITING_FOR_NOTIFY:
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_finish_user_kill(dir, user, TRUE);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen break;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen case USER_KILL_STATE_NONE:
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen case USER_KILL_STATE_DELAY:
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen case USER_KILL_STATE_KILLING_NOTIFY_RECEIVED:
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen break;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen case USER_KILL_STATE_KILLED_WAITING_FOR_EVERYONE:
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_user_killed_everywhere(dir, dir->self_host,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen NULL, username_hash);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen break;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen}
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenvoid director_user_killed_everywhere(struct director *dir,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct director_host *src,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct director_host *orig_src,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen unsigned int username_hash)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct user *user;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user = user_directory_lookup(dir->users, username_hash);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (user == NULL ||
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->kill_state != USER_KILL_STATE_KILLED_WAITING_FOR_EVERYONE)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen return;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_user_kill_finish_delayed(dir, user);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (orig_src == NULL) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen orig_src = dir->self_host;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen orig_src->last_seq++;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen director_update_send(dir, src, t_strdup_printf(
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen "USER-KILLED-EVERYWHERE\t%s\t%u\t%u\t%u\n",
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen net_ip2addr(&orig_src->ip), orig_src->port, orig_src->last_seq,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen user->username_hash));
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen}
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid director_set_state_changed(struct director *dir)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dir->state_change_callback(dir);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid director_update_send(struct director *dir, struct director_host *src,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const char *cmd)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_assert(src != NULL);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (dir->left != NULL)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_connection_send_except(dir->left, src, cmd);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (dir->right != NULL && dir->right != dir->left)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_connection_send_except(dir->right, src, cmd);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstruct director *
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainendirector_init(const struct director_settings *set,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const struct ip_addr *listen_ip, unsigned int listen_port,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_state_change_callback_t *callback)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director *dir;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dir = i_new(struct director, 1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dir->set = set;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dir->self_port = listen_port;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dir->self_ip = *listen_ip;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dir->state_change_callback = callback;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_array_init(&dir->dir_hosts, 16);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_array_init(&dir->pending_requests, 16);
5733207dc3ec10e6e5a6e0a8b30fbd1b061062b9Timo Sirainen dir->users = user_directory_init(set->director_user_expire,
5733207dc3ec10e6e5a6e0a8b30fbd1b061062b9Timo Sirainen set->director_username_hash);
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen dir->mail_hosts = mail_hosts_init();
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
fb35b9f2c80954da842c20d5128b5e506835d93eTimo Sirainen dir->ipc_proxy = ipc_client_init(DIRECTOR_IPC_PROXY_PATH);
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen dir->ring_min_version = DIRECTOR_VERSION_MINOR;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return dir;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid director_deinit(struct director **_dir)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director *dir = *_dir;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director_host *const *hostp;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *_dir = NULL;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
23e1e4033d311a50253259de8866525980b23227Timo Sirainen director_connections_deinit(dir);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen user_directory_deinit(&dir->users);
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen mail_hosts_deinit(&dir->mail_hosts);
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen mail_hosts_deinit(&dir->orig_config_hosts);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen ipc_client_deinit(&dir->ipc_proxy);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->to_reconnect != NULL)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen timeout_remove(&dir->to_reconnect);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dir->to_handshake_warning != NULL)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen timeout_remove(&dir->to_handshake_warning);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (dir->to_request != NULL)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen timeout_remove(&dir->to_request);
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen if (dir->to_sync != NULL)
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen timeout_remove(&dir->to_sync);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen array_foreach(&dir->dir_hosts, hostp)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen director_host_free(*hostp);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen array_free(&dir->pending_requests);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen array_free(&dir->dir_hosts);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_free(dir);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}