]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dbox: Optimized saving messages.
authorTimo Sirainen <tss@iki.fi>
Mon, 30 Mar 2009 21:32:25 +0000 (17:32 -0400)
committerTimo Sirainen <tss@iki.fi>
Mon, 30 Mar 2009 21:32:25 +0000 (17:32 -0400)
--HG--
branch : HEAD

src/lib-storage/index/dbox/dbox-file.c
src/lib-storage/index/dbox/dbox-file.h
src/lib-storage/index/dbox/dbox-map.c

index dc1b6032e462c79b3dca892c37d2791a2b28d394..4650b430a8e709bc8f409ea13e2d6324e6816a72 100644 (file)
@@ -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)
index 1b8bc313dd1f4c808936e2d94ddd21afdc009211..bc3475c45f5eb5383a94df1c75342500d106c421 100644 (file)
@@ -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. */
index c2a73b600bd4905ce0d12df0c1d4b4e402050c6e..391051b5bed046ba44a9d680664516f9ef5584c8 100644 (file)
@@ -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);