]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dbox, maildir: When copying messages, copy the cached fields also.
authorTimo Sirainen <tss@iki.fi>
Wed, 20 Oct 2010 15:07:03 +0000 (16:07 +0100)
committerTimo Sirainen <tss@iki.fi>
Wed, 20 Oct 2010 15:07:03 +0000 (16:07 +0100)
Copy only fields whose caching decision is not "no" in the destination mailbox.

src/lib-storage/index/dbox-multi/mdbox-save.c
src/lib-storage/index/dbox-single/sdbox-copy.c
src/lib-storage/index/index-storage.c
src/lib-storage/index/index-storage.h
src/lib-storage/index/maildir/maildir-copy.c
src/lib-storage/index/maildir/maildir-save.c
src/lib-storage/index/maildir/maildir-storage.h

index d3eb9fd99391acecfeab432aca60470454572695..1f69f1b678c0ecbacc5c8053f0915f4406b5193e 100644 (file)
@@ -434,6 +434,7 @@ int mdbox_copy(struct mail_save_context *_ctx, struct mail *mail)
                mail_index_update_ext(ctx->ctx.trans, ctx->ctx.seq,
                                      ctx->mbox->guid_ext_id, data, NULL);
        }
+       index_copy_cache_fields(_ctx, mail, ctx->ctx.seq);
 
        save_mail = array_append_space(&ctx->mails);
        save_mail->seq = ctx->ctx.seq;
index d5a2cb9bfb145460b43573cc2eaf63a2953d093c..e71a789a0ffdd4b8d609caa2fb9906194ee11d16 100644 (file)
@@ -127,6 +127,8 @@ sdbox_copy_hardlink(struct mail_save_context *_ctx, struct mail *mail)
        }
 
        dbox_save_add_to_index(ctx);
+       index_copy_cache_fields(_ctx, mail, ctx->seq);
+
        sdbox_save_add_file(_ctx, dest_file);
        if (_ctx->dest_mail != NULL) {
                mail_set_seq(_ctx->dest_mail, ctx->seq);
index b5c0a3b785425152b4f6801588faf31d4154a1a3..17e3a2a5bcd085dab7fbedbbc6302a8504014bb3 100644 (file)
@@ -600,3 +600,58 @@ void index_save_context_free(struct mail_save_context *ctx)
        i_free_and_null(ctx->pop3_uidl);
        index_attachment_save_free(ctx);
 }
+
+static void
+mail_copy_cache_field(struct mail_save_context *ctx, struct mail *src_mail,
+                     uint32_t dest_seq, const char *name, buffer_t *buf)
+{
+       struct mailbox_transaction_context *dest_trans = ctx->transaction;
+       struct index_transaction_context *dest_itrans =
+               (struct index_transaction_context *)dest_trans;
+       struct index_transaction_context *src_itrans =
+               (struct index_transaction_context *)src_mail->transaction;
+       const struct mail_cache_field *dest_field;
+       unsigned int src_field_idx, dest_field_idx;
+
+       src_field_idx = mail_cache_register_lookup(src_mail->box->cache, name);
+       i_assert(src_field_idx != -1U);
+
+       dest_field_idx = mail_cache_register_lookup(dest_trans->box->cache, name);
+       if (dest_field_idx == -1U) {
+               /* unknown field */
+               return;
+       }
+       dest_field = mail_cache_register_get_field(dest_trans->box->cache,
+                                                  dest_field_idx);
+       if ((dest_field->decision &
+            ~MAIL_CACHE_DECISION_FORCED) == MAIL_CACHE_DECISION_NO) {
+               /* field not wanted in destination mailbox */
+               return;
+       }
+
+       buffer_set_used_size(buf, 0);
+       if (mail_cache_lookup_field(src_itrans->cache_view, buf,
+                                   src_mail->seq, src_field_idx) > 0) {
+               mail_cache_add(dest_itrans->cache_trans, dest_seq,
+                              dest_field_idx, buf->data, buf->used);
+       }
+}
+
+void index_copy_cache_fields(struct mail_save_context *ctx,
+                            struct mail *src_mail, uint32_t dest_seq)
+{
+       T_BEGIN {
+               struct mailbox_status src_status;
+               const char *const *namep;
+               buffer_t *buf;
+
+               index_storage_get_status(src_mail->box, STATUS_CACHE_FIELDS,
+                                        &src_status);
+
+               buf = buffer_create_dynamic(pool_datastack_create(), 1024);
+               array_foreach(src_status.cache_fields, namep) {
+                       mail_copy_cache_field(ctx, src_mail, dest_seq,
+                                             *namep, buf);
+               }
+       } T_END;
+}
index 0d46ae04843301436183503aef104e7896d2911b..e548f617831f291afb0af4af89fd1dbfb7c263ee 100644 (file)
@@ -166,6 +166,8 @@ int index_transaction_commit(struct mailbox_transaction_context *t,
                             struct mail_transaction_commit_changes *changes_r);
 void index_transaction_rollback(struct mailbox_transaction_context *t);
 void index_save_context_free(struct mail_save_context *ctx);
+void index_copy_cache_fields(struct mail_save_context *ctx,
+                            struct mail *src_mail, uint32_t dest_seq);
 
 bool index_keyword_array_cmp(const ARRAY_TYPE(keyword_indexes) *k1,
                             const ARRAY_TYPE(keyword_indexes) *k2);
index 080f85893b537ccb3868b3bd1e7d96cd4a374a87..2703ea173628e1f925a7c4b772f668568072fde5 100644 (file)
@@ -104,7 +104,7 @@ maildir_copy_hardlink(struct mail_save_context *ctx, struct mail *mail)
        }
 
        /* hardlinked to tmp/, treat as normal copied mail */
-       mf = maildir_save_add(ctx, dest_fname);
+       mf = maildir_save_add(ctx, dest_fname, mail);
        if (mail_get_special(mail, MAIL_FETCH_GUID, &guid) == 0) {
                if (*guid != '\0')
                        maildir_save_set_dest_basename(ctx, mf, guid);
index b272d482cad0abb7a95891236af318512e1e5325..8960181fe0d5f42c4833e3523c4d8cd723983e20 100644 (file)
@@ -140,7 +140,8 @@ maildir_save_transaction_init(struct mailbox_transaction_context *t)
 }
 
 struct maildir_filename *
-maildir_save_add(struct mail_save_context *_ctx, const char *tmp_fname)
+maildir_save_add(struct mail_save_context *_ctx, const char *tmp_fname,
+                struct mail *src_mail)
 {
        struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
        struct maildir_filename *mf;
@@ -212,8 +213,9 @@ maildir_save_add(struct mail_save_context *_ctx, const char *tmp_fname)
        _ctx->dest_mail->saving = TRUE;
 
        if (ctx->input == NULL) {
-               /* FIXME: copying with hardlinking. we could copy the
-                  cached data directly */
+               /* copying with hardlinking. */
+               i_assert(src_mail != NULL);
+               index_copy_cache_fields(_ctx, src_mail, ctx->seq);
                ctx->cur_dest_mail = NULL;
        } else {
                input = index_mail_cache_parse_init(_ctx->dest_mail,
@@ -404,7 +406,7 @@ int maildir_save_begin(struct mail_save_context *_ctx, struct istream *input)
                                ctx->input = i_stream_create_crlf(input);
                        else
                                ctx->input = i_stream_create_lf(input);
-                       mf = maildir_save_add(_ctx, fname);
+                       mf = maildir_save_add(_ctx, fname, NULL);
                        if (_ctx->guid != NULL) {
                                maildir_save_set_dest_basename(_ctx, mf,
                                                               _ctx->guid);
index 794b4fed09b0bb129d29d2db4f5086426f6be062..8562eec994a58d637acd88396de89a25a22c5f4c 100644 (file)
@@ -120,7 +120,8 @@ int maildir_save_finish(struct mail_save_context *ctx);
 void maildir_save_cancel(struct mail_save_context *ctx);
 
 struct maildir_filename *
-maildir_save_add(struct mail_save_context *_ctx, const char *tmp_fname);
+maildir_save_add(struct mail_save_context *_ctx, const char *tmp_fname,
+                struct mail *src_mail);
 void maildir_save_set_dest_basename(struct mail_save_context *ctx,
                                    struct maildir_filename *mf,
                                    const char *basename);