dovecot-2.0: maildir: uidlist can now override message's GUID

dovecot at dovecot.org dovecot at dovecot.org
Thu Sep 16 18:29:15 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/b93405cdd4e9
changeset: 12128:b93405cdd4e9
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Sep 16 16:28:58 2010 +0100
description:
maildir: uidlist can now override message's GUID

diffstat:

 src/lib-storage/index/maildir/maildir-mail.c    |   13 ++-
 src/lib-storage/index/maildir/maildir-save.c    |   10 ++-
 src/lib-storage/index/maildir/maildir-uidlist.c |  104 ++++++++++++++++---------
 src/lib-storage/index/maildir/maildir-uidlist.h |   12 ++-
 4 files changed, 95 insertions(+), 44 deletions(-)

diffs (298 lines):

diff -r 6a99212b636d -r b93405cdd4e9 src/lib-storage/index/maildir/maildir-mail.c
--- a/src/lib-storage/index/maildir/maildir-mail.c	Thu Sep 16 16:26:48 2010 +0100
+++ b/src/lib-storage/index/maildir/maildir-mail.c	Thu Sep 16 16:28:58 2010 +0100
@@ -469,11 +469,20 @@
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
-	const char *path, *fname, *end, *uidl;
+	const char *path, *fname, *end, *guid, *uidl;
 
 	switch (field) {
+	case MAIL_FETCH_GUID:
+		/* use GUID from uidlist if it exists */
+		guid = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
+						  MAILDIR_UIDLIST_REC_EXT_GUID);
+		if (guid != NULL) {
+			*value_r = guid;
+			return 0;
+		}
+
+		/* default to base filename: */
 	case MAIL_FETCH_UIDL_FILE_NAME:
-	case MAIL_FETCH_GUID:
 		if (mail->data.guid != NULL) {
 			*value_r = mail->data.guid;
 			return 0;
diff -r 6a99212b636d -r b93405cdd4e9 src/lib-storage/index/maildir/maildir-save.c
--- a/src/lib-storage/index/maildir/maildir-save.c	Thu Sep 16 16:26:48 2010 +0100
+++ b/src/lib-storage/index/maildir/maildir-save.c	Thu Sep 16 16:28:58 2010 +0100
@@ -33,6 +33,7 @@
 	uoff_t size, vsize;
 	enum mail_flags flags;
 	unsigned int preserve_filename:1;
+	unsigned int save_guid:1; /* tmp_name contains the GUID */
 	unsigned int keywords_count;
 	/* unsigned int keywords[]; */
 };
@@ -786,6 +787,7 @@
 		mf->dest_basename = p_strdup(ctx->pool,
 					     maildir_filename_generate());
 		mf->preserve_filename = FALSE;
+		mf->save_guid = TRUE;
 	}
 }
 
@@ -828,6 +830,7 @@
 	struct maildir_filename *mf;
 	struct seq_range_iter iter;
 	enum maildir_uidlist_rec_flag flags;
+	struct maildir_uidlist_rec *rec;
 	unsigned int n = 0;
 	uint32_t uid;
 	bool newdir, bret;
@@ -845,8 +848,13 @@
 		if (newdir)
 			flags |= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR;
 		ret = maildir_uidlist_sync_next_uid(ctx->uidlist_sync_ctx,
-						    dest, uid, flags);
+						    dest, uid, flags, &rec);
 		i_assert(ret > 0);
+		i_assert(rec != NULL);
+		if (mf->save_guid) {
+			maildir_uidlist_sync_set_ext(ctx->uidlist_sync_ctx, rec,
+				MAILDIR_UIDLIST_REC_EXT_GUID, mf->tmp_name);
+		}
 	} T_END;
 	i_assert(!seq_range_array_iter_nth(&iter, n, &uid));
 }
diff -r 6a99212b636d -r b93405cdd4e9 src/lib-storage/index/maildir/maildir-uidlist.c
--- a/src/lib-storage/index/maildir/maildir-uidlist.c	Thu Sep 16 16:26:48 2010 +0100
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c	Thu Sep 16 16:28:58 2010 +0100
@@ -1141,14 +1141,41 @@
 }
 
 static void
-maildir_uidlist_set_ext_real(struct maildir_uidlist *uidlist, uint32_t uid,
+maildir_uidlist_rec_set_ext(struct maildir_uidlist_rec *rec, pool_t pool,
+			    enum maildir_uidlist_rec_ext_key key,
+			    const char *value)
+{
+	const unsigned char *p;
+	buffer_t *buf;
+	unsigned int len;
+
+	/* copy existing extensions, except for the one we're updating */
+	buf = buffer_create_dynamic(pool_datastack_create(), 128);
+	if (rec->extensions != NULL) {
+		p = rec->extensions;
+		while (*p != '\0') {
+			/* <key><value>\0 */
+			len = strlen((const char *)p) + 1;
+			if (*p != (unsigned char)key)
+				buffer_append(buf, p, len);
+			p += len;
+		}
+	}
+	if (value != NULL) {
+		buffer_append_c(buf, key);
+		buffer_append(buf, value, strlen(value) + 1);
+	}
+	buffer_append_c(buf, '\0');
+
+	rec->extensions = p_malloc(pool, buf->used);
+	memcpy(rec->extensions, buf->data, buf->used);
+}
+
+void maildir_uidlist_set_ext(struct maildir_uidlist *uidlist, uint32_t uid,
 			     enum maildir_uidlist_rec_ext_key key,
 			     const char *value)
 {
 	struct maildir_uidlist_rec *rec;
-	const unsigned char *p;
-	buffer_t *buf;
-	unsigned int len;
 	int ret;
 
 	ret = maildir_uidlist_lookup_rec(uidlist, uid, &rec);
@@ -1165,27 +1192,10 @@
 		}
 	}
 
-	buf = buffer_create_dynamic(pool_datastack_create(), 128);
-
-	/* copy existing extensions, except for the one we're updating */
-	if (rec->extensions != NULL) {
-		p = rec->extensions;
-		while (*p != '\0') {
-			/* <key><value>\0 */
-			len = strlen((const char *)p) + 1;
-			if (*p != (unsigned char)key)
-				buffer_append(buf, p, len);
-			p += len;
-		}
-	}
-	if (value != NULL) {
-		buffer_append_c(buf, key);
-		buffer_append(buf, value, strlen(value) + 1);
-	}
-	buffer_append_c(buf, '\0');
-
-	rec->extensions = p_malloc(uidlist->record_pool, buf->used);
-	memcpy(rec->extensions, buf->data, buf->used);
+	T_BEGIN {
+		maildir_uidlist_rec_set_ext(rec, uidlist->record_pool,
+					    key, value);
+	} T_END;
 
 	if (rec->uid != (uint32_t)-1) {
 		/* message already exists in uidlist, need to recreate it */
@@ -1193,15 +1203,6 @@
 	}
 }
 
-void maildir_uidlist_set_ext(struct maildir_uidlist *uidlist, uint32_t uid,
-			     enum maildir_uidlist_rec_ext_key key,
-			     const char *value)
-{
-	T_BEGIN {
-		maildir_uidlist_set_ext_real(uidlist, uid, key, value);
-	} T_END;
-}
-
 static void
 maildir_uidlist_generate_uid_validity(struct maildir_uidlist *uidlist)
 {
@@ -1645,10 +1646,12 @@
 static int
 maildir_uidlist_sync_next_partial(struct maildir_uidlist_sync_ctx *ctx,
 				  const char *filename, uint32_t uid,
-				  enum maildir_uidlist_rec_flag flags)
+				  enum maildir_uidlist_rec_flag flags,
+				  struct maildir_uidlist_rec **rec_r)
 {
 	struct maildir_uidlist *uidlist = ctx->uidlist;
-	struct maildir_uidlist_rec *rec;
+	struct maildir_uidlist_rec *rec, *const *recs;
+	unsigned int count;
 
 	/* we'll update uidlist directly */
 	rec = hash_table_lookup(uidlist->files, filename);
@@ -1686,6 +1689,11 @@
 		rec->uid = uid;
 		if (uidlist->next_uid <= uid)
 			uidlist->next_uid = uid + 1;
+		else {
+			recs = array_get(&uidlist->records, &count);
+			if (count > 1 && uid < recs[count-1]->uid)
+				uidlist->unsorted = TRUE;
+		}
 	}
 
 	rec->flags = (rec->flags | flags) & ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
@@ -1693,6 +1701,7 @@
 	hash_table_insert(uidlist->files, rec->filename, rec);
 
 	ctx->finished = FALSE;
+	*rec_r = rec;
 	return 1;
 }
 
@@ -1719,17 +1728,22 @@
 			      const char *filename,
 			      enum maildir_uidlist_rec_flag flags)
 {
-	return maildir_uidlist_sync_next_uid(ctx, filename, 0, flags);
+	struct maildir_uidlist_rec *rec;
+
+	return maildir_uidlist_sync_next_uid(ctx, filename, 0, flags, &rec);
 }
 
 int maildir_uidlist_sync_next_uid(struct maildir_uidlist_sync_ctx *ctx,
 				  const char *filename, uint32_t uid,
-				  enum maildir_uidlist_rec_flag flags)
+				  enum maildir_uidlist_rec_flag flags,
+				  struct maildir_uidlist_rec **rec_r)
 {
 	struct maildir_uidlist *uidlist = ctx->uidlist;
 	struct maildir_uidlist_rec *rec, *old_rec;
 	const char *p, *dir;
 
+	*rec_r = NULL;
+
 	if (ctx->failed)
 		return -1;
 	for (p = filename; *p != '\0'; p++) {
@@ -1746,7 +1760,7 @@
 
 	if (ctx->partial) {
 		return maildir_uidlist_sync_next_partial(ctx, filename,
-							 uid, flags);
+							 uid, flags, rec_r);
 	}
 
 	rec = hash_table_lookup(ctx->files, filename);
@@ -1791,6 +1805,7 @@
 	rec->flags = (rec->flags | flags) & ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
 	rec->filename = p_strdup(ctx->record_pool, filename);
 	hash_table_insert(ctx->files, rec->filename, rec);
+	*rec_r = rec;
 	return 1;
 }
 
@@ -1823,6 +1838,17 @@
 	ctx->uidlist->recreate = TRUE;
 }
 
+void maildir_uidlist_sync_set_ext(struct maildir_uidlist_sync_ctx *ctx,
+				  struct maildir_uidlist_rec *rec,
+				  enum maildir_uidlist_rec_ext_key key,
+				  const char *value)
+{
+	pool_t pool = ctx->partial ?
+		ctx->uidlist->record_pool : ctx->record_pool;
+
+	maildir_uidlist_rec_set_ext(rec, pool, key, value);
+}
+
 const char *
 maildir_uidlist_sync_get_full_filename(struct maildir_uidlist_sync_ctx *ctx,
 				       const char *filename)
diff -r 6a99212b636d -r b93405cdd4e9 src/lib-storage/index/maildir/maildir-uidlist.h
--- a/src/lib-storage/index/maildir/maildir-uidlist.h	Thu Sep 16 16:26:48 2010 +0100
+++ b/src/lib-storage/index/maildir/maildir-uidlist.h	Thu Sep 16 16:28:58 2010 +0100
@@ -10,6 +10,7 @@
 struct maildir_mailbox;
 struct maildir_uidlist;
 struct maildir_uidlist_sync_ctx;
+struct maildir_uidlist_rec;
 
 enum maildir_uidlist_sync_flags {
 	MAILDIR_UIDLIST_SYNC_PARTIAL	= 0x01,
@@ -44,7 +45,9 @@
 	   isn't written to uidlist. */
 	MAILDIR_UIDLIST_REC_EXT_VSIZE		= 'W',
 	/* POP3 UIDL overriding the default format */
-	MAILDIR_UIDLIST_REC_EXT_POP3_UIDL	= 'P'
+	MAILDIR_UIDLIST_REC_EXT_POP3_UIDL	= 'P',
+	/* Message GUID (default is the base filename) */
+	MAILDIR_UIDLIST_REC_EXT_GUID		= 'G'
 };
 
 int maildir_uidlist_lock(struct maildir_uidlist *uidlist);
@@ -109,9 +112,14 @@
 			      enum maildir_uidlist_rec_flag flags);
 int maildir_uidlist_sync_next_uid(struct maildir_uidlist_sync_ctx *ctx,
 				  const char *filename, uint32_t uid,
-				  enum maildir_uidlist_rec_flag flags);
+				  enum maildir_uidlist_rec_flag flags,
+				  struct maildir_uidlist_rec **rec_r);
 void maildir_uidlist_sync_remove(struct maildir_uidlist_sync_ctx *ctx,
 				 const char *filename);
+void maildir_uidlist_sync_set_ext(struct maildir_uidlist_sync_ctx *ctx,
+				  struct maildir_uidlist_rec *rec,
+				  enum maildir_uidlist_rec_ext_key key,
+				  const char *value);
 const char *
 maildir_uidlist_sync_get_full_filename(struct maildir_uidlist_sync_ctx *ctx,
 				       const char *filename);


More information about the dovecot-cvs mailing list