replication-plugin.c revision 82e772ab84c4a476f2ce7cb34d9836f5a6138eea
/* Copyright (c) 2012 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 "network.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"
#include <stdlib.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;
}
if (ret < 0)
else
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" */
ret = -1;
} 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) {
ret = -1;
} else if (buf[0] == '+') {
/* success */
ret = 0;
} else if (buf[0] == '-') {
/* failure */
i_warning("replication(%s): Sync failure: %s",
ret = -1;
} else {
i_warning("replication(%s): "
"Remote sent invalid input: %s",
}
}
alarm(0);
return ret;
}
enum replication_priority priority)
{
struct replication_user *ruser;
/* we're running dsync, which means that the remote is telling
us about a change. don't trigger a replication back to it */
return;
}
/* public namespace. we can't handle this for now. */
return;
}
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;
}
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;
}
}
{
}
static void
{
}
static void
bool rename_children ATTR_UNUSED)
{
}
bool subscribed ATTR_UNUSED)
{
}
{
i_warning("%s: Couldn't send final notification "
"due to fifo being busy", fifo_path);
}
}
}
{
struct replication_user *ruser;
const char *value;
/* 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;
}
}