From: Timo Sirainen Date: Mon, 30 Mar 2009 21:32:25 +0000 (-0400) Subject: dbox: Optimized saving messages. X-Git-Tag: 2.0.alpha1~1038^2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=93ea960ffd255b51208b6fa1b30425a35a210a4a;p=thirdparty%2Fdovecot%2Fcore.git dbox: Optimized saving messages. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/dbox/dbox-file.c b/src/lib-storage/index/dbox/dbox-file.c index dc1b6032e4..4650b430a8 100644 --- a/src/lib-storage/index/dbox/dbox-file.c +++ b/src/lib-storage/index/dbox/dbox-file.c @@ -661,12 +661,10 @@ int dbox_file_seek_next(struct dbox_file *file, uoff_t *offset_r, bool *last_r) } static int -dbox_file_seek_append_pos(struct dbox_file *file, uoff_t append_offset) +dbox_file_seek_append_pos(struct dbox_file *file, uoff_t *append_offset_r) { struct stat st; - i_assert(append_offset != 0); - if (file->file_version != DBOX_VERSION || file->msg_header_size != sizeof(struct dbox_message_header)) { /* created by an incompatible version, can't append */ @@ -677,22 +675,15 @@ dbox_file_seek_append_pos(struct dbox_file *file, uoff_t append_offset) dbox_file_set_syscall_error(file, "fstat()"); return -1; } - if ((uoff_t)st.st_size != append_offset) { - /* not end of file? either previous write crashed or map index - got broken. play it safe and resync everything. */ - dbox_file_set_corrupted(file, "file size (%"PRIuUOFF_T - ") not expected (%"PRIuUOFF_T")", - st.st_size, append_offset); - return 0; - } + *append_offset_r = st.st_size; file->output = o_stream_create_fd_file(file->fd, 0, FALSE); - o_stream_seek(file->output, append_offset); + o_stream_seek(file->output, st.st_size); return 1; } -int dbox_file_get_append_stream(struct dbox_file *file, uoff_t last_msg_offset, - uoff_t last_msg_size, struct ostream **stream_r) +int dbox_file_get_append_stream(struct dbox_file *file, uoff_t *append_offset_r, + struct ostream **stream_r) { int ret; @@ -723,8 +714,7 @@ int dbox_file_get_append_stream(struct dbox_file *file, uoff_t last_msg_offset, } else if (file->output == NULL) { i_assert(file->lock != NULL || file->single_mbox != NULL); - ret = dbox_file_seek_append_pos(file, last_msg_offset + - last_msg_size); + ret = dbox_file_seek_append_pos(file, append_offset_r); if (ret <= 0) return ret; } @@ -743,10 +733,13 @@ uoff_t dbox_file_get_next_append_offset(struct dbox_file *file) 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()"); + (void)o_stream_flush(file->output); - o_stream_seek(file->output, append_offset); + if (file->output->offset != append_offset) { + if (ftruncate(file->fd, append_offset) < 0) + dbox_file_set_syscall_error(file, "ftruncate()"); + o_stream_seek(file->output, append_offset); + } } int dbox_file_flush_append(struct dbox_file *file) diff --git a/src/lib-storage/index/dbox/dbox-file.h b/src/lib-storage/index/dbox/dbox-file.h index 1b8bc313dd..bc3475c45f 100644 --- a/src/lib-storage/index/dbox/dbox-file.h +++ b/src/lib-storage/index/dbox/dbox-file.h @@ -157,12 +157,9 @@ int dbox_file_seek_next(struct dbox_file *file, uoff_t *offset_r, bool *last_r); /* Returns TRUE if mail_size bytes can be appended to the file. */ bool dbox_file_can_append(struct dbox_file *file, uoff_t mail_size); -/* Get output stream for appending a new message. last_msg_offset points to - the beginning of the last message in the file, or 0 for new files. Returns - 1 if ok, 0 if file can't be appended to (old file version or corruption) - or -1 if error. */ -int dbox_file_get_append_stream(struct dbox_file *file, uoff_t last_msg_offset, - uoff_t last_msg_size, +/* Get output stream for appending a new message. Returns 1 if ok, 0 if file + can't be appended to (old file version or corruption) or -1 if error. */ +int dbox_file_get_append_stream(struct dbox_file *file, uoff_t *append_offset_r, struct ostream **stream_r); /* Returns the next offset for append a message. dbox_file_get_append_stream() must have been called for this file already at least once. */ diff --git a/src/lib-storage/index/dbox/dbox-map.c b/src/lib-storage/index/dbox/dbox-map.c index c2a73b600b..391051b5be 100644 --- a/src/lib-storage/index/dbox/dbox-map.c +++ b/src/lib-storage/index/dbox/dbox-map.c @@ -510,11 +510,9 @@ dbox_map_file_try_append(struct dbox_map_append_context *ctx, { struct dbox_map *map = ctx->map; struct dbox_storage *storage = map->storage; - const struct mail_index_header *hdr; struct dbox_file *file; struct stat st; - uint32_t seq, tmp_file_id; - uoff_t tmp_offset, tmp_size, last_msg_offset, last_msg_size, new_size; + uoff_t append_offset; bool deleted, file_too_old = FALSE; int ret; @@ -542,33 +540,16 @@ dbox_map_file_try_append(struct dbox_map_append_context *ctx, if (errno != ENOENT) i_error("stat(%s) failed: %m", file->current_path); /* the file was unlinked between opening and locking it. */ - } else if (dbox_map_refresh(map) == 0) { - /* now that the file is locked and map is refreshed, make sure - we still have the last msg's offset. we have to go through - the whole map, because existing messages may have already - been appended to this file. */ - last_msg_offset = 0; - hdr = mail_index_get_header(map->view); - for (seq = 1; seq <= hdr->messages_count; seq++) { - if (dbox_map_lookup_seq(map, seq, &tmp_file_id, - &tmp_offset, &tmp_size) < 0) - break; - if (tmp_file_id == file->file_id && - last_msg_offset < tmp_offset) { - last_msg_offset = tmp_offset; - last_msg_size = tmp_size; - } - } - - new_size = last_msg_offset + last_msg_size + mail_size; - if (seq > hdr->messages_count && last_msg_offset > 0 && - new_size <= storage->rotate_size && - dbox_file_get_append_stream(file, last_msg_offset, - last_msg_size, output_r) > 0) { - /* success */ - *file_r = file; - return TRUE; - } + } else if (dbox_file_get_append_stream(file, &append_offset, + output_r) <= 0) { + /* couldn't append to this file */ + } else if (append_offset + mail_size > storage->rotate_size) { + /* file was too large after all */ + dbox_file_cancel_append(file, append_offset); + } else { + /* success */ + *file_r = file; + return TRUE; } /* failure */ @@ -622,7 +603,7 @@ dbox_map_find_appendable_file(struct dbox_map_append_context *ctx, append_offset = dbox_file_get_next_append_offset(files[i-1]); if (append_offset + mail_size <= map->storage->rotate_size && - dbox_file_get_append_stream(files[i-1], 0, 0, + dbox_file_get_append_stream(files[i-1], &append_offset, output_r) > 0) { *file_r = files[i-1]; *existing_r = TRUE; @@ -698,6 +679,7 @@ int dbox_map_append_next(struct dbox_map_append_context *ctx, uoff_t mail_size, { struct dbox_file *file = NULL; struct dbox_map_append *append; + uoff_t append_offset; bool existing; int ret; @@ -714,7 +696,8 @@ int dbox_map_append_next(struct dbox_map_append_context *ctx, uoff_t mail_size, file = ctx->map->storage->rotate_size == 0 ? dbox_file_init_single(ctx->mbox, 0) : dbox_file_init_multi(ctx->map->storage, 0); - ret = dbox_file_get_append_stream(file, 0, 0, output_r); + ret = dbox_file_get_append_stream(file, &append_offset, + output_r); if (ret <= 0) { i_assert(ret < 0); (void)unlink(file->current_path);