Mercurial > dovecot > original-hg > dovecot-1.2
changeset 6636:6d870394cc3b HEAD
Handle maildir -> dbox file conversion when metadata is wanted to be updated.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 28 Oct 2007 00:09:06 +0300 |
parents | e4f9e2b94a90 |
children | ce0088893a20 |
files | src/lib-storage/index/dbox/dbox-file.c src/lib-storage/index/dbox/dbox-file.h src/lib-storage/index/dbox/dbox-save.c src/lib-storage/index/dbox/dbox-sync-file.c src/lib-storage/index/dbox/dbox-sync.c |
diffstat | 5 files changed, 135 insertions(+), 45 deletions(-) [+] |
line wrap: on
line diff
--- 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 @@ *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 @@ pool_alloconly_create("dbox metadata", 512); } file->metadata_read_offset = 0; + p_array_init(&file->metadata, file->metadata_pool, 16); - if (file->maildir_file) { - /* no metadata in maildir files, but we do later some kludging - to return metadata when needed. */ - return 0; - } + 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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'; +}
--- 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 @@ 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 @@ 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
--- 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 @@ /* 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 @@ 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);
--- 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 @@ } /* 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 @@ 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 @@ } 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; +} + +static int dbox_sync_file_changes(struct dbox_sync_context *ctx, struct dbox_file *file, const struct dbox_sync_file_entry *entry, uint32_t seq) { @@ -193,11 +274,8 @@ dbox_sync_update_metadata(ctx, file, entry, seq); ret = dbox_file_metadata_write(file); if (ret <= 0) { - if (ret < 0) - return -1; - /* FIXME: handle ret=0 case by splitting the file - (or converting maildir file to dbox) */ - return 1; + return ret < 0 ? -1 : + dbox_sync_file_split(ctx, file, offset, seq); } mail_index_update_flags(ctx->trans, seq, MODIFY_REMOVE,
--- a/src/lib-storage/index/dbox/dbox-sync.c Sat Oct 27 23:46:11 2007 +0300 +++ b/src/lib-storage/index/dbox/dbox-sync.c Sun Oct 28 00:09:06 2007 +0300 @@ -233,8 +233,8 @@ const void *data; size_t data_size; - /*if (mbox->last_interactive_change < - ioloop_time - DBOX_FLUSH_SECS_INTERACTIVE)*/ + if (mbox->last_interactive_change < + ioloop_time - DBOX_FLUSH_SECS_INTERACTIVE) return TRUE; mail_index_get_header_ext(mbox->ibox.view, mbox->dbox_hdr_ext_id,