From: Timo Sirainen Date: Wed, 25 Feb 2009 02:39:59 +0000 (-0500) Subject: dbox: Save optimizations. X-Git-Tag: 2.0.alpha1~1038^2~76 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2acd7a89285b2cb0e3855357edf8c4f4e2fdef29;p=thirdparty%2Fdovecot%2Fcore.git dbox: Save optimizations. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/dbox/dbox-file.c b/src/lib-storage/index/dbox/dbox-file.c index d4170d0a85..66df4261c2 100644 --- a/src/lib-storage/index/dbox/dbox-file.c +++ b/src/lib-storage/index/dbox/dbox-file.c @@ -515,6 +515,8 @@ void dbox_file_unlock(struct dbox_file *file) { if (file->lock != NULL) file_unlock(&file->lock); + if (file->input != NULL) + i_stream_sync(file->input); } static int @@ -730,16 +732,27 @@ void dbox_file_cancel_append(struct dbox_file *file, uoff_t append_offset) { if (ftruncate(file->fd, append_offset) < 0) dbox_file_set_syscall_error(file, "ftruncate()"); - if (file->input != NULL) - i_stream_sync(file->input); o_stream_seek(file->output, append_offset); } -void dbox_file_finish_append(struct dbox_file *file) +int dbox_file_flush_append(struct dbox_file *file) { - if (file->input != NULL) - i_stream_sync(file->input); + i_assert(file->output != NULL); + + if (o_stream_flush(file->output) < 0) { + dbox_file_set_syscall_error(file, "write()"); + return -1; + } + + if ((file->storage->storage.flags & + MAIL_STORAGE_FLAG_FSYNC_DISABLE) == 0) { + if (fdatasync(file->fd) < 0) { + dbox_file_set_syscall_error(file, "fdatasync()"); + return -1; + } + } + return 0; } static uoff_t diff --git a/src/lib-storage/index/dbox/dbox-file.h b/src/lib-storage/index/dbox/dbox-file.h index f02e68bd0b..5a3e0e3326 100644 --- a/src/lib-storage/index/dbox/dbox-file.h +++ b/src/lib-storage/index/dbox/dbox-file.h @@ -164,8 +164,8 @@ int dbox_file_get_append_stream(struct dbox_file *file, uoff_t last_msg_offset, uoff_t dbox_file_get_next_append_offset(struct dbox_file *file); /* Truncate file to append_offset */ void dbox_file_cancel_append(struct dbox_file *file, uoff_t append_offset); -/* Finish appending the current mail. */ -void dbox_file_finish_append(struct dbox_file *file); +/* Flush writes to dbox file. */ +int dbox_file_flush_append(struct dbox_file *file); /* Seek to given metadata block. Returns 1 if ok, 0 if file/offset is corrupted, -1 if I/O error. If message has already been expunged, diff --git a/src/lib-storage/index/dbox/dbox-map.c b/src/lib-storage/index/dbox/dbox-map.c index d520b3ddc7..013fef55cd 100644 --- a/src/lib-storage/index/dbox/dbox-map.c +++ b/src/lib-storage/index/dbox/dbox-map.c @@ -294,8 +294,6 @@ dbox_map_find_appendable_file(struct dbox_map_append_context *ctx, struct ostream **output_r, bool *existing_r) { struct dbox_map *map = ctx->map; - bool fsync_disable = (map->storage->storage.flags & - MAIL_STORAGE_FLAG_FSYNC_DISABLE) != 0; struct dbox_file *const *files; const struct mail_index_header *hdr; unsigned int i, count, backwards_lookup_count; @@ -323,13 +321,8 @@ dbox_map_find_appendable_file(struct dbox_map_append_context *ctx, /* can't append to this file anymore */ if (files[i-1]->fd != -1) { /* avoid wasting fds by closing the file */ - if (!fsync_disable) { - if (fdatasync(files[i-1]->fd) < 0) { - dbox_file_set_syscall_error(files[i-1], - "fdatasync()"); - return -1; - } - } + if (dbox_file_flush_append(files[i-1]) < 0) + return -1; dbox_file_unlock(files[i-1]); dbox_file_close(files[i-1]); } @@ -431,9 +424,10 @@ int dbox_map_append_next(struct dbox_map_append_context *ctx, uoff_t mail_size, append->file = file; append->offset = (*output_r)->offset; } - if (!existing) + if (!existing) { + i_assert(file->output != NULL); array_append(&ctx->files, &file, 1); - + } *file_r = file; return 0; } @@ -467,8 +461,6 @@ int dbox_map_append_assign_map_uids(struct dbox_map_append_context *ctx, uint32_t *first_map_uid_r, uint32_t *last_map_uid_r) { - bool fsync_disable = (ctx->map->storage->storage.flags & - MAIL_STORAGE_FLAG_FSYNC_DISABLE) != 0; struct dbox_file *const *files; const struct dbox_map_append *appends; struct mail_index_sync_ctx *sync_ctx; @@ -508,11 +500,8 @@ int dbox_map_append_assign_map_uids(struct dbox_map_append_context *ctx, if (files[i]->single_mbox != NULL) continue; - if (!fsync_disable && files[i]->single_mbox == NULL && - files[i]->fd != -1) { - if (fdatasync(files[i]->fd) < 0) { - dbox_file_set_syscall_error(files[i], - "fdatasync()"); + if (files[i]->single_mbox == NULL && files[i]->output != NULL) { + if (dbox_file_flush_append(files[i]) < 0) { ret = -1; break; } @@ -631,6 +620,11 @@ void dbox_map_append_rollback(struct dbox_map_append_context **_ctx) for (i = 0; i < count; i++) { file = files[i]; + if (file->output != NULL) { + /* flush before truncating */ + (void)o_stream_flush(file->output); + } + if (file->file_id != 0) { /* FIXME: truncate? */ } else { diff --git a/src/lib-storage/index/dbox/dbox-save.c b/src/lib-storage/index/dbox/dbox-save.c index de8dd492de..964f5818bf 100644 --- a/src/lib-storage/index/dbox/dbox-save.c +++ b/src/lib-storage/index/dbox/dbox-save.c @@ -78,13 +78,11 @@ int dbox_save_begin(struct mail_save_context *_ctx, struct istream *input) struct dbox_save_mail *save_mail; struct istream *crlf_input; enum mail_flags save_flags; - const struct stat *st; uoff_t mail_size; /* get the size of the mail to be saved, if possible */ - st = i_stream_stat(input, TRUE); - mail_size = st == NULL || st->st_size == -1 ? 0 : st->st_size; - + if (i_stream_get_size(input, TRUE, &mail_size) <= 0) + mail_size = 0; if (dbox_map_append_next(ctx->append_ctx, mail_size, &ctx->cur_file, &ctx->cur_output) < 0) { ctx->failed = TRUE; @@ -217,26 +215,24 @@ static void dbox_save_write_metadata(struct dbox_save_context *ctx) o_stream_send(ctx->cur_output, str_data(str), str_len(str)); } -static int dbox_save_mail_write_header(struct dbox_save_mail *mail) +static int dbox_save_mail_write_metadata(struct dbox_save_context *ctx, + struct dbox_save_mail *mail) { struct dbox_message_header dbox_msg_hdr; i_assert(mail->file->msg_header_size == sizeof(dbox_msg_hdr)); + dbox_save_write_metadata(ctx); dbox_msg_header_fill(&dbox_msg_hdr, mail->message_size); - if (pwrite_full(mail->file->fd, &dbox_msg_hdr, - sizeof(dbox_msg_hdr), mail->append_offset) < 0) { - dbox_file_set_syscall_error(mail->file, "write()"); + if (o_stream_pwrite(ctx->cur_output, &dbox_msg_hdr, + sizeof(dbox_msg_hdr), mail->append_offset) < 0) { + dbox_file_set_syscall_error(mail->file, "pwrite()"); return -1; } - /* we're done writing to single-files now, so fsync them here. */ - if ((mail->file->storage->storage.flags & - MAIL_STORAGE_FLAG_FSYNC_DISABLE) == 0 && - mail->file->single_mbox != NULL) { - if (fdatasync(mail->file->fd) < 0) { - dbox_file_set_syscall_error(mail->file, "fdatasync()"); + if (mail->file->single_mbox != NULL) { + /* we're done writing to single-files now */ + if (dbox_file_flush_append(mail->file) < 0) return -1; - } } return 0; } @@ -244,9 +240,7 @@ static int dbox_save_mail_write_header(struct dbox_save_mail *mail) static int dbox_save_finish_write(struct mail_save_context *_ctx) { struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx; - struct mail_storage *storage = &ctx->mbox->storage->storage; struct dbox_save_mail *save_mail; - uoff_t metadata_offset = 0; unsigned int count; ctx->finished = TRUE; @@ -256,30 +250,21 @@ static int dbox_save_finish_write(struct mail_save_context *_ctx) index_mail_cache_parse_deinit(_ctx->dest_mail, _ctx->received_date, !ctx->failed); + count = array_count(&ctx->mails); + save_mail = array_idx_modifiable(&ctx->mails, count - 1); + if (!ctx->failed) T_BEGIN { - metadata_offset = ctx->cur_output->offset; - dbox_save_write_metadata(ctx); - if (o_stream_flush(ctx->cur_output) < 0) { - mail_storage_set_critical(storage, - "o_stream_flush(%s) failed: %m", - ctx->cur_file->current_path); + save_mail->message_size = ctx->cur_output->offset - + save_mail->append_offset - + save_mail->file->msg_header_size; + + if (dbox_save_mail_write_metadata(ctx, save_mail) < 0) ctx->failed = TRUE; - } } T_END; o_stream_unref(&ctx->cur_output); i_stream_unref(&ctx->input); - count = array_count(&ctx->mails); - save_mail = array_idx_modifiable(&ctx->mails, count - 1); - if (!ctx->failed) { - dbox_file_finish_append(save_mail->file); - save_mail->message_size = metadata_offset - - save_mail->append_offset - - save_mail->file->msg_header_size; - if (dbox_save_mail_write_header(save_mail) < 0) - ctx->failed = TRUE; - } if (ctx->failed) { dbox_file_cancel_append(save_mail->file, save_mail->append_offset);