]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Delay creating mail event until mail_event() is called
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 29 Nov 2021 14:46:04 +0000 (15:46 +0100)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 21 Dec 2021 10:06:58 +0000 (10:06 +0000)
Mails can be accessed a lot. The event handling code takes up a lot of CPU,
but most of the time the created event wasn't actually used for anything.

src/lib-storage/index/index-mail.c
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage.h
src/lib-storage/mail.c

index ff2ed246ca27ea52d8b3642677f88bd0a29f907c..238c95b1fb2795b98b84f8ed4d4ddcf97e02c971 100644 (file)
@@ -1753,14 +1753,6 @@ index_mail_alloc(struct mailbox_transaction_context *t,
        return &mail->mail.mail;
 }
 
-static void index_mail_init_event(struct mail *mail)
-{
-       struct mail_private *p = (struct mail_private *)mail;
-
-       p->_event = event_create(mail->box->event);
-       event_add_category(p->_event, &event_category_mail);
-}
-
 void index_mail_init(struct index_mail *mail,
                     struct mailbox_transaction_context *t,
                     enum mail_fetch_field wanted_fields,
@@ -1775,7 +1767,6 @@ void index_mail_init(struct index_mail *mail,
        mail->mail.v = *t->box->mail_vfuncs;
        mail->mail.mail.box = t->box;
        mail->mail.mail.transaction = t;
-       index_mail_init_event(&mail->mail.mail);
        t->mail_ref_count++;
        if (data_pool != NULL)
                mail->mail.data_pool = data_pool;
@@ -2115,36 +2106,9 @@ void index_mail_update_access_parts_post(struct mail *_mail)
        }
 }
 
-static bool index_mail_get_age_days(struct mail *mail, int *days_r)
-{
-       int age_days;
-       const struct mail_index_header *hdr =
-               mail_index_get_header(mail->transaction->view);
-       int n_days = N_ELEMENTS(hdr->day_first_uid);
-
-       for (age_days = 0; age_days < n_days; age_days++) {
-               if (mail->uid >= hdr->day_first_uid[age_days])
-                       break;
-       }
-
-       if (age_days == n_days) {
-               /* mail is too old, cannot determine its age from
-                  day_first_uid[]. */
-               return FALSE;
-       }
-
-       if (hdr->day_stamp != 0) {
-               /* offset for hdr->day_stamp */
-               age_days += (ioloop_time - hdr->day_stamp) / (3600 * 24);
-       }
-       *days_r = age_days;
-       return TRUE;
-}
-
 void index_mail_set_seq(struct mail *_mail, uint32_t seq, bool saving)
 {
        struct index_mail *mail = INDEX_MAIL(_mail);
-       int age_days;
 
        if (mail->data.seq == seq) {
                if (!saving)
@@ -2163,17 +2127,9 @@ void index_mail_set_seq(struct mail *_mail, uint32_t seq, bool saving)
                              &mail->mail.mail.uid);
 
        /* Recreate the mail event when changing mails. Even though the same
-          mail struct is reused, they are practically different mails. */
-       event_unref(&mail->mail._event);
-       index_mail_init_event(_mail);
-       event_add_int(mail->mail._event, "seq", _mail->seq);
-       event_add_int(mail->mail._event, "uid", _mail->uid);
-       /* Add mail age field to event. */
-       if (index_mail_get_age_days(_mail, &age_days))
-               event_add_int(mail->mail._event, "mail_age_days", age_days);
-
-       event_set_append_log_prefix(mail->mail._event, t_strdup_printf(
-               "%sUID %u: ", saving ? "saving " : "", _mail->uid));
+          mail struct is reused, they are practically different mails. The
+          event should have already been freed by close(). */
+       i_assert(mail->mail._event == NULL);
 
        if (mail_index_view_is_inconsistent(_mail->transaction->view)) {
                mail_set_expunged(&mail->mail.mail);
index f5f569c36e94fc364e3752b6bc3dca8abd385baf..bc462bbd222cd1bdaff84e0bb3fb1d8323987410 100644 (file)
@@ -578,6 +578,7 @@ struct mail_private {
           allows mail_log plugin to log the copy operation using the original
           mailbox name. */
        struct mail *vmail;
+       /* Event is created lazily. Use mail_event() to access it. */
        struct event *_event;
 
        uint32_t seq_pvt;
index 17e724359e226722584a0fdac95b709bd4eb09d2..64e0e49a34f88f192e0c3bf31da3754e3bbe2787 100644 (file)
@@ -871,7 +871,8 @@ void mail_add_temp_wanted_fields(struct mail *mail,
                                 struct mailbox_header_lookup_ctx *headers)
        ATTR_NULL(3);
 
-/* Returns mail's event. */
+/* Returns mail's event. This lazily creates the event when called for the
+   first time for the mail. */
 struct event *mail_event(struct mail *mail);
 /* Returns message's flags */
 enum mail_flags mail_get_flags(struct mail *mail);
index 366670330a24a7e8adcb3c602f73fa055cb7e572..272db1e1e4a74529aea40bc0561a5e930ef1d69d 100644 (file)
@@ -99,17 +99,56 @@ void mail_add_temp_wanted_fields(struct mail *mail,
        p->v.add_temp_wanted_fields(mail, fields, headers);
 }
 
+static bool index_mail_get_age_days(struct mail *mail, int *days_r)
+{
+       int age_days;
+       const struct mail_index_header *hdr =
+               mail_index_get_header(mail->transaction->view);
+       int n_days = N_ELEMENTS(hdr->day_first_uid);
+
+       for (age_days = 0; age_days < n_days; age_days++) {
+               if (mail->uid >= hdr->day_first_uid[age_days])
+                       break;
+       }
+
+       if (age_days == n_days) {
+               /* mail is too old, cannot determine its age from
+                  day_first_uid[]. */
+               return FALSE;
+       }
+
+       if (hdr->day_stamp != 0) {
+               /* offset for hdr->day_stamp */
+               age_days += (ioloop_time - hdr->day_stamp) / (3600 * 24);
+       }
+       *days_r = age_days;
+       return TRUE;
+}
+
 void mail_event_create(struct mail *mail)
 {
        struct mail_private *p = (struct mail_private *)mail;
+       int age_days;
+
+       if (p->_event != NULL)
+               return;
+       p->_event = event_create(mail->box->event);
+       event_add_category(p->_event, &event_category_mail);
+       event_add_int(p->_event, "seq", mail->seq);
+       event_add_int(p->_event, "uid", mail->uid);
+       /* Add mail age field to event. */
+       if (index_mail_get_age_days(mail, &age_days))
+               event_add_int(p->_event, "mail_age_days", age_days);
 
-       i_assert(p->_event != NULL);
+       event_set_append_log_prefix(p->_event, t_strdup_printf(
+               "%sUID %u: ", mail->saving ? "saving " : "", mail->uid));
 }
 
 struct event *mail_event(struct mail *mail)
 {
        struct mail_private *p = (struct mail_private *)mail;
 
+       mail_event_create(mail);
        return p->_event;
 }