*_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);
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)
{
/* 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 */
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;
};
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);
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)
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);