changeset 10655:fc0ac73f0b36 HEAD

Added support for marking mailbox index deleted. Don't allow any changes after that. This is going to help with race conditions when deleting mailboxes.
author Timo Sirainen <tss@iki.fi>
date Sun, 07 Feb 2010 03:25:32 +0200
parents 302a4f807276
children 9d3b5cbef222
files src/doveadm/doveadm-dump-log.c src/lib-index/mail-index-private.h src/lib-index/mail-index-sync-update.c src/lib-index/mail-index-transaction-export.c src/lib-index/mail-index-transaction-private.h src/lib-index/mail-index-transaction-update.c src/lib-index/mail-index-transaction.c src/lib-index/mail-index.c src/lib-index/mail-index.h src/lib-index/mail-transaction-log-file.c src/lib-index/mail-transaction-log-private.h src/lib-index/mail-transaction-log.h src/lib-storage/index/cydir/cydir-save.c src/lib-storage/index/dbox-multi/mdbox-save.c src/lib-storage/index/dbox-single/sdbox-save.c src/lib-storage/index/index-storage.c src/lib-storage/index/index-transaction.c src/lib-storage/index/maildir/maildir-copy.c src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/mbox/mbox-save.c
diffstat 20 files changed, 102 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/doveadm/doveadm-dump-log.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/doveadm/doveadm-dump-log.c	Sun Feb 07 03:25:32 2010 +0200
@@ -109,6 +109,9 @@
 	case MAIL_TRANSACTION_MODSEQ_UPDATE:
 		name = "modseq-update";
 		break;
+	case MAIL_TRANSACTION_INDEX_DELETED:
+		name = "index-deleted";
+		break;
 	default:
 		name = t_strdup_printf("unknown: %x", type);
 		break;
@@ -411,6 +414,8 @@
 		}
 		break;
 	}
+	case MAIL_TRANSACTION_INDEX_DELETED:
+		break;
 	default:
 		break;
 	}
--- a/src/lib-index/mail-index-private.h	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-index/mail-index-private.h	Sun Feb 07 03:25:32 2010 +0200
@@ -226,6 +226,7 @@
 	unsigned int index_lock_timeout:1;
 
 	unsigned int opened:1;
+	unsigned int index_deleted:1; /* no changes allowed anymore */
 	unsigned int log_locked:1;
 	unsigned int readonly:1;
 	unsigned int mapping:1;
--- a/src/lib-index/mail-index-sync-update.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-index/mail-index-sync-update.c	Sun Feb 07 03:25:32 2010 +0200
@@ -814,6 +814,12 @@
 		ret = sync_modseq_update(ctx, rec, hdr->size);
 		break;
 	}
+	case MAIL_TRANSACTION_INDEX_DELETED:
+		if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0)
+			break;
+		/* transaction log syncing should have already set this */
+		i_assert(ctx->view->index->index_deleted);
+		break;
 	default:
 		mail_index_sync_set_corrupted(ctx,
 			"Unknown transaction record type 0x%x",
--- a/src/lib-index/mail-index-transaction-export.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-index/mail-index-transaction-export.c	Sun Feb 07 03:25:32 2010 +0200
@@ -455,6 +455,13 @@
 				  MAIL_TRANSACTION_HEADER_UPDATE);
 	}
 
+	if (t->index_deleted) {
+		static uint8_t null4[4] = { 0, 0, 0, 0 };
+		mail_transaction_log_append_add(ctx.append_ctx,
+						MAIL_TRANSACTION_INDEX_DELETED,
+						&null4, 4);
+	}
+
 	/* Update the tail offsets only when committing the sync transaction.
 	   Other transactions may not know the latest tail offset and might
 	   end up shrinking it. (Alternatively the shrinking tail offsets could
--- a/src/lib-index/mail-index-transaction-private.h	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-index/mail-index-transaction-private.h	Sun Feb 07 03:25:32 2010 +0200
@@ -85,6 +85,7 @@
 	unsigned int pre_hdr_changed:1;
 	unsigned int post_hdr_changed:1;
 	unsigned int reset:1;
+	unsigned int index_deleted:1;
 	/* non-extension updates. flag updates don't change this because
 	   they may be added and removed, so be sure to check that the updates
 	   array is non-empty also. */
--- a/src/lib-index/mail-index-transaction-update.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-index/mail-index-transaction-update.c	Sun Feb 07 03:25:32 2010 +0200
@@ -97,6 +97,7 @@
 	t->pre_hdr_changed = FALSE;
 	t->post_hdr_changed = FALSE;
 	t->reset = FALSE;
+	t->index_deleted = FALSE;
 	t->log_updates = FALSE;
 	t->log_ext_updates = FALSE;
 }
@@ -1169,6 +1170,13 @@
 	t->reset = TRUE;
 }
 
+void mail_index_set_deleted(struct mail_index_transaction *t)
+{
+	i_assert((t->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0);
+
+	t->index_deleted = TRUE;
+}
+
 void mail_index_transaction_set_max_modseq(struct mail_index_transaction *t,
 					   uint64_t max_modseq,
 					   ARRAY_TYPE(seq_range) *seqs)
--- a/src/lib-index/mail-index-transaction.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-index/mail-index-transaction.c	Sun Feb 07 03:25:32 2010 +0200
@@ -213,6 +213,11 @@
 		mail_index_transaction_rollback(_t);
 		return -1;
 	}
+	if (t->view->index->index_deleted) {
+		/* no further changes allowed */
+		mail_index_transaction_rollback(_t);
+		return -1;
+	}
 
 	*_t = NULL;
 	memset(result_r, 0, sizeof(*result_r));
--- a/src/lib-index/mail-index.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-index/mail-index.c	Sun Feb 07 03:25:32 2010 +0200
@@ -744,6 +744,11 @@
 	}
 }
 
+bool mail_index_is_deleted(struct mail_index *index)
+{
+	return index->index_deleted;
+}
+
 void mail_index_fchown(struct mail_index *index, int fd, const char *path)
 {
 	mode_t mode;
--- a/src/lib-index/mail-index.h	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-index/mail-index.h	Sun Feb 07 03:25:32 2010 +0200
@@ -446,6 +446,12 @@
 /* Reset the index before committing this transaction. This is usually done
    only when UIDVALIDITY changes. */
 void mail_index_reset(struct mail_index_transaction *t);
+/* Mark index deleted. No further changes will be possible after the
+   transaction has been committed. */
+void mail_index_set_deleted(struct mail_index_transaction *t);
+/* Returns TRUE if index has been set deleted. This gets set only after
+   index has been opened/refreshed and the transaction has been seen. */
+bool mail_index_is_deleted(struct mail_index *index);
 
 /* Lookup a keyword, returns TRUE if found, FALSE if not. */
 bool mail_index_keyword_lookup(struct mail_index *index,
--- a/src/lib-index/mail-transaction-log-file.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-index/mail-transaction-log-file.c	Sun Feb 07 03:25:32 2010 +0200
@@ -72,6 +72,7 @@
 	file->log = log;
 	file->filepath = i_strdup(path);
 	file->fd = -1;
+	file->index_deleted_offset = (uoff_t)-1;
 	return file;
 }
 
@@ -1101,14 +1102,19 @@
 		return 0;
 
 	/* external transactions: */
-	if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) ==
-	    MAIL_TRANSACTION_HEADER_UPDATE) {
+	switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
+	case MAIL_TRANSACTION_HEADER_UPDATE:
 		/* see if this updates mailbox_sync_offset */
 		ret = log_file_track_mailbox_sync_offset_hdr(file, data,
 							     trans_size -
 							     sizeof(*hdr));
 		if (ret != 0)
 			return ret < 0 ? -1 : 0;
+		break;
+	case MAIL_TRANSACTION_INDEX_DELETED:
+		file->log->index->index_deleted = TRUE;
+		file->index_deleted_offset = file->sync_offset + trans_size;
+		break;
 	}
 
 	if (file->max_tail_offset == file->sync_offset) {
@@ -1133,6 +1139,10 @@
 
 	data = buffer_get_data(file->buffer, &size);
 	while (file->sync_offset - file->buffer_offset + sizeof(*hdr) <= size) {
+		if (unlikely(file->index_deleted_offset == file->sync_offset)) {
+			/* ignore everything that comes after _INDEX_DELETED */
+			break;
+		}
 		hdr = CONST_PTR_OFFSET(data, file->sync_offset -
 				       file->buffer_offset);
 		trans_size = mail_index_offset_to_uint32(hdr->size);
--- a/src/lib-index/mail-transaction-log-private.h	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-index/mail-transaction-log-private.h	Sun Feb 07 03:25:32 2010 +0200
@@ -65,6 +65,10 @@
 	   sync_offset is less than this. */
 	uoff_t saved_tail_sync_offset;
 
+	/* if we've seen _INDEX_DELETED transaction in this file, this is the
+	   offset. otherwise (uoff_t)-1 */
+	uoff_t index_deleted_offset;
+
 	struct modseq_cache modseq_cache[LOG_FILE_MODSEQ_CACHE_SIZE];
 
 	struct file_lock *file_lock;
--- a/src/lib-index/mail-transaction-log.h	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-index/mail-transaction-log.h	Sun Feb 07 03:25:32 2010 +0200
@@ -42,6 +42,7 @@
 	MAIL_TRANSACTION_UID_UPDATE		= 0x00004000,
 	MAIL_TRANSACTION_MODSEQ_UPDATE		= 0x00008000,
 	MAIL_TRANSACTION_EXT_HDR_UPDATE32	= 0x00010000,
+	MAIL_TRANSACTION_INDEX_DELETED		= 0x00020000,
 
 	MAIL_TRANSACTION_TYPE_MASK		= 0x000fffff,
 
--- a/src/lib-storage/index/cydir/cydir-save.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-storage/index/cydir/cydir-save.c	Sun Feb 07 03:25:32 2010 +0200
@@ -85,6 +85,11 @@
 	enum mail_flags save_flags;
 	struct istream *crlf_input;
 
+	if (mail_index_is_deleted(ctx->mbox->ibox.index)) {
+		mailbox_set_deleted(trans->box);
+		return -1;
+	}
+
 	T_BEGIN {
 		const char *path;
 
--- a/src/lib-storage/index/dbox-multi/mdbox-save.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-save.c	Sun Feb 07 03:25:32 2010 +0200
@@ -97,6 +97,11 @@
 	struct dbox_save_mail *save_mail;
 	uoff_t mail_size, append_offset;
 
+	if (mail_index_is_deleted(ctx->mbox->ibox.index)) {
+		mailbox_set_deleted(_ctx->transaction->box);
+		return -1;
+	}
+
 	/* get the size of the mail to be saved, if possible */
 	if (i_stream_get_size(input, TRUE, &mail_size) <= 0) {
 		const struct stat *st;
--- a/src/lib-storage/index/dbox-single/sdbox-save.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-storage/index/dbox-single/sdbox-save.c	Sun Feb 07 03:25:32 2010 +0200
@@ -78,6 +78,11 @@
 	struct dbox_file *file;
 	int ret;
 
+	if (mail_index_is_deleted(ctx->mbox->ibox.index)) {
+		mailbox_set_deleted(_ctx->transaction->box);
+		return -1;
+	}
+
 	file = sdbox_file_init(ctx->mbox, 0);
 	ctx->append_ctx = dbox_file_append_init(file);
 	ret = dbox_file_get_append_stream(ctx->append_ctx,
--- a/src/lib-storage/index/index-storage.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-storage/index/index-storage.c	Sun Feb 07 03:25:32 2010 +0200
@@ -441,6 +441,11 @@
 	index_thread_mailbox_opened(ibox);
 	if (hook_mailbox_opened != NULL)
 		hook_mailbox_opened(box);
+
+	if (mail_index_is_deleted(ibox->index)) {
+		mailbox_set_deleted(box);
+		return -1;
+	}
 	return 0;
 }
 
@@ -649,7 +654,10 @@
 
 void mail_storage_set_index_error(struct index_mailbox *ibox)
 {
-	mail_storage_set_internal_error(ibox->box.storage);
+	if (mail_index_is_deleted(ibox->index))
+		mailbox_set_deleted(&ibox->box);
+	else
+		mail_storage_set_internal_error(ibox->box.storage);
 	mail_index_reset_error(ibox->index);
 }
 
--- a/src/lib-storage/index/index-transaction.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-storage/index/index-transaction.c	Sun Feb 07 03:25:32 2010 +0200
@@ -122,6 +122,8 @@
 	_t->changes = changes_r;
 
 	ret = mail_index_transaction_commit_full(&itrans, &result);
+	if (ret < 0 && mail_index_is_deleted(ibox->index))
+		mailbox_set_deleted(&ibox->box);
 
 	changes_r->ignored_uid_changes = result.ignored_uid_changes;
 	changes_r->ignored_modseq_changes = result.ignored_modseq_changes;
--- a/src/lib-storage/index/maildir/maildir-copy.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-storage/index/maildir/maildir-copy.c	Sun Feb 07 03:25:32 2010 +0200
@@ -170,6 +170,11 @@
 		return 0;
 	}
 
+	if (mail_index_is_deleted(dest_mbox->ibox.index)) {
+		mailbox_set_deleted(&dest_mbox->ibox.box);
+		return -1;
+	}
+
 	memset(&do_ctx, 0, sizeof(do_ctx));
 	do_ctx.dest_path = str_new(default_pool, 512);
 
--- a/src/lib-storage/index/maildir/maildir-save.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-storage/index/maildir/maildir-save.c	Sun Feb 07 03:25:32 2010 +0200
@@ -305,6 +305,11 @@
 	string_t *path;
 	int fd;
 
+	if (mail_index_is_deleted(mbox->ibox.index)) {
+		mailbox_set_deleted(box);
+		return -1;
+	}
+
 	path = t_str_new(256);
 	str_append(path, dir);
 	str_append_c(path, '/');
--- a/src/lib-storage/index/mbox/mbox-save.c	Sun Feb 07 01:55:06 2010 +0200
+++ b/src/lib-storage/index/mbox/mbox-save.c	Sun Feb 07 03:25:32 2010 +0200
@@ -261,6 +261,11 @@
 		return -1;
 	}
 
+	if (mail_index_is_deleted(mbox->ibox.index)) {
+		mailbox_set_deleted(&mbox->ibox.box);
+		return -1;
+	}
+
 	if ((_t->flags & MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS) != 0 ||
 	    ctx->ctx.uid != 0)
 		want_mail = TRUE;