<commit_before>/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "istream.h"
#include "dsync-ibc.h"
#include "dsync-mail.h"
#include "dsync-mailbox-import.h"
#include "dsync-mailbox-export.h"
#include "dsync-brain-private.h"

const char *dsync_box_state_names[DSYNC_BOX_STATE_DONE+1] = {
	"mailbox",
	"changes",
	"attributes",
	"mail_requests",
	"mails",
	"recv_last_common",
	"done"
};

static bool dsync_brain_master_sync_recv_mailbox(struct dsync_brain *brain)
{
	const struct dsync_mailbox *dsync_box;
	enum dsync_ibc_recv_ret ret;

	i_assert(brain->master_brain);

	if ((ret = dsync_ibc_recv_mailbox(brain->ibc, &dsync_box)) == 0)
		return FALSE;
	if (ret == DSYNC_IBC_RECV_RET_FINISHED) {
		i_error("Remote sent end-of-list instead of a mailbox");
		brain->failed = TRUE;
		return TRUE;
	}
	if (memcmp(dsync_box->mailbox_guid, brain->local_dsync_box.mailbox_guid,
		   sizeof(dsync_box->mailbox_guid)) != 0) {
		i_error("Remote sent mailbox with a wrong GUID");
		brain->failed = TRUE;
		return TRUE;
	}

	if (dsync_box->mailbox_lost) {
		/* remote lost the mailbox. it's probably already deleted, but
		   verify it on next sync just to be sure */
		dsync_brain_sync_mailbox_deinit(brain);
		return TRUE;
	}
	dsync_brain_mailbox_update_pre(brain, brain->box,
				       &brain->local_dsync_box, dsync_box);

	if (brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_CHANGED &&
	    !dsync_boxes_need_sync(&brain->local_dsync_box, dsync_box)) {
		/* no fields appear to have changed, skip this mailbox */
		dsync_brain_sync_mailbox_deinit(brain);
		return TRUE;
	}
	if (dsync_brain_sync_mailbox_open(brain, dsync_box) < 0)
		return TRUE;
	dsync_brain_sync_init_box_states(brain);
	return TRUE;
}

static bool dsync_brain_recv_mailbox_attribute(struct dsync_brain *brain)
{
	const struct dsync_mailbox_attribute *attr;
	enum dsync_ibc_recv_ret ret;

	if ((ret = dsync_ibc_recv_mailbox_attribute(brain->ibc, &attr)) == 0)
		return FALSE;
	if (ret == DSYNC_IBC_RECV_RET_FINISHED) {
		brain->box_recv_state = DSYNC_BOX_STATE_CHANGES;
		return TRUE;
	}
	if (dsync_mailbox_import_attribute(brain->box_importer, attr) < 0)
		brain->failed = TRUE;
	return TRUE;
}

static void dsync_brain_send_mailbox_attribute(struct dsync_brain *brain)
{
	const struct dsync_mailbox_attribute *attr;

	while ((attr = dsync_mailbox_export_next_attr(brain->box_exporter)) != NULL) {
		if (dsync_ibc_send_mailbox_attribute(brain->ibc, attr) == 0)
			return;
	}
	dsync_ibc_send_end_of_list(brain->ibc);
	brain->box_send_state = DSYNC_BOX_STATE_CHANGES;
}

static bool dsync_brain_recv_mail_change(struct dsync_brain *brain)
{
	const struct dsync_mail_change *change;
	enum dsync_ibc_recv_ret ret;

	if ((ret = dsync_ibc_recv_change(brain->ibc, &change)) == 0)
		return FALSE;
	if (ret == DSYNC_IBC_RECV_RET_FINISHED) {
		dsync_mailbox_import_changes_finish(brain->box_importer);
		if (brain->mail_requests && brain->box_exporter != NULL)
			brain->box_recv_state = DSYNC_BOX_STATE_MAIL_REQUESTS;
		else
			brain->box_recv_state = DSYNC_BOX_STATE_MAILS;
		return TRUE;
	}
	if (dsync_mailbox_import_change(brain->box_importer, change) < 0)
		brain->failed = TRUE;
	return TRUE;
}

static void dsync_brain_send_mail_change(struct dsync_brain *brain)
{
	const struct dsync_mail_change *change;

	while ((change = dsync_mailbox_export_next(brain->box_exporter)) != NULL) {
		if (dsync_ibc_send_change(brain->ibc, change) == 0)
			return;
	}
	dsync_ibc_send_end_of_list(brain->ibc);
	if (brain->mail_requests && brain->box_importer != NULL)
		brain->box_send_state = DSYNC_BOX_STATE_MAIL_REQUESTS;
	else
		brain->box_send_state = DSYNC_BOX_STATE_MAILS;
}

static bool dsync_brain_recv_mail_request(struct dsync_brain *brain)
{
	const struct dsync_mail_request *request;
	enum dsync_ibc_recv_ret ret;

	i_assert(brain->mail_requests);
	i_assert(brain->box_exporter != NULL);

	if ((ret = dsync_ibc_recv_mail_request(brain->ibc, &request)) == 0)
		return FALSE;
	if (ret == DSYNC_IBC_RECV_RET_FINISHED) {
		brain->box_recv_state = brain->box_importer != NULL ?
			DSYNC_BOX_STATE_MAILS :
			DSYNC_BOX_STATE_RECV_LAST_COMMON;
		return TRUE;
	}
	dsync_mailbox_export_want_mail(brain->box_exporter, request);
	return TRUE;
}

static bool dsync_brain_send_mail_request(struct dsync_brain *brain)
{
	const struct dsync_mail_request *request;

	i_assert(brain->mail_requests);

	while ((request = dsync_mailbox_import_next_request(brain->box_importer)) != NULL) {
		if (dsync_ibc_send_mail_request(brain->ibc, request) == 0)
			return TRUE;
	}
	if (brain->box_recv_state <= DSYNC_BOX_STATE_CHANGES)
		return FALSE;

	dsync_ibc_send_end_of_list(brain->ibc);
	if (brain->box_exporter != NULL)
		brain->box_send_state = DSYNC_BOX_STATE_MAILS;
	else {
		i_assert(brain->box_recv_state != DSYNC_BOX_STATE_DONE);
		brain->box_send_state = DSYNC_BOX_STATE_DONE;
	}
	return TRUE;
}

static void dsync_brain_sync_half_finished(struct dsync_brain *brain)
{
	struct dsync_mailbox_state state;
	const char *error;

	if (brain->box_recv_state < DSYNC_BOX_STATE_RECV_LAST_COMMON ||
	    brain->box_send_state < DSYNC_BOX_STATE_RECV_LAST_COMMON)<commit_msg>dsync: Mail requests were lost when attributes were being synced.<commit_after>/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "istream.h"
#include "dsync-ibc.h"
#include "dsync-mail.h"
#include "dsync-mailbox-import.h"
#include "dsync-mailbox-export.h"
#include "dsync-brain-private.h"

const char *dsync_box_state_names[DSYNC_BOX_STATE_DONE+1] = {
	"mailbox",
	"changes",
	"attributes",
	"mail_requests",
	"mails",
	"recv_last_common",
	"done"
};

static bool dsync_brain_master_sync_recv_mailbox(struct dsync_brain *brain)
{
	const struct dsync_mailbox *dsync_box;
	enum dsync_ibc_recv_ret ret;

	i_assert(brain->master_brain);

	if ((ret = dsync_ibc_recv_mailbox(brain->ibc, &dsync_box)) == 0)
		return FALSE;
	if (ret == DSYNC_IBC_RECV_RET_FINISHED) {
		i_error("Remote sent end-of-list instead of a mailbox");
		brain->failed = TRUE;
		return TRUE;
	}
	if (memcmp(dsync_box->mailbox_guid, brain->local_dsync_box.mailbox_guid,
		   sizeof(dsync_box->mailbox_guid)) != 0) {
		i_error("Remote sent mailbox with a wrong GUID");
		brain->failed = TRUE;
		return TRUE;
	}

	if (dsync_box->mailbox_lost) {
		/* remote lost the mailbox. it's probably already deleted, but
		   verify it on next sync just to be sure */
		dsync_brain_sync_mailbox_deinit(brain);
		return TRUE;
	}
	dsync_brain_mailbox_update_pre(brain, brain->box,
				       &brain->local_dsync_box, dsync_box);

	if (brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_CHANGED &&
	    !dsync_boxes_need_sync(&brain->local_dsync_box, dsync_box)) {
		/* no fields appear to have changed, skip this mailbox */
		dsync_brain_sync_mailbox_deinit(brain);
		return TRUE;
	}
	if (dsync_brain_sync_mailbox_open(brain, dsync_box) < 0)
		return TRUE;
	dsync_brain_sync_init_box_states(brain);
	return TRUE;
}

static bool dsync_brain_recv_mailbox_attribute(struct dsync_brain *brain)
{
	const struct dsync_mailbox_attribute *attr;
	enum dsync_ibc_recv_ret ret;

	if ((ret = dsync_ibc_recv_mailbox_attribute(brain->ibc, &attr)) == 0)
		return FALSE;
	if (ret == DSYNC_IBC_RECV_RET_FINISHED) {
		brain->box_recv_state = DSYNC_BOX_STATE_CHANGES;
		return TRUE;
	}
	if (dsync_mailbox_import_attribute(brain->box_importer, attr) < 0)
		brain->failed = TRUE;
	return TRUE;
}

static void dsync_brain_send_mailbox_attribute(struct dsync_brain *brain)
{
	const struct dsync_mailbox_attribute *attr;

	while ((attr = dsync_mailbox_export_next_attr(brain->box_exporter)) != NULL) {
		if (dsync_ibc_send_mailbox_attribute(brain->ibc, attr) == 0)
			return;
	}
	dsync_ibc_send_end_of_list(brain->ibc);
	brain->box_send_state = DSYNC_BOX_STATE_CHANGES;
}

static bool dsync_brain_recv_mail_change(struct dsync_brain *brain)
{
	const struct dsync_mail_change *change;
	enum dsync_ibc_recv_ret ret;

	if ((ret = dsync_ibc_recv_change(brain->ibc, &change)) == 0)
		return FALSE;
	if (ret == DSYNC_IBC_RECV_RET_FINISHED) {
		dsync_mailbox_import_changes_finish(brain->box_importer);
		if (brain->mail_requests && brain->box_exporter != NULL)
			brain->box_recv_state = DSYNC_BOX_STATE_MAIL_REQUESTS;
		else
			brain->box_recv_state = DSYNC_BOX_STATE_MAILS;
		return TRUE;
	}
	if (dsync_mailbox_import_change(brain->box_importer, change) < 0)
		brain->failed = TRUE;
	return TRUE;
}

static void dsync_brain_send_mail_change(struct dsync_brain *brain)
{
	const struct dsync_mail_change *change;

	while ((change = dsync_mailbox_export_next(brain->box_exporter)) != NULL) {
		if (dsync_ibc_send_change(brain->ibc, change) == 0)
			return;
	}
	dsync_ibc_send_end_of_list(brain->ibc);
	if (brain->mail_requests && brain->box_importer != NULL)
		brain->box_send_state = DSYNC_BOX_STATE_MAIL_REQUESTS;
	else
		brain->box_send_state = DSYNC_BOX_STATE_MAILS;
}

static bool dsync_brain_recv_mail_request(struct dsync_brain *brain)
{
	const struct dsync_mail_request *request;
	enum dsync_ibc_recv_ret ret;

	i_assert(brain->mail_requests);
	i_assert(brain->box_exporter != NULL);

	if ((ret = dsync_ibc_recv_mail_request(brain->ibc, &request)) == 0)
		return FALSE;
	if (ret == DSYNC_IBC_RECV_RET_FINISHED) {
		brain->box_recv_state = brain->box_importer != NULL ?
			DSYNC_BOX_STATE_MAILS :
			DSYNC_BOX_STATE_RECV_LAST_COMMON;
		return TRUE;
	}
	dsync_mailbox_export_want_mail(brain->box_exporter, request);
	return TRUE;
}

static bool dsync_brain_send_mail_request(struct dsync_brain *brain)
{
	const struct dsync_mail_request *request;

	i_assert(brain->mail_requests);

	while ((request = dsync_mailbox_import_next_request(brain->box_importer)) != NULL) {
		if (dsync_ibc_send_mail_request(brain->ibc, request) == 0)
			return TRUE;
	}
	if (brain->box_recv_state < DSYNC_BOX_STATE_MAIL_REQUESTS)
		return FALSE;

	dsync_ibc_send_end_of_list(brain->ibc);
	if (brain->box_exporter != NULL)
		brain->box_send_state = DSYNC_BOX_STATE_MAILS;
	else {
		i_assert(brain->box_recv_state != DSYNC_BOX_STATE_DONE);
		brain->box_send_state = DSYNC_BOX_STATE_DONE;
	}
	return TRUE;
}

static void dsync_brain_sync_half_finished(struct dsync_brain *brain)
{
	struct dsync_mailbox_state state;
	const char *error;

	if (brain->box_recv_state < DSYNC_BOX_STATE_RECV_LAST_COMMON ||
	    brain->box_send_state < DSYNC_BOX_STATE_RECV_LAST_COMMON)
{'fraction_non_alphanumeric': 0.10870615518407575, 'fraction_numerical': 0.0030920861919025992, 'mean_word_length': 5.88622754491018, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 107, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7643900', 'n_tokens_mistral': 4350, 'n_tokens_neox': 4051, 'n_words': 714}