[dovecot-cvs] dovecot/src/imap cmd-copy.c,1.12,1.13 cmd-fetch.c,1.18,1.19 cmd-store.c,1.17,1.18 imap-fetch-body-section.c,1.14,1.15 imap-fetch.c,1.9,1.10 imap-fetch.h,1.3,1.4 imap-search.c,1.3,1.4 imap-thread.c,1.3,1.4

cras at procontrol.fi cras at procontrol.fi
Thu Aug 7 00:16:03 EEST 2003


Update of /home/cvs/dovecot/src/imap
In directory danu:/tmp/cvs-serv13163/imap

Modified Files:
	cmd-copy.c cmd-fetch.c cmd-store.c imap-fetch-body-section.c 
	imap-fetch.c imap-fetch.h imap-search.c imap-thread.c 
Log Message:
Index cache file rewrite. It's not finished yet and mbox support is
completely broken. But it's getting difficult to maintain outside cvs :)



Index: cmd-copy.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-copy.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- cmd-copy.c	27 Jul 2003 04:48:32 -0000	1.12
+++ cmd-copy.c	6 Aug 2003 20:15:30 -0000	1.13
@@ -12,7 +12,8 @@
 	int failed = FALSE;
 
 	fetch_ctx = box->fetch_init(box, MAIL_FETCH_STREAM_HEADER |
-				    MAIL_FETCH_STREAM_BODY, messageset, uidset);
+				    MAIL_FETCH_STREAM_BODY, NULL,
+				    messageset, uidset);
 	if (fetch_ctx == NULL)
 		return FALSE;
 

Index: cmd-fetch.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-fetch.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- cmd-fetch.c	27 Jul 2003 04:48:32 -0000	1.18
+++ cmd-fetch.c	6 Aug 2003 20:15:30 -0000	1.19
@@ -70,7 +70,10 @@
 	}
 
 	if (strncmp(section, "HEADER", 6) == 0) {
-		*fetch_data |= MAIL_FETCH_STREAM_HEADER;
+		/* exact header matches could be cached */
+		if (strncmp(section, "HEADER.FIELDS ", 14) != 0)
+			*fetch_data |= MAIL_FETCH_STREAM_HEADER;
+
 		if (check_header_section(section+6))
 			return TRUE;
 	} else if (*section >= '0' && *section <= '9') {

Index: cmd-store.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-store.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- cmd-store.c	27 Jul 2003 04:48:32 -0000	1.17
+++ cmd-store.c	6 Aug 2003 20:15:30 -0000	1.18
@@ -96,9 +96,16 @@
 	/* and update the flags */
 	box = client->mailbox;
 
-	failed = !box->lock(box, MAILBOX_LOCK_FLAGS | MAILBOX_LOCK_READ);
+	if (!box->is_readonly(box)) {
+		/* read-only, don't every try to get write locking */
+		failed = FALSE;
+	} else {
+		failed = !box->lock(box, MAILBOX_LOCK_FLAGS |
+				    MAILBOX_LOCK_READ);
+	}
+
 	fetch_ctx = failed ? NULL :
-		box->fetch_init(box, MAIL_FETCH_FLAGS,
+		box->fetch_init(box, MAIL_FETCH_FLAGS, NULL,
 				messageset, client->cmd_uid);
 	if (fetch_ctx == NULL)
 		failed = TRUE;

Index: imap-fetch-body-section.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-fetch-body-section.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- imap-fetch-body-section.c	4 Jun 2003 15:57:58 -0000	1.14
+++ imap-fetch-body-section.c	6 Aug 2003 20:15:30 -0000	1.15
@@ -20,6 +20,9 @@
 #define MAX_HEADER_BUFFER_SIZE (32*1024)
 
 struct fetch_header_field_context {
+        struct imap_fetch_context *fetch_ctx;
+	struct mail *mail;
+
 	buffer_t *dest;
 	struct ostream *output;
 	uoff_t dest_size;
@@ -116,26 +119,6 @@
 	return ret >= 0;
 }
 
-static const char **get_fields_array(const char *fields)
-{
-	const char **field_list, **field;
-
-	while (*fields == ' ')
-		fields++;
-	if (*fields == '(')
-		fields++;
-
-	field_list = t_strsplit(fields, " )");
-
-	/* array ends at ")" element */
-	for (field = field_list; *field != NULL; field++) {
-		if (strcmp(*field, ")") == 0)
-			*field = NULL;
-	}
-
-	return field_list;
-}
-
 static int header_match(const char *const *fields,
 			const char *name, size_t size)
 {
@@ -252,10 +235,16 @@
 	struct message_header_line *hdr;
 
 	if (strncmp(section, "HEADER.FIELDS ", 14) == 0) {
-		ctx->fields = get_fields_array(section + 14);
+		ctx->fields = imap_fetch_get_body_fields(section + 14);
 		ctx->match_func = header_match;
+
+		if (ctx->fetch_ctx->body_fetch_from_cache) {
+			input = ctx->mail->get_headers(ctx->mail, ctx->fields);
+			if (input == NULL)
+				return FALSE;
+		}
 	} else if (strncmp(section, "HEADER.FIELDS.NOT ", 18) == 0) {
-		ctx->fields = get_fields_array(section + 18);
+		ctx->fields = imap_fetch_get_body_fields(section + 18);
 		ctx->match_func = header_match_not;
 	} else if (strcmp(section, "MIME") == 0) {
 		/* Mime-Version + Content-* fields */
@@ -329,18 +318,21 @@
 	   the size first and then send the data directly to output stream. */
 
 	memset(&hdr_ctx, 0, sizeof(hdr_ctx));
+	hdr_ctx.mail = mail;
+	hdr_ctx.fetch_ctx = ctx;
 	hdr_ctx.skip = body->skip;
 	hdr_ctx.max_size = body->max_size;
 	hdr_ctx.fix_nuls = !mail->has_no_nuls;
 
 	failed = FALSE;
-	start_offset = input->v_offset;
+	start_offset = input == NULL ? 0 : input->v_offset;
 
 	t_push();
 
 	/* first pass, we need at least the size */
 	if (size->virtual_size > MAX_HEADER_BUFFER_SIZE &&
-	    body->max_size > MAX_HEADER_BUFFER_SIZE) {
+	    body->max_size > MAX_HEADER_BUFFER_SIZE &&
+	    !ctx->body_fetch_from_cache) {
 		if (!fetch_header_fields(input, header_section, &hdr_ctx))
 			failed = TRUE;
 
@@ -392,9 +384,13 @@
 	struct istream *stream;
 	struct message_size hdr_size;
 
-	stream = mail->get_stream(mail, &hdr_size, NULL);
-	if (stream == NULL)
-		return FALSE;
+	if (ctx->body_fetch_from_cache)
+		stream = NULL;
+	else {
+		stream = mail->get_stream(mail, &hdr_size, NULL);
+		if (stream == NULL)
+			return FALSE;
+	}
 
 	return fetch_header_from(ctx, stream, &hdr_size,
 				 mail, body, body->section);

Index: imap-fetch.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-fetch.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- imap-fetch.c	26 Jul 2003 16:55:11 -0000	1.9
+++ imap-fetch.c	6 Aug 2003 20:15:30 -0000	1.10
@@ -1,6 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "common.h"
+#include "buffer.h"
 #include "istream.h"
 #include "ostream.h"
 #include "str.h"
@@ -12,6 +13,31 @@
 
 #include <unistd.h>
 
+const char *const *imap_fetch_get_body_fields(const char *fields)
+{
+	const char **field_list, **field, **dest;
+
+	while (*fields == ' ')
+		fields++;
+	if (*fields == '(')
+		fields++;
+
+	field_list = t_strsplit(fields, " )");
+
+	/* array ends at ")" element */
+	for (field = dest = field_list; *field != NULL; field++) {
+		if (strcmp(*field, ")") == 0)
+			break;
+		if (**field != '\0') {
+			*dest = *field;
+			dest++;
+		}
+	}
+	*dest = NULL;
+
+	return field_list;
+}
+
 static void fetch_uid(struct imap_fetch_context *ctx, struct mail *mail)
 {
 	str_printfa(ctx->str, "UID %u ", mail->uid);
@@ -265,6 +291,10 @@
 	struct mailbox *box = client->mailbox;
 	struct imap_fetch_context ctx;
 	struct mail *mail;
+	struct imap_fetch_body_data *body;
+	const char *null = NULL;
+	const char *const *wanted_headers, *const *arr;
+	buffer_t *buffer;
 	int all_found;
 
 	memset(&ctx, 0, sizeof(ctx));
@@ -277,9 +307,7 @@
 
 	if (!box->is_readonly(box)) {
 		/* If we have any BODY[..] sections, \Seen flag is added for
-		   all messages */
-		struct imap_fetch_body_data *body;
-
+		   all messages. */
 		for (body = bodies; body != NULL; body = body->next) {
 			if (!body->peek) {
 				ctx.update_seen = TRUE;
@@ -291,12 +319,34 @@
 			ctx.update_seen = TRUE;
 	}
 
+	/* If we have only BODY[HEADER.FIELDS (...)] fetches, get them
+	   separately rather than parsing the full header so mail storage
+	   can try to cache them. */
+	ctx.body_fetch_from_cache = TRUE;
+	buffer = buffer_create_dynamic(data_stack_pool, 64, (size_t)-1);
+	for (body = bodies; body != NULL; body = body->next) {
+		if (strncmp(body->section, "HEADER.FIELDS ", 14) != 0) {
+                        ctx.body_fetch_from_cache = FALSE;
+			break;
+		}
+
+		arr = imap_fetch_get_body_fields(body->section + 14);
+		while (*arr != NULL) {
+			buffer_append(buffer, arr, sizeof(*arr));
+			arr++;
+		}
+	}
+	buffer_append(buffer, &null, sizeof(null));
+	wanted_headers = !ctx.body_fetch_from_cache ? NULL :
+		buffer_get_data(buffer, NULL);
+
 	if (ctx.update_seen) {
 		if (!box->lock(box, MAILBOX_LOCK_FLAGS | MAILBOX_LOCK_READ))
 			return -1;
 	}
 
-	ctx.fetch_ctx = box->fetch_init(box, fetch_data, messageset, uidset);
+	ctx.fetch_ctx = box->fetch_init(box, fetch_data, wanted_headers,
+					messageset, uidset);
 	if (ctx.fetch_ctx == NULL)
 		ctx.failed = TRUE;
 	else {

Index: imap-fetch.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-fetch.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- imap-fetch.h	23 Jul 2003 01:44:16 -0000	1.3
+++ imap-fetch.h	6 Aug 2003 20:15:30 -0000	1.4
@@ -33,7 +33,7 @@
 	int update_seen;
 	struct mail_full_flags seen_flag;
 
-	int first, failed;
+	int first, failed, body_fetch_from_cache;
 };
 
 int imap_fetch(struct client *client,
@@ -45,5 +45,7 @@
 int imap_fetch_body_section(struct imap_fetch_context *ctx,
 			    const struct imap_fetch_body_data *body,
 			    struct mail *mail);
+
+const char *const *imap_fetch_get_body_fields(const char *fields);
 
 #endif

Index: imap-search.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-search.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- imap-search.c	27 Jan 2003 04:23:45 -0000	1.3
+++ imap-search.c	6 Aug 2003 20:15:30 -0000	1.4
@@ -21,20 +21,26 @@
 	return arg;
 }
 
-#define ARG_NEW(type, value) \
-	arg_new(data, args, next_sarg, type, value)
+#define ARG_NEW(type) \
+	arg_new(data, args, next_sarg, type, TRUE, NULL)
+
+#define ARG_NEW_FLAG(type) \
+	arg_new(data, args, next_sarg, type, FALSE, NULL)
+
+#define ARG_NEW_HEADER(type, hdr_name) \
+	arg_new(data, args, next_sarg, type, TRUE, hdr_name)
 
 static int arg_new(struct search_build_data *data, struct imap_arg **args,
 		   struct mail_search_arg **next_sarg,
-		   enum mail_search_arg_type type, int value)
+		   enum mail_search_arg_type type, int have_value,
+		   const char *hdr_name)
 {
 	struct mail_search_arg *sarg;
 
 	*next_sarg = sarg = search_arg_new(data->pool, type);
-	if (value == 0)
+	if (!have_value)
 		return TRUE;
 
-	/* first arg */
 	if ((*args)->type == IMAP_ARG_EOL) {
 		data->error = "Missing parameter for argument";
 		return FALSE;
@@ -49,23 +55,8 @@
 	sarg->value.str = str_ucase(IMAP_ARG_STR(*args));
 	*args += 1;
 
-	/* second arg */
-	if (value == 2) {
-		if ((*args)->type == IMAP_ARG_EOL) {
-			data->error = "Missing parameter for argument";
-			return FALSE;
-		}
-
-		if ((*args)->type != IMAP_ARG_ATOM &&
-		    (*args)->type != IMAP_ARG_STRING) {
-			data->error = "Invalid parameter for argument";
-			return FALSE;
-		}
-
-                sarg->hdr_field_name = sarg->value.str;
-		sarg->value.str = str_ucase(IMAP_ARG_STR(*args));
-		*args += 1;
-	}
+	if (hdr_name != NULL)
+                sarg->hdr_field_name = hdr_name;
 
 	return TRUE;
 }
@@ -122,40 +113,40 @@
 	switch (*str) {
 	case 'A':
 		if (strcmp(str, "ANSWERED") == 0)
-			return ARG_NEW(SEARCH_ANSWERED, 0);
+			return ARG_NEW_FLAG(SEARCH_ANSWERED);
 		else if (strcmp(str, "ALL") == 0)
-			return ARG_NEW(SEARCH_ALL, 0);
+			return ARG_NEW_FLAG(SEARCH_ALL);
 		break;
 	case 'B':
 		if (strcmp(str, "BODY") == 0) {
 			/* <string> */
-			return ARG_NEW(SEARCH_BODY, 1);
+			return ARG_NEW(SEARCH_BODY);
 		} else if (strcmp(str, "BEFORE") == 0) {
 			/* <date> */
-			return ARG_NEW(SEARCH_BEFORE, 1);
+			return ARG_NEW(SEARCH_BEFORE);
 		} else if (strcmp(str, "BCC") == 0) {
 			/* <string> */
-			return ARG_NEW(SEARCH_BCC, 1);
+			return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
 		}
 		break;
 	case 'C':
 		if (strcmp(str, "CC") == 0) {
 			/* <string> */
-			return ARG_NEW(SEARCH_CC, 1);
+			return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
 		}
 		break;
 	case 'D':
 		if (strcmp(str, "DELETED") == 0)
-			return ARG_NEW(SEARCH_DELETED, 0);
+			return ARG_NEW_FLAG(SEARCH_DELETED);
 		else if (strcmp(str, "DRAFT") == 0)
-			return ARG_NEW(SEARCH_DRAFT, 0);
+			return ARG_NEW_FLAG(SEARCH_DRAFT);
 		break;
 	case 'F':
 		if (strcmp(str, "FLAGGED") == 0)
-			return ARG_NEW(SEARCH_FLAGGED, 0);
+			return ARG_NEW_FLAG(SEARCH_FLAGGED);
 		else if (strcmp(str, "FROM") == 0) {
 			/* <string> */
-			return ARG_NEW(SEARCH_FROM, 1);
+			return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
 		}
 		break;
 	case 'H':
@@ -174,43 +165,20 @@
 			}
 
 			key = str_ucase(IMAP_ARG_STR(*args));
-
-			if (strcmp(key, "FROM") == 0) {
-				*args += 1;
-				return ARG_NEW(SEARCH_FROM, 1);
-			} else if (strcmp(key, "TO") == 0) {
-				*args += 1;
-				return ARG_NEW(SEARCH_TO, 1);
-			} else if (strcmp(key, "CC") == 0) {
-				*args += 1;
-				return ARG_NEW(SEARCH_CC, 1);
-			} else if (strcmp(key, "BCC") == 0) {
-				*args += 1;
-				return ARG_NEW(SEARCH_BCC, 1);
-			} else if (strcmp(key, "SUBJECT") == 0) {
-				*args += 1;
-				return ARG_NEW(SEARCH_SUBJECT, 1);
-			} else if (strcmp(key, "IN-REPLY-TO") == 0) {
-				*args += 1;
-				return ARG_NEW(SEARCH_IN_REPLY_TO, 1);
-			} else if (strcmp(key, "MESSAGE-ID") == 0) {
-				*args += 1;
-				return ARG_NEW(SEARCH_MESSAGE_ID, 1);
-			} else {
-				return ARG_NEW(SEARCH_HEADER, 2);
-			}
+			*args += 1;
+			return ARG_NEW_HEADER(SEARCH_HEADER, key);
 		}
 		break;
 	case 'K':
 		if (strcmp(str, "KEYWORD") == 0) {
 			/* <flag> */
-			return ARG_NEW(SEARCH_KEYWORD, 1);
+			return ARG_NEW(SEARCH_KEYWORD);
 		}
 		break;
 	case 'L':
 		if (strcmp(str, "LARGER") == 0) {
 			/* <n> */
-			return ARG_NEW(SEARCH_LARGER, 1);
+			return ARG_NEW(SEARCH_LARGER);
 		}
 		break;
 	case 'N':
@@ -260,10 +228,10 @@
 			return TRUE;
 		} if (strcmp(str, "ON") == 0) {
 			/* <date> */
-			return ARG_NEW(SEARCH_ON, 1);
+			return ARG_NEW(SEARCH_ON);
 		} if (strcmp(str, "OLD") == 0) {
 			/* OLD == NOT RECENT */
-			if (!ARG_NEW(SEARCH_RECENT, 0))
+			if (!ARG_NEW_FLAG(SEARCH_RECENT))
 				return FALSE;
 
 			(*next_sarg)->not = TRUE;
@@ -272,71 +240,71 @@
 		break;
 	case 'R':
 		if (strcmp(str, "RECENT") == 0)
-			return ARG_NEW(SEARCH_RECENT, 0);
+			return ARG_NEW_FLAG(SEARCH_RECENT);
 		break;
 	case 'S':
 		if (strcmp(str, "SEEN") == 0)
-			return ARG_NEW(SEARCH_SEEN, 0);
+			return ARG_NEW_FLAG(SEARCH_SEEN);
 		else if (strcmp(str, "SUBJECT") == 0) {
 			/* <string> */
-			return ARG_NEW(SEARCH_SUBJECT, 1);
+			return ARG_NEW_HEADER(SEARCH_HEADER, str);
 		} else if (strcmp(str, "SENTBEFORE") == 0) {
 			/* <date> */
-			return ARG_NEW(SEARCH_SENTBEFORE, 1);
+			return ARG_NEW(SEARCH_SENTBEFORE);
 		} else if (strcmp(str, "SENTON") == 0) {
 			/* <date> */
-			return ARG_NEW(SEARCH_SENTON, 1);
+			return ARG_NEW(SEARCH_SENTON);
 		} else if (strcmp(str, "SENTSINCE") == 0) {
 			/* <date> */
-			return ARG_NEW(SEARCH_SENTSINCE, 1);
+			return ARG_NEW(SEARCH_SENTSINCE);
 		} else if (strcmp(str, "SINCE") == 0) {
 			/* <date> */
-			return ARG_NEW(SEARCH_SINCE, 1);
+			return ARG_NEW(SEARCH_SINCE);
 		} else if (strcmp(str, "SMALLER") == 0) {
 			/* <n> */
-			return ARG_NEW(SEARCH_SMALLER, 1);
+			return ARG_NEW(SEARCH_SMALLER);
 		}
 		break;
 	case 'T':
 		if (strcmp(str, "TEXT") == 0) {
 			/* <string> */
-			return ARG_NEW(SEARCH_TEXT, 1);
+			return ARG_NEW(SEARCH_TEXT);
 		} else if (strcmp(str, "TO") == 0) {
 			/* <string> */
-			return ARG_NEW(SEARCH_TO, 1);
+			return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
 		}
 		break;
 	case 'U':
 		if (strcmp(str, "UID") == 0) {
 			/* <message set> */
-			return ARG_NEW(SEARCH_UID, 1);
+			return ARG_NEW(SEARCH_UID);
 		} else if (strcmp(str, "UNANSWERED") == 0) {
-			if (!ARG_NEW(SEARCH_ANSWERED, 0))
+			if (!ARG_NEW_FLAG(SEARCH_ANSWERED))
 				return FALSE;
 			(*next_sarg)->not = TRUE;
 			return TRUE;
 		} else if (strcmp(str, "UNDELETED") == 0) {
-			if (!ARG_NEW(SEARCH_DELETED, 0))
+			if (!ARG_NEW_FLAG(SEARCH_DELETED))
 				return FALSE;
 			(*next_sarg)->not = TRUE;
 			return TRUE;
 		} else if (strcmp(str, "UNDRAFT") == 0) {
-			if (!ARG_NEW(SEARCH_DRAFT, 0))
+			if (!ARG_NEW_FLAG(SEARCH_DRAFT))
 				return FALSE;
 			(*next_sarg)->not = TRUE;
 			return TRUE;
 		} else if (strcmp(str, "UNFLAGGED") == 0) {
-			if (!ARG_NEW(SEARCH_FLAGGED, 0))
+			if (!ARG_NEW_FLAG(SEARCH_FLAGGED))
 				return FALSE;
 			(*next_sarg)->not = TRUE;
 			return TRUE;
 		} else if (strcmp(str, "UNKEYWORD") == 0) {
-			if (!ARG_NEW(SEARCH_KEYWORD, 0))
+			if (!ARG_NEW_FLAG(SEARCH_KEYWORD))
 				return FALSE;
 			(*next_sarg)->not = TRUE;
 			return TRUE;
 		} else if (strcmp(str, "UNSEEN") == 0) {
-			if (!ARG_NEW(SEARCH_SEEN, 0))
+			if (!ARG_NEW_FLAG(SEARCH_SEEN))
 				return FALSE;
 			(*next_sarg)->not = TRUE;
 			return TRUE;
@@ -345,7 +313,7 @@
 	default:
 		if (*str == '*' || (*str >= '0' && *str <= '9')) {
 			/* <message-set> */
-			if (!ARG_NEW(SEARCH_SET, 0))
+			if (!ARG_NEW_FLAG(SEARCH_SET))
 				return FALSE;
 
 			(*next_sarg)->value.str = str;

Index: imap-thread.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-thread.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- imap-thread.c	27 Jan 2003 04:23:45 -0000	1.3
+++ imap-thread.c	6 Aug 2003 20:15:30 -0000	1.4
@@ -103,7 +103,7 @@
 		struct mail_search_arg *args, enum mail_thread_type type)
 {
 	static const char *wanted_headers[] = {
-		"message-id", "in-reply-to", "references",
+		"message-id", "in-reply-to", "references", "subject",
 		NULL
 	};
 	struct thread_context *ctx;



More information about the dovecot-cvs mailing list