Skip to content

Commit

Permalink
dsync: Avoid finishing importer successfully on exporter failures.
Browse files Browse the repository at this point in the history
At least dsync_mailbox_import_changes_finish() could have been called when
exporter was already failed.
  • Loading branch information
sirainen committed Jan 28, 2016
1 parent 79490ec commit e1bef59
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 50 deletions.
53 changes: 33 additions & 20 deletions src/doveadm/dsync/dsync-brain-mails.c
Expand Up @@ -97,14 +97,36 @@ static void dsync_brain_send_end_of_list(struct dsync_brain *brain,
dsync_ibc_send_end_of_list(brain->ibc, type);
}

static int dsync_brain_export_deinit(struct dsync_brain *brain)
{
const char *errstr;
enum mail_error error;

if (dsync_mailbox_export_deinit(&brain->box_exporter,
&errstr, &error) < 0) {
i_error("Exporting mailbox %s failed: %s",
mailbox_get_vname(brain->box), errstr);
brain->mail_error = error;
brain->failed = TRUE;
return -1;
}
return 0;
}

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

while ((attr = dsync_mailbox_export_next_attr(brain->box_exporter)) != NULL) {
while ((ret = dsync_mailbox_export_next_attr(brain->box_exporter, &attr)) > 0) {
if (dsync_ibc_send_mailbox_attribute(brain->ibc, attr) == 0)
return;
}
if (ret < 0) {
if (dsync_brain_export_deinit(brain) == 0)
i_unreached();
return;
}
dsync_brain_send_end_of_list(brain, DSYNC_IBC_EOL_MAILBOX_ATTRIBUTE);
brain->box_send_state = DSYNC_BOX_STATE_CHANGES;
}
Expand Down Expand Up @@ -133,11 +155,17 @@ static bool dsync_brain_recv_mail_change(struct dsync_brain *brain)
static void dsync_brain_send_mail_change(struct dsync_brain *brain)
{
const struct dsync_mail_change *change;
int ret;

while ((change = dsync_mailbox_export_next(brain->box_exporter)) != NULL) {
while ((ret = dsync_mailbox_export_next(brain->box_exporter, &change)) > 0) {
if (dsync_ibc_send_change(brain->ibc, change) == 0)
return;
}
if (ret < 0) {
if (dsync_brain_export_deinit(brain) == 0)
i_unreached();
return;
}
dsync_brain_send_end_of_list(brain, DSYNC_IBC_EOL_MAIL_CHANGES);
if (brain->mail_requests && brain->box_importer != NULL)
brain->box_send_state = DSYNC_BOX_STATE_MAIL_REQUESTS;
Expand Down Expand Up @@ -188,22 +216,6 @@ static bool dsync_brain_send_mail_request(struct dsync_brain *brain)
return TRUE;
}

static int dsync_brain_export_deinit(struct dsync_brain *brain)
{
const char *errstr;
enum mail_error error;

if (dsync_mailbox_export_deinit(&brain->box_exporter,
&errstr, &error) < 0) {
i_error("Exporting mailbox %s failed: %s",
mailbox_get_vname(brain->box), errstr);
brain->mail_error = error;
brain->failed = TRUE;
return -1;
}
return 0;
}

static void dsync_brain_sync_half_finished(struct dsync_brain *brain)
{
struct dsync_mailbox_state state;
Expand All @@ -227,7 +239,8 @@ static void dsync_brain_sync_half_finished(struct dsync_brain *brain)
state.last_messages_count =
brain->local_dsync_box.messages_count;
} else {
if (dsync_mailbox_import_deinit(&brain->box_importer, TRUE,
if (dsync_mailbox_import_deinit(&brain->box_importer,
!brain->failed,
&state.last_common_uid,
&state.last_common_modseq,
&state.last_common_pvt_modseq,
Expand Down Expand Up @@ -284,7 +297,7 @@ static bool dsync_brain_send_mail(struct dsync_brain *brain)
return FALSE;
}

while ((mail = dsync_mailbox_export_next_mail(brain->box_exporter)) != NULL) {
while (dsync_mailbox_export_next_mail(brain->box_exporter, &mail) > 0) {
if (dsync_ibc_send_mail(brain->ibc, mail) == 0)
return TRUE;
}
Expand Down
54 changes: 30 additions & 24 deletions src/doveadm/dsync/dsync-mailbox-export.c
Expand Up @@ -648,38 +648,41 @@ dsync_mailbox_export_iter_next_attr(struct dsync_mailbox_exporter *exporter)
return dsync_mailbox_export_iter_next_nonexistent_attr(exporter);
}

const struct dsync_mailbox_attribute *
dsync_mailbox_export_next_attr(struct dsync_mailbox_exporter *exporter)
int dsync_mailbox_export_next_attr(struct dsync_mailbox_exporter *exporter,
const struct dsync_mailbox_attribute **attr_r)
{
int ret;

if (exporter->error != NULL)
return NULL;
return -1;

if (exporter->attr.value_stream != NULL)
i_stream_unref(&exporter->attr.value_stream);

if (exporter->attr_iter != NULL) {
if (dsync_mailbox_export_iter_next_attr(exporter) <= 0)
return NULL;
ret = dsync_mailbox_export_iter_next_attr(exporter);
} else {
if (dsync_mailbox_export_iter_next_nonexistent_attr(exporter) <= 0)
return NULL;
ret = dsync_mailbox_export_iter_next_nonexistent_attr(exporter);
}
return &exporter->attr;
if (ret > 0)
*attr_r = &exporter->attr;
return ret;
}

const struct dsync_mail_change *
dsync_mailbox_export_next(struct dsync_mailbox_exporter *exporter)
int dsync_mailbox_export_next(struct dsync_mailbox_exporter *exporter,
const struct dsync_mail_change **change_r)
{
struct dsync_mail_change *const *changes;
unsigned int count;

if (exporter->error != NULL)
return NULL;
return -1;

changes = array_get(&exporter->sorted_changes, &count);
if (exporter->change_idx == count)
return NULL;
return changes[exporter->change_idx++];
return 0;
*change_r = changes[exporter->change_idx++];
return 1;
}

static int
Expand Down Expand Up @@ -837,31 +840,33 @@ void dsync_mailbox_export_want_mail(struct dsync_mailbox_exporter *exporter,
instances->requested = TRUE;
}

const struct dsync_mail *
dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter)
int dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter,
const struct dsync_mail **mail_r)
{
struct mail *mail;
const char *const *guids;
unsigned int count;
int ret;

if (exporter->error != NULL)
return NULL;
return -1;
if (!exporter->body_search_initialized) {
exporter->body_search_initialized = TRUE;
if (dsync_mailbox_export_body_search_init(exporter) < 0) {
i_assert(exporter->error != NULL);
return NULL;
return -1;
}
}

while (mailbox_search_next(exporter->search_ctx, &mail)) {
exporter->search_pos++;
if ((ret = dsync_mailbox_export_mail(exporter, mail)) > 0)
return &exporter->dsync_mail;
if ((ret = dsync_mailbox_export_mail(exporter, mail)) > 0) {
*mail_r = &exporter->dsync_mail;
return 1;
}
if (ret < 0) {
i_assert(exporter->error != NULL);
return NULL;
return -1;
}
/* the message was expunged. if the GUID has another instance,
try sending it later. */
Expand All @@ -872,11 +877,11 @@ dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter)
dsync_mailbox_export_body_search_deinit(exporter);
if ((ret = dsync_mailbox_export_body_search_init(exporter)) < 0) {
i_assert(exporter->error != NULL);
return NULL;
return -1;
}
if (ret > 0) {
/* not finished yet */
return dsync_mailbox_export_next_mail(exporter);
return dsync_mailbox_export_next_mail(exporter, mail_r);
}

/* finished with messages. if there are any expunged messages,
Expand All @@ -886,9 +891,10 @@ dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter)
memset(&exporter->dsync_mail, 0, sizeof(exporter->dsync_mail));
exporter->dsync_mail.guid =
guids[exporter->expunged_guid_idx++];
return &exporter->dsync_mail;
*mail_r = &exporter->dsync_mail;
return 1;
}
return NULL;
return 0;
}

int dsync_mailbox_export_deinit(struct dsync_mailbox_exporter **_exporter,
Expand Down
15 changes: 9 additions & 6 deletions src/doveadm/dsync/dsync-mailbox-export.h
Expand Up @@ -14,15 +14,18 @@ dsync_mailbox_export_init(struct mailbox *box,
struct dsync_transaction_log_scan *log_scan,
uint32_t last_common_uid,
enum dsync_mailbox_exporter_flags flags);
const struct dsync_mailbox_attribute *
dsync_mailbox_export_next_attr(struct dsync_mailbox_exporter *exporter);
const struct dsync_mail_change *
dsync_mailbox_export_next(struct dsync_mailbox_exporter *exporter);
/* Returns 1 if attribute was returned, 0 if no more attributes, -1 on error */
int dsync_mailbox_export_next_attr(struct dsync_mailbox_exporter *exporter,
const struct dsync_mailbox_attribute **attr_r);
/* Returns 1 if change was returned, 0 if no more changes, -1 on error */
int dsync_mailbox_export_next(struct dsync_mailbox_exporter *exporter,
const struct dsync_mail_change **change_r);

void dsync_mailbox_export_want_mail(struct dsync_mailbox_exporter *exporter,
const struct dsync_mail_request *request);
const struct dsync_mail *
dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter);
/* Returns 1 if mail was returned, 0 if no more mails, -1 on error */
int dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter,
const struct dsync_mail **mail_r);
int dsync_mailbox_export_deinit(struct dsync_mailbox_exporter **exporter,
const char **errstr_r, enum mail_error *error_r);

Expand Down

0 comments on commit e1bef59

Please sign in to comment.