Skip to content

Commit

Permalink
lib-index: Fix updating mail_index_header.day_first_uid
Browse files Browse the repository at this point in the history
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 d9ee2f9
  • Loading branch information
sirainen committed Feb 17, 2017
1 parent fbfcbf3 commit 9d2f3c3
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/lib-index/mail-index-transaction-update.c
Expand Up @@ -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++)
Expand Down
71 changes: 71 additions & 0 deletions src/lib-index/test-mail-index-transaction-update.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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) = {
Expand All @@ -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);
}

0 comments on commit 9d2f3c3

Please sign in to comment.