]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
mdbox: Don't leave partially written messages to mdbox files.
authorTimo Sirainen <tss@iki.fi>
Wed, 5 Jan 2011 16:47:40 +0000 (18:47 +0200)
committerTimo Sirainen <tss@iki.fi>
Wed, 5 Jan 2011 16:47:40 +0000 (18:47 +0200)
src/lib-storage/index/dbox-common/dbox-file.c
src/lib-storage/index/dbox-common/dbox-file.h
src/lib-storage/index/dbox-multi/mdbox-map.c
src/lib-storage/index/dbox-single/sdbox-save.c

index 21713e0633e645f8062fd6fed5e2b44d8513dcad..65f7f2f2f200428c9b088ebadcc99c0e1dc568f3 100644 (file)
@@ -479,6 +479,13 @@ int dbox_file_append_commit(struct dbox_file_append_context **_ctx)
        *_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 @@ int dbox_file_append_flush(struct dbox_file_append_context *ctx)
        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 @@ int dbox_file_get_append_stream(struct dbox_file_append_context *ctx,
                /* 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 */
index d458716412d284f0ec3ab866282ad7e2461deb59..e1318fe7e6d4214f973a35302f89a677f56c6002 100644 (file)
@@ -126,7 +126,7 @@ struct dbox_file {
 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 @@ void dbox_file_append_rollback(struct dbox_file_append_context **ctx);
    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);
 
index 68fcd5cdd5c7dcba1816936ad0f7df5093c9affb..5ebd99e37ce429bf1aa00910e434277f79981c50 100644 (file)
@@ -1097,15 +1097,19 @@ int mdbox_map_append_next(struct mdbox_map_append_context *ctx,
 
 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)
index a6b014685df8ea13bca9cd55bb47f064306c51f2..b859f15c0c2d2426617252cf0437a54f4b5e4ab4 100644 (file)
@@ -186,8 +186,11 @@ static int dbox_save_finish_write(struct mail_save_context *_ctx)
 
        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);