/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "hash.h"
#include "mail-cache-private.h"
#include "mail-namespace.h"
#include "mail-storage-private.h"
#include "dsync-ibc.h"
#include "dsync-mailbox-tree.h"
#include "dsync-mailbox-import.h"
#include "dsync-mailbox-export.h"
#include "dsync-transaction-log-scan.h"
#include "dsync-brain-private.h"
static int
{
int ret;
if (brain->backup_send) {
/* make sure mailbox isn't modified */
}
if (ret < 0) {
mailbox_free(&box);
return -1;
}
if (existence != MAILBOX_EXISTENCE_SELECT) {
mailbox_free(&box);
"Mailbox was already deleted" :
"Mailbox is no longer selectable";
return 0;
}
return 1;
}
enum mail_error *error_r)
{
int ret;
continue;
return ret;
}
return 0;
}
static void
{
}
}
static const struct dsync_mailbox_state *
const guid_128_t mailbox_guid)
{
}
static void
const guid_128_t mailbox_guid)
{
}
{
if (brain->backup_send) {
/* we have an exporter, but no importer. */
} else if (brain->backup_recv) {
/* we have an importer, but no exporter */
} else {
}
}
static void
const struct dsync_mailbox *local_dsync_box,
bool wait_for_remote_box)
{
if (wait_for_remote_box) {
} else {
}
else {
}
else {
}
}
static void
const struct dsync_mailbox *remote_dsync_box)
{
sizeof(remote_dsync_box->mailbox_guid)) == 0);
} else {
last_common_uid = 0;
last_common_modseq = 0;
}
if (brain->mail_requests)
if (brain->master_brain)
if (brain->empty_hdr_workaround)
}
const struct dsync_mailbox *remote_dsync_box)
{
bool pvt_too_old;
int ret;
highest_wanted_uid = last_common_uid == 0 ?
if (ret < 0) {
i_error("Failed to read transaction log for mailbox %s",
return -1;
}
if (ret == 0) {
if (pvt_too_old) {
} else {
}
}
if (last_common_uid != 0) {
/* if last_common_* is higher than our current ones it means
that the incremental sync state is stale and we need to do
a full resync */
ret = 0;
ret = 0;
ret = 0;
}
}
if (ret == 0) {
i_warning("Failed to do incremental sync for mailbox %s, "
"retry with a full sync (%s)",
"Incremental sync failed: %s", desync_reason));
return 0;
}
if (!brain->mail_requests)
if (remote_dsync_box->have_save_guids &&
if (brain->no_mail_prefetch)
if (brain->sync_since_timestamp > 0 ||
brain->sync_until_timestamp > 0)
if (brain->sync_max_size > 0)
if (remote_dsync_box->messages_count == 0) {
/* remote mailbox is empty - we don't really need to export
header hashes since they're not going to match anything
anyway. */
}
return 1;
}
{
const char *errstr;
}
const char *changes_during_sync;
bool require_full_resync;
&brain->mail_error);
if (require_full_resync)
}
}
enum mail_error *error_r)
{
const char *errstr;
/* get metadata first, since it may autocreate the mailbox */
if (error == MAIL_ERROR_NOTFOUND ||
error == MAIL_ERROR_NOTPOSSIBLE) {
/* Mailbox isn't selectable, try the next one. We
should have already caught \Noselect mailboxes, but
check them anyway here. The NOTPOSSIBLE check is
mainly for invalid mbox files. */
return 0;
}
i_error("Failed to access mailbox %s: %s",
return -1;
}
sizeof(dsync_box_r->mailbox_guid));
return 1;
}
static bool
const struct dsync_mailbox *dsync_box)
{
return TRUE;
}
static int
struct dsync_mailbox *dsync_box_r)
{
int ret;
break;
}
/* no more mailboxes */
return -1;
}
if (brain->backup_send) {
/* make sure mailbox isn't modified */
}
for (;;) {
if (ret < 0) {
}
mailbox_free(&box);
return ret;
}
/* if mailbox's last_common_* state equals the current state,
we can skip the mailbox */
i_debug("brain %c: Skipping mailbox %s with unchanged state "
}
mailbox_free(&box);
return 0;
}
if (synced) {
/* ok, the mailbox really changed */
break;
}
/* mailbox appears to have changed. do a full sync here and get the
state again. Lock before syncing. */
mailbox_free(&box);
return -1;
}
i_error("Can't sync mailbox %s: %s",
mailbox_free(&box);
return -1;
}
}
*dsync_box_r = dsync_box;
return 1;
}
static bool
struct dsync_mailbox *dsync_box_r)
{
int ret;
if (brain->no_mail_sync)
return FALSE;
;
return ret > 0;
}
{
return;
}
/* start exporting this mailbox (wait for remote to start importing) */
}
const struct dsync_mailbox *box1,
const struct dsync_mailbox *box2)
{
if (brain->no_mail_sync)
return FALSE;
return TRUE;
}
static int
const struct mailbox_cache_field *f2)
{
}
static void
const struct dsync_mailbox *remote_box,
struct mailbox_update *update)
{
int ret;
/* remote has no cached fields. there's nothing to update. */
return;
}
if (array_count(&local_sorted) == 0) {
/* local has no cached fields. set them to same as remote. */
return;
}
/* figure out what to change */
if (ret == 0) {
/* field exists in both local and remote */
/* use local decision and timestamp */
} else {
}
} else if (ret < 0) {
/* remote field doesn't exist */
li++;
} else {
/* local field doesn't exist */
/* field hasn't be used for a long time, remote
will probably drop this soon as well */
} else {
}
ri++;
}
}
if (array_count(&changes) > 0) {
}
}
const struct dsync_mailbox *local_box,
const struct dsync_mailbox *remote_box,
const char **reason_r)
{
/* Keep the UIDVALIDITY for the mailbox that has more
messages. If they equal, use the higher UIDVALIDITY. */
/* we can't continue syncing this mailbox in this
session, because the other side already started
sending mailbox changes, but not for all mails. */
*reason_r = "UIDVALIDITY changed during a stateful sync, need to restart";
}
}
if (update.uid_validity == 0 &&
/* no changes */
return ret;
}
i_error("Couldn't update mailbox %s metadata: %s",
}
return ret;
}
static void
const struct dsync_mailbox *dsync_box,
bool ignore)
{
i_debug("brain %c: We don't have mailbox %s",
}
i_zero(&delete_box);
sizeof(delete_box.mailbox_guid));
if (ignore)
else
}
{
int ret;
bool resync;
return FALSE;
if (ret < 0) {
return TRUE;
}
i_error("Couldn't allocate mailbox GUID %s: %s",
return TRUE;
}
i_debug("brain %c: Ignore nonexistent "
"mailbox GUID %s with -1 sync",
}
return TRUE;
}
//FIXME: verify this from log, and if not log an error.
"Mailbox GUID %s was lost",
return TRUE;
}
/* Lock before syncing */
mailbox_free(&box);
return TRUE;
}
i_error("Can't sync mailbox %s: %s",
mailbox_free(&box);
return TRUE;
}
mailbox_free(&box);
if (ret < 0) {
return TRUE;
}
/* another process just deleted this mailbox? */
i_debug("brain %c: Skipping lost mailbox %s",
}
return TRUE;
}
sizeof(dsync_box->mailbox_guid)) == 0);
/* no fields appear to have changed, skip this mailbox */
i_debug("brain %c: Skipping unchanged mailbox %s",
}
mailbox_free(&box);
return TRUE;
}
return TRUE;
if (resync)
return TRUE;
}
return TRUE;
}