]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Ignore new mail appends if they're already in transaction log.
authorTimo Sirainen <tss@iki.fi>
Thu, 29 Apr 2004 12:49:27 +0000 (15:49 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 29 Apr 2004 12:49:27 +0000 (15:49 +0300)
--HG--
branch : HEAD

src/lib-index/mail-index-sync-update.c
src/lib-index/mail-transaction-log.c

index 1db0c3f083ca6a16272617e7cd9bd7f8d02b368b..ec08c7dfa525ec4a10479828c1edc0bb75082e46 100644 (file)
@@ -151,10 +151,6 @@ static int mail_index_sync_appends(struct mail_index_update_ctx *ctx,
                 mail_index_header_update_lowwaters(&ctx->hdr, &appends[i]);
 
                if (appends[i].uid < next_uid) {
-                       /* FIXME: should we rather just update the record?
-                          this can actually happen if append was written to
-                          transaction log but index wasn't updated, then
-                          another sync wrote it again.. */
                        mail_transaction_log_view_set_corrupted(ctx->log_view,
                                "Append with UID %u, but next_uid = %u",
                                appends[i].uid, next_uid);
index 2c12bc4028d0201a07eb40dcb7bf74acb53a9cd6..f1faaaf868567d0121d4afac50767552863defa3 100644 (file)
@@ -877,6 +877,73 @@ mail_transaction_log_fix_sequences(struct mail_transaction_log *log,
        return 0;
 }
 
+static int mail_transaction_log_fix_appends(struct mail_transaction_log *log,
+                                           struct mail_index_transaction *t)
+{
+       struct mail_transaction_log_view *sync_view;
+       const struct mail_index_record *old, *old_end;
+       struct mail_index_record *appends, *end, *rec, *dest;
+       const struct mail_transaction_header *hdr;
+       const void *data;
+       size_t size;
+       int ret, deleted = FALSE;
+
+       if (t->appends == NULL)
+               return 0;
+
+       appends = buffer_get_modifyable_data(t->appends, &size);
+       end = PTR_OFFSET(appends, size);
+
+       if (appends == end)
+               return 0;
+
+       /* 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;
+
+               old = data;
+               old_end = CONST_PTR_OFFSET(old, hdr->size);
+               for (; old != old_end; old++) {
+                       /* appends are sorted */
+                       for (rec = appends; rec != end; rec++) {
+                               if (rec->uid >= old->uid) {
+                                       if (rec->uid == old->uid) {
+                                               rec->uid = 0;
+                                               deleted = TRUE;
+                                       }
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (deleted) {
+               /* compress deleted appends away */
+               for (rec = dest = appends; rec != end; rec++) {
+                       if (rec->uid != 0)
+                               dest++;
+                       else if (rec != dest)
+                               *rec = *dest;
+               }
+               buffer_set_used_size(t->appends,
+                                    (char *)dest - (char *)appends);
+       }
+
+       mail_transaction_log_view_close(sync_view);
+       return ret;
+}
+
 static int
 log_append_buffer(struct mail_transaction_log_file *file, const buffer_t *buf,
                  enum mail_transaction_type type, int external)
@@ -944,7 +1011,8 @@ int mail_transaction_log_append(struct mail_index_transaction *t,
        file = log->head;
        append_offset = file->hdr.used_size;
 
-       if (mail_transaction_log_fix_sequences(log, t) < 0) {
+       if (mail_transaction_log_fix_sequences(log, t) < 0 ||
+           mail_transaction_log_fix_appends(log, t) < 0) {
                if (!log->index->log_locked)
                        (void)mail_transaction_log_file_lock(file, F_UNLCK);
                return -1;