Mercurial > dovecot > core-2.2
changeset 10723:eae6e4a7ee55 HEAD
Mailbox deletion: If mailbox deletion seems to have crashed, allow retrying the deletion.
We'll assume that if deletion transaction was written over 5 minutes ago,
the deletion crashed.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 15 Feb 2010 04:31:35 +0200 |
parents | 31aca1df525b |
children | 4fd02780d09f |
files | src/lib-storage/mail-storage.c |
diffstat | 1 files changed, 42 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/mail-storage.c Mon Feb 15 04:29:47 2010 +0200 +++ b/src/lib-storage/mail-storage.c Mon Feb 15 04:31:35 2010 +0200 @@ -20,6 +20,8 @@ #include <stdlib.h> #include <ctype.h> +#define MAILBOX_DELETE_RETRY_SECS (60*5) + struct mail_storage_module_register mail_storage_module_register = { 0 }; struct mail_module_register mail_module_register = { 0 }; @@ -616,12 +618,17 @@ return box->v.update(box, update); } -static int mailbox_mark_index_deleted(struct mailbox *box) +static int mailbox_mark_index_deleted(struct mailbox *box, bool del) { + enum mail_index_transaction_flags trans_flags = 0; struct mail_index_transaction *trans; - trans = mail_index_transaction_begin(box->view, 0); - mail_index_set_deleted(trans); + trans_flags = del ? 0 : MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL; + trans = mail_index_transaction_begin(box->view, trans_flags); + if (del) + mail_index_set_deleted(trans); + else + mail_index_set_undeleted(trans); if (mail_index_transaction_commit(&trans) < 0) { mail_storage_set_index_error(box); return -1; @@ -633,6 +640,21 @@ return mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ); } +static bool mailbox_try_undelete(struct mailbox *box) +{ + time_t mtime; + + if (mail_index_get_modification_time(box->index, &mtime) < 0) + return FALSE; + if (mtime + MAILBOX_DELETE_RETRY_SECS > time(NULL)) + return FALSE; + + if (mailbox_mark_index_deleted(box, FALSE) < 0) + return FALSE; + box->mailbox_deleted = FALSE; + return TRUE; +} + int mailbox_delete(struct mailbox *box) { enum mail_error error; @@ -654,9 +676,23 @@ (void)mail_storage_get_last_error(box->storage, &error); if (error != MAIL_ERROR_NOTFOUND) return -1; - /* \noselect mailbox */ - } else { - if (mailbox_mark_index_deleted(box) < 0) + if (!box->mailbox_deleted) { + /* \noselect mailbox */ + } else { + /* if deletion happened a long time ago, it means it + crashed while doing it. undelete the mailbox in + that case. */ + if (!mailbox_try_undelete(box)) + return -1; + + /* retry */ + if (mailbox_open(box) < 0) + return -1; + } + } + + if (box->opened) { + if (mailbox_mark_index_deleted(box, TRUE) < 0) return -1; } ret = box->v.delete(box);