changeset 5562:24b751bc0995 HEAD

Added sync_notify() callback to struct mail_storage. It's now called for expunges and flag/keyword changes (except with cydir).
author Timo Sirainen <tss@iki.fi>
date Tue, 17 Apr 2007 15:41:26 +0300
parents ead3e882c9c9
children 063b184597fa
files src/lib-storage/index/cydir/cydir-storage.c src/lib-storage/index/cydir/cydir-sync.c src/lib-storage/index/cydir/cydir-sync.h src/lib-storage/index/dbox/dbox-storage.c src/lib-storage/index/dbox/dbox-sync-expunge.c src/lib-storage/index/dbox/dbox-sync.c src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/maildir/maildir-sync.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/index/mbox/mbox-sync-private.h src/lib-storage/index/mbox/mbox-sync-update.c src/lib-storage/index/mbox/mbox-sync.c src/lib-storage/mail-storage-private.h
diffstat 13 files changed, 134 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/cydir/cydir-storage.c	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Tue Apr 17 15:41:26 2007 +0300
@@ -453,6 +453,7 @@
 		cydir_storage_sync_init,
 		index_mailbox_sync_next,
 		index_mailbox_sync_deinit,
+		NULL,
 		cydir_notify_changes,
 		index_transaction_begin,
 		index_transaction_commit,
--- a/src/lib-storage/index/cydir/cydir-sync.c	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/cydir/cydir-sync.c	Tue Apr 17 15:41:26 2007 +0300
@@ -27,7 +27,7 @@
 
 static string_t *cydir_get_path_prefix(struct cydir_mailbox *mbox)
 {
-	string_t *path = t_str_new(256);
+	string_t *path = str_new(default_pool, 256);
 	const char *dir;
 
 	dir = mailbox_list_get_path(mbox->storage->storage.list,
@@ -38,13 +38,44 @@
 	return path;
 }
 
+static int
+cydir_sync_expunge(struct cydir_sync_context *ctx, uint32_t seq1, uint32_t seq2)
+{
+	struct mailbox *box = &ctx->mbox->ibox.box;
+	uint32_t uid;
+
+	if (ctx->path == NULL) {
+		ctx->path = cydir_get_path_prefix(ctx->mbox);
+		ctx->path_dir_prefix_len = str_len(ctx->path);
+	}
+
+	for (; seq1 <= seq2; seq1++) {
+		if (mail_index_lookup_uid(ctx->sync_view, seq1, &uid) < 0) {
+			mail_storage_set_index_error(&ctx->mbox->ibox);
+			return -1;
+		}
+
+		str_truncate(ctx->path, ctx->path_dir_prefix_len);
+		str_printfa(ctx->path, "%u.", uid);
+		if (unlink(str_c(ctx->path)) == 0) {
+			if (box->v.sync_notify != NULL) {
+				box->v.sync_notify(box, uid,
+						   MAILBOX_SYNC_TYPE_EXPUNGE);
+			}
+		} else if (errno != ENOENT) {
+			mail_storage_set_critical(&ctx->mbox->storage->storage,
+				"unlink(%s) failed: %m", str_c(ctx->path));
+			/* continue anyway */
+		}
+	}
+	return 0;
+}
+
 static int cydir_sync_index(struct cydir_sync_context *ctx)
 {
 	const struct mail_index_header *hdr;
 	struct mail_index_sync_rec sync_rec;
-	string_t *path = NULL;
-	unsigned int prefix_len = 0;
-	uint32_t seq1, seq2, uid;
+	uint32_t seq1, seq2;
 	int ret;
 
 	hdr = mail_index_get_header(ctx->sync_view);
@@ -53,12 +84,8 @@
 			return -1;
 	}
 
-	/* unlink expunged messages */
 	while ((ret = mail_index_sync_next(ctx->index_sync_ctx,
 					   &sync_rec)) > 0) {
-		if (sync_rec.type != MAIL_INDEX_SYNC_TYPE_EXPUNGE)
-			continue;
-
 		if (mail_index_lookup_uid_range(ctx->sync_view,
 						sync_rec.uid1, sync_rec.uid2,
 						&seq1, &seq2) < 0) {
@@ -66,30 +93,24 @@
 			return -1;
 		}
 		if (seq1 == 0) {
-			/* already expunged everything. nothing to do. */
+			/* already expunged, nothing to do. */
 			continue;
 		}
 
-		if (path == NULL) {
-			path = cydir_get_path_prefix(ctx->mbox);
-			prefix_len = str_len(path);
-		}
-
-		for (; seq1 <= seq2; seq1++) {
-			if (mail_index_lookup_uid(ctx->sync_view, seq1,
-						  &uid) < 0) {
-				mail_storage_set_index_error(&ctx->mbox->ibox);
+		switch (sync_rec.type) {
+		case MAIL_INDEX_SYNC_TYPE_APPEND:
+			/* don't care */
+			break;
+		case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
+			if (cydir_sync_expunge(ctx, seq1, seq2) < 0)
 				return -1;
-			}
-
-			str_truncate(path, prefix_len);
-			str_printfa(path, "%u.", uid);
-			if (unlink(str_c(path)) < 0 && errno != ENOENT) {
-				mail_storage_set_critical(
-					&ctx->mbox->storage->storage,
-					"unlink(%s) failed: %m", str_c(path));
-				/* continue anyway */
-			}
+			break;
+		case MAIL_INDEX_SYNC_TYPE_FLAGS:
+		case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
+		case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
+		case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
+			/* FIXME: should be bother calling sync_notify()? */
+			break;
 		}
 	}
 	return 0;
@@ -137,6 +158,8 @@
 	} else {
 		mail_index_sync_rollback(&ctx->index_sync_ctx);
 	}
+	if (ctx->path != NULL)
+		str_free(&ctx->path);
 	i_free(ctx);
 	return 0;
 }
--- a/src/lib-storage/index/cydir/cydir-sync.h	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/cydir/cydir-sync.h	Tue Apr 17 15:41:26 2007 +0300
@@ -8,6 +8,9 @@
 	struct cydir_mailbox *mbox;
         struct mail_index_sync_ctx *index_sync_ctx;
 	struct mail_index_view *sync_view;
+
+	string_t *path;
+	unsigned int path_dir_prefix_len;
 };
 
 int cydir_sync_begin(struct cydir_mailbox *mbox,
--- a/src/lib-storage/index/dbox/dbox-storage.c	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-storage.c	Tue Apr 17 15:41:26 2007 +0300
@@ -595,6 +595,7 @@
 		dbox_storage_sync_init,
 		index_mailbox_sync_next,
 		index_mailbox_sync_deinit,
+		NULL,
 		dbox_notify_changes,
 		index_transaction_begin,
 		index_transaction_commit,
--- a/src/lib-storage/index/dbox/dbox-sync-expunge.c	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-sync-expunge.c	Tue Apr 17 15:41:26 2007 +0300
@@ -35,8 +35,10 @@
                   const struct dbox_sync_file_entry *sync_entry,
 		  unsigned int *sync_idx, uint32_t *uid1_r, uint32_t *uid2_r)
 {
+	struct mailbox *box = &ctx->mbox->ibox.box;
 	const struct dbox_sync_rec *sync_recs;
 	unsigned int count;
+	uint32_t uid;
 
 	sync_recs = array_get(&sync_entry->sync_recs, &count);
 
@@ -49,6 +51,15 @@
 		if (dbox_sync_rec_get_uids(ctx, &sync_recs[*sync_idx],
 					   uid1_r, uid2_r) < 0)
 			return -1;
+
+		if (box->v.sync_notify != NULL) {
+			/* all of the UIDs uid1..uid2 should exist */
+			for (uid = *uid1_r; uid <= *uid2_r; uid++) {
+				box->v.sync_notify(box, uid,
+						   MAILBOX_SYNC_TYPE_EXPUNGE);
+			}
+		}
+
 		return 1;
 	}
 
--- a/src/lib-storage/index/dbox/dbox-sync.c	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-sync.c	Tue Apr 17 15:41:26 2007 +0300
@@ -155,6 +155,8 @@
 		     const unsigned char *array, const unsigned char *mask)
 {
 	struct dbox_mailbox *mbox = ctx->mbox;
+	struct mailbox *box = &mbox->ibox.box;
+	enum mailbox_sync_type sync_type;
 	uint32_t file_seq, uid2;
 	uoff_t offset;
 	unsigned int i, start;
@@ -172,7 +174,27 @@
 	if ((ret = dbox_file_seek(mbox, file_seq, offset, FALSE)) <= 0)
 		return ret;
 
+	switch (sync_rec->type) {
+	case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
+		sync_type = MAILBOX_SYNC_TYPE_EXPUNGE;
+		break;
+	case MAIL_INDEX_SYNC_TYPE_FLAGS:
+		sync_type = MAILBOX_SYNC_TYPE_FLAGS;
+		break;
+	case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
+	case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
+	case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
+		sync_type = MAILBOX_SYNC_TYPE_KEYWORDS;
+		break;
+	default:
+		sync_type = 0;
+		i_unreached();
+	}
 	while (mbox->file->seeked_uid <= uid2) {
+		if (box->v.sync_notify != NULL) {
+			box->v.sync_notify(box, mbox->file->seeked_uid,
+					   sync_type);
+		}
 		for (i = 0; i < flag_count; ) {
 			if (!mask[i]) {
 				i++;
--- a/src/lib-storage/index/maildir/maildir-storage.c	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Tue Apr 17 15:41:26 2007 +0300
@@ -1055,6 +1055,7 @@
 		maildir_storage_sync_init,
 		index_mailbox_sync_next,
 		index_mailbox_sync_deinit,
+		NULL,
 		maildir_notify_changes,
 		index_transaction_begin,
 		index_transaction_commit,
--- a/src/lib-storage/index/maildir/maildir-sync.c	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Tue Apr 17 15:41:26 2007 +0300
@@ -232,7 +232,7 @@
 	struct mail_index_transaction *trans;
 
 	ARRAY_DEFINE(sync_recs, struct mail_index_sync_rec);
-	uint32_t seq;
+	uint32_t seq, uid;
 	int dirty_state;
 };
 
@@ -397,9 +397,15 @@
 }
 
 static int maildir_expunge(struct maildir_mailbox *mbox, const char *path,
-			   void *context __attr_unused__)
+			   struct maildir_index_sync_context *ctx)
 {
+	struct mailbox *box = &mbox->ibox.box;
+
 	if (unlink(path) == 0) {
+		if (box->v.sync_notify != NULL) {
+			box->v.sync_notify(box, ctx->uid,
+					   MAILBOX_SYNC_TYPE_EXPUNGE);
+		}
 		mbox->dirty_cur_time = ioloop_time;
 		return 1;
 	}
@@ -414,9 +420,11 @@
 static int maildir_sync_flags(struct maildir_mailbox *mbox, const char *path,
 			      struct maildir_index_sync_context *ctx)
 {
+	struct mailbox *box = &mbox->ibox.box;
 	const struct mail_index_sync_rec *recs;
 	const char *dir, *fname, *newfname, *newpath;
 	enum mail_flags flags;
+	enum mailbox_sync_type sync_type = 0;
 	ARRAY_TYPE(keyword_indexes) keywords;
 	unsigned int i, count;
 	uint8_t flags8;
@@ -441,11 +449,13 @@
 		switch (recs[i].type) {
 		case MAIL_INDEX_SYNC_TYPE_FLAGS:
 			mail_index_sync_flags_apply(&recs[i], &flags8);
+			sync_type |= MAILBOX_SYNC_TYPE_FLAGS;
 			break;
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
 			mail_index_sync_keywords_apply(&recs[i], &keywords);
+			sync_type |= MAILBOX_SYNC_TYPE_KEYWORDS;
 			break;
 		case MAIL_INDEX_SYNC_TYPE_APPEND:
 		case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
@@ -453,12 +463,15 @@
 			break;
 		}
 	}
-
+	i_assert(sync_type != 0);
 
 	newfname = maildir_filename_set_flags(ctx->keywords_sync_ctx,
 					      fname, flags8, &keywords);
 	newpath = t_strconcat(dir, newfname, NULL);
 	if (rename(path, newpath) == 0) {
+		if (box->v.sync_notify != NULL)
+			box->v.sync_notify(box, ctx->uid, sync_type);
+
 		if ((flags8 & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
 			ctx->dirty_state = -1;
 		mbox->dirty_cur_time = ioloop_time;
@@ -556,6 +569,7 @@
 		}
 
 		ctx->seq = seq;
+		ctx->uid = uid;
 		if (expunged) {
 			maildir_sync_check_timeouts(ctx->maildir_sync_ctx,
 						    TRUE);
--- a/src/lib-storage/index/mbox/mbox-storage.c	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Tue Apr 17 15:41:26 2007 +0300
@@ -998,6 +998,7 @@
 		mbox_storage_sync_init,
 		index_mailbox_sync_next,
 		index_mailbox_sync_deinit,
+		NULL,
 		mbox_notify_changes,
 		index_transaction_begin,
 		index_transaction_commit,
--- a/src/lib-storage/index/mbox/mbox-sync-private.h	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync-private.h	Tue Apr 17 15:41:26 2007 +0300
@@ -165,7 +165,7 @@
 
 void mbox_sync_apply_index_syncs(struct mbox_sync_context *sync_ctx,
 				 struct mbox_sync_mail *mail,
-				 bool *keywords_changed_r);
+				 enum mailbox_sync_type *sync_type_r);
 int mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset);
 void mbox_sync_file_update_ext_modified(struct mbox_sync_context *sync_ctx);
 void mbox_sync_file_updated(struct mbox_sync_context *sync_ctx, bool dirty);
--- a/src/lib-storage/index/mbox/mbox-sync-update.c	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync-update.c	Tue Apr 17 15:41:26 2007 +0300
@@ -382,7 +382,7 @@
 void mbox_sync_update_header(struct mbox_sync_mail_context *ctx)
 {
 	uint8_t old_flags;
-	bool keywords_changed;
+	enum mailbox_sync_type sync_type;
 
 	i_assert(ctx->mail.uid != 0 || ctx->mail.pseudo);
 
@@ -390,12 +390,12 @@
 
 	if (array_count(&ctx->sync_ctx->syncs) > 0) {
 		mbox_sync_apply_index_syncs(ctx->sync_ctx, &ctx->mail,
-					    &keywords_changed);
+					    &sync_type);
 
 		if ((old_flags & XSTATUS_FLAGS_MASK) !=
 		    (ctx->mail.flags & XSTATUS_FLAGS_MASK))
 			mbox_sync_update_xstatus(ctx);
-		if (keywords_changed)
+		if ((sync_type & MAILBOX_SYNC_TYPE_KEYWORDS) != 0)
 			mbox_sync_update_xkeywords(ctx);
 	}
 
--- a/src/lib-storage/index/mbox/mbox-sync.c	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync.c	Tue Apr 17 15:41:26 2007 +0300
@@ -284,18 +284,18 @@
 
 void mbox_sync_apply_index_syncs(struct mbox_sync_context *sync_ctx,
 				 struct mbox_sync_mail *mail,
-				 bool *keywords_changed_r)
+				 enum mailbox_sync_type *sync_type_r)
 {
 	const struct mail_index_sync_rec *syncs;
 	unsigned int i, count;
-
-	*keywords_changed_r = FALSE;
+	enum mailbox_sync_type sync_type = 0;
 
 	syncs = array_get(&sync_ctx->syncs, &count);
 	for (i = 0; i < count; i++) {
 		switch (syncs[i].type) {
 		case MAIL_INDEX_SYNC_TYPE_FLAGS:
 			mail_index_sync_flags_apply(&syncs[i], &mail->flags);
+			sync_type |= MAILBOX_SYNC_TYPE_FLAGS;
 			break;
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
@@ -313,12 +313,14 @@
 			}
 			if (mail_index_sync_keywords_apply(&syncs[i],
 							   &mail->keywords))
-				*keywords_changed_r = TRUE;
+				sync_type |= MAILBOX_SYNC_TYPE_KEYWORDS;
 			break;
 		default:
 			break;
 		}
 	}
+
+	*sync_type_r = sync_type;
 }
 
 static int
@@ -481,8 +483,9 @@
 static int mbox_sync_update_index(struct mbox_sync_mail_context *mail_ctx,
 				  const struct mail_index_record *rec)
 {
-        struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
+	struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
 	struct mbox_sync_mail *mail = &mail_ctx->mail;
+	struct mailbox *box = &sync_ctx->mbox->ibox.box;
 	uint8_t mbox_flags;
 
 	mbox_flags = mail->flags & MAIL_FLAGS_MASK;
@@ -509,7 +512,7 @@
 		   sync records are automatically applied to rec->flags at the
 		   end of index syncing, so calculate those new flags first */
 		struct mbox_sync_mail idx_mail;
-		bool keywords_changed;
+		enum mailbox_sync_type sync_type;
 
 		memset(&idx_mail, 0, sizeof(idx_mail));
 		idx_mail.flags = rec->flags;
@@ -525,7 +528,9 @@
 			return -1;
 		}
 		mbox_sync_apply_index_syncs(sync_ctx, &idx_mail,
-					    &keywords_changed);
+					    &sync_type);
+		if (sync_type != 0 && box->v.sync_notify != NULL)
+			box->v.sync_notify(box, rec->uid, sync_type);
 
 #define SYNC_FLAGS (MAIL_RECENT | MAIL_INDEX_MAIL_FLAG_DIRTY)
 		if ((idx_mail.flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
@@ -720,6 +725,12 @@
 static void mbox_sync_handle_expunge(struct mbox_sync_mail_context *mail_ctx)
 {
 	struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
+	struct mailbox *box = &sync_ctx->mbox->ibox.box;
+
+	if (box->v.sync_notify != NULL) {
+		box->v.sync_notify(box, mail_ctx->mail.uid,
+				   MAILBOX_SYNC_TYPE_EXPUNGE);
+	}
 
 	mail_ctx->mail.expunged = TRUE;
 	mail_ctx->mail.offset = mail_ctx->mail.from_offset;
@@ -727,6 +738,7 @@
 		mail_ctx->body_offset - mail_ctx->mail.from_offset +
 		mail_ctx->mail.body_size;
 	mail_ctx->mail.body_size = 0;
+	mail_ctx->mail.uid = 0;
 
 	if (sync_ctx->seq == 1) {
 		/* expunging first message, fix space to contain next
@@ -1210,7 +1222,6 @@
 				return -1;
 			sync_ctx->dest_first_mail = FALSE;
 		} else {
-			mail_ctx->mail.uid = 0;
 			mbox_sync_handle_expunge(mail_ctx);
 		}
 
--- a/src/lib-storage/mail-storage-private.h	Tue Apr 17 15:40:39 2007 +0300
+++ b/src/lib-storage/mail-storage-private.h	Tue Apr 17 15:41:26 2007 +0300
@@ -91,6 +91,9 @@
 			   enum mailbox_status_items status_items,
 			   struct mailbox_status *status_r);
 
+	void (*sync_notify)(struct mailbox *box, uint32_t uid,
+			    enum mailbox_sync_type sync_type);
+
 	void (*notify_changes)(struct mailbox *box);
 
 	struct mailbox_transaction_context *