From: Timo Sirainen Date: Mon, 15 Feb 2010 02:31:35 +0000 (+0200) Subject: Mailbox deletion: If mailbox deletion seems to have crashed, allow retrying the deletion. X-Git-Tag: 2.0.beta3~75 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2555e5dc02cd2fdfd01df0d6d1d6f09274dc9d5c;p=thirdparty%2Fdovecot%2Fcore.git 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. --HG-- branch : HEAD --- diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index c1d3476d71..bda49dac65 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -20,6 +20,8 @@ #include #include +#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 @@ int mailbox_update(struct mailbox *box, const struct mailbox_update *update) 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 @@ static int mailbox_mark_index_deleted(struct mailbox *box) 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 @@ int mailbox_delete(struct mailbox *box) (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);