[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-mail.c, 1.21, 1.22 maildir-save.c, 1.67, 1.68 maildir-storage.h, 1.46, 1.47

tss-movial at dovecot.org tss-movial at dovecot.org
Mon Mar 6 21:05:12 EET 2006


Update of /var/lib/cvs/dovecot/src/lib-storage/index/maildir
In directory talvi:/tmp/cvs-serv23804/lib-storage/index/maildir

Modified Files:
	maildir-mail.c maildir-save.c maildir-storage.h 
Log Message:
Support accessing saved mails that haven't been committed yet (fixes quota for maildir).



Index: maildir-mail.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-mail.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- maildir-mail.c	6 Mar 2006 16:42:10 -0000	1.21
+++ maildir-mail.c	6 Mar 2006 19:05:09 -0000	1.22
@@ -42,18 +42,25 @@
 }
 
 static struct istream *
-maildir_open_mail(struct maildir_mailbox *mbox, uint32_t uid, bool *deleted)
+maildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
+		  bool *deleted_r)
 {
-	int fd;
+	const char *path;
+	int fd = -1;
 
-	*deleted = FALSE;
+	*deleted_r = FALSE;
 
-	fd = -1;
-	if (maildir_file_do(mbox, uid, do_open, &fd) < 0)
-		return NULL;
+	if (mail->uid != 0) {
+		if (maildir_file_do(mbox, mail->uid, do_open, &fd) < 0)
+			return NULL;
+	} else {
+		path = maildir_save_file_get_path(mail->transaction, mail->seq);
+		if (do_open(mbox, path, &fd) <= 0)
+			return NULL;
+	}
 
 	if (fd == -1) {
-		*deleted = TRUE;
+		*deleted_r = TRUE;
 		return NULL;
 	}
 
@@ -72,6 +79,7 @@
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
 	struct index_mail_data *data = &mail->data;
 	struct stat st;
+	const char *path;
 	int fd;
 
 	(void)index_mail_get_received_date(_mail);
@@ -92,9 +100,14 @@
 						  "fstat(maildir) failed: %m");
 			return (time_t)-1;
 		}
-	} else {
+	} else if (_mail->uid != 0) {
 		if (maildir_file_do(mbox, _mail->uid, do_stat, &st) <= 0)
 			return (time_t)-1;
+	} else {
+		path = maildir_save_file_get_path(_mail->transaction,
+						  _mail->seq);
+		if (do_stat(mbox, path, &st) <= 0)
+			return (time_t)-1;
 	}
 
 	data->received_date = st.st_mtime;
@@ -121,9 +134,15 @@
 			return data->virtual_size;
 	}
 
-	fname = maildir_uidlist_lookup(mbox->uidlist, _mail->uid, &flags);
-	if (fname == NULL)
-		return (uoff_t)-1;
+	if (_mail->uid != 0) {
+		fname = maildir_uidlist_lookup(mbox->uidlist, _mail->uid,
+					       &flags);
+		if (fname == NULL)
+			return (uoff_t)-1;
+	} else {
+		fname = maildir_save_file_get_path(_mail->transaction,
+						   _mail->seq);
+	}
 
 	/* size can be included in filename */
 	p = strstr(fname, MAILDIR_EXTRA_SEP_S MAILDIR_EXTRA_VIRTUAL_SIZE "=");
@@ -156,8 +175,13 @@
 	const char *fname, *end;
 
 	if (field == MAIL_FETCH_UIDL_FILE_NAME) {
-	    	fname = maildir_uidlist_lookup(mbox->uidlist,
-					       _mail->uid, &flags);
+		if (_mail->uid != 0) {
+			fname = maildir_uidlist_lookup(mbox->uidlist,
+						       _mail->uid, &flags);
+		} else {
+			fname = maildir_save_file_get_path(_mail->transaction,
+							   _mail->seq);
+		}
 		end = strchr(fname, MAILDIR_INFO_SEP);
 		return end == NULL ? fname : t_strdup_until(fname, end);
 	}
@@ -179,9 +203,15 @@
 	if (size != (uoff_t)-1)
 		return size;
 
-	fname = maildir_uidlist_lookup(mbox->uidlist, _mail->uid, &flags);
-	if (fname == NULL)
-		return (uoff_t)-1;
+	if (_mail->uid != 0) {
+		fname = maildir_uidlist_lookup(mbox->uidlist, _mail->uid,
+					       &flags);
+		if (fname == NULL)
+			return (uoff_t)-1;
+	} else {
+		fname = maildir_save_file_get_path(_mail->transaction,
+						   _mail->seq);
+	}
 
 	/* size can be included in filename */
 	p = strstr(fname, MAILDIR_EXTRA_SEP_S MAILDIR_EXTRA_FILE_SIZE "=");
@@ -199,8 +229,14 @@
 	}
 
 	if (size == (uoff_t)-1) {
-		if (maildir_file_do(mbox, _mail->uid, do_stat, &st) <= 0)
-			return (uoff_t)-1;
+		if (_mail->uid != 0) {
+			if (maildir_file_do(mbox, _mail->uid,
+					    do_stat, &st) <= 0)
+				return (uoff_t)-1;
+		} else {
+			if (do_stat(mbox, fname, &st) <= 0)
+				return (uoff_t)-1;
+		}
 		size = st.st_size;
 	}
 
@@ -208,7 +244,6 @@
 			     &size, sizeof(size));
 	data->physical_size = size;
 	return size;
-
 }
 
 static struct istream *maildir_mail_get_stream(struct mail *_mail,
@@ -221,7 +256,7 @@
 	bool deleted;
 
 	if (data->stream == NULL) {
-		data->stream = maildir_open_mail(mbox, _mail->uid, &deleted);
+		data->stream = maildir_open_mail(mbox, _mail, &deleted);
 		if (data->stream == NULL) {
 			_mail->expunged = deleted;
 			return NULL;

Index: maildir-save.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-save.c,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -d -r1.67 -r1.68
--- maildir-save.c	6 Mar 2006 18:16:12 -0000	1.67
+++ maildir-save.c	6 Mar 2006 19:05:09 -0000	1.68
@@ -36,7 +36,7 @@
 	struct maildir_index_sync_context *sync_ctx;
 
 	const char *tmpdir, *newdir, *curdir;
-	struct maildir_filename *files;
+	struct maildir_filename *files, **files_tail;
 
 	buffer_t *keywords_buffer;
 	array_t ARRAY_DEFINE(keywords_array, unsigned int);
@@ -45,10 +45,11 @@
 	struct ostream *output;
 	int fd;
 	time_t received_date;
-	uint32_t seq;
+	uint32_t first_seq, seq;
 
 	unsigned int synced:1;
 	unsigned int failed:1;
+	unsigned int moving:1;
 	unsigned int finished:1;
 };
 
@@ -103,6 +104,7 @@
 	ctx->pool = pool;
 	ctx->mbox = mbox;
 	ctx->trans = t->ictx.trans;
+	ctx->files_tail = &ctx->files;
 
 	ctx->tmpdir = p_strconcat(pool, mbox->path, "/tmp", NULL);
 	ctx->newdir = p_strconcat(pool, mbox->path, "/new", NULL);
@@ -125,6 +127,17 @@
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)t->ictx.ibox;
 	struct maildir_filename *mf;
 
+	if (!ctx->synced && want_mail) {
+		/* we could support adding the missing mails to index, but
+		   currently there's no need. */
+		i_assert(ctx->files == NULL);
+
+		if (maildir_storage_sync_force(mbox) < 0)
+			ctx->failed = TRUE;
+		else
+			ctx->synced = TRUE;
+	}
+
 	/* now, we want to be able to rollback the whole append session,
 	   so we'll just store the name of this temp file and move it later
 	   into new/ or cur/. */
@@ -132,10 +145,13 @@
 	mf = p_malloc(ctx->pool, sizeof(*mf) +
 		      sizeof(unsigned int) * (keywords == NULL ? 0 :
 					      keywords->count));
-	mf->next = ctx->files;
 	mf->basename = p_strdup(ctx->pool, base_fname);
 	mf->flags = flags;
-	ctx->files = mf;
+
+	if (*ctx->files_tail != NULL)
+		(*ctx->files_tail)->next = mf;
+	*ctx->files_tail = mf;
+	ctx->files_tail = &mf->next;
 
 	if (keywords != NULL) {
 		i_assert(sizeof(keywords->idx[0]) == sizeof(unsigned int));
@@ -146,13 +162,6 @@
 		       sizeof(unsigned int) * keywords->count);
 	}
 
-	if (!ctx->synced && want_mail) {
-		if (maildir_storage_sync_force(mbox) < 0)
-			ctx->failed = TRUE;
-		else
-			ctx->synced = TRUE;
-	}
-
 	if (ctx->synced) {
 		/* insert into index */
 		mail_index_append(ctx->trans, 0, &ctx->seq);
@@ -162,6 +171,11 @@
 			mail_index_update_keywords(ctx->trans, ctx->seq,
 						   MODIFY_REPLACE, keywords);
 		}
+
+		if (ctx->first_seq == 0) {
+			ctx->first_seq = ctx->seq;
+			i_assert(ctx->files->next == NULL);
+		}
 	} else {
 		ctx->seq = 0;
 	}
@@ -169,6 +183,65 @@
 	return ctx->seq;
 }
 
+static const char *
+maildir_get_updated_filename(struct maildir_save_context *ctx,
+			     struct maildir_filename *mf)
+{
+	if (mf->keywords_count == 0) {
+		if ((mf->flags & MAIL_FLAGS_MASK) == MAIL_RECENT)
+			return NULL;
+		return maildir_filename_set_flags(NULL, mf->basename,
+						  mf->flags & MAIL_FLAGS_MASK,
+						  NULL);
+	}
+
+	buffer_update_const_data(ctx->keywords_buffer, mf + 1,
+				 mf->keywords_count * sizeof(unsigned int));
+	return maildir_filename_set_flags(
+			maildir_sync_get_keywords_sync_ctx(ctx->sync_ctx),
+			mf->basename, mf->flags & MAIL_FLAGS_MASK,
+			&ctx->keywords_array);
+}
+
+static const char *maildir_mf_get_path(struct maildir_save_context *ctx,
+				       struct maildir_filename *mf)
+{
+	const char *fname;
+
+	if (!ctx->moving && (mf->flags & MAILDIR_SAVE_FLAG_HARDLINK) == 0) {
+		/* file is still in tmp/ */
+		return t_strdup_printf("%s/%s", ctx->tmpdir, mf->basename);
+	}
+
+	/* already moved to new/ or cur/ */
+	fname = maildir_get_updated_filename(ctx, mf);
+	if (fname == NULL)
+		return t_strdup_printf("%s/%s", ctx->newdir, mf->basename);
+	else
+		return t_strdup_printf("%s/%s", ctx->curdir, fname);
+}
+
+const char *maildir_save_file_get_path(struct mailbox_transaction_context *_t,
+				       uint32_t seq)
+{
+	struct maildir_transaction_context *t =
+		(struct maildir_transaction_context *)_t;
+	struct maildir_save_context *ctx = t->save_ctx;
+	struct maildir_filename *mf;
+
+	i_assert(seq >= ctx->first_seq);
+
+	seq -= ctx->first_seq;
+	mf = ctx->files;
+	while (seq > 0) {
+		mf = mf->next;
+		i_assert(mf != NULL);
+		seq--;
+	}
+
+	return maildir_mf_get_path(ctx, mf);
+}
+
 int maildir_save_init(struct mailbox_transaction_context *_t,
 		      enum mail_flags flags, struct mail_keywords *keywords,
 		      time_t received_date, int timezone_offset __attr_unused__,
@@ -328,32 +401,11 @@
 	(void)maildir_save_finish(_ctx, NULL);
 }
 
-static const char *
-maildir_get_updated_filename(struct maildir_save_context *ctx,
-			     struct maildir_filename *mf)
-{
-	if (mf->keywords_count == 0) {
-		if ((mf->flags & MAIL_FLAGS_MASK) == MAIL_RECENT)
-			return NULL;
-		return maildir_filename_set_flags(NULL, mf->basename,
-						  mf->flags & MAIL_FLAGS_MASK,
-						  NULL);
-	}
-
-	buffer_update_const_data(ctx->keywords_buffer, mf + 1,
-				 mf->keywords_count * sizeof(unsigned int));
-	return maildir_filename_set_flags(
-			maildir_sync_get_keywords_sync_ctx(ctx->sync_ctx),
-			mf->basename, mf->flags & MAIL_FLAGS_MASK,
-			&ctx->keywords_array);
-}
-
 static void
 maildir_transaction_unlink_copied_files(struct maildir_save_context *ctx,
 					struct maildir_filename *pos)
 {
 	struct maildir_filename *mf;
-	const char *path, *dest;
 
 	/* try to unlink the mails already moved */
 	for (mf = ctx->files; mf != pos; mf = mf->next) {
@@ -361,14 +413,7 @@
 			continue;
 
 		t_push();
-		dest = maildir_get_updated_filename(ctx, mf);
-		if (dest != NULL)
-			path = t_strdup_printf("%s/%s", ctx->curdir, dest);
-		else {
-			path = t_strdup_printf("%s/%s",
-					       ctx->newdir, mf->basename);
-		}
-		(void)unlink(path);
+		(void)unlink(maildir_mf_get_path(ctx, mf));
 		t_pop();
 	}
 	ctx->files = pos;
@@ -410,6 +455,7 @@
 
 	/* move them into new/ and/or cur/ */
 	ret = 0;
+	ctx->moving = TRUE;
 	for (mf = ctx->files; mf != NULL && ret == 0; mf = mf->next) {
 		t_push();
 		dest = maildir_get_updated_filename(ctx, mf);

Index: maildir-storage.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.h,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- maildir-storage.h	6 Mar 2006 18:16:12 -0000	1.46
+++ maildir-storage.h	6 Mar 2006 19:05:09 -0000	1.47
@@ -129,6 +129,8 @@
 uint32_t maildir_save_add(struct maildir_transaction_context *t,
 			  const char *base_fname, enum mail_flags flags,
 			  struct mail_keywords *keywords, bool want_mail);
+const char *maildir_save_file_get_path(struct mailbox_transaction_context *t,
+				       uint32_t seq);
 
 int maildir_transaction_save_commit_pre(struct maildir_save_context *ctx);
 void maildir_transaction_save_commit_post(struct maildir_save_context *ctx);



More information about the dovecot-cvs mailing list