From: Timo Sirainen Date: Wed, 15 Feb 2017 20:13:12 +0000 (+0200) Subject: lib-index: Fix updating mail_index_header.day_first_uid X-Git-Tag: 2.3.0.rc1~2088 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dfa4b048ec9a174a42d6668e94501db2fb70793a;p=thirdparty%2Fdovecot%2Fcore.git lib-index: Fix updating mail_index_header.day_first_uid 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 --- diff --git a/src/lib-index/mail-index-transaction-update.c b/src/lib-index/mail-index-transaction-update.c index 9213d88243..e7f903e48c 100644 --- a/src/lib-index/mail-index-transaction-update.c +++ b/src/lib-index/mail-index-transaction-update.c @@ -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++) diff --git a/src/lib-index/test-mail-index-transaction-update.c b/src/lib-index/test-mail-index-transaction-update.c index 0e5dc7a1bb..59bc76a076 100644 --- a/src/lib-index/test-mail-index-transaction-update.c +++ b/src/lib-index/test-mail-index-transaction-update.c @@ -6,6 +6,7 @@ #include "mail-index-private.h" #include "mail-index-transaction-private.h" +#include 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 (*const 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); }