changeset 10674:22354f505277 HEAD

lib-index: Added support for undeleting a deleted index.
author Timo Sirainen <tss@iki.fi>
date Tue, 09 Feb 2010 04:08:31 +0200
parents 6552652a9504
children 9cefc944d82a
files src/doveadm/doveadm-dump-log.c src/lib-index/mail-index-sync-update.c src/lib-index/mail-index-sync.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
diffstat 12 files changed, 86 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/doveadm/doveadm-dump-log.c	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/doveadm/doveadm-dump-log.c	Tue Feb 09 04:08:31 2010 +0200
@@ -112,6 +112,9 @@
 	case MAIL_TRANSACTION_INDEX_DELETED:
 		name = "index-deleted";
 		break;
+	case MAIL_TRANSACTION_INDEX_UNDELETED:
+		name = "index-undeleted";
+		break;
 	default:
 		name = t_strdup_printf("unknown: %x", type);
 		break;
@@ -415,6 +418,7 @@
 		break;
 	}
 	case MAIL_TRANSACTION_INDEX_DELETED:
+	case MAIL_TRANSACTION_INDEX_UNDELETED:
 		break;
 	default:
 		break;
--- a/src/lib-index/mail-index-sync-update.c	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/lib-index/mail-index-sync-update.c	Tue Feb 09 04:08:31 2010 +0200
@@ -819,11 +819,12 @@
 			/* next sync finishes the deletion */
 			ctx->view->index->index_delete_requested = TRUE;
 		} else {
-			/* transaction log syncing should have already
-			   set this */
-			i_assert(ctx->view->index->index_deleted);
+			/* transaction log reading handles this */
 		}
 		break;
+	case MAIL_TRANSACTION_INDEX_UNDELETED:
+		ctx->view->index->index_delete_requested = FALSE;
+		break;
 	default:
 		mail_index_sync_set_corrupted(ctx,
 			"Unknown transaction record type 0x%x",
--- a/src/lib-index/mail-index-sync.c	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/lib-index/mail-index-sync.c	Tue Feb 09 04:08:31 2010 +0200
@@ -389,6 +389,13 @@
 		return 0;
 	}
 
+	if (index->index_deleted) {
+		/* 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. */
@@ -482,11 +489,6 @@
 
 	index->syncing = TRUE;
 
-	if (index->index_delete_requested) {
-		/* finish this sync by marking the index deleted */
-		mail_index_set_deleted(ctx->ext_trans);
-	}
-
 	*ctx_r = ctx;
 	*view_r = ctx->view;
 	*trans_r = ctx->ext_trans;
@@ -536,6 +538,8 @@
 		case MAIL_TRANSACTION_FLAG_UPDATE:
 		case MAIL_TRANSACTION_KEYWORD_UPDATE:
 		case MAIL_TRANSACTION_KEYWORD_RESET:
+		case MAIL_TRANSACTION_INDEX_DELETED:
+		case MAIL_TRANSACTION_INDEX_UNDELETED:
 			return TRUE;
 		default:
 			break;
@@ -770,9 +774,15 @@
         struct mail_index_sync_ctx *ctx = *_ctx;
 	struct mail_index *index = ctx->index;
 	uint32_t next_uid;
-	bool want_rotate;
+	bool want_rotate, index_undeleted;
 	int ret = 0;
 
+	index_undeleted = ctx->ext_trans->index_undeleted;
+	if (index->index_delete_requested && !index_undeleted) {
+		/* finish this sync by marking the index deleted */
+		mail_index_set_deleted(ctx->ext_trans);
+	}
+
 	mail_index_sync_update_mailbox_offset(ctx);
 	if (mail_cache_need_compress(index->cache)) {
 		/* if cache compression fails, we don't really care.
@@ -796,6 +806,13 @@
 		return -1;
 	}
 
+	if (index_undeleted) {
+		index->index_deleted = FALSE;
+		index->index_delete_requested = FALSE;
+	}
+	if (index->index_delete_requested)
+		index->index_deleted = TRUE;
+
 	/* refresh the mapping with newly committed external transactions
 	   and the synced expunges. sync using file handler here so that the
 	   expunge handlers get called. */
--- a/src/lib-index/mail-index-transaction-export.c	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/lib-index/mail-index-transaction-export.c	Tue Feb 09 04:08:31 2010 +0200
@@ -394,6 +394,7 @@
 void mail_index_transaction_export(struct mail_index_transaction *t,
 				   struct mail_transaction_log_append_ctx *append_ctx)
 {
+	static uint8_t null4[4] = { 0, 0, 0, 0 };
 	enum mail_index_sync_type change_mask = 0;
 	struct mail_index_export_context ctx;
 
@@ -401,6 +402,12 @@
 	ctx.trans = t;
 	ctx.append_ctx = append_ctx;
 
+	if (t->index_undeleted) {
+		i_assert(!t->index_deleted);
+		mail_transaction_log_append_add(ctx.append_ctx,
+			MAIL_TRANSACTION_INDEX_UNDELETED, &null4, 4);
+	}
+
 	/* send all extension introductions and resizes before appends
 	   to avoid resize overhead as much as possible */
         mail_transaction_log_append_ext_intros(&ctx);
@@ -456,7 +463,7 @@
 	}
 
 	if (t->index_deleted) {
-		static uint8_t null4[4] = { 0, 0, 0, 0 };
+		i_assert(!t->index_undeleted);
 		mail_transaction_log_append_add(ctx.append_ctx,
 						MAIL_TRANSACTION_INDEX_DELETED,
 						&null4, 4);
--- a/src/lib-index/mail-index-transaction-private.h	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/lib-index/mail-index-transaction-private.h	Tue Feb 09 04:08:31 2010 +0200
@@ -86,6 +86,7 @@
 	unsigned int post_hdr_changed:1;
 	unsigned int reset:1;
 	unsigned int index_deleted:1;
+	unsigned int index_undeleted: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. */
@@ -96,7 +97,8 @@
 
 #define MAIL_INDEX_TRANSACTION_HAS_CHANGES(t) \
 	((t)->log_updates || (t)->log_ext_updates || \
-	 (array_is_created(&(t)->updates) && array_count(&(t)->updates) > 0))
+	 (array_is_created(&(t)->updates) && array_count(&(t)->updates) > 0) || \
+	 (t)->index_deleted || (t)->index_undeleted)
 
 extern void (*hook_mail_index_transaction_created)
 		(struct mail_index_transaction *t);
--- a/src/lib-index/mail-index-transaction-update.c	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/lib-index/mail-index-transaction-update.c	Tue Feb 09 04:08:31 2010 +0200
@@ -98,6 +98,7 @@
 	t->post_hdr_changed = FALSE;
 	t->reset = FALSE;
 	t->index_deleted = FALSE;
+	t->index_undeleted = FALSE;
 	t->log_updates = FALSE;
 	t->log_ext_updates = FALSE;
 }
@@ -1172,9 +1173,18 @@
 
 void mail_index_set_deleted(struct mail_index_transaction *t)
 {
+	i_assert(!t->index_undeleted);
+
 	t->index_deleted = TRUE;
 }
 
+void mail_index_set_undeleted(struct mail_index_transaction *t)
+{
+	i_assert(!t->index_deleted);
+
+	t->index_undeleted = 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	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/lib-index/mail-index-transaction.c	Tue Feb 09 04:08:31 2010 +0200
@@ -208,20 +208,33 @@
 				       struct mail_index_transaction_commit_result *result_r)
 {
 	struct mail_index_transaction *t = *_t;
+	struct mail_index *index = t->view->index;
+	bool index_undeleted = t->index_undeleted;
 
 	if (mail_index_view_is_inconsistent(t->view)) {
 		mail_index_transaction_rollback(_t);
 		return -1;
 	}
-	if (t->view->index->index_deleted) {
-		/* no further changes allowed */
-		mail_index_transaction_rollback(_t);
-		return -1;
+	if (!index_undeleted) {
+		if (t->view->index->index_deleted ||
+		    (t->view->index->index_delete_requested &&
+		     !t->view->index->syncing)) {
+			/* no further changes allowed */
+			mail_index_transaction_rollback(_t);
+			return -1;
+		}
 	}
 
 	*_t = NULL;
 	memset(result_r, 0, sizeof(*result_r));
-	return t->v.commit(t, result_r);
+	if (t->v.commit(t, result_r) < 0)
+		return -1;
+
+	if (index_undeleted) {
+		index->index_deleted = FALSE;
+		index->index_delete_requested = FALSE;
+	}
+	return 0;
 }
 
 void mail_index_transaction_rollback(struct mail_index_transaction **_t)
--- a/src/lib-index/mail-index.c	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/lib-index/mail-index.c	Tue Feb 09 04:08:31 2010 +0200
@@ -748,7 +748,7 @@
 
 bool mail_index_is_deleted(struct mail_index *index)
 {
-	return index->index_deleted;
+	return index->index_delete_requested || index->index_deleted;
 }
 
 void mail_index_fchown(struct mail_index *index, int fd, const char *path)
--- a/src/lib-index/mail-index.h	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/lib-index/mail-index.h	Tue Feb 09 04:08:31 2010 +0200
@@ -449,6 +449,8 @@
 /* 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);
+/* Mark a deleted index as undeleted. Afterwards index can be changed again. */
+void mail_index_set_undeleted(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);
--- a/src/lib-index/mail-transaction-log-file.c	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/lib-index/mail-transaction-log-file.c	Tue Feb 09 04:08:31 2010 +0200
@@ -72,7 +72,6 @@
 	file->log = log;
 	file->filepath = i_strdup(path);
 	file->fd = -1;
-	file->index_deleted_offset = (uoff_t)-1;
 	return file;
 }
 
@@ -1112,9 +1111,18 @@
 			return ret < 0 ? -1 : 0;
 		break;
 	case MAIL_TRANSACTION_INDEX_DELETED:
+		if (file->sync_offset < file->index_undeleted_offset)
+			break;
 		file->log->index->index_deleted = TRUE;
 		file->index_deleted_offset = file->sync_offset + trans_size;
 		break;
+	case MAIL_TRANSACTION_INDEX_UNDELETED:
+		if (file->sync_offset < file->index_deleted_offset)
+			break;
+		file->log->index->index_deleted = FALSE;
+		file->log->index->index_delete_requested = FALSE;
+		file->index_undeleted_offset = file->sync_offset + trans_size;
+		break;
 	}
 
 	if (file->max_tail_offset == file->sync_offset) {
@@ -1139,10 +1147,6 @@
 
 	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	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/lib-index/mail-transaction-log-private.h	Tue Feb 09 04:08:31 2010 +0200
@@ -65,9 +65,9 @@
 	   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;
+	/* if we've seen _INDEX_[UN9DELETED transaction in this file,
+	   this is the offset. otherwise (uoff_t)-1 */
+	uoff_t index_deleted_offset, index_undeleted_offset;
 
 	struct modseq_cache modseq_cache[LOG_FILE_MODSEQ_CACHE_SIZE];
 
--- a/src/lib-index/mail-transaction-log.h	Tue Feb 09 02:04:00 2010 +0200
+++ b/src/lib-index/mail-transaction-log.h	Tue Feb 09 04:08:31 2010 +0200
@@ -43,6 +43,7 @@
 	MAIL_TRANSACTION_MODSEQ_UPDATE		= 0x00008000,
 	MAIL_TRANSACTION_EXT_HDR_UPDATE32	= 0x00010000,
 	MAIL_TRANSACTION_INDEX_DELETED		= 0x00020000,
+	MAIL_TRANSACTION_INDEX_UNDELETED	= 0x00040000,
 
 	MAIL_TRANSACTION_TYPE_MASK		= 0x000fffff,