replication-plugin.c revision 1fa1180b97d7164a656f8c0b8a29553c160f1e8b
/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "str.h"
#include "strescape.h"
#include "fd-set-nonblock.h"
#include "ioloop.h"
#include "net.h"
#include "write-full.h"
#include "mail-user.h"
#include "mail-namespace.h"
#include "mail-storage-private.h"
#include "notify-plugin.h"
#include "replication-common.h"
#include "replication-plugin.h"
#define REPLICATION_SOCKET_NAME "replication-notify"
#define REPLICATION_FIFO_NAME "replication-notify-fifo"
#define REPLICATION_NOTIFY_DELAY_MSECS 500
#define REPLICATION_SYNC_TIMEOUT_SECS 10
#define REPLICATION_USER_CONTEXT(obj) \
struct replication_user {
const char *socket_path;
enum replication_priority priority;
unsigned int sync_secs;
};
struct replication_mail_txn_context {
struct mail_namespace *ns;
bool new_messages;
};
static int fifo_fd;
static bool fifo_failed;
static char *fifo_path;
static int
enum replication_priority priority)
{
if (fifo_failed)
return -1;
if (fifo_fd == -1) {
if (fifo_fd == -1) {
fifo_failed = TRUE;
return -1;
}
}
/* <username> \t <priority> */
switch (priority) {
i_unreached();
case REPLICATION_PRIORITY_LOW:
break;
break;
}
if (ret > 0)
/* busy, try again later */
return 0;
} else {
/* server was probably restarted, don't bother logging
this. */
}
fifo_fd = -1;
return -1;
}
return 1;
}
{
int ret;
!fifo_failed) {
/* retry once, in case replication server was restarted */
}
if (ret != 0) {
}
}
{
char buf[1024];
int fd;
if (fd == -1) {
return -1;
}
/* <username> \t "sync" */
} else {
/* + | - */
if (ret < 0) {
i_error("read(%s) failed: %m",
ruser->socket_path);
} else {
i_warning("replication(%s): Sync failure: "
"Timeout in %u secs",
}
} else if (ret == 0) {
} else if (buf[0] == '+') {
/* success */
} else if (buf[0] == '-') {
/* failure */
i_warning("replication(%s): Sync failure: %s",
i_warning("replication(%s): "
"Remote sent invalid input: %s",
}
}
alarm(0);
return success ? 0 : -1;
}
enum replication_priority priority,
const char *event)
{
struct replication_user *ruser;
return;
i_debug("replication: Replication requested by '%s', priority=%d",
}
if (priority == REPLICATION_PRIORITY_SYNC) {
return;
}
/* sync replication failed, try as "high" via fifo */
}
}
}
static void *
{
struct replication_mail_txn_context *ctx;
return ctx;
}
{
struct replication_mail_txn_context *ctx =
(struct replication_mail_txn_context *)txn;
}
{
struct replication_mail_txn_context *ctx =
(struct replication_mail_txn_context *)txn;
/* copy between storages, e.g. new mail delivery */
} else {
/* copy within storage, which isn't as high priority since the
mail already exists. and especially copies to Trash or to
lazy-expunge namespace is pretty low priority. */
}
}
static void
struct mail_transaction_commit_changes *changes)
{
struct replication_mail_txn_context *ctx =
(struct replication_mail_txn_context *)txn;
struct replication_user *ruser =
enum replication_priority priority;
}
}
{
REPLICATION_PRIORITY_LOW, "mailbox create");
}
static void
{
REPLICATION_PRIORITY_LOW, "mailbox delete");
}
static void
{
REPLICATION_PRIORITY_LOW, "mailbox rename");
}
bool subscribed ATTR_UNUSED)
{
REPLICATION_PRIORITY_LOW, "mailbox subscribe");
}
{
i_warning("%s: Couldn't send final notification "
"due to fifo being busy", fifo_path);
}
}
}
{
struct replication_user *ruser;
const char *value;
if (user->mail_debug)
i_debug("replication: No mail_replica setting - replication disabled");
return;
}
/* we're running dsync, which means that the remote is telling
us about a change. don't trigger a replication back to it */
if (user->mail_debug)
i_debug("replication: We're running dsync - replication disabled");
return;
}
/* we'll assume that all users have the same base_dir.
they really should. */
}
i_error("replication(%s): "
"Invalid replication_sync_timeout value: %s",
}
}
static const struct notify_vfuncs replication_vfuncs = {
};
static struct notify_context *replication_ctx;
static struct mail_storage_hooks replication_mail_storage_hooks = {
};
{
fifo_fd = -1;
}
void replication_plugin_deinit(void)
{
if (fifo_fd != -1) {
fifo_fd = -1;
}
}