}
}
- if (!mail_index_need_sync(index, flags,
- log_file_seq, log_file_offset)) {
+ if (!mail_index_need_sync(index, flags, log_file_seq, log_file_offset) &&
+ !index->index_deleted) {
if (locked)
mail_transaction_log_sync_unlock(index->log);
return 0;
}
- if (index->index_deleted &&
- (flags & MAIL_INDEX_SYNC_FLAG_DELETING_INDEX) == 0) {
- /* index is already deleted. we can't sync. */
- if (locked)
- mail_transaction_log_sync_unlock(index->log);
- return -1;
- }
-
if (!locked) {
/* it looks like we have something to sync. lock the file and
check again. */
log_file_offset);
}
+ if (index->index_deleted &&
+ (flags & MAIL_INDEX_SYNC_FLAG_DELETING_INDEX) == 0) {
+ /* index is already deleted. we can't sync. */
+ if (locked)
+ mail_transaction_log_sync_unlock(index->log);
+ return -1;
+ }
+
hdr = &index->map->hdr;
if (hdr->log_file_tail_offset > hdr->log_file_head_offset ||
hdr->log_file_seq > seq ||
ctx->ext_trans = mail_index_transaction_begin(ctx->view, trans_flags);
ctx->ext_trans->sync_transaction = TRUE;
ctx->ext_trans->commit_deleted_index =
- (flags & MAIL_INDEX_SYNC_FLAG_DELETING_INDEX) != 0;
+ (flags & (MAIL_INDEX_SYNC_FLAG_DELETING_INDEX |
+ MAIL_INDEX_SYNC_FLAG_TRY_DELETING_INDEX)) != 0;
*ctx_r = ctx;
*view_r = ctx->view;
index_undeleted = ctx->ext_trans->index_undeleted;
delete_index = index->index_delete_requested && !index_undeleted &&
- (ctx->flags & MAIL_INDEX_SYNC_FLAG_DELETING_INDEX) != 0;
+ (ctx->flags & (MAIL_INDEX_SYNC_FLAG_DELETING_INDEX |
+ MAIL_INDEX_SYNC_FLAG_TRY_DELETING_INDEX)) != 0;
if (delete_index) {
/* finish this sync by marking the index deleted */
mail_index_set_deleted(ctx->ext_trans);
+ } else if (index->index_deleted && !index_undeleted &&
+ (ctx->flags & MAIL_INDEX_SYNC_FLAG_TRY_DELETING_INDEX) == 0) {
+ /* another process just marked the index deleted.
+ finish the sync, but return error. */
+ ret = -1;
}
mail_index_sync_update_mailbox_offset(ctx);
MAIL_INDEX_SYNC_FLAG_FSYNC = 0x10,
/* If we see "delete index" request transaction, finish it.
This flag also allows committing more changes to a deleted index. */
- MAIL_INDEX_SYNC_FLAG_DELETING_INDEX = 0x20
+ MAIL_INDEX_SYNC_FLAG_DELETING_INDEX = 0x20,
+ /* Same as MAIL_INDEX_SYNC_FLAG_DELETING_INDEX, but finish index
+ deletion only once and fail the rest (= avoid race conditions when
+ multiple processes try to mark the index deleted) */
+ MAIL_INDEX_SYNC_FLAG_TRY_DELETING_INDEX = 0x40
};
enum mail_index_view_sync_flags {
/* sync the mailbox. this finishes the index deletion and it can
succeed only for a single session. we do it here, so the rest of
the deletion code doesn't have to worry about race conditions. */
- if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0)
+ box->delete_sync_check = TRUE;
+ ret = mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ);
+ box->delete_sync_check = FALSE;
+ if (ret < 0)
return -1;
box->marked_deleted = del;