]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
indexes: Fixes to handling shrinking tail offsets.
authorTimo Sirainen <tss@iki.fi>
Tue, 10 Mar 2009 16:28:22 +0000 (12:28 -0400)
committerTimo Sirainen <tss@iki.fi>
Tue, 10 Mar 2009 16:28:22 +0000 (12:28 -0400)
--HG--
branch : HEAD

src/lib-index/mail-index-sync.c
src/lib-index/mail-index-transaction-private.h
src/lib-index/mail-transaction-log-append.c
src/lib-index/mail-transaction-log-file.c

index 7c4f5d26f3dcce3dd3c0cdee36f59cb29e3fb10e..131b0207a63bc7ce8f85bdccd8d190c44cf9edc8 100644 (file)
@@ -461,6 +461,7 @@ int mail_index_sync_begin_to(struct mail_index *index,
        if ((ctx->flags & MAIL_INDEX_SYNC_FLAG_AVOID_FLAG_UPDATES) != 0)
                trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_AVOID_FLAG_UPDATES;
        ctx->ext_trans = mail_index_transaction_begin(ctx->view, trans_flags);
+       ctx->ext_trans->sync_transaction = TRUE;
 
        index->syncing = TRUE;
 
index 9f9d260aa7edbe50b7c5412df2446404085ab913..260b105475070c6d6b4b4ff78dd250c2ef02fa0e 100644 (file)
@@ -73,6 +73,7 @@ struct mail_index_transaction {
 
        unsigned int no_appends:1;
 
+       unsigned int sync_transaction:1;
        unsigned int appends_nonsorted:1;
        unsigned int pre_hdr_changed:1;
        unsigned int post_hdr_changed:1;
index 6f4f77f3995e50a36d50d39f22be9d8b9b0ba2fa..4a264cde65b67065050bb7d93b9d70c388efe545 100644 (file)
@@ -523,6 +523,13 @@ static void log_append_sync_offset_if_needed(struct log_append_context *ctx)
        buffer_t *buf;
        uint32_t offset;
 
+       /* Update the tail offsets only when committing the sync transaction.
+          Other transactions may not know the latest tail offset and might
+          end up shrinking it. (Alternatively the shrinking tail offsets could
+          just be ignored, which would probably work fine too.) */
+       if (!ctx->trans->sync_transaction)
+               return;
+
        if (ctx->file->max_tail_offset == ctx->file->sync_offset) {
                /* FIXME: when we remove exclusive log locking, we
                   can't rely on this. then write non-changed offset + check
index e02363328f85f4d590485195066020ca1cebe5b1..c3c7bf40d5860067b0d6c0b39dec03932c02f329 100644 (file)
@@ -147,8 +147,11 @@ mail_transaction_log_file_skip_to_head(struct mail_transaction_log_file *file)
                file->sync_offset = modseq_hdr->log_offset;
                file->sync_highest_modseq = modseq_hdr->highest_modseq;
        }
-       file->saved_tail_offset = log->index->map->hdr.log_file_tail_offset;
-       file->saved_tail_sync_offset = file->saved_tail_offset;
+       if (file->hdr.file_seq == log->index->map->hdr.log_file_seq) {
+               file->saved_tail_offset =
+                       log->index->map->hdr.log_file_tail_offset;
+               file->saved_tail_sync_offset = file->saved_tail_offset;
+       }
        if (file->saved_tail_offset > file->max_tail_offset)
                file->max_tail_offset = file->saved_tail_offset;
 }
@@ -755,9 +758,9 @@ log_file_track_mailbox_sync_offset_hdr(struct mail_transaction_log_file *file,
        const unsigned int offset_pos =
                offsetof(struct mail_index_header, log_file_tail_offset);
        const unsigned int offset_size = sizeof(ihdr->log_file_tail_offset);
-       uint32_t sync_offset;
+       uint32_t tail_offset;
 
-       i_assert(offset_size == sizeof(sync_offset));
+       i_assert(offset_size == sizeof(tail_offset));
 
        if (size < sizeof(*u) || size < sizeof(*u) + u->size) {
                mail_transaction_log_file_set_corrupted(file,
@@ -767,28 +770,31 @@ log_file_track_mailbox_sync_offset_hdr(struct mail_transaction_log_file *file,
 
        if (u->offset <= offset_pos &&
            u->offset + u->size >= offset_pos + offset_size) {
-               memcpy(&sync_offset,
+               memcpy(&tail_offset,
                       CONST_PTR_OFFSET(u + 1, offset_pos - u->offset),
-                      sizeof(sync_offset));
+                      sizeof(tail_offset));
 
-               if (sync_offset < file->saved_tail_offset) {
+               if (tail_offset < file->saved_tail_offset) {
                        if (file->sync_offset < file->saved_tail_sync_offset) {
                                /* saved_tail_offset was already set in header,
                                   but we still had to resync the file to find
                                   modseqs. ignore this record. */
                                return 1;
                        }
-                       mail_transaction_log_file_set_corrupted(file,
+                       mail_index_set_error(file->log->index,
+                               "Transaction log file %s seq %u: "
                                "log_file_tail_offset update shrank it "
-                               "(%u vs %"PRIuUOFF_T", file_seq=%u)",
-                               sync_offset, file->saved_tail_offset,
-                               file->hdr.file_seq);
-                       return -1;
+                               "(%u vs %"PRIuUOFF_T" "
+                               "sync_offset=%"PRIuUOFF_T")",
+                               file->filepath, file->hdr.file_seq,
+                               tail_offset, file->saved_tail_offset,
+                               file->sync_offset);
+               } else {
+                       file->saved_tail_offset = tail_offset;
+                       if (tail_offset > file->max_tail_offset)
+                               file->max_tail_offset = tail_offset;
+                       return 1;
                }
-               file->saved_tail_offset = sync_offset;
-               if (sync_offset > file->max_tail_offset)
-                       file->max_tail_offset = sync_offset;
-               return 1;
        }
        return 0;
 }