changeset 21571:3538545077cb

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
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Wed, 15 Feb 2017 22:13:12 +0200
parents d1860907acf9
children bd590ae82f96
files src/lib-index/mail-index-transaction-update.c src/lib-index/test-mail-index-transaction-update.c
diffstat 2 files changed, 72 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-index-transaction-update.c	Wed Feb 15 22:12:15 2017 +0200
+++ b/src/lib-index/mail-index-transaction-update.c	Wed Feb 15 22:13:12 2017 +0200
@@ -148,7 +148,7 @@
 
 	/* @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++)
--- a/src/lib-index/test-mail-index-transaction-update.c	Wed Feb 15 22:12:15 2017 +0200
+++ b/src/lib-index/test-mail-index-transaction-update.c	Wed Feb 15 22:13:12 2017 +0200
@@ -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 @@
 	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 @@
 		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);
 }