changeset 25:55e09f36d23d HEAD

after a few times of trying to access uncached fields, they're cached the next time mailbox is opened. also some mbox fixes.
author Timo Sirainen <tss@iki.fi>
date Sun, 25 Aug 2002 23:50:09 +0300
parents e8de6f485c65
children 91e73c5bb8f3
files src/lib-index/Makefile.am src/lib-index/mail-index-update-cache.c src/lib-index/mail-index-update.c src/lib-index/mail-index.c src/lib-index/mail-index.h src/lib-index/maildir/maildir-update.c src/lib-index/mbox/mbox-append.c src/lib-index/mbox/mbox-from.c src/lib-index/mbox/mbox-index.c src/lib-storage/index/index-fetch.c
diffstat 10 files changed, 246 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/Makefile.am	Sun Aug 25 20:51:10 2002 +0300
+++ b/src/lib-index/Makefile.am	Sun Aug 25 23:50:09 2002 +0300
@@ -13,6 +13,7 @@
         mail-index-fsck.c \
         mail-index-data.c \
         mail-index-update.c \
+        mail-index-update-cache.c \
         mail-index-util.c \
         mail-lockdir.c \
         mail-messageset.c \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-index/mail-index-update-cache.c	Sun Aug 25 23:50:09 2002 +0300
@@ -0,0 +1,45 @@
+/* Copyright (C) 2002 Timo Sirainen */
+
+#include "lib.h"
+#include "mail-index.h"
+
+static int cache_record(MailIndex *index, MailIndexRecord *rec,
+			MailField cache_fields)
+{
+	MailIndexUpdate *update;
+	IOBuffer *inbuf;
+
+	inbuf = index->open_mail(index, rec);
+	if (inbuf == NULL)
+		return FALSE;
+
+	cache_fields &= ~rec->cached_fields;
+
+	update = index->update_begin(index, rec);
+	mail_index_update_headers(update, inbuf, cache_fields, NULL, NULL);
+	return index->update_end(update);
+}
+
+int mail_index_update_cache(MailIndex *index)
+{
+	MailIndexRecord *rec;
+	MailField cache_fields;
+
+	if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
+		return FALSE;
+
+	cache_fields = index->get_header(index)->cache_fields;
+
+	rec = index->lookup(index, 1);
+	while (rec != NULL) {
+		if ((rec->cached_fields & cache_fields) != cache_fields) {
+			if (!cache_record(index, rec, cache_fields))
+				return FALSE;
+		}
+
+		rec = index->next(index, rec);
+	}
+
+	index->header->flags &= ~MAIL_INDEX_FLAG_CACHE_FIELDS;
+	return TRUE;
+}
--- a/src/lib-index/mail-index-update.c	Sun Aug 25 20:51:10 2002 +0300
+++ b/src/lib-index/mail-index-update.c	Sun Aug 25 23:50:09 2002 +0300
@@ -232,8 +232,6 @@
 
 static MailField mail_header_get_field(const char *str, unsigned int len)
 {
-	if (len == 10 && strncasecmp(str, "Message-ID", 10) == 0)
-		return FIELD_TYPE_MESSAGEID;
 	if (len == 7 && strncasecmp(str, "Subject", 7) == 0)
 		return FIELD_TYPE_SUBJECT;
 	if (len == 4 && strncasecmp(str, "From", 4) == 0)
@@ -329,10 +327,10 @@
 }
 
 void mail_index_update_headers(MailIndexUpdate *update, IOBuffer *inbuf,
+                               MailField cache_fields,
 			       MessageHeaderFunc header_func, void *context)
 {
 	HeaderUpdateContext ctx;
-	MailField cache_fields;
 	MessagePart *part;
 	MessageSize hdr_size, body_size;
 	Pool pool;
@@ -344,7 +342,9 @@
 	ctx.header_func = header_func;
 	ctx.context = context;
 
-	cache_fields = update->index->header->cache_fields;
+	if (cache_fields == 0)
+                cache_fields = update->index->header->cache_fields;
+
 	if ((cache_fields & (FIELD_TYPE_BODY|FIELD_TYPE_BODYSTRUCTURE)) != 0) {
 		/* for body / bodystructure, we need need to
 		   fully parse the message */
@@ -360,6 +360,7 @@
 
 		if (cache_fields & FIELD_TYPE_BODY) {
 			t_push();
+			io_buffer_seek(inbuf, 0);
 			value = imap_part_get_bodystructure(pool, &part,
 							    inbuf, FALSE);
 			update->index->update_field(update, FIELD_TYPE_BODY,
@@ -369,6 +370,7 @@
 
 		if (cache_fields & FIELD_TYPE_BODYSTRUCTURE) {
 			t_push();
+			io_buffer_seek(inbuf, 0);
 			value = imap_part_get_bodystructure(pool, &part,
 							    inbuf, TRUE);
 			update->index->update_field(update,
--- a/src/lib-index/mail-index.c	Sun Aug 25 20:51:10 2002 +0300
+++ b/src/lib-index/mail-index.c	Sun Aug 25 23:50:09 2002 +0300
@@ -506,7 +506,7 @@
 		if (hdr.flags & MAIL_INDEX_FLAG_REBUILD) {
 			/* index is corrupted, rebuild */
 			if (!mail_index_rebuild_all(index))
-				return FALSE;
+				break;
 		}
 
 		if (hdr.flags & MAIL_INDEX_FLAG_FSCK) {
@@ -515,6 +515,12 @@
 				break;
 		}
 
+		if (hdr.flags & MAIL_INDEX_FLAG_CACHE_FIELDS) {
+			/* need to update cached fields */
+			if (!mail_index_update_cache(index))
+				break;
+		}
+
 		if (!index->sync(index))
 			break;
 		if (!mail_index_open_init(index, update_recent, &hdr))
@@ -525,8 +531,6 @@
 
 	index->updating = FALSE;
 
-	/* last_recent_uid update, hash or modifylog creation
-	   may create locks */
 	if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
 		failed = TRUE;
 
@@ -894,26 +898,34 @@
 
 	/* first check if the field even could be in the file */
 	if ((rec->cached_fields & field) != field) {
-		/* no, but make sure the future records will have it.
-		   we don't immediately mark the index to cache this field
-		   for old messages as some clients never ask the info again */
-		index->set_cache_fields |= field;
+		if ((index->header->cache_fields & field) == 0) {
+			/* no, but make sure the future records will have it.
+			   we don't immediately mark the index to cache this
+			   field for old messages as some clients never ask
+			   the info again */
+			index->set_cache_fields |= field;
+		} else {
+			/* this is at least the second time it's being asked,
+			   make sure it'll be cached soon. */
+			index->set_flags |= MAIL_INDEX_FLAG_CACHE_FIELDS;
+		}
+
 		return NULL;
 	}
 
 	datarec = mail_index_data_lookup(index->data, rec, field);
-	if (datarec != NULL) {
-		if (mail_index_data_record_verify(index->data, datarec))
-			return datarec->data;
-
-		/* index is corrupted, it will be rebuilt */
-	} else {
-		/* field doesn't exist, make sure it willl be added later
-		   when there's time */
-                index->set_flags |= MAIL_INDEX_FLAG_CACHE_FIELDS;
+	if (datarec == NULL) {
+		/* corrupted, the field should have been there */
+		index->set_flags |= MAIL_INDEX_FLAG_REBUILD;
+		return NULL;
 	}
 
-	return NULL;
+	if (!mail_index_data_record_verify(index->data, datarec)) {
+		/* index is corrupted, it will be rebuilt */
+		return NULL;
+	}
+
+	return datarec->data;
 }
 
 unsigned int mail_index_get_sequence(MailIndex *index, MailIndexRecord *rec)
--- a/src/lib-index/mail-index.h	Sun Aug 25 20:51:10 2002 +0300
+++ b/src/lib-index/mail-index.h	Sun Aug 25 23:50:09 2002 +0300
@@ -37,21 +37,20 @@
 	FIELD_TYPE_ENVELOPE		= 0x0002,
 	FIELD_TYPE_BODY			= 0x0004,
 	FIELD_TYPE_BODYSTRUCTURE	= 0x0008,
-	FIELD_TYPE_MESSAGEID		= 0x0010,
-	FIELD_TYPE_FROM			= 0x0020,
-	FIELD_TYPE_TO			= 0x0040,
-	FIELD_TYPE_CC			= 0x0080,
-	FIELD_TYPE_BCC			= 0x0100,
-	FIELD_TYPE_SUBJECT		= 0x0200,
-	FIELD_TYPE_MD5			= 0x0400,
+	FIELD_TYPE_FROM			= 0x0010,
+	FIELD_TYPE_TO			= 0x0020,
+	FIELD_TYPE_CC			= 0x0040,
+	FIELD_TYPE_BCC			= 0x0080,
+	FIELD_TYPE_SUBJECT		= 0x0100,
+	FIELD_TYPE_MD5			= 0x0200,
 
-	FIELD_TYPE_LAST			= 0x0800,
-	FIELD_TYPE_MAX_BITS		= 11
+	FIELD_TYPE_LAST			= 0x0400,
+	FIELD_TYPE_MAX_BITS		= 10
 } MailField;
 
 #define IS_HEADER_FIELD(field) \
-	(((field) & (FIELD_TYPE_MESSAGEID | FIELD_TYPE_FROM | FIELD_TYPE_TO | \
-		     FIELD_TYPE_CC | FIELD_TYPE_BCC | FIELD_TYPE_SUBJECT)) != 0)
+	(((field) & (FIELD_TYPE_FROM | FIELD_TYPE_TO | FIELD_TYPE_CC | \
+		     FIELD_TYPE_BCC | FIELD_TYPE_SUBJECT)) != 0)
 
 typedef enum {
 	MAIL_LOCK_UNLOCK = 0,
@@ -345,7 +344,9 @@
 int mail_index_rebuild_all(MailIndex *index);
 int mail_index_sync_file(MailIndex *index);
 void mail_index_update_headers(MailIndexUpdate *update, IOBuffer *inbuf,
+                               MailField cache_fields,
 			       MessageHeaderFunc header_func, void *context);
+int mail_index_update_cache(MailIndex *index);
 
 /* Max. mmap()ed size for a message */
 #define MAIL_MMAP_BLOCK_SIZE (1024*256)
--- a/src/lib-index/maildir/maildir-update.c	Sun Aug 25 20:51:10 2002 +0300
+++ b/src/lib-index/maildir/maildir-update.c	Sun Aug 25 23:50:09 2002 +0300
@@ -12,6 +12,6 @@
 
 	inbuf = io_buffer_create_mmap(fd, default_pool,
 				      MAIL_MMAP_BLOCK_SIZE, 0);
-	mail_index_update_headers(update, inbuf, NULL, NULL);
+	mail_index_update_headers(update, inbuf, 0, NULL, NULL);
 	return TRUE;
 }
--- a/src/lib-index/mbox/mbox-append.c	Sun Aug 25 20:51:10 2002 +0300
+++ b/src/lib-index/mbox/mbox-append.c	Sun Aug 25 23:50:09 2002 +0300
@@ -142,7 +142,7 @@
 	inbuf->size = stop_offset;
 	io_buffer_seek(inbuf, start_offset);
 
-	mail_index_update_headers(update, inbuf, mbox_header_func, &ctx);
+	mail_index_update_headers(update, inbuf, 0, mbox_header_func, &ctx);
 
 	inbuf->size = old_size;
 	io_buffer_seek(inbuf, stop_offset);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-index/mbox/mbox-from.c	Sun Aug 25 23:50:09 2002 +0300
@@ -0,0 +1,145 @@
+/* Copyright (C) 2002 Timo Sirainen */
+
+#include "lib.h"
+
+#include <time.h>
+#include <ctype.h>
+
+static const char *weekdays[] = {
+	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+static const char *months[] = {
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+time_t mbox_from_parse_date(const char *msg, unsigned int size)
+{
+	const char *msg_end;
+	struct tm tm;
+	int i;
+
+	i_assert(size > 5);
+
+	/* From <sender> <date> <moreinfo> */
+	if (strncmp(msg, "From ", 5) != 0)
+		return 0;
+
+	msg_end = msg + size;
+
+	/* skip sender */
+	msg += 5;
+	while (*msg != ' ' && msg < msg_end) msg++;
+	while (*msg == ' ' && msg < msg_end) msg++;
+
+	/* next 24 chars are the date in asctime() format,
+	   eg. "Thu Nov 29 22:33:52 2001" */
+	if (msg+24 > msg_end)
+		return 0;
+
+	memset(&tm, 0, sizeof(tm));
+
+	/* skip weekday */
+	msg += 4;
+
+	/* month */
+	for (i = 0; i < 12; i++) {
+		if (strncasecmp(months[i], msg, 3) == 0) {
+			tm.tm_mon = i;
+			break;
+		}
+	}
+
+	if (i == 12 || msg[3] != ' ')
+		return 0;
+	msg += 4;
+
+	/* day */
+	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ' ')
+		return 0;
+	tm.tm_mday = (msg[0]-'0') * 10 + (msg[1]-'0');
+	msg += 3;
+
+	/* hour */
+	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ':')
+		return 0;
+	tm.tm_hour = (msg[0]-'0') * 10 + (msg[1]-'0');
+	msg += 3;
+
+	/* minute */
+	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ':')
+		return 0;
+	tm.tm_min = (msg[0]-'0') * 10 + (msg[1]-'0');
+	msg += 3;
+
+	/* second */
+	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ' ')
+		return 0;
+	tm.tm_sec = (msg[0]-'0') * 10 + (msg[1]-'0');
+	msg += 3;
+
+	/* year */
+	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) ||
+	    !i_isdigit(msg[2]) || !i_isdigit(msg[3]))
+		return 0;
+	tm.tm_year = (msg[0]-'0') * 1000 + (msg[1]-'0') * 100 +
+		(msg[2]-'0') * 10 + (msg[3]-'0') - 1900;
+
+	tm.tm_isdst = -1;
+	return mktime(&tm);
+}
+
+const char *mbox_from_create(const char *sender, time_t time)
+{
+	struct tm *tm;
+	char *ret, *p;
+	int len, year;
+
+	len = strlen(sender);
+	ret = t_malloc(len + 24 + 1);
+	memcpy(ret, sender, len);
+
+	/* we could use simply asctime(), but i18n etc. may break it.
+	   Example: "Thu Nov 29 22:33:52 2001" */
+	tm = localtime(&time);
+	p = ret + len;
+
+	/* week day */
+	strcpy(p, weekdays[tm->tm_wday]); p += 3;
+	*p++ = ' ';
+
+	/* month */
+	strcpy(p, months[tm->tm_mon]); p += 3;
+	*p++ = ' ';
+
+	/* day */
+	*p++ = (tm->tm_mday / 10) + '0';
+	*p++ = (tm->tm_mday % 10) + '0';
+	*p++ = ' ';
+
+	/* hour */
+	*p++ = (tm->tm_hour / 10) + '0';
+	*p++ = (tm->tm_hour % 10) + '0';
+	*p++ = ':';
+
+	/* minute */
+	*p++ = (tm->tm_min / 10) + '0';
+	*p++ = (tm->tm_min % 10) + '0';
+	*p++ = ':';
+
+	/* second */
+	*p++ = (tm->tm_sec / 10) + '0';
+	*p++ = (tm->tm_sec % 10) + '0';
+	*p++ = ' ';
+
+	/* year */
+	year = tm->tm_year + 1900;
+	*p++ = (year / 1000) + '0';
+	*p++ = ((year / 100) % 10) + '0';
+	*p++ = ((year / 10) % 10) + '0';
+	*p++ = (year % 10) + '0';
+
+	*p++ = '\0';
+	return ret;
+}
--- a/src/lib-index/mbox/mbox-index.c	Sun Aug 25 20:51:10 2002 +0300
+++ b/src/lib-index/mbox/mbox-index.c	Sun Aug 25 23:50:09 2002 +0300
@@ -27,11 +27,14 @@
 		case 'F':
 			flags |= MAIL_FLAGGED;
 			break;
+		case 'D':
+			flags |= MAIL_DELETED;
+			break;
 		case 'R':
 			flags |= MAIL_SEEN;
 			break;
-		case 'D':
-			flags |= MAIL_DELETED;
+		case 'T':
+			flags |= MAIL_DRAFT;
 			break;
 		}
 	}
--- a/src/lib-storage/index/index-fetch.c	Sun Aug 25 20:51:10 2002 +0300
+++ b/src/lib-storage/index/index-fetch.c	Sun Aug 25 23:50:09 2002 +0300
@@ -199,11 +199,8 @@
 	IOBuffer *inbuf;
 
 	inbuf = ctx->index->open_mail(ctx->index, rec);
-	if (inbuf == NULL) {
-		i_error("Couldn't open message UID %u (index %s)",
-			rec->uid, ctx->index->filepath);
+	if (inbuf == NULL)
 		return FALSE;
-	}
 
 	if (MSG_HAS_VALID_CRLF_DATA(rec)) {
 		imap_msgcache_message(ctx->cache, rec->uid,