dsync-brain-mailbox.c revision f43ce62fa945f597e8a48e09c53d46dcc95445d4
/* Copyright (c) 2013-2016 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
{
enum mailbox_flags flags = 0;
enum mailbox_existence existence;
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)
{
struct mail_namespace *ns;
int ret;
continue;
return ret;
}
return 0;
}
static void
{
const struct mailbox_cache_field *src_field;
struct mailbox_cache_field *dest_field;
}
}
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)
{
const struct dsync_mailbox_state *state;
if (wait_for_remote_box) {
} else {
}
else {
}
else {
}
}
static void
const struct dsync_mailbox *remote_dsync_box)
{
enum dsync_mailbox_import_flags import_flags = 0;
const struct dsync_mailbox_state *state;
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->hdr_hash_v2)
if (brain->empty_hdr_workaround)
}
const struct dsync_mailbox *remote_dsync_box)
{
struct mailbox_status status;
enum dsync_mailbox_exporter_flags exporter_flags = 0;
const char *desync_reason = "";
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) {
"Private modseq %llu no longer in transaction log",
(unsigned long long)last_common_pvt_modseq);
} else {
"Modseq %llu no longer in transaction log",
(unsigned long long)last_common_modseq);
}
}
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;
(unsigned long long)status.highest_modseq,
(unsigned long long)last_common_modseq);
ret = 0;
(unsigned long long)status.highest_pvt_modseq,
(unsigned long long)last_common_pvt_modseq);
ret = 0;
}
}
if (ret == 0) {
i_warning("Failed to do incremental sync for mailbox %s, "
"retry with a full sync (%s)",
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 (brain->hdr_hash_v2)
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;
}
{
enum mail_error error;
const char *errstr;
}
&brain->mail_error);
if (require_full_resync)
}
}
enum mail_error *error_r)
{
const enum mailbox_status_items status_items =
const enum mailbox_metadata_items metadata_items =
struct mailbox_status status;
struct mailbox_metadata metadata;
const char *errstr;
enum mail_error error;
/* 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)
{
const struct dsync_mailbox_state *state;
return TRUE;
}
static int
struct dsync_mailbox *dsync_box_r)
{
enum mailbox_flags flags = 0;
struct dsync_mailbox dsync_box;
struct dsync_mailbox_node *node;
enum mail_error error;
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 "
"uidvalidity=%u uidnext=%u highestmodseq=%llu highestpvtmodseq=%llu messages=%u",
(unsigned long long)dsync_box.highest_modseq,
(unsigned long long)dsync_box.highest_pvt_modseq,
}
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 */
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;
}
{
struct dsync_mailbox dsync_box;
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)
{
struct mailbox_update update;
const struct dsync_mailbox_state *state;
/* 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. */
}
}
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)
{
struct dsync_mailbox delete_box;
i_debug("brain %c: We don't have mailbox %s",
}
sizeof(delete_box.mailbox_guid));
}
{
const struct dsync_mailbox *dsync_box;
struct dsync_mailbox local_dsync_box;
const char *errstr;
enum mail_error error;
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.
i_debug("brain %c: Change during sync: "
"Mailbox GUID %s was lost",
}
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;
return TRUE;
}
return TRUE;
}