]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Make sure we don't set cache_offsets to old cache files.
authorTimo Sirainen <tss@iki.fi>
Sun, 4 Jul 2004 21:56:12 +0000 (00:56 +0300)
committerTimo Sirainen <tss@iki.fi>
Sun, 4 Jul 2004 21:56:12 +0000 (00:56 +0300)
--HG--
branch : HEAD

src/lib-index/mail-cache-compress.c
src/lib-index/mail-cache-transaction.c
src/lib-index/mail-index-private.h
src/lib-index/mail-index-transaction-private.h
src/lib-index/mail-index-transaction.c
src/lib-index/mail-transaction-log.c

index 35525448175b0cab15ca7a835719967c5c12328f..916432e22447bd100bd2098d2f7cd1c5c99e65cc 100644 (file)
@@ -188,7 +188,8 @@ mail_cache_copy(struct mail_cache *cache, struct mail_index_view *view, int fd)
                if (keep_fields == cached_fields &&
                    cache_rec->prev_offset == 0) {
                        /* just one unmodified block, save it */
-                        mail_index_update_cache(t, seq, output->offset, NULL);
+                       mail_index_update_cache(t, seq, hdr.file_seq,
+                                               output->offset, NULL);
                        o_stream_send(output, cache_rec, cache_rec->size);
 
                        if ((cache_rec->size & 3) != 0) {
@@ -198,7 +199,8 @@ mail_cache_copy(struct mail_cache *cache, struct mail_index_view *view, int fd)
                } else {
                        /* a) dropping fields
                           b) multiple blocks, sort them into buffer */
-                        mail_index_update_cache(t, seq, output->offset, NULL);
+                       mail_index_update_cache(t, seq, hdr.file_seq,
+                                               output->offset, NULL);
 
                        t_push();
                        cache_rec = mail_cache_compress_record(cache_view, seq,
index c2537d728f843d8a84bdbf235d971f98e676c961..46e62be8d5951be24b8faac1aa03b67e55462969 100644 (file)
@@ -369,6 +369,7 @@ mail_cache_transaction_flush(struct mail_cache_transaction_ctx *ctx)
                   synced. */
                for (; seq_idx < seq_limit; seq_idx++) {
                        mail_index_update_cache(ctx->trans, seq[seq_idx],
+                                               cache->hdr->file_seq,
                                                write_offset, &old_offset);
                        if (old_offset != 0) {
                                /* we added records for this message multiple
index 41658a92d440804062b3ce92c22d989a184f92e2..0baa38b26c94ccc39195f0bf7ce59f2bd9d65b35 100644 (file)
@@ -132,8 +132,8 @@ int mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
 
 void mail_index_reset_cache(struct mail_index_transaction *t,
                            uint32_t new_file_seq);
-void mail_index_update_cache(struct mail_index_transaction *t,
-                            uint32_t seq, uint32_t offset,
+void mail_index_update_cache(struct mail_index_transaction *t, uint32_t seq,
+                            uint32_t file_seq, uint32_t offset,
                             uint32_t *old_offset_r);
 
 int mail_index_fix_header(struct mail_index *index, struct mail_index_map *map,
index 122dcef5b6e44e01a8a7936f83dc77249f278775..5f9d81139d0aa79a546699e388f5e570f724a112 100644 (file)
@@ -22,7 +22,7 @@ struct mail_index_transaction {
 
        buffer_t *extra_rec_updates[MAIL_INDEX_MAX_EXTRA_RECORDS];
 
-       uint32_t new_cache_file_seq;
+       uint32_t new_cache_file_seq, last_cache_file_seq;
        buffer_t *cache_updates;
         struct mail_cache_transaction_ctx *cache_trans_ctx;
 
index 5a9fc80db88230c0750294761987219ef8a6bbb2..05cc08e381d230498308fd56cf7bf08f29e02eb2 100644 (file)
@@ -563,18 +563,44 @@ static int mail_index_update_seq_buffer(buffer_t **buffer, uint32_t seq,
        return FALSE;
 }
 
+static void
+mail_index_transaction_reset_cache_updates(struct mail_index_transaction *t)
+{
+       struct mail_index_record *rec;
+       uint32_t seq;
+
+       if (t->last_cache_file_seq == 0)
+               return;
+
+       buffer_set_used_size(t->cache_updates, 0);
+
+       if (t->first_new_seq != 0) {
+               for (seq = t->first_new_seq; seq <= t->last_new_seq; seq++) {
+                       rec = mail_index_transaction_lookup(t, seq);
+                       rec->cache_offset = 0;
+               }
+       }
+}
+
 void mail_index_reset_cache(struct mail_index_transaction *t,
                            uint32_t new_file_seq)
 {
+       mail_index_transaction_reset_cache_updates(t);
        t->new_cache_file_seq = new_file_seq;
+        t->last_cache_file_seq = new_file_seq;
 }
 
-void mail_index_update_cache(struct mail_index_transaction *t,
-                            uint32_t seq, uint32_t offset,
+void mail_index_update_cache(struct mail_index_transaction *t, uint32_t seq,
+                            uint32_t file_seq, uint32_t offset,
                             uint32_t *old_offset_r)
 {
        struct mail_index_record *rec;
 
+       if (file_seq > t->last_cache_file_seq) {
+               mail_index_transaction_reset_cache_updates(t);
+                t->last_cache_file_seq = file_seq;
+       }
+
        if (seq >= t->first_new_seq) {
                /* just appended message, modify it directly */
                rec = mail_index_transaction_lookup(t, seq);
index 4f40665cf332cd4ffa66a2f3d76d30beab411624..82155e59b47026f82f5fb718225aad171bf4f65f 100644 (file)
@@ -883,62 +883,45 @@ static int mail_transaction_log_lock_head(struct mail_transaction_log *log)
        return ret;
 }
 
-static int mail_transaction_log_fix_appends(struct mail_transaction_log *log,
-                                           struct mail_index_transaction *t)
+static void
+mail_transaction_log_append_fix(struct mail_index_transaction *t,
+                               const struct mail_transaction_header *hdr,
+                               const void *data)
 {
-       struct mail_transaction_log_view *sync_view;
+        const struct mail_transaction_append_header *append_hdr = data;
        const struct mail_index_record *old, *old_end;
        struct mail_index_record *appends, *end, *rec, *dest;
-        const struct mail_transaction_append_header *append_hdr;
-       const struct mail_transaction_header *hdr;
-       const void *data;
+       uint32_t record_size = t->append_record_size;
        size_t size;
-       uint32_t record_size;
-       int ret, deleted = FALSE;
+       int deleted = FALSE;
 
        if (t->appends == NULL)
-               return 0;
+               return;
 
-       record_size = t->append_record_size;
        appends = buffer_get_modifyable_data(t->appends, &size);
        end = PTR_OFFSET(appends, size);
 
        if (appends == end)
-               return 0;
+               return;
 
        /* we'll just check that none of the appends are already in
           transaction log. this could happen if we crashed before we had
           a chance to update index file */
-       sync_view = mail_transaction_log_view_open(log);
-       ret = mail_transaction_log_view_set(sync_view, t->view->log_file_seq,
-                                           t->view->log_file_offset,
-                                           log->head->hdr.file_seq,
-                                           log->head->hdr.used_size,
-                                           MAIL_TRANSACTION_TYPE_MASK);
-       while ((ret = mail_transaction_log_view_next(sync_view,
-                                                    &hdr, &data, NULL)) == 1) {
-               if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) !=
-                   MAIL_TRANSACTION_APPEND)
-                       continue;
-
-                append_hdr = data;
-
-               old = CONST_PTR_OFFSET(data, sizeof(*append_hdr));
-               old_end = CONST_PTR_OFFSET(data, hdr->size);
-               while (old != old_end) {
-                       /* appends are sorted */
-                       for (rec = appends; rec != end; ) {
-                               if (rec->uid >= old->uid) {
-                                       if (rec->uid == old->uid) {
-                                               rec->uid = 0;
-                                               deleted = TRUE;
-                                       }
-                                       break;
+       old = CONST_PTR_OFFSET(data, sizeof(*append_hdr));
+       old_end = CONST_PTR_OFFSET(data, hdr->size);
+       while (old != old_end) {
+               /* appends are sorted */
+               for (rec = appends; rec != end; ) {
+                       if (rec->uid >= old->uid) {
+                               if (rec->uid == old->uid) {
+                                       rec->uid = 0;
+                                       deleted = TRUE;
                                }
-                               rec = PTR_OFFSET(rec, record_size);
+                               break;
                        }
-                        old = CONST_PTR_OFFSET(old, append_hdr->record_size);
+                       rec = PTR_OFFSET(rec, record_size);
                }
+               old = CONST_PTR_OFFSET(old, append_hdr->record_size);
        }
 
        if (deleted) {
@@ -953,6 +936,44 @@ static int mail_transaction_log_fix_appends(struct mail_transaction_log *log,
                buffer_set_used_size(t->appends,
                                     (char *)dest - (char *)appends);
        }
+}
+
+static int mail_transaction_log_scan_pending(struct mail_transaction_log *log,
+                                            struct mail_index_transaction *t)
+{
+       struct mail_transaction_log_view *sync_view;
+       const struct mail_transaction_header *hdr;
+       const void *data;
+       uint32_t max_cache_file_seq = 0;
+       int ret;
+
+       sync_view = mail_transaction_log_view_open(log);
+       ret = mail_transaction_log_view_set(sync_view, t->view->log_file_seq,
+                                           t->view->log_file_offset,
+                                           log->head->hdr.file_seq,
+                                           log->head->hdr.used_size,
+                                           MAIL_TRANSACTION_TYPE_MASK);
+       while ((ret = mail_transaction_log_view_next(sync_view,
+                                                    &hdr, &data, NULL)) == 1) {
+               switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
+               case MAIL_TRANSACTION_APPEND:
+                       mail_transaction_log_append_fix(t, hdr, data);
+                       break;
+               case MAIL_TRANSACTION_CACHE_RESET: {
+                       const struct mail_transaction_cache_reset *reset = data;
+
+                       max_cache_file_seq = reset->new_file_seq;
+                       break;
+               }
+               }
+       }
+
+       /* make sure we're not writing cache_offsets to old cache file */
+       if (t->new_cache_file_seq == 0 && max_cache_file_seq != 0 &&
+           max_cache_file_seq != t->last_cache_file_seq) {
+               buffer_free(t->cache_updates);
+               t->cache_updates = NULL;
+       }
 
        mail_transaction_log_view_close(sync_view);
        return ret;
@@ -1107,10 +1128,15 @@ int mail_transaction_log_append(struct mail_index_transaction *t,
        file = log->head;
        append_offset = file->hdr.used_size;
 
-       if (mail_transaction_log_fix_appends(log, t) < 0) {
-               if (!log->index->log_locked)
-                       (void)mail_transaction_log_file_lock(file, F_UNLCK);
-               return -1;
+       if (t->appends != NULL ||
+           (t->cache_updates != NULL && t->new_cache_file_seq == 0)) {
+               if (mail_transaction_log_scan_pending(log, t) < 0) {
+                       if (!log->index->log_locked) {
+                               (void)mail_transaction_log_file_lock(file,
+                                                                    F_UNLCK);
+                       }
+                       return -1;
+               }
        }
 
        ret = 0;