director.c revision ac1118842c3d80285e32d2cd53bda3e95e5be217
/* Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "str.h"
#include "ipc-client.h"
#include "user-directory.h"
#include "mail-host.h"
#include "director-host.h"
#include "director-connection.h"
#include "director.h"
#define DIRECTOR_IPC_PROXY_PATH "ipc"
#define DIRECTOR_RECONNECT_RETRY_SECS 60
{
return FALSE;
return FALSE;
return TRUE;
}
{
struct director_host *const *hosts;
unsigned int i, count;
for (i = 0; i < count; i++) {
return;
}
}
i_fatal("director_servers doesn't list ourself");
}
{
return;
if (!director_is_self_ip_set(dir))
i_fatal("director_servers doesn't list ourself (%s:%u)",
}
}
{
struct director_host *const *hosts;
unsigned int i, count;
for (i = 0; i < count; i++) {
return i;
}
i_unreached();
}
{
unsigned int port;
int fd;
return 0;
i_debug("Connecting to %s:%u",
}
if (fd == -1) {
return -1;
}
/* Reset timestamp so that director_connect() won't skip this host
while we're still trying to connect to it */
host->last_failed = 0;
return 0;
}
static struct director_host *
{
struct director_host *const *hosts;
if (count == 1)
return NULL;
}
{
struct director_host *const *hosts;
/* try to connect to first working server on our right side.
the left side is supposed to connect to us. */
for (i = 1; i < count; i++) {
/* failed recently, don't try retrying here */
continue;
}
break;
}
if (i == count) {
/* we're the only one */
i_debug("director: Couldn't connect to right side, "
"we must be the only director left");
}
/* since we couldn't connect to it,
it must have failed recently */
}
if (!dir->ring_handshaked)
else
}
}
{
if (dir->ring_handshake_warning_sent) {
i_warning("Directors have been connected, "
"continuing delayed requests");
}
i_debug("Director ring handshaked");
}
{
if (cur_host != preferred_host)
else {
/* the connection hasn't finished sync yet.
keep this timeout for now. */
}
}
{
struct director_host *host;
if (dir->ring_handshake_warning_sent) {
i_warning("Ring is synced, continuing delayed requests");
}
/* try to reconnect to preferred host later */
dir->to_reconnect =
}
} else {
}
}
{
if (dir->sync_frozen) {
return;
}
return;
}
/* we're synced again when we receive this SYNC back */
i_debug("Ring is desynced (seq=%u, sending SYNC to %s)",
}
}
{
}
{
if (dir->sync_pending) {
}
}
struct director_host *orig_src,
{
/* update state in case this is the first mail host being added */
}
"HOST\t%s\t%u\t%u\t%s\t%u\n",
}
struct director_host *orig_src,
{
}
"HOST-REMOVE\t%s\t%u\t%u\t%s\n",
}
}
struct director_host *orig_src,
{
}
"HOST-FLUSH\t%s\t%u\t%u\t%s\n",
}
{
}
struct director_user_kill_finish_ctx {
};
static void
{
}
static void
{
struct director_user_kill_finish_ctx *ctx;
}
struct director_kill_context {
unsigned int username_hash;
bool self;
};
static void
{
/* we're alone */
} else if (self ||
} else {
}
}
{
switch (state) {
return;
case IPC_CLIENT_CMD_STATE_OK:
break;
i_error("Failed to kill user %u connections: %s",
/* we can't really do anything but continue anyway */
break;
}
return;
}
{
i_error("Finishing user %u move timed out, "
}
struct director_host *orig_src,
{
const char *cmd;
struct director_kill_context *ctx;
/* 1. move this user's host, and set its "killing" flag to delay all of
its future connections until all directors have killed the
connections and notified us about it.
2. tell the other directors about the move
3. once user kill callback is called, tell the other directors
with USER-KILLED that we're done killing the user.
4. when some director gets a duplicate USER-KILLED, it's
responsible for notifying all directors that user is completely
killed.
5. after receiving USER-KILLED-EVERYWHERE notification,
new connections are again allowed for the user.
*/
host, ioloop_time);
} else {
/* user is already in this host */
return;
}
}
}
}
"USER-MOVE\t%s\t%u\t%u\t%u\t%s\n",
}
{
return;
switch (user->kill_state) {
case USER_KILL_STATE_KILLING:
break;
break;
case USER_KILL_STATE_NONE:
case USER_KILL_STATE_DELAY:
break;
break;
}
}
struct director_host *src,
struct director_host *orig_src,
unsigned int username_hash)
{
return;
}
"USER-KILLED-EVERYWHERE\t%s\t%u\t%u\t%u\n",
user->username_hash));
}
{
}
const char *cmd)
{
}
struct director *
{
const char *path;
return dir;
}
{
struct director_host *const *hostp;
}