]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-index: Fix updating mail_index_header.day_first_uid
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 15 Feb 2017 20:13:12 +0000 (22:13 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 17 Feb 2017 09:33:25 +0000 (11:33 +0200)
If user received a mail every day, the day_first_uid wasn't being updated.
This caused wrong caching decisions to be made in dovecot.index.cache:

 - Accessing >1 week old emails should have changed caching decision from
"tmp" to "yes". This might not have happened, although as long as
day_first_uid[7] pointed to an existing mail and email client accessed
all the mails, this wouldn't have changed anything.

 - Cache compression is supposed to drop >1 week old mails when caching
decision is "tmp". Not enough mails were being dropped because
day_first_uid[7] pointed to a much older than 1 week old mails.

Also added a unit test to make sure this works.

Broken by d9ee2f9fb3ef7b9391bfeeff1b374aead51667aa

src/lib-index/mail-index-transaction-update.c
src/lib-index/test-mail-index-transaction-update.c

index 8b1bd7302d31a5c30ce81ec5cf9bb1ad9a7eb7ea..0e9a570e178d60f106f1e7ff25ed7bf38a0d48d7 100644 (file)
@@ -148,7 +148,7 @@ void mail_index_update_day_headers(struct mail_index_transaction *t,
 
        /* @UNSAFE: move days forward and fill the missing days with old
           day_first_uid[0]. */
-       if (days > 1 && days < max_days)
+       if (days > 0 && days < max_days)
                memmove(hdr.day_first_uid + days, hdr.day_first_uid,
                        (max_days - days) * sizeof(hdr.day_first_uid[0]));
        for (i = 1; i < days; i++)
index d45d402da03026a882eb750417779ff5f1a3ec27..11c4c84bf633061d7344655927c67ceec2138a44 100644 (file)
@@ -6,6 +6,7 @@
 #include "mail-index-private.h"
 #include "mail-index-transaction-private.h"
 
+#include <time.h>
 
 static struct mail_index_header hdr;
 static struct mail_index_record rec;
@@ -586,6 +587,74 @@ static void test_mail_index_expunge(void)
        mail_index_transaction_cleanup(t);
 }
 
+static void test_mail_index_update_day_first_uid(void)
+{
+       struct {
+               uint32_t now;
+               uint32_t old_day_stamp;
+               uint32_t new_day_stamp;
+               uint32_t new_day_first_uid[8];
+       } tests[] = {
+               /* 1487116800 = 2017-02-15 00:00:00 UTC */
+               { 1487116800, 1487116800, 1487116800, { 8, 7, 6, 5, 4, 3, 2, 1 } },
+               /* still same day */
+               { 1487116800+3600*24-1, 1487116800, 1487116800, { 8, 7, 6, 5, 4, 3, 2, 1 } },
+               /* one day earlier */
+               { 1487116800-1, 1487116800, 1487116800, { 8, 7, 6, 5, 4, 3, 2, 1 } },
+               /* next day */
+               { 1487116800+3600*24, 1487116800, 1487116800+3600*24, { 9, 8, 7, 6, 5, 4, 3, 2 } },
+               { 1487116800+3600*24*2-1, 1487116800, 1487116800+3600*24, { 9, 8, 7, 6, 5, 4, 3, 2 } },
+               /* 2 days */
+               { 1487116800+3600*24*2, 1487116800, 1487116800+3600*24*2, { 9, 8, 8, 7, 6, 5, 4, 3 } },
+               /* 3 days */
+               { 1487116800+3600*24*3, 1487116800, 1487116800+3600*24*3, { 9, 8, 8, 8, 7, 6, 5, 4 } },
+               /* 4 days */
+               { 1487116800+3600*24*4, 1487116800, 1487116800+3600*24*4, { 9, 8, 8, 8, 8, 7, 6, 5 } },
+               /* 5 days */
+               { 1487116800+3600*24*5, 1487116800, 1487116800+3600*24*5, { 9, 8, 8, 8, 8, 8, 7, 6 } },
+               /* 6 days */
+               { 1487116800+3600*24*6, 1487116800, 1487116800+3600*24*6, { 9, 8, 8, 8, 8, 8, 8, 7 } },
+               /* 7 days */
+               { 1487116800+3600*24*7, 1487116800, 1487116800+3600*24*7, { 9, 8, 8, 8, 8, 8, 8, 8 } },
+               /* 8 days */
+               { 1487116800+3600*24*8, 1487116800, 1487116800+3600*24*8, { 9, 8, 8, 8, 8, 8, 8, 8 } },
+               /* 366 days */
+               { 1487116800+3600*24*366, 1487116800, 1487116800+3600*24*366, { 9, 8, 8, 8, 8, 8, 8, 8 } },
+       };
+       struct mail_index_transaction *t;
+       struct mail_index_record *rec;
+       unsigned int i, j;
+
+       test_begin("mail index update day first uid");
+
+       hdr.messages_count = 10;
+       t = mail_index_transaction_new();
+       t->view = t_new(struct mail_index_view, 1);
+       t->view->map = t_new(struct mail_index_map, 1);
+
+       t_array_init(&t->appends, 1);
+       rec = array_append_space(&t->appends);
+       rec->uid = 9;
+
+       for (i = 0; i < N_ELEMENTS(tests); i++) {
+               i_zero(&hdr);
+               for (j = 0; j < N_ELEMENTS(hdr.day_first_uid); j++)
+                       hdr.day_first_uid[j] = 8-j;
+               hdr.day_stamp = tests[i].old_day_stamp + timezone;
+               memcpy(t->post_hdr_change, &hdr, sizeof(hdr));
+               mail_index_update_day_headers(t, tests[i].now + timezone);
+
+               struct mail_index_header new_hdr;
+               memcpy(&new_hdr, t->post_hdr_change, sizeof(new_hdr));
+               test_assert_idx(new_hdr.day_stamp == tests[i].new_day_stamp + timezone, i);
+               test_assert_idx(memcmp(new_hdr.day_first_uid,
+                                      tests[i].new_day_first_uid,
+                                      sizeof(uint32_t) * 8) == 0, i);
+       }
+
+       test_end();
+}
+
 int main(void)
 {
        static void (*test_functions[])(void) = {
@@ -599,7 +668,9 @@ int main(void)
                test_mail_index_transaction_get_flag_update_pos,
                test_mail_index_modseq_update,
                test_mail_index_expunge,
+               test_mail_index_update_day_first_uid,
                NULL
        };
+       tzset();
        return test_run(test_functions);
 }