# HG changeset patch # User Timo Sirainen # Date 1294246060 -7200 # Node ID 39f5ef8d612c88e1bce3fc9ac7573729728e0af0 # Parent b32e7bc87a09a3c617c8254753ee33354257e0a5 mdbox: Don't leave partially written messages to mdbox files. diff -r b32e7bc87a09 -r 39f5ef8d612c src/lib-storage/index/dbox-common/dbox-file.c --- a/src/lib-storage/index/dbox-common/dbox-file.c Wed Jan 05 18:11:04 2011 +0200 +++ b/src/lib-storage/index/dbox-common/dbox-file.c Wed Jan 05 18:47:40 2011 +0200 @@ -479,6 +479,13 @@ *_ctx = NULL; ret = dbox_file_append_flush(ctx); + if (ctx->last_checkpoint_offset != ctx->output->offset) { + o_stream_close(ctx->output); + if (ftruncate(ctx->file->fd, ctx->last_checkpoint_offset) < 0) { + dbox_file_set_syscall_error(ctx->file, "ftruncate()"); + return -1; + } + } o_stream_unref(&ctx->output); ctx->file->appending = FALSE; i_free(ctx); @@ -538,6 +545,11 @@ return 0; } +void dbox_file_append_checkpoint(struct dbox_file_append_context *ctx) +{ + ctx->last_checkpoint_offset = ctx->output->offset; +} + int dbox_file_get_append_stream(struct dbox_file_append_context *ctx, struct ostream **output_r) { @@ -548,6 +560,11 @@ /* file creation had failed */ return -1; } + if (ctx->last_checkpoint_offset != ctx->output->offset) { + /* a message was aborted. don't try appending to this + file anymore. */ + return -1; + } if (file->file_version == 0) { /* newly created file, write the file header */ diff -r b32e7bc87a09 -r 39f5ef8d612c src/lib-storage/index/dbox-common/dbox-file.h --- a/src/lib-storage/index/dbox-common/dbox-file.h Wed Jan 05 18:11:04 2011 +0200 +++ b/src/lib-storage/index/dbox-common/dbox-file.h Wed Jan 05 18:47:40 2011 +0200 @@ -126,7 +126,7 @@ struct dbox_file_append_context { struct dbox_file *file; - uoff_t first_append_offset, last_flush_offset; + uoff_t first_append_offset, last_checkpoint_offset, last_flush_offset; struct ostream *output; }; @@ -173,6 +173,9 @@ can't be appended to (old file version or corruption) or -1 if error. */ int dbox_file_get_append_stream(struct dbox_file_append_context *ctx, struct ostream **output_r); +/* Call after message has been fully saved. If this isn't done, the writes + since the last checkpoint are truncated. */ +void dbox_file_append_checkpoint(struct dbox_file_append_context *ctx); /* Flush output buffer. */ int dbox_file_append_flush(struct dbox_file_append_context *ctx); diff -r b32e7bc87a09 -r 39f5ef8d612c src/lib-storage/index/dbox-multi/mdbox-map.c --- a/src/lib-storage/index/dbox-multi/mdbox-map.c Wed Jan 05 18:11:04 2011 +0200 +++ b/src/lib-storage/index/dbox-multi/mdbox-map.c Wed Jan 05 18:47:40 2011 +0200 @@ -1097,15 +1097,19 @@ void mdbox_map_append_finish(struct mdbox_map_append_context *ctx) { - struct mdbox_map_append *appends; + struct mdbox_map_append *appends, *last; unsigned int count; uoff_t cur_offset; appends = array_get_modifiable(&ctx->appends, &count); - i_assert(count > 0 && appends[count-1].size == (uint32_t)-1); - cur_offset = appends[count-1].file_append->output->offset; - i_assert(cur_offset >= appends[count-1].offset); - appends[count-1].size = cur_offset - appends[count-1].offset; + i_assert(count > 0); + last = &appends[count-1]; + i_assert(last->size == (uint32_t)-1); + + cur_offset = last->file_append->output->offset; + i_assert(cur_offset >= last->offset); + last->size = cur_offset - last->offset; + dbox_file_append_checkpoint(last->file_append); } void mdbox_map_append_abort(struct mdbox_map_append_context *ctx) diff -r b32e7bc87a09 -r 39f5ef8d612c src/lib-storage/index/dbox-single/sdbox-save.c --- a/src/lib-storage/index/dbox-single/sdbox-save.c Wed Jan 05 18:11:04 2011 +0200 +++ b/src/lib-storage/index/dbox-single/sdbox-save.c Wed Jan 05 18:47:40 2011 +0200 @@ -186,8 +186,11 @@ if (ctx->ctx.failed) dbox_file_append_rollback(&ctx->append_ctx); - else if (dbox_file_append_commit(&ctx->append_ctx) < 0) - ctx->ctx.failed = TRUE; + else { + dbox_file_append_checkpoint(ctx->append_ctx); + if (dbox_file_append_commit(&ctx->append_ctx) < 0) + ctx->ctx.failed = TRUE; + } i_stream_unref(&ctx->ctx.input); dbox_file_close(*files);