dovecot: Handle maildir -> dbox file conversion when metadata is...

dovecot at dovecot.org dovecot at dovecot.org
Sun Oct 28 00:09:10 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/6d870394cc3b
changeset: 6636:6d870394cc3b
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Oct 28 00:09:06 2007 +0300
description:
Handle maildir -> dbox file conversion when metadata is wanted to be updated.

diffstat:

5 files changed, 136 insertions(+), 46 deletions(-)
src/lib-storage/index/dbox/dbox-file.c      |   59 ++++++++++------
src/lib-storage/index/dbox/dbox-file.h      |    7 +-
src/lib-storage/index/dbox/dbox-save.c      |   18 ++---
src/lib-storage/index/dbox/dbox-sync-file.c |   94 ++++++++++++++++++++++++---
src/lib-storage/index/dbox/dbox-sync.c      |    4 -

diffs (truncated from 332 to 300 lines):

diff -r e4f9e2b94a90 -r 6d870394cc3b src/lib-storage/index/dbox/dbox-file.c
--- a/src/lib-storage/index/dbox/dbox-file.c	Sat Oct 27 23:46:11 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-file.c	Sun Oct 28 00:09:06 2007 +0300
@@ -731,9 +731,6 @@ int dbox_file_metadata_seek(struct dbox_
 
 	*expunged_r = FALSE;
 
-	if (file->metadata_read_offset == metadata_offset)
-		return 1;
-
 	if (file->metadata_pool != NULL) {
 		if (array_is_created(&file->metadata_changes))
 			array_free(&file->metadata_changes);
@@ -743,12 +740,11 @@ int dbox_file_metadata_seek(struct dbox_
 			pool_alloconly_create("dbox metadata", 512);
 	}
 	file->metadata_read_offset = 0;
-
-	if (file->maildir_file) {
-		/* no metadata in maildir files, but we do later some kludging
-		   to return metadata when needed. */
-		return 0;
-	}
+	p_array_init(&file->metadata, file->metadata_pool, 16);
+
+	if (file->metadata_read_offset == metadata_offset)
+		return 1;
+	i_assert(!file->maildir_file); /* previous check should catch this */
 
 	if (file->input == NULL) {
 		if ((ret = dbox_file_open(file, TRUE, &deleted)) <= 0)
@@ -765,7 +761,6 @@ int dbox_file_metadata_seek(struct dbox_
 	metadata_data_offset = file->input->v_offset;
 
 	*expunged_r = TRUE;
-	p_array_init(&file->metadata, file->metadata_pool, 16);
 	for (;;) {
 		prev_offset = file->input->v_offset;
 		if ((line = i_stream_read_next_line(file->input)) == NULL)
@@ -839,10 +834,6 @@ void dbox_file_metadata_set(struct dbox_
 		return;
 	}
 
-	if (file->metadata_pool == NULL) {
-		file->metadata_pool =
-			pool_alloconly_create("dbox metadata", 512);
-	}
 	data = p_strdup_printf(file->metadata_pool, "%c%s", (char)key, value);
 
 	if (!array_is_created(&file->metadata_changes))
@@ -1019,7 +1010,7 @@ int dbox_file_metadata_write(struct dbox
 	return ret < 0 ? -1 : 1;
 }
 
-void dbox_file_metadata_write_to(struct dbox_file *file, struct ostream *output)
+int dbox_file_metadata_write_to(struct dbox_file *file, struct ostream *output)
 {
 	struct dbox_metadata_header metadata_hdr;
 	char space[DBOX_EXTRA_SPACE];
@@ -1029,13 +1020,15 @@ void dbox_file_metadata_write_to(struct 
 	memset(&metadata_hdr, 0, sizeof(metadata_hdr));
 	memcpy(metadata_hdr.magic_post, DBOX_MAGIC_POST,
 	       sizeof(metadata_hdr.magic_post));
-	o_stream_send(output, &metadata_hdr, sizeof(metadata_hdr));
+	if (o_stream_send(output, &metadata_hdr, sizeof(metadata_hdr)) < 0)
+		return -1;
 
 	metadata = array_get(&file->metadata, &count);
 	if (!array_is_created(&file->metadata_changes)) {
 		for (i = 0; i < count; i++) {
-			o_stream_send_str(output, metadata[i]);
-			o_stream_send(output, "\n", 1);
+			if (o_stream_send_str(output, metadata[i]) < 0 ||
+			    o_stream_send(output, "\n", 1) < 0)
+				return -1;
 		}
 	} else {
 		changes = array_get(&file->metadata_changes, &changes_count);
@@ -1046,20 +1039,25 @@ void dbox_file_metadata_write_to(struct 
 					break;
 			}
 			if (j == changes_count) {
-				o_stream_send_str(output, metadata[i]);
-				o_stream_send(output, "\n", 1);
+				if (o_stream_send_str(output, metadata[i]) < 0)
+					return -1;
+				if (o_stream_send(output, "\n", 1) < 0)
+					return -1;
 			}
 		}
 		/* write modified metadata */
 		for (i = 0; i < changes_count; i++) {
-			o_stream_send_str(output, metadata[i]);
-			o_stream_send(output, "\n", 1);
+			if (o_stream_send_str(output, changes[j]) < 0 ||
+			    o_stream_send(output, "\n", 1) < 0)
+				return -1;
 		}
 	}
 
 	memset(space, ' ', sizeof(space));
-	o_stream_send(output, space, sizeof(space));
-	o_stream_send(output, "\n", 1);
+	if (o_stream_send(output, space, sizeof(space)) < 0 ||
+	    o_stream_send(output, "\n", 1) < 0)
+		return -1;
+	return 0;
 }
 
 bool dbox_file_lookup(struct dbox_mailbox *mbox, struct mail_index_view *view,
@@ -1123,3 +1121,16 @@ void dbox_mail_metadata_keywords_append(
 	}
 	str_truncate(str, str_len(str)-1);
 }
+
+void dbox_msg_header_fill(struct dbox_message_header *dbox_msg_hdr,
+			  uint32_t uid, uoff_t message_size)
+{
+	memset(dbox_msg_hdr, ' ', sizeof(*dbox_msg_hdr));
+	memcpy(dbox_msg_hdr->magic_pre, DBOX_MAGIC_PRE,
+	       sizeof(dbox_msg_hdr->magic_pre));
+	dbox_msg_hdr->type = DBOX_MESSAGE_TYPE_NORMAL;
+	dec2hex(dbox_msg_hdr->uid_hex, uid, sizeof(dbox_msg_hdr->uid_hex));
+	dec2hex(dbox_msg_hdr->message_size_hex, message_size,
+		sizeof(dbox_msg_hdr->message_size_hex));
+	dbox_msg_hdr->save_lf = '\n';
+}
diff -r e4f9e2b94a90 -r 6d870394cc3b src/lib-storage/index/dbox/dbox-file.h
--- a/src/lib-storage/index/dbox/dbox-file.h	Sat Oct 27 23:46:11 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-file.h	Sun Oct 28 00:09:06 2007 +0300
@@ -200,8 +200,7 @@ void dbox_file_metadata_set(struct dbox_
    fit to its reserved space and message isn't last in file, -1 if I/O error. */
 int dbox_file_metadata_write(struct dbox_file *file);
 /* Write all metadata to output stream. Returns 0 if ok, -1 if I/O error. */
-void dbox_file_metadata_write_to(struct dbox_file *file,
-				 struct ostream *output);
+int dbox_file_metadata_write_to(struct dbox_file *file, struct ostream *output);
 
 /* Get file/offset for wanted message. Returns TRUE if found. */
 bool dbox_file_lookup(struct dbox_mailbox *mbox, struct mail_index_view *view,
@@ -214,6 +213,10 @@ void dbox_mail_metadata_keywords_append(
 					string_t *str,
 					const struct mail_keywords *keywords);
 
+/* Fill dbox_message_header with given uid/size. */
+void dbox_msg_header_fill(struct dbox_message_header *dbox_msg_hdr,
+			  uint32_t uid, uoff_t message_size);
+
 void dbox_file_set_syscall_error(struct dbox_file *file, const char *function);
 
 #endif
diff -r e4f9e2b94a90 -r 6d870394cc3b src/lib-storage/index/dbox/dbox-save.c
--- a/src/lib-storage/index/dbox/dbox-save.c	Sat Oct 27 23:46:11 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-save.c	Sun Oct 28 00:09:06 2007 +0300
@@ -131,7 +131,13 @@ int dbox_save_init(struct mailbox_transa
 	/* write a dummy header. it'll get rewritten when we're finished */
 	memset(&dbox_msg_hdr, 0, sizeof(dbox_msg_hdr));
 	o_stream_cork(ctx->cur_output);
-	o_stream_send(ctx->cur_output, &dbox_msg_hdr, sizeof(dbox_msg_hdr));
+	if (o_stream_send(ctx->cur_output, &dbox_msg_hdr,
+			  sizeof(dbox_msg_hdr)) < 0) {
+		mail_storage_set_critical(_t->box->storage,
+			"o_stream_send(%s) failed: %m",
+			ctx->cur_file->path);
+		ctx->failed = TRUE;
+	}
 
 	ctx->cur_received_date = received_date != (time_t)-1 ?
 		received_date : ioloop_time;
@@ -274,15 +280,7 @@ dbox_save_mail_write_header(struct dbox_
 	i_assert(mail->file->msg_header_size == sizeof(dbox_msg_hdr));
 
 	mail->file->last_append_uid = uid;
-
-	memset(&dbox_msg_hdr, ' ', sizeof(dbox_msg_hdr));
-	memcpy(dbox_msg_hdr.magic_pre, DBOX_MAGIC_PRE,
-	       sizeof(dbox_msg_hdr.magic_pre));
-	dbox_msg_hdr.type = DBOX_MESSAGE_TYPE_NORMAL;
-	dec2hex(dbox_msg_hdr.uid_hex, uid, sizeof(dbox_msg_hdr.uid_hex));
-	dec2hex(dbox_msg_hdr.message_size_hex, mail->message_size,
-		sizeof(dbox_msg_hdr.message_size_hex));
-	dbox_msg_hdr.save_lf = '\n';
+	dbox_msg_header_fill(&dbox_msg_hdr, uid, mail->message_size);
 
 	orig_offset = output->offset;
 	o_stream_seek(output, mail->append_offset);
diff -r e4f9e2b94a90 -r 6d870394cc3b src/lib-storage/index/dbox/dbox-sync-file.c
--- a/src/lib-storage/index/dbox/dbox-sync-file.c	Sat Oct 27 23:46:11 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-sync-file.c	Sun Oct 28 00:09:06 2007 +0300
@@ -57,7 +57,8 @@ dbox_sync_update_metadata(struct dbox_sy
 	}
 
 	/* expunge state */
-	if (array_is_created(&entry->expunges) &&
+	if (entry != NULL &&
+	    array_is_created(&entry->expunges) &&
 	    seq_range_exists(&entry->expunges, seq)) {
 		dbox_file_metadata_set(file, DBOX_METADATA_EXPUNGED, "1");
 		mail_index_expunge(ctx->trans, seq);
@@ -125,15 +126,19 @@ dbox_sync_file_expunge(struct dbox_sync_
 		input = i_stream_create_limit(file->input, offset,
 					      file->msg_header_size +
 					      physical_size);
-		o_stream_send_istream(output, input);
+		ret = o_stream_send_istream(output, input) < 0 ? -1 : 0;
 		i_stream_unref(&input);
+		if (ret < 0)
+			break;
 
 		/* write metadata */
 		metadata_offset = dbox_file_get_metadata_offset(file, offset,
 								physical_size);
 		(void)dbox_file_metadata_seek(file, metadata_offset, &expunged);
 		dbox_sync_update_metadata(ctx, file, entry, seq);
-		dbox_file_metadata_write_to(file, output);
+		if ((ret = dbox_file_metadata_write_to(file, output)) < 0)
+			break;
+
 		mail_index_update_flags(ctx->trans, seq, MODIFY_REMOVE,
 			(enum mail_flags)MAIL_INDEX_MAIL_FLAG_DIRTY);
 	}
@@ -169,6 +174,82 @@ dbox_sync_file_expunge(struct dbox_sync_
 }
 
 static int
+dbox_sync_file_split(struct dbox_sync_context *ctx, struct dbox_file *in_file,
+		     uoff_t offset, uint32_t seq)
+{
+	struct dbox_index_append_context *append_ctx;
+	struct dbox_file *out_file;
+	struct istream *input;
+	struct ostream *output;
+	struct dbox_message_header dbox_msg_hdr;
+	struct dbox_mail_index_record rec;
+	uint32_t uid;
+	uoff_t size, append_offset;
+	int ret;
+	bool expunged;
+
+	/* FIXME: for now we handle only maildir file conversion */
+	i_assert(in_file->maildir_file);
+
+	ret = dbox_file_get_mail_stream(in_file, offset, &uid,
+					&size, &input, &expunged);
+	if (ret <= 0)
+		return ret;
+	if (expunged) {
+		mail_index_expunge(ctx->trans, seq);
+		return 1;
+	}
+
+	append_ctx = dbox_index_append_begin(ctx->mbox->dbox_index);
+	if (dbox_index_append_next(append_ctx, size, &out_file, &output) < 0 ||
+	    dbox_file_metadata_seek(out_file, 0, &expunged) < 0) {
+		dbox_index_append_rollback(&append_ctx);
+		i_stream_unref(&input);
+		return -1;
+	}
+	append_offset = output->offset;
+	dbox_msg_header_fill(&dbox_msg_hdr, uid, size);
+	dbox_sync_update_metadata(ctx, out_file, NULL, seq);
+
+	/* copy the message */
+	o_stream_cork(output);
+	if (o_stream_send(output, &dbox_msg_hdr, sizeof(dbox_msg_hdr)) < 0 ||
+	    o_stream_send_istream(output, input) < 0 ||
+	    dbox_file_metadata_write_to(out_file, output) < 0 ||
+	    o_stream_flush(output) < 0) {
+		mail_storage_set_critical(&ctx->mbox->storage->storage,
+			"write(%s) failed: %m", out_file->path);
+		ret = -1;
+	} else {
+		dbox_file_finish_append(out_file);
+		out_file->last_append_uid = uid;
+
+		ret = dbox_index_append_assign_file_ids(append_ctx);
+	}
+
+	if (ret < 0)
+		dbox_index_append_rollback(&append_ctx);
+	else
+		ret = dbox_index_append_commit(&append_ctx);
+	i_stream_unref(&input);
+
+	if (ret == 0) {
+		/* update message position in index file */
+		memset(&rec, 0, sizeof(rec));
+		if ((rec.file_id & DBOX_FILE_ID_FLAG_UID) == 0) {
+			rec.file_id = out_file->file_id;
+			rec.offset = append_offset;
+		}
+		mail_index_update_ext(ctx->trans, seq, ctx->mbox->dbox_ext_id,
+				      &rec, NULL);
+
+		/* when everything is done, unlink the old file */
+		ret = dbox_sync_file_unlink(in_file);
+	}
+	return ret < 0 ? -1 : 1;
+}
+


More information about the dovecot-cvs mailing list