[dovecot-cvs] dovecot/src/lib-storage/index Makefile.am,1.7,1.8 index-copy.c,1.25,1.26 index-fetch.c,1.39,1.40 index-fetch.h,1.14,1.15 index-messageset.c,1.11,1.12 index-messageset.h,1.5,1.6 index-search.c,1.64,1.65 index-storage.c,1.25,1.26 index-storage.h,1.28,1.29 Message-Id: <20030120145254.505F0238C6@danu.procontrol.fi>

cras at procontrol.fi cras at procontrol.fi
Mon Jan 20 16:52:54 EET 2003


Update of /home/cvs/dovecot/src/lib-storage/index
In directory danu:/tmp/cvs-serv7093/lib-storage/index

Modified Files:
	Makefile.am index-copy.c index-fetch.c index-fetch.h 
	index-messageset.c index-messageset.h index-search.c 
	index-storage.c index-storage.h index-update-flags.c 
Removed Files:
	index-fetch-section.c index-msgcache.c index-sort.c 
	index-sort.h 
Log Message:
mail-storage.h interface changes, affects pretty much everything.
FETCH, SEARCH, SORT and THREAD handling were pretty much moved from
lib-storage/ to imap/ so adding non-index storages would be much easier now.
Also POP3 server can now be easily implemented with lib-storage.

Not too well tested, and at least one major problem: partial fetching is
_slow_.



Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/Makefile.am,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- Makefile.am	22 Dec 2002 17:52:47 -0000	1.7
+++ Makefile.am	20 Jan 2003 14:52:51 -0000	1.8
@@ -13,20 +13,16 @@
 	index-copy.c \
 	index-expunge.c \
 	index-fetch.c \
-	index-fetch-section.c \
+	index-mail.c \
 	index-mailbox-check.c \
 	index-messageset.c \
-	index-msgcache.c \
 	index-save.c \
 	index-search.c \
-	index-sort.c \
 	index-status.c \
 	index-storage.c \
 	index-sync.c \
 	index-update-flags.c
 
 noinst_HEADERS = \
-	index-fetch.h \
 	index-messageset.h \
-	index-sort.h \
 	index-storage.h

Index: index-copy.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-copy.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- index-copy.c	11 Jan 2003 19:55:57 -0000	1.25
+++ index-copy.c	20 Jan 2003 14:52:51 -0000	1.26
@@ -8,51 +8,49 @@
 
 #include <unistd.h>
 
-struct copy_context {
-	struct mailbox *dest;
-	const char **custom_flags;
-	int copy_inside_mailbox;
-};
-
-static int copy_cb(struct mail_index *index, struct mail_index_record *rec,
-		   unsigned int client_seq __attr_unused__,
-		   unsigned int idx_seq __attr_unused__, void *context)
+static int copy_messageset(struct messageset_context *ctx,
+			   struct index_mailbox *src, struct mailbox *dest)
 {
-	struct copy_context *ctx = context;
-	struct index_mailbox *dest_ibox = NULL;
+        const struct messageset_mail *mail;
+	struct mail_full_flags flags;
 	struct istream *input;
 	time_t internal_date;
 	int failed, deleted;
 
-	input = index->open_mail(index, rec, &internal_date, &deleted);
-	if (input == NULL)
-		return FALSE;
+	memset(&flags, 0, sizeof(flags));
+	flags.custom_flags =
+		mail_custom_flags_list_get(src->index->custom_flags);
+	flags.custom_flags_count = MAIL_CUSTOM_FLAGS_COUNT;
 
-	if (ctx->copy_inside_mailbox) {
-                /* kludgy.. */
-		dest_ibox = (struct index_mailbox *) ctx->dest;
-		dest_ibox->delay_save_unlocking = TRUE;
-	}
+	while ((mail = index_messageset_next(ctx)) != NULL) {
+		input = src->index->open_mail(src->index, mail->rec,
+					      &internal_date, &deleted);
+		if (input == NULL) {
+			if (deleted)
+				continue;
+			return FALSE;
+		}
 
-	/* save it in destination mailbox */
-	failed = !ctx->dest->save(ctx->dest, rec->msg_flags,
-				  ctx->custom_flags, internal_date, 0,
-				  input, input->v_limit);
+		/* save it in destination mailbox */
+		flags.flags = mail->rec->msg_flags;
+		failed = !dest->save(dest, &flags, internal_date, 0,
+				     input, input->v_limit);
+		i_stream_unref(input);
 
-	if (ctx->copy_inside_mailbox)
-		dest_ibox->delay_save_unlocking = FALSE;
+		if (failed)
+			return FALSE;
+	}
 
-	i_stream_unref(input);
-	return !failed;
+	return TRUE;
 }
 
 int index_storage_copy(struct mailbox *box, struct mailbox *destbox,
 		       const char *messageset, int uidset)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
-        struct copy_context ctx;
+        struct messageset_context *ctx;
 	enum mail_lock_type lock_type;
-	int failed;
+	int ret, copy_inside_mailbox;
 
 	if (destbox->readonly) {
 		mail_storage_set_error(box->storage,
@@ -60,15 +58,18 @@
 		return FALSE;
 	}
 
-	ctx.copy_inside_mailbox =
+	copy_inside_mailbox =
 		destbox->storage == box->storage &&
 		strcmp(destbox->name, box->name) == 0;
 
-	if (ctx.copy_inside_mailbox) {
+	if (copy_inside_mailbox) {
 		/* copying inside same mailbox */
 		if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
 			return FALSE;
 
+		/* kludgy.. */
+		((struct index_mailbox *) destbox)->delay_save_unlocking = TRUE;
+
 		lock_type = MAIL_LOCK_EXCLUSIVE;
 	} else {
 		lock_type = MAIL_LOCK_SHARED;
@@ -77,15 +78,16 @@
 	if (!index_storage_sync_and_lock(ibox, TRUE, lock_type))
 		return FALSE;
 
-	ctx.custom_flags =
-		mail_custom_flags_list_get(ibox->index->custom_flags);
-	ctx.dest = destbox;
+	ctx = index_messageset_init(ibox, messageset, uidset);
+	ret = copy_messageset(ctx, ibox, destbox);
+	if (index_messageset_deinit(ctx) < 0)
+		ret = FALSE;
 
-	failed = index_messageset_foreach(ibox, messageset, uidset,
-					  copy_cb, &ctx) <= 0;
+	if (copy_inside_mailbox)
+		((struct index_mailbox *) destbox)->delay_save_unlocking = TRUE;
 
 	if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
 		return FALSE;
 
-	return !failed;
+	return ret;
 }

Index: index-fetch.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-fetch.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- index-fetch.c	5 Jan 2003 13:09:52 -0000	1.39
+++ index-fetch.c	20 Jan 2003 14:52:51 -0000	1.40
@@ -3,414 +3,157 @@
 #include "lib.h"
 #include "ostream.h"
 #include "str.h"
+#include "mail-index.h"
+#include "mail-modifylog.h"
 #include "mail-custom-flags.h"
 #include "index-storage.h"
-#include "index-fetch.h"
 #include "index-messageset.h"
-#include "message-send.h"
-#include "imap-date.h"
-#include "imap-util.h"
-#include "imap-message-cache.h"
-
-#include <unistd.h>
-
-static int index_fetch_internaldate(struct mail_index_record *rec,
-				    struct fetch_context *ctx)
-{
-	time_t date;
+#include "index-mail.h"
 
-	date = imap_msgcache_get_internal_date(ctx->cache);
-	if (date != (time_t)-1) {
-		str_printfa(ctx->str, "INTERNALDATE \"%s\" ",
-			    imap_to_datetime(date));
-		return TRUE;
-	} else {
-		mail_storage_set_critical(ctx->storage,
-			"Couldn't generate INTERNALDATE for UID %u (index %s)",
-			rec->uid, ctx->index->filepath);
-		return FALSE;
-	}
-}
+struct mail_fetch_context {
+	struct index_mailbox *ibox;
+	struct mail_index *index;
 
-static int index_fetch_body(struct mail_index_record *rec,
-			    struct fetch_context *ctx)
-{
-	const char *body;
+	struct messageset_context *msgset_ctx;
+	struct index_mail mail;
 
-	body = imap_msgcache_get(ctx->cache, IMAP_CACHE_BODY);
-	if (body != NULL) {
-		str_printfa(ctx->str, "BODY (%s) ", body);
-		return TRUE;
-	} else {
-		mail_storage_set_critical(ctx->storage,
-			"Couldn't generate BODY for UID %u (index %s)",
-			rec->uid, ctx->index->filepath);
-		return FALSE;
-	}
-}
+	int update_seen;
+};
 
-static int index_fetch_bodystructure(struct mail_index_record *rec,
-				     struct fetch_context *ctx)
+struct mail_fetch_context *
+index_storage_fetch_init(struct mailbox *box,
+			 enum mail_fetch_field wanted_fields, int *update_seen,
+			 const char *messageset, int uidset)
 {
-	const char *bodystructure;
+	struct index_mailbox *ibox = (struct index_mailbox *) box;
+        struct mail_fetch_context *ctx;
 
-	bodystructure = imap_msgcache_get(ctx->cache, IMAP_CACHE_BODYSTRUCTURE);
-	if (bodystructure != NULL) {
-		str_printfa(ctx->str, "BODYSTRUCTURE (%s) ", bodystructure);
-		return TRUE;
-	} else {
-		mail_storage_set_critical(ctx->storage,
-			"Couldn't generate BODYSTRUCTURE for UID %u (index %s)",
-			rec->uid, ctx->index->filepath);
-		return FALSE;
-	}
-}
+	ctx = i_new(struct mail_fetch_context, 1);
 
-static int index_fetch_envelope(struct mail_index_record *rec,
-				struct fetch_context *ctx)
-{
-	const char *envelope;
+	if (!box->readonly)
+		*update_seen = FALSE;
 
-	envelope = imap_msgcache_get(ctx->cache, IMAP_CACHE_ENVELOPE);
-	if (envelope != NULL) {
-		str_printfa(ctx->str, "ENVELOPE (%s) ", envelope);
-		return TRUE;
-	} else {
-		mail_storage_set_critical(ctx->storage,
-			"Couldn't generate ENVELOPE for UID %u (index %s)",
-			rec->uid, ctx->index->filepath);
-		return FALSE;
+	/* need exclusive lock to update the \Seen flags */
+	if (*update_seen) {
+		if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
+			return NULL;
 	}
-}
 
-static int index_fetch_rfc822_size(struct mail_index_record *rec,
-				   struct fetch_context *ctx)
-{
-	uoff_t size;
+	if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED))
+		return NULL;
 
-	size = imap_msgcache_get_virtual_size(ctx->cache);
-	if (size == (uoff_t)-1) {
-		mail_storage_set_critical(ctx->storage,
-			"Couldn't get RFC822.SIZE for UID %u (index %s)",
-			rec->uid, ctx->index->filepath);
-		return FALSE;
+	if (*update_seen &&
+	    ibox->index->header->messages_count ==
+	    ibox->index->header->seen_messages_count) {
+		/* if all messages are already seen, there's no point in
+		   keeping exclusive lock */
+		*update_seen = FALSE;
+		(void)index_storage_lock(ibox, MAIL_LOCK_SHARED);
 	}
 
-	str_printfa(ctx->str, "RFC822.SIZE %"PRIuUOFF_T" ", size);
-	return TRUE;
-}
-
-static void index_fetch_flags(struct mail_index_record *rec,
-			      struct fetch_context *ctx)
-{
-	enum mail_flags flags;
-
-	flags = rec->msg_flags;
-	if (rec->uid >= ctx->index->first_recent_uid)
-		flags |= MAIL_RECENT;
-	if (ctx->update_seen)
-		flags |= MAIL_SEEN;
-
-	str_printfa(ctx->str, "FLAGS (%s) ",
-		    imap_write_flags(flags, ctx->custom_flags,
-				     ctx->custom_flags_count));
-}
+	ctx->ibox = ibox;
+	ctx->index = ibox->index;
+	ctx->update_seen = *update_seen;
 
-static void index_fetch_uid(struct mail_index_record *rec,
-			    struct fetch_context *ctx)
-{
-	str_printfa(ctx->str, "UID %u ", rec->uid);
+	index_mail_init(ibox, &ctx->mail, wanted_fields, NULL);
+	ctx->msgset_ctx = index_messageset_init(ibox, messageset, uidset);
+	return ctx;
 }
 
-static int index_fetch_send_rfc822(struct mail_index_record *rec,
-				   struct fetch_context *ctx)
+int index_storage_fetch_deinit(struct mail_fetch_context *ctx, int *all_found)
 {
-	struct message_size hdr_size, body_size;
-	struct istream *input;
-	const char *str;
-
-	if (!imap_msgcache_get_rfc822(ctx->cache, &input,
-				      &hdr_size, &body_size)) {
-		mail_storage_set_critical(ctx->storage,
-			"Couldn't get RFC822 for UID %u (index %s)",
-			rec->uid, ctx->index->filepath);
-		return FALSE;
-	}
-
-	str = t_strdup_printf(" RFC822 {%"PRIuUOFF_T"}\r\n",
-			      hdr_size.virtual_size + body_size.virtual_size);
-	if (ctx->first) {
-		str++; ctx->first = FALSE;
-	}
-	if (o_stream_send_str(ctx->output, str) < 0)
-		return FALSE;
-
-	body_size.physical_size += hdr_size.physical_size;
-	body_size.virtual_size += hdr_size.virtual_size;
-	return message_send(ctx->output, input, &body_size, 0, (uoff_t)-1);
-}
+	int ret;
 
-static int index_fetch_send_rfc822_header(struct mail_index_record *rec,
-					  struct fetch_context *ctx)
-{
-	struct message_size hdr_size;
-	struct istream *input;
-	const char *str;
+	ret = index_messageset_deinit(ctx->msgset_ctx);
 
-	if (!imap_msgcache_get_rfc822(ctx->cache, &input, &hdr_size, NULL)) {
-		mail_storage_set_critical(ctx->storage,
-			"Couldn't get RFC822.HEADER for UID %u (index %s)",
-			rec->uid, ctx->index->filepath);
-		return FALSE;
-	}
+	if (all_found != NULL)
+		*all_found = ret > 0;
 
-	str = t_strdup_printf(" RFC822.HEADER {%"PRIuUOFF_T"}\r\n",
-			      hdr_size.virtual_size);
-	if (ctx->first) {
-		str++; ctx->first = FALSE;
-	}
-	if (o_stream_send_str(ctx->output, str) < 0)
-		return FALSE;
+	if (!index_storage_lock(ctx->ibox, MAIL_LOCK_UNLOCK))
+		ret = -1;
 
-	return message_send(ctx->output, input, &hdr_size, 0, (uoff_t)-1);
+	if (ctx->ibox->fetch_mail.pool != NULL)
+		index_mail_deinit(&ctx->ibox->fetch_mail);
+	index_mail_deinit(&ctx->mail);
+	i_free(ctx);
+	return ret >= 0;
 }
 
-static int index_fetch_send_rfc822_text(struct mail_index_record *rec,
-					struct fetch_context *ctx)
+struct mail *index_storage_fetch_next(struct mail_fetch_context *ctx)
 {
-	struct message_size body_size;
-	struct istream *input;
-	const char *str;
-
-	if (!imap_msgcache_get_rfc822(ctx->cache, &input, NULL, &body_size)) {
-		mail_storage_set_critical(ctx->storage,
-			"Couldn't get RFC822.TEXT for UID %u (index %s)",
-			rec->uid, ctx->index->filepath);
-		return FALSE;
-	}
-
-	str = t_strdup_printf(" RFC822.TEXT {%"PRIuUOFF_T"}\r\n",
-			      body_size.virtual_size);
-	if (ctx->first) {
-		str++; ctx->first = FALSE;
-	}
-	if (o_stream_send_str(ctx->output, str) < 0)
-		return FALSE;
+	const struct messageset_mail *msgset_mail;
+	struct mail_index_record *rec;
+	int ret;
 
-	return message_send(ctx->output, input, &body_size, 0, (uoff_t)-1);
-}
+	do {
+		msgset_mail = index_messageset_next(ctx->msgset_ctx);
+		if (msgset_mail == NULL)
+			return NULL;
 
-static enum imap_cache_field index_get_cache(struct mail_fetch_data *fetch_data)
-{
-	struct mail_fetch_body_data *sect;
-	enum imap_cache_field field;
+		rec = msgset_mail->rec;
+		ctx->mail.mail.seen_updated = FALSE;
+		if (ctx->update_seen && (rec->msg_flags & MAIL_SEEN) == 0) {
+			if (ctx->index->update_flags(ctx->index, rec,
+						     msgset_mail->idx_seq,
+						     rec->msg_flags | MAIL_SEEN,
+						     FALSE))
+				ctx->mail.mail.seen_updated = TRUE;
+		}
 
-	field = 0;
-	if (fetch_data->body)
-		field |= IMAP_CACHE_BODY;
-	if (fetch_data->bodystructure)
-		field |= IMAP_CACHE_BODYSTRUCTURE;
-	if (fetch_data->envelope)
-		field |= IMAP_CACHE_ENVELOPE;
-	if (fetch_data->internaldate)
-		field |= IMAP_CACHE_INTERNALDATE;
+		ctx->mail.mail.seq = msgset_mail->client_seq;
+		ctx->mail.mail.uid = rec->uid;
 
-	if (fetch_data->rfc822_size)
-		field |= IMAP_CACHE_VIRTUAL_SIZE;
-	if (fetch_data->rfc822) {
-		field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_HDR_SIZE |
-			IMAP_CACHE_MESSAGE_BODY_SIZE;
-	}
-	if (fetch_data->rfc822_header)
-		field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_HDR_SIZE;
-	if (fetch_data->rfc822_text)
-		field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_BODY_SIZE;
+		ret = index_mail_next(&ctx->mail, rec);
+	} while (ret == 0);
 
-	/* check what body[] sections want */
-	sect = fetch_data->body_sections;
-	for (; sect != NULL; sect = sect->next)
-		field |= index_fetch_body_get_cache(sect->section);
-	return field;
+	return ret < 0 ? NULL : &ctx->mail.mail;
 }
 
-static int fetch_msgcache_open(struct fetch_context *ctx,
-			       struct mail_index_record *rec)
+static struct mail *
+fetch_record(struct index_mailbox *ibox, struct mail_index_record *rec,
+	     enum mail_fetch_field wanted_fields)
 {
-	enum imap_cache_field fields;
+	if (ibox->fetch_mail.pool != NULL)
+		index_mail_deinit(&ibox->fetch_mail);
 
-	fields = index_get_cache(ctx->fetch_data);
-	if (fields == 0)
-		return TRUE;
+	index_mail_init(ibox, &ibox->fetch_mail, wanted_fields, NULL);
+	if (index_mail_next(&ibox->fetch_mail, rec) <= 0)
+		return NULL;
 
-	return index_msgcache_open(ctx->cache, ctx->index, rec, fields);
+	return &ibox->fetch_mail.mail;
 }
 
-static int index_fetch_mail(struct mail_index *index __attr_unused__,
-			    struct mail_index_record *rec,
-			    unsigned int client_seq, unsigned int idx_seq,
-			    void *context)
+struct mail *index_storage_fetch_uid(struct mailbox *box, unsigned int uid,
+				     enum mail_fetch_field wanted_fields)
 {
-	struct fetch_context *ctx = context;
-	struct mail_fetch_body_data *sect;
-	size_t len, orig_len;
-	int failed, data_written, fetch_flags;
-
-	/* first see what we need to do. this way we don't first do some
-	   light parsing and later notice that we need to do heavier parsing
-	   anyway */
-	if (!fetch_msgcache_open(ctx, rec)) {
-		/* most likely message not found, just ignore it. */
-		imap_msgcache_close(ctx->cache);
-		ctx->failed = TRUE;
-		return TRUE;
-	}
-
-	if (ctx->update_seen && (rec->msg_flags & MAIL_SEEN) == 0) {
-		(void)index->update_flags(index, rec, idx_seq,
-					  rec->msg_flags | MAIL_SEEN, FALSE);
-		fetch_flags = TRUE;
-	} else {
-		fetch_flags = FALSE;
-	}
-
-	ctx->str = t_str_new(2048);
-
-	str_printfa(ctx->str, "* %u FETCH (", client_seq);
-	orig_len = str_len(ctx->str);
-
-	failed = TRUE;
-	data_written = FALSE;
-	do {
-		/* these can't fail */
-		if (ctx->fetch_data->uid)
-			index_fetch_uid(rec, ctx);
-		if (ctx->fetch_data->flags || fetch_flags)
-			index_fetch_flags(rec, ctx);
-
-		/* rest can */
-		if (ctx->fetch_data->internaldate)
-			if (!index_fetch_internaldate(rec, ctx))
-				break;
-		if (ctx->fetch_data->body)
-			if (!index_fetch_body(rec, ctx))
-				break;
-		if (ctx->fetch_data->bodystructure)
-			if (!index_fetch_bodystructure(rec, ctx))
-				break;
-		if (ctx->fetch_data->envelope)
-			if (!index_fetch_envelope(rec, ctx))
-				break;
-		if (ctx->fetch_data->rfc822_size)
-			if (!index_fetch_rfc822_size(rec, ctx))
-				break;
-
-		/* send the data written into temp string,
-		   not including the trailing zero */
-		ctx->first = str_len(ctx->str) == orig_len;
-		len = str_len(ctx->str);
-		if (len > 0) {
-			if (!ctx->first)
-				str_truncate(ctx->str, --len);
-
-			if (o_stream_send(ctx->output,
-					  str_c(ctx->str), len) < 0)
-				break;
-		}
-
-		data_written = TRUE;
-
-		/* large data */
-		if (ctx->fetch_data->rfc822)
-			if (!index_fetch_send_rfc822(rec, ctx))
-				break;
-		if (ctx->fetch_data->rfc822_text)
-			if (!index_fetch_send_rfc822_text(rec, ctx))
-				break;
-		if (ctx->fetch_data->rfc822_header)
-			if (!index_fetch_send_rfc822_header(rec, ctx))
-				break;
-
-		sect = ctx->fetch_data->body_sections;
-		for (; sect != NULL; sect = sect->next) {
-			if (!index_fetch_body_section(rec, sect, ctx))
-				break;
-		}
+	struct index_mailbox *ibox = (struct index_mailbox *) box;
+        struct mail_index_record *rec;
 
-		failed = FALSE;
-	} while (0);
+	i_assert(ibox->index->lock_type != MAIL_LOCK_UNLOCK);
 
-	if (data_written) {
-		if (o_stream_send(ctx->output, ")\r\n", 3) < 0)
-			failed = TRUE;
-	}
+	rec = ibox->index->lookup_uid_range(ibox->index, uid, uid, NULL);
+	if (rec == NULL)
+		return NULL;
 
-	imap_msgcache_close(ctx->cache);
-	return !failed;
+	return fetch_record(ibox, rec, wanted_fields);
 }
 
-int index_storage_fetch(struct mailbox *box, struct mail_fetch_data *fetch_data,
-			struct ostream *output, int *all_found)
+struct mail *index_storage_fetch_seq(struct mailbox *box, unsigned int seq,
+				     enum mail_fetch_field wanted_fields)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
-	struct fetch_context ctx;
-	struct mail_fetch_body_data *sect;
-	int ret;
-
-	memset(&ctx, 0, sizeof(ctx));
-
-	if (!box->readonly) {
-		/* If we have any BODY[..] sections, \Seen flag is added for
-		   all messages */
-		sect = fetch_data->body_sections;
-		for (; sect != NULL; sect = sect->next) {
-			if (!sect->peek) {
-				ctx.update_seen = TRUE;
-				break;
-			}
-		}
-
-		if (fetch_data->rfc822 || fetch_data->rfc822_text)
-			ctx.update_seen = TRUE;
-	}
-
-	/* need exclusive lock to update the \Seen flags */
-	if (ctx.update_seen) {
-		if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
-			return FALSE;
-	}
-
-	if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED))
-		return FALSE;
-
-	if (ctx.update_seen &&
-	    ibox->index->header->messages_count ==
-	    ibox->index->header->seen_messages_count) {
-		/* if all messages are already seen, there's no point in
-		   keeping exclusive lock */
-		ctx.update_seen = FALSE;
-		(void)index_storage_lock(ibox, MAIL_LOCK_SHARED);
-	}
-
-	ctx.box = box;
-	ctx.storage = box->storage;
-	ctx.cache = ibox->cache;
-	ctx.index = ibox->index;
-	ctx.custom_flags =
-		mail_custom_flags_list_get(ibox->index->custom_flags);
-        ctx.custom_flags_count = MAIL_CUSTOM_FLAGS_COUNT;
-
-	ctx.fetch_data = fetch_data;
-	ctx.output = output;
+        struct mail_index_record *rec;
+	unsigned int expunges_before;
 
-	ret = index_messageset_foreach(ibox, fetch_data->messageset,
-				       fetch_data->uidset,
-				       index_fetch_mail, &ctx);
+	i_assert(ibox->index->lock_type != MAIL_LOCK_UNLOCK);
 
-	if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
-		return FALSE;
+	if (mail_modifylog_seq_get_expunges(ibox->index->modifylog, seq, seq,
+					    &expunges_before) == NULL)
+		return NULL;
 
-	if (all_found != NULL)
-		*all_found = ret == 1 && !ctx.failed;
+	rec = ibox->index->lookup(ibox->index, seq - expunges_before);
+	if (rec == NULL)
+		return NULL;
 
-	return ret > 0;
+	return fetch_record(ibox, rec, wanted_fields);
 }

Index: index-fetch.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-fetch.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- index-fetch.h	5 Jan 2003 13:09:52 -0000	1.14
+++ index-fetch.h	20 Jan 2003 14:52:51 -0000	1.15
@@ -10,7 +10,7 @@
 	const char **custom_flags;
 	unsigned int custom_flags_count;
 
-	struct mail_fetch_data *fetch_data;
+	//struct mail_fetch_data *fetch_data;
 	struct ostream *output;
 	string_t *str;
 	int update_seen, failed;

Index: index-messageset.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-messageset.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- index-messageset.c	11 Jan 2003 19:55:57 -0000	1.11
+++ index-messageset.c	20 Jan 2003 14:52:51 -0000	1.12
@@ -1,342 +1,291 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2003 Timo Sirainen */
 
 #include "lib.h"
 #include "mail-index.h"
 #include "mail-index-util.h"
 #include "mail-modifylog.h"
+#include "index-storage.h"
 #include "index-messageset.h"
 
-static unsigned int get_next_number(const char **str)
-{
-	unsigned int num;
+struct messageset_context {
+	struct index_mailbox *ibox;
+	struct mail_index *index;
 
-	num = 0;
-	while (**str != '\0') {
-		if (**str < '0' || **str > '9')
-			break;
+	const struct modify_log_expunge *expunges;
+	int expunges_found;
 
-		num = num*10 + (**str - '0');
-		(*str)++;
-	}
+	struct messageset_mail mail;
+	unsigned int messages_count;
+	unsigned int num1, num2;
 
-	return num;
-}
+	const char *messageset, *p;
+	int uidset;
 
-static int mail_index_foreach(struct mail_index *index,
-			      unsigned int seq, unsigned int seq2,
-			      msgset_foreach_callback_t callback, void *context)
-{
-	struct mail_index_record *rec;
-	const struct modify_log_expunge *expunges;
-	unsigned int idx_seq, expunges_before, temp;
-	int expunges_found;
+	int first, ret;
+	const char *error;
+};
 
-	if (seq > seq2) {
-		/* swap, as specified by latest IMAP4rev1 spec */
-		temp = seq;
-		seq = seq2;
-		seq2 = temp;
-	}
+static int uidset_init(struct messageset_context *ctx);
+static int seqset_init(struct messageset_context *ctx);
 
-	/* get list of expunged messages in our range. the expunges_before
-	   can be used to calculate the current real sequence position */
-	expunges = mail_modifylog_seq_get_expunges(index->modifylog, seq, seq2,
-						   &expunges_before);
-	if (expunges == NULL)
-		return -1;
+struct messageset_context *
+index_messageset_init(struct index_mailbox *ibox,
+		      const char *messageset, int uidset)
+{
+	struct messageset_context *ctx;
 
-	i_assert(expunges_before < seq);
-	expunges_found = expunges->uid1 != 0;
+	i_assert(ibox->index->lock_type != MAIL_LOCK_UNLOCK);
 
-	/* Reset index errors, since we later rely on it to check if failed */
-	index_reset_error(index);
+	ctx = i_new(struct messageset_context, 1);
+	ctx->ibox = ibox;
+	ctx->index = ibox->index;
+	ctx->messages_count = ibox->synced_messages_count;
+	ctx->p = ctx->messageset = messageset;
+	ctx->uidset = uidset;
 
-	/* get the first non-expunged message. note that if all messages
-	   were expunged in the range, this points outside wanted range. */
-	idx_seq = seq - expunges_before;
-	rec = index->lookup(index, idx_seq);
-	for (; rec != NULL; seq++, idx_seq++) {
-		/* skip expunged sequences */
-		i_assert(rec->uid != 0);
+	/* Reset index errors, we rely on it to check for failures */
+	index_reset_error(ctx->index);
 
-		while (expunges->uid1 != 0 && expunges->uid1 < rec->uid) {
-			i_assert(expunges->uid2 < rec->uid);
+	return ctx;
+}
 
-			seq += expunges->seq_count;
-			expunges++;
-		}
-		i_assert(!(expunges->uid1 <= rec->uid &&
-			   expunges->uid2 >= rec->uid));
+struct messageset_context *
+index_messageset_init_range(struct index_mailbox *ibox,
+			    unsigned int num1, unsigned int num2, int uidset)
+{
+	struct messageset_context *ctx;
 
-		if (seq > seq2)
-			break;
+	ctx = index_messageset_init(ibox, NULL, uidset);
+	ctx->num1 = num1;
+	ctx->num2 = num2;
+	return ctx;
+}
 
-		t_push();
-		if (!callback(index, rec, seq, idx_seq, context)) {
-			t_pop();
-			return 0;
-		}
-		t_pop();
+int index_messageset_deinit(struct messageset_context *ctx)
+{
+	int ret = ctx->ret;
 
-		rec = index->next(index, rec);
+	if (ret == 1 && ctx->expunges_found) {
+		/* some of the messages weren't found */
+		ret = 0;
 	}
 
-	if (rec == NULL &&
-	    index->get_last_error(index) != MAIL_INDEX_ERROR_NONE) {
-		/* error occured */
-		return -1;
+	if (ret == -1)
+		mail_storage_set_index_error(ctx->ibox);
+	else if (ret == -2) {
+		/* user error */
+		mail_storage_set_syntax_error(ctx->ibox->box.storage,
+					      "%s", ctx->error);
 	}
 
-	return !expunges_found && seq > seq2 ? 1 : 2;
+	i_free(ctx);
+	return ret;
 }
 
-static int mail_index_messageset_foreach(struct mail_index *index,
-					 const char *messageset,
-					 unsigned int messages_count,
-					 msgset_foreach_callback_t callback,
-					 void *context, const char **error)
+static unsigned int get_next_number(const char **str)
 {
-	const char *input;
-	unsigned int seq, seq2;
-	int ret, all_found;
+	unsigned int num;
 
-	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
+	num = 0;
+	while (**str != '\0') {
+		if (**str < '0' || **str > '9')
+			break;
 
-	*error = NULL;
-	if (messages_count == 0) {
-		*error = "No messages in mailbox";
-		return -2;
+		num = num*10 + (**str - '0');
+		(*str)++;
 	}
 
-	all_found = TRUE;
-	input = messageset;
-	while (*input != '\0') {
-		if (*input == '*') {
-			/* last message */
-			seq = messages_count;
-			input++;
-		} else {
-			seq = get_next_number(&input);
-			if (seq == 0) {
-				*error = t_strconcat("Invalid messageset: ",
-						     messageset, NULL);
-				return -2;
-			}
-		}
+	return num;
+}
 
-		if (*input != ':')
-			seq2 = seq;
-		else {
-			/* first:last range */
-			input++;
+static int messageset_parse_next(struct messageset_context *ctx)
+{
+	if (ctx->p == NULL) {
+		/* num1..num2 already set.  */
+		ctx->p = "";
+		return TRUE;
+	}
 
-			if (*input != '*') {
-				seq2 = get_next_number(&input);
-				if (seq2 == 0) {
-					*error = t_strconcat("Invalid "
-							     "messageset: ",
-							     messageset, NULL);
-					return -2;
-				}
-			} else {
-				seq2 = messages_count;
-				input++;
-			}
+	if (*ctx->p == '*') {
+		/* last message */
+		ctx->num1 = (unsigned int)-1;
+		ctx->p++;
+	} else {
+		ctx->num1 = get_next_number(&ctx->p);
+		if (ctx->num1 == 0) {
+			ctx->error = t_strconcat("Invalid messageset: ",
+						 ctx->messageset, NULL);
+			return FALSE;
 		}
+	}
 
-		if (*input == ',')
-			input++;
-		else if (*input != '\0') {
-			*error = t_strdup_printf("Unexpected char '%c' "
-						 "with messageset: %s",
-						 *input, messageset);
-			return -2;
-		}
+	if (*ctx->p != ':')
+		ctx->num2 = ctx->num1;
+	else {
+		/* first:last range */
+		ctx->p++;
 
-		if (seq > messages_count || seq2 > messages_count) {
-			/* non-existent messages requested */
-			if (seq <= messages_count)
-				seq = seq2;
-			*error = t_strdup_printf("Message sequence %u "
-						 "larger than mailbox size %u",
-						 seq, messages_count);
-			return -2;
+		if (*ctx->p == '*') {
+			ctx->num2 = (unsigned int)-1;
+			ctx->p++;
+		} else {
+			ctx->num2 = get_next_number(&ctx->p);
+			if (ctx->num2 == 0) {
+				ctx->error = t_strconcat("Invalid messageset: ",
+							 ctx->messageset, NULL);
+				return FALSE;
+			}
 		}
+	}
 
-		t_push();
-		ret = mail_index_foreach(index, seq, seq2, callback, context);
-		t_pop();
-		if (ret <= 0)
-			return ret;
-		if (ret == 2)
-			all_found = FALSE;
+	if (*ctx->p == ',')
+		ctx->p++;
+	else if (*ctx->p != '\0') {
+		ctx->error = t_strdup_printf("Unexpected char '%c' "
+					     "with messageset: %s",
+					     *ctx->p, ctx->messageset);
+		return FALSE;
 	}
 
-	return all_found ? 1 : 2;
+	if (ctx->num1 > ctx->num2) {
+		/* swap, as specified by latest IMAP4rev1 draft */
+		unsigned int temp = ctx->num1;
+		ctx->num1 = ctx->num2;
+		ctx->num2 = temp;
+	}
+
+	return TRUE;
 }
 
-static int mail_index_uid_foreach(struct mail_index *index,
-				  unsigned int uid, unsigned int uid2,
-				  msgset_foreach_callback_t callback,
-				  void *context)
+static int uidset_init(struct messageset_context *ctx)
 {
-	struct mail_index_record *rec;
-	const struct modify_log_expunge *expunges;
-	unsigned int client_seq, idx_seq, expunges_before, temp;
-	int expunges_found;
+	unsigned int expunges_before;
 
-	if (uid > uid2) {
-		/* swap, as specified by latest IMAP4rev1 spec */
-		temp = uid;
-		uid = uid2;
-		uid2 = temp;
+	if (ctx->num1 == (unsigned int)-1) {
+		struct mail_index_record *rec;
+
+		rec = ctx->index->lookup(ctx->index, ctx->messages_count);
+		ctx->num1 = rec == NULL ? 0 : rec->uid;
 	}
 
+	if (ctx->num2 == (unsigned int)-1)
+		ctx->num2 = ctx->index->header->next_uid-1;
+
 	/* get list of expunged messages in our range. */
-	expunges = mail_modifylog_uid_get_expunges(index->modifylog, uid, uid2,
-						   &expunges_before);
-	if (expunges == NULL)
+	ctx->expunges = mail_modifylog_uid_get_expunges(ctx->index->modifylog,
+							ctx->num1, ctx->num2,
+							&expunges_before);
+	if (ctx->expunges == NULL)
 		return -1;
 
-	expunges_found = expunges->uid1 != 0;
+	if (ctx->expunges->uid1 != 0)
+		ctx->expunges_found = TRUE;
 
-	rec = index->lookup_uid_range(index, uid, uid2, &idx_seq);
-	if (rec == NULL)
-		return expunges_found ? 2 : 1;
+	/* get the first message */
+	ctx->mail.rec = ctx->index->lookup_uid_range(ctx->index,
+						     ctx->num1, ctx->num2,
+						     &ctx->mail.idx_seq);
+	if (ctx->mail.rec == NULL) {
+		return ctx->index->get_last_error(ctx->index) ==
+			MAIL_INDEX_ERROR_NONE ? 1 : -1;
+	}
 
-	client_seq = idx_seq + expunges_before;
-	while (rec != NULL && rec->uid <= uid2) {
-		while (expunges->uid1 != 0 && expunges->uid1 < rec->uid) {
-			i_assert(expunges->uid2 < rec->uid);
+	ctx->mail.client_seq = ctx->mail.idx_seq + expunges_before;
+	return 0;
+}
 
-			client_seq += expunges->seq_count;
-			expunges++;
-		}
-		i_assert(!(expunges->uid1 <= rec->uid &&
-			   expunges->uid2 >= rec->uid));
+static int seqset_init(struct messageset_context *ctx)
+{
+	unsigned int expunges_before;
 
-		t_push();
-		if (!callback(index, rec, client_seq, idx_seq, context)) {
-			t_pop();
-			return 0;
-		}
-		t_pop();
+	if (ctx->num1 == (unsigned int)-1)
+		ctx->num1 = ctx->messages_count;
 
-		client_seq++; idx_seq++;
-		rec = index->next(index, rec);
-	}
+	if (ctx->num2 == (unsigned int)-1)
+		ctx->num2 = ctx->messages_count;
 
-	if (rec == NULL &&
-	    index->get_last_error(index) != MAIL_INDEX_ERROR_NONE) {
-		/* error occured */
+	/* get list of expunged messages in our range. the expunges_before
+	   can be used to calculate the current real sequence position */
+	ctx->expunges = mail_modifylog_seq_get_expunges(ctx->index->modifylog,
+							ctx->num1, ctx->num2,
+							&expunges_before);
+	if (ctx->expunges == NULL)
 		return -1;
+
+	i_assert(expunges_before < ctx->num1);
+	if (ctx->expunges->uid1 != 0)
+		ctx->expunges_found = TRUE;
+
+	/* get the first non-expunged message. note that if all messages
+	   were expunged in the range, this points outside wanted range. */
+	ctx->mail.idx_seq = ctx->num1 - expunges_before;
+	ctx->mail.rec = ctx->index->lookup(ctx->index, ctx->mail.idx_seq);
+	if (ctx->mail.rec == NULL) {
+		return ctx->index->get_last_error(ctx->index) ==
+			MAIL_INDEX_ERROR_NONE ? 1 : -1;
 	}
 
-	return expunges_found ? 2 : 1;
+	ctx->mail.client_seq = ctx->num1;
+	return 0;
 }
 
-static int mail_index_uidset_foreach(struct mail_index *index,
-				     const char *uidset,
-				     unsigned int messages_count,
-				     msgset_foreach_callback_t callback,
-				     void *context, const char **error)
+const struct messageset_mail *
+index_messageset_next(struct messageset_context *ctx)
 {
-	struct mail_index_record *rec;
-	const char *input;
-	unsigned int uid, uid2;
-	int ret, all_found;
+	struct messageset_mail *mail = &ctx->mail;
+	int last;
 
-	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
+	if (ctx->ret != 0)
+		return NULL;
 
-	*error = NULL;
+	if (!ctx->uidset)
+		last = mail->rec == NULL || mail->client_seq >= ctx->num2;
+	else
+		last = mail->rec == NULL || mail->rec->uid >= ctx->num2;
 
-	all_found = TRUE;
-	input = uidset;
-	while (*input != '\0') {
-		if (*input == '*') {
-			/* last message */
-			if (messages_count == 0)
-				uid = 0;
-			else {
-				rec = index->lookup(index, messages_count);
-				uid = rec == NULL ? 0 : rec->uid;
-			}
-			input++;
-		} else {
-			uid = get_next_number(&input);
-			if (uid == 0) {
-				*error = t_strconcat("Invalid uidset: ",
-						     uidset, NULL);
-				return -2;
+	if (!last) {
+		mail->rec = ctx->index->next(ctx->index, mail->rec);
+		mail->client_seq++;
+		mail->idx_seq++;
+	} else {
+		do {
+			if (ctx->p != NULL && *ctx->p == '\0') {
+				/* finished */
+				ctx->ret = 1;
+				return NULL;
 			}
-		}
 
-		if (*input != ':')
-			uid2 = uid;
-		else {
-			/* first:last range */
-			input++;
-
-			if (*input != '*') {
-				uid2 = get_next_number(&input);
-				if (uid2 == 0) {
-					*error = t_strconcat("Invalid uidset: ",
-							     uidset, NULL);
-					return -2;
-				}
-			} else {
-				uid2 = index->header->next_uid-1;
-				input++;
+			if (!messageset_parse_next(ctx)) {
+				ctx->ret = -2;
+				return NULL;
 			}
-		}
 
-		if (*input == ',')
-			input++;
-		else if (*input != '\0') {
-			*error = t_strdup_printf("Unexpected char '%c' with "
-						 "uidset: %s", *input, uidset);
-			return -2;
-		}
+			if (ctx->uidset)
+				ctx->ret = uidset_init(ctx);
+			else
+				ctx->ret = seqset_init(ctx);
+		} while (ctx->ret == 1);
 
-		t_push();
-		ret = mail_index_uid_foreach(index, uid, uid2,
-					     callback, context);
-		t_pop();
-		if (ret <= 0)
-			return ret;
-		if (ret == 2)
-			all_found = FALSE;
+		if (ctx->ret != 0)
+			return NULL;
 	}
 
-	return all_found ? 1 : 2;
-}
-
-int index_messageset_foreach(struct index_mailbox *ibox,
-			     const char *messageset, int uidset,
-			     msgset_foreach_callback_t callback, void *context)
-{
-	const char *error;
-	int ret;
+	/* fix client_seq */
+	while (ctx->expunges->uid1 != 0 &&
+	       ctx->expunges->uid1 < mail->rec->uid) {
+		i_assert(ctx->expunges->uid2 < mail->rec->uid);
 
-	if (uidset) {
-		ret = mail_index_uidset_foreach(ibox->index, messageset,
-						ibox->synced_messages_count,
-						callback, context, &error);
-	} else {
-		ret = mail_index_messageset_foreach(ibox->index, messageset,
-						    ibox->synced_messages_count,
-						    callback, context, &error);
+		mail->client_seq += ctx->expunges->seq_count;
+		ctx->expunges++;
 	}
 
-	if (ret < 0) {
-		if (ret == -2) {
-			/* user error */
-			mail_storage_set_syntax_error(ibox->box.storage,
-						      "%s", error);
-		} else {
-			mail_storage_set_index_error(ibox);
-		}
+	i_assert(!(ctx->expunges->uid1 <= mail->rec->uid &&
+		   ctx->expunges->uid2 >= mail->rec->uid));
+
+	if (!ctx->uidset && mail->client_seq > ctx->num2) {
+		/* finished this set - see if there's more */
+		return index_messageset_next(ctx);
 	}
 
-	return ret;
+	return mail;
 }

Index: index-messageset.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-messageset.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- index-messageset.h	11 Jan 2003 19:55:57 -0000	1.5
+++ index-messageset.h	20 Jan 2003 14:52:51 -0000	1.6
@@ -1,20 +1,29 @@
 #ifndef __INDEX_MESSAGESET_H
 #define __INDEX_MESSAGESET_H
 
-#include "index-storage.h"
+struct index_mailbox;
 
-/* If FALSE is returned, the loop is stopped. */
-typedef int (*msgset_foreach_callback_t)(struct mail_index *index,
-					 struct mail_index_record *rec,
-					 unsigned int client_seq,
-					 unsigned int idx_seq,
-					 void *context);
+struct messageset_mail {
+	struct mail_index_record *rec;
+	unsigned int client_seq;
+	unsigned int idx_seq;
+};
 
-/* Returns 1 if all were found, 2 if some messages were deleted,
-   0 callback returned FALSE, -1 if internal error occured or -2 if messageset
-   was invalid. */
-int index_messageset_foreach(struct index_mailbox *ibox,
-			     const char *messageset, int uidset,
-			     msgset_foreach_callback_t callback, void *context);
+struct messageset_context;
+
+struct messageset_context *
+index_messageset_init(struct index_mailbox *ibox,
+		      const char *messageset, int uidset);
+
+struct messageset_context *
+index_messageset_init_range(struct index_mailbox *ibox,
+			    unsigned int num1, unsigned int num2, int uidset);
+
+/* Returns 1 if all were found, 0 if some messages were deleted,
+   -1 if internal error occured or -2 if messageset was invalid. */
+int index_messageset_deinit(struct messageset_context *ctx);
+
+const struct messageset_mail *
+index_messageset_next(struct messageset_context *ctx);
 
 #endif

Index: index-search.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-search.c,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -d -r1.64 -r1.65
--- index-search.c	13 Jan 2003 21:29:09 -0000	1.64
+++ index-search.c	20 Jan 2003 14:52:51 -0000	1.65
@@ -2,21 +2,19 @@
 
 #include "lib.h"
 #include "istream.h"
-#include "ostream.h"
-#include "mmap-util.h"
+#include "str.h"
+#include "message-address.h"
 #include "message-date.h"
-#include "message-size.h"
 #include "message-body-search.h"
 #include "message-header-search.h"
 #include "imap-date.h"
 #include "imap-envelope.h"
 #include "index-storage.h"
-#include "index-sort.h"
-#include "mail-index-util.h"
-#include "mail-modifylog.h"
+#include "index-messageset.h"
+#include "index-mail.h"
 #include "mail-custom-flags.h"
+#include "mail-modifylog.h"
 #include "mail-search.h"
-#include "mail-thread.h"
 
 #include <stdlib.h>
 #include <ctype.h>
@@ -29,24 +27,23 @@
 #define TXT_UNKNOWN_CHARSET "[BADCHARSET] Unknown charset"
 #define TXT_INVALID_SEARCH_KEY "Invalid search key"
 
-struct search_index_context {
-	pool_t hdr_pool;
+struct mail_search_context {
 	struct index_mailbox *ibox;
-	struct mail_index_record *rec;
-	unsigned int client_seq;
-	const char *charset;
-	const char *error;
+	char *charset;
+	struct mail_search_arg *args;
 
-	unsigned int cached:1;
-	unsigned int threading:1;
+	struct messageset_context *msgset_ctx;
+	struct index_mail imail;
+	struct mail *mail;
 
-	/* for threading: */
-	const char *message_id, *in_reply_to, *references;
-	time_t sent_date;
+	pool_t hdr_pool;
+	const char *error;
+
+	int failed;
 };
 
 struct search_header_context {
-        struct search_index_context *index_context;
+        struct mail_search_context *index_context;
 	struct mail_search_arg *args;
 
 	const unsigned char *name, *value;
@@ -57,13 +54,11 @@
 };
 
 struct search_body_context {
-        struct search_index_context *index_ctx;
+        struct mail_search_context *index_ctx;
 	struct istream *input;
-	struct message_part *part;
+	const struct message_part *part;
 };
 
-static enum mail_sort_type sort_unsorted[] = { MAIL_SORT_END };
-
 static int msgset_contains(const char *set, unsigned int match_num,
 			   unsigned int max_num)
 {
@@ -175,7 +170,7 @@
 {
 	switch (type) {
 	case SEARCH_ALL:
-		return TRUE;
+		return 1;
 	case SEARCH_SET:
 		return msgset_contains(value, client_seq,
 				       ibox->synced_messages_count);
@@ -206,9 +201,10 @@
 
 static void search_index_arg(struct mail_search_arg *arg, void *context)
 {
-	struct search_index_context *ctx = context;
+	struct mail_search_context *ctx = context;
 
-	switch (search_arg_match_index(ctx->ibox, ctx->rec, ctx->client_seq,
+	switch (search_arg_match_index(ctx->ibox, ctx->imail.data.rec,
+				       ctx->mail->seq,
 				       arg->type, arg->value.str)) {
 	case -1:
 		/* unknown */
@@ -222,19 +218,8 @@
 	}
 }
 
-static struct imap_message_cache *
-search_open_cache(struct search_index_context *ctx)
-{
-	if (!ctx->cached) {
-		(void)index_msgcache_open(ctx->ibox->cache,
-					  ctx->ibox->index, ctx->rec, 0);
-		ctx->cached = TRUE;
-	}
-	return ctx->ibox->cache;
-}
-
 /* Returns >0 = matched, 0 = not matched, -1 = unknown */
-static int search_arg_match_cached(struct search_index_context *ctx,
+static int search_arg_match_cached(struct mail_search_context *ctx,
 				   enum mail_search_arg_type type,
 				   const char *value)
 {
@@ -246,8 +231,7 @@
 	case SEARCH_BEFORE:
 	case SEARCH_ON:
 	case SEARCH_SINCE:
-		internal_date = imap_msgcache_get_internal_date(
-					search_open_cache(ctx));
+		internal_date = ctx->mail->get_received_date(ctx->mail);
 		if (internal_date == (time_t)-1)
 			return -1;
 
@@ -270,8 +254,7 @@
 	/* sizes */
 	case SEARCH_SMALLER:
 	case SEARCH_LARGER:
-		virtual_size = imap_msgcache_get_virtual_size(
-					search_open_cache(ctx));
+		virtual_size = ctx->mail->get_size(ctx->mail);
 		if (virtual_size == (uoff_t)-1)
 			return -1;
 
@@ -288,7 +271,7 @@
 
 static void search_cached_arg(struct mail_search_arg *arg, void *context)
 {
-	struct search_index_context *ctx = context;
+	struct mail_search_context *ctx = context;
 
 	switch (search_arg_match_cached(ctx, arg->type,
 					arg->value.str)) {
@@ -318,7 +301,8 @@
 
 	/* NOTE: Latest IMAP4rev1 draft specifies that timezone is ignored
 	   in searches. sent_time is returned as UTC, so change it. */
-	if (!message_date_parse(sent_value, &sent_time, &timezone_offset))
+	if (!message_date_parse((const unsigned char *) sent_value, (size_t)-1,
+				&sent_time, &timezone_offset))
 		return 0;
 	sent_time -= timezone_offset * 60;
 
@@ -336,7 +320,7 @@
 }
 
 static struct header_search_context *
-search_header_context(struct search_index_context *ctx,
+search_header_context(struct mail_search_context *ctx,
 		      struct mail_search_arg *arg)
 {
 	int unknown_charset;
@@ -363,7 +347,7 @@
 }
 
 /* Returns >0 = matched, 0 = not matched, -1 = unknown */
-static int search_arg_match_envelope(struct search_index_context *ctx,
+static int search_arg_match_envelope(struct mail_search_context *ctx,
 				     struct mail_search_arg *arg)
 {
 	struct mail_index *index = ctx->ibox->index;
@@ -408,7 +392,8 @@
 	t_push();
 
 	/* get field from hopefully cached envelope */
-	envelope = index->lookup_field(index, ctx->rec, DATA_FIELD_ENVELOPE);
+	envelope = index->lookup_field(index, ctx->imail.data.rec,
+				       DATA_FIELD_ENVELOPE);
 	if (envelope != NULL) {
 		ret = imap_envelope_parse(envelope, env_field,
 					  IMAP_ENVELOPE_RESULT_TYPE_STRING,
@@ -457,7 +442,7 @@
 
 static void search_envelope_arg(struct mail_search_arg *arg, void *context)
 {
-	struct search_index_context *ctx = context;
+	struct mail_search_context *ctx = context;
 
 	switch (search_arg_match_envelope(ctx, arg)) {
 	case -1:
@@ -534,13 +519,24 @@
 	} else {
 		t_push();
 
-		/* then check if the value matches */
 		hdr_search_ctx = search_header_context(ctx->index_context, arg);
 		if (hdr_search_ctx == NULL)
 			ret = 0;
-		else {
-			len = ctx->value_len;
-			ret = message_header_search(ctx->value, len,
+		else if (arg->type == SEARCH_FROM || arg->type == SEARCH_TO ||
+			 arg->type == SEARCH_CC || arg->type == SEARCH_BCC) {
+			/* we have to match against normalized address */
+			struct message_address *addr;
+			string_t *str;
+
+			addr = message_address_parse(data_stack_pool,
+						     ctx->value, ctx->value_len,
+						     0);
+			str = t_str_new(ctx->value_len);
+			message_address_write(str, addr);
+			ret = message_header_search(str_data(str), str_len(str),
+						    hdr_search_ctx) ? 1 : 0;
+		} else {
+			ret = message_header_search(ctx->value, ctx->value_len,
 						    hdr_search_ctx) ? 1 : 0;
 		}
 		t_pop();
@@ -549,34 +545,15 @@
         ARG_SET_RESULT(arg, ret);
 }
 
-static void search_header(struct message_part *part __attr_unused__,
+static void search_header(struct message_part *part,
 			  const unsigned char *name, size_t name_len,
 			  const unsigned char *value, size_t value_len,
 			  void *context)
 {
 	struct search_header_context *ctx = context;
-	int timezone_offset;
-
-	if (ctx->threading) {
-		struct search_index_context *ictx = ctx->index_context;
 
-		if (name_len == 10 && memcasecmp(name, "Message-ID", 10) == 0)
-			ictx->message_id = t_strndup(value, value_len);
-		else if (name_len == 11 &&
-			 memcasecmp(name, "In-Reply-To", 11) == 0)
-			ictx->in_reply_to = t_strndup(value, value_len);
-		else if (name_len == 10 &&
-			 memcasecmp(name, "References", 10) == 0)
-			ictx->references = t_strndup(value, value_len);
-		else if (name_len == 4 && memcasecmp(name, "Date", 4) == 0) {
-			t_push();
-			if (!message_date_parse(t_strndup(value, value_len),
-						&ictx->sent_date,
-						&timezone_offset))
-				ictx->sent_date = 0;
-			t_pop();
-		}
-	}
+	index_mail_parse_header(part, name, name_len, value, value_len,
+				ctx->index_context->mail);
 
 	if ((ctx->custom_header && name_len > 0) ||
 	    (name_len == 4 && memcasecmp(name, "Date", 4) == 0) ||
@@ -620,36 +597,39 @@
 }
 
 static int search_arg_match_text(struct mail_search_arg *args,
-				 struct search_index_context *ctx)
+				 struct mail_search_context *ctx)
 {
 	struct istream *input;
 	int have_headers, have_body, have_text;
 
 	/* first check what we need to use */
 	mail_search_args_analyze(args, &have_headers, &have_body, &have_text);
-	if (ctx->threading)
-		have_headers = TRUE;
 	if (!have_headers && !have_body && !have_text)
 		return TRUE;
 
 	if (have_headers || have_text) {
 		struct search_header_context hdr_ctx;
 
-		if (!imap_msgcache_get_data(search_open_cache(ctx), &input))
+		input = ctx->mail->get_stream(ctx->mail, NULL, NULL);
+		if (input == NULL)
 			return FALSE;
 
 		memset(&hdr_ctx, 0, sizeof(hdr_ctx));
 		hdr_ctx.index_context = ctx;
 		hdr_ctx.custom_header = TRUE;
 		hdr_ctx.args = args;
-		hdr_ctx.threading = ctx->threading;
 
+		index_mail_init_parse_header(&ctx->imail);
 		message_parse_header(NULL, input, NULL,
 				     search_header, &hdr_ctx);
 	} else {
-		if (!imap_msgcache_get_rfc822(search_open_cache(ctx), &input,
-					      NULL, NULL))
+		struct message_size hdr_size;
+
+		input = ctx->mail->get_stream(ctx->mail, &hdr_size, NULL);
+		if (input == NULL)
 			return FALSE;
+
+		i_stream_seek(input, hdr_size.physical_size);
 	}
 
 	if (have_text || have_body) {
@@ -658,7 +638,7 @@
 		memset(&body_ctx, 0, sizeof(body_ctx));
 		body_ctx.index_ctx = ctx;
 		body_ctx.input = input;
-		body_ctx.part = imap_msgcache_get_parts(search_open_cache(ctx));
+		body_ctx.part = ctx->mail->get_parts(ctx->mail);
 
 		mail_search_args_foreach(args, search_body, &body_ctx);
 	}
@@ -706,7 +686,7 @@
 }
 
 static int search_get_sequid(struct index_mailbox *ibox,
-			     struct mail_search_arg *args,
+			     const struct mail_search_arg *args,
 			     unsigned int *first_seq, unsigned int *last_seq,
 			     unsigned int *first_uid, unsigned int *last_uid)
 {
@@ -744,7 +724,7 @@
 }
 
 static int search_limit_by_flags(struct index_mailbox *ibox,
-				 struct mail_search_arg *args,
+				 const struct mail_search_arg *args,
 				 unsigned int *first_uid,
 				 unsigned int *last_uid)
 {
@@ -809,8 +789,10 @@
 		return FALSE;
 	}
 
-	(void)mail_modifylog_seq_get_expunges(ibox->index->modifylog, seq, seq,
-					      &expunges_before);
+	if (mail_modifylog_seq_get_expunges(ibox->index->modifylog, seq, seq,
+					    &expunges_before) == NULL)
+		return FALSE;
+
 	seq -= expunges_before;
 
 	rec = ibox->index->lookup(ibox->index, seq);
@@ -819,7 +801,7 @@
 }
 
 static int search_get_uid_range(struct index_mailbox *ibox,
-				struct mail_search_arg *args,
+				const struct mail_search_arg *args,
 				unsigned int *first_uid, unsigned int *last_uid)
 {
 	unsigned int first_seq, last_seq, uid;
@@ -868,180 +850,143 @@
 	return 1;
 }
 
-static int search_messages(struct index_mailbox *ibox, const char *charset,
-			   struct mail_search_arg *args,
-			   struct mail_sort_context *sort_ctx,
-			   struct mail_thread_context *thread_ctx,
-                           struct index_sort_context *index_sort_ctx,
-			   struct ostream *output, int uid_result)
+int index_storage_search_get_sorting(struct mailbox *box __attr_unused__,
+				     enum mail_sort_type *sort_program)
 {
-	struct search_index_context ctx;
-	struct mail_index_record *rec;
-        struct mail_search_arg *arg;
-	const struct modify_log_expunge *expunges;
-	unsigned int first_uid, last_uid, client_seq, expunges_before;
-	const char *str;
-	int found, failed;
+	/* currently we don't support sorting */
+	*sort_program = MAIL_SORT_END;
+	return TRUE;
+}
+
+struct mail_search_context *
+index_storage_search_init(struct mailbox *box, const char *charset,
+			  struct mail_search_arg *args,
+			  const enum mail_sort_type *sort_program,
+			  enum mail_fetch_field wanted_fields,
+			  const char *const wanted_headers[])
+{
+	struct index_mailbox *ibox = (struct index_mailbox *) box;
+	struct mail_search_context *ctx;
+	unsigned int first_uid, last_uid;
+
+	if (sort_program != NULL && *sort_program != MAIL_SORT_END) {
+		i_error("BUG: index_storage_search_init(): "
+			"invalid sort_program");
+		return NULL;
+	}
+
+	if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED))
+		return NULL;
+
+	ctx = i_new(struct mail_search_context, 1);
+	ctx->ibox = ibox;
+	ctx->charset = i_strdup(charset);
+	ctx->args = args;
+
+	ctx->mail = (struct mail *) &ctx->imail;
+	index_mail_init(ibox, &ctx->imail, wanted_fields, wanted_headers);
 
 	if (ibox->synced_messages_count == 0)
-		return TRUE;
+		return ctx;
 
 	/* see if we can limit the records we look at */
 	switch (search_get_uid_range(ibox, args, &first_uid, &last_uid)) {
 	case -1:
 		/* error */
-		return FALSE;
+		ctx->failed = TRUE;
+		return ctx;
 	case 0:
 		/* nothing found */
-		return TRUE;
+		return ctx;
 	}
 
-	rec = ibox->index->lookup_uid_range(ibox->index, first_uid, last_uid,
-					    &client_seq);
-	if (rec == NULL)
-		return TRUE;
-
-	expunges = mail_modifylog_uid_get_expunges(ibox->index->modifylog,
-						   rec->uid, last_uid,
-						   &expunges_before);
-	client_seq += expunges_before;
-	index_sort_ctx->synced_sequences = expunges->uid1 == 0;
-
-	memset(&ctx, 0, sizeof(ctx));
-	ctx.ibox = ibox;
-	ctx.charset = charset;
-	ctx.threading = thread_ctx != NULL;
-
-	for (; rec != NULL && rec->uid <= last_uid; client_seq++) {
-		while (expunges->uid1 != 0 && expunges->uid1 < rec->uid) {
-			i_assert(expunges->uid2 < rec->uid);
-
-			client_seq += expunges->seq_count;
-			expunges++;
-		}
-		i_assert(!(expunges->uid1 <= rec->uid &&
-			   expunges->uid2 >= rec->uid));
-
-		ctx.rec = rec;
-		ctx.client_seq = client_seq;
-		ctx.cached = FALSE;
-
-		ctx.message_id = ctx.in_reply_to = ctx.references = NULL;
-
-		mail_search_args_reset(args);
+	ctx->msgset_ctx =
+		index_messageset_init_range(ibox, first_uid, last_uid, TRUE);
+	return ctx;
+}
 
-		t_push();
+int index_storage_search_deinit(struct mail_search_context *ctx)
+{
+	int ret;
 
-		mail_search_args_foreach(args, search_index_arg, &ctx);
-		mail_search_args_foreach(args, search_cached_arg, &ctx);
-		mail_search_args_foreach(args, search_envelope_arg, &ctx);
-		failed = !search_arg_match_text(args, &ctx);
-                imap_msgcache_close(ibox->cache);
+	ret = !ctx->failed && ctx->error == NULL;
 
-		if (ctx.error != NULL) {
-			t_pop();
-			break;
-		}
+	if (ctx->msgset_ctx != NULL) {
+		if (index_messageset_deinit(ctx->msgset_ctx) < 0)
+			ret = FALSE;
+	}
 
-		if (!failed) {
-			found = TRUE;
-			for (arg = args; arg != NULL; arg = arg->next) {
-				if (arg->result != 1) {
-					found = FALSE;
-					break;
-				}
-			}
+	if (!index_storage_lock(ctx->ibox, MAIL_LOCK_UNLOCK))
+		ret = FALSE;
 
-			if (found) {
-				unsigned int id = uid_result ?
-					rec->uid : client_seq;
+	if (ctx->error != NULL) {
+		mail_storage_set_error(ctx->ibox->box.storage,
+				       "%s", ctx->error);
+	}
 
-				index_sort_ctx->current_client_seq = client_seq;
-				index_sort_ctx->current_rec = rec;
+	if (ctx->hdr_pool != NULL)
+		pool_unref(ctx->hdr_pool);
 
-				if (sort_ctx != NULL)
-					mail_sort_input(sort_ctx, id);
-				else if (thread_ctx != NULL) {
-					mail_thread_input(thread_ctx, id,
-							  ctx.message_id,
-							  ctx.in_reply_to,
-							  ctx.references,
-							  ctx.sent_date);
-				} else {
-					o_stream_send(output, " ", 1);
+	if (ctx->ibox->fetch_mail.pool != NULL)
+		index_mail_deinit(&ctx->ibox->fetch_mail);
+        index_mail_deinit(&ctx->imail);
+	i_free(ctx);
+	return ret;
+}
 
-					str = dec2str(id);
-					o_stream_send_str(output, str);
-				}
-			}
-		}
-		t_pop();
+struct mail *index_storage_search_next(struct mail_search_context *ctx)
+{
+	const struct messageset_mail *msgset_mail;
+        struct mail_search_arg *arg;
+	int found, ret;
 
-		rec = ibox->index->next(ibox->index, rec);
+	if (ctx->msgset_ctx == NULL) {
+		/* initialization failed or didn't found any messages */
+		return NULL;
 	}
 
-	if (ctx.hdr_pool != NULL)
-		pool_unref(ctx.hdr_pool);
-
-	if (ctx.error != NULL)
-		mail_storage_set_error(ibox->box.storage, "%s", ctx.error);
-	return ctx.error == NULL;
-}
+	do {
+		msgset_mail = index_messageset_next(ctx->msgset_ctx);
+		if (msgset_mail == NULL)
+			return NULL;
 
-int index_storage_search(struct mailbox *box, const char *charset,
-			 struct mail_search_arg *args,
-			 enum mail_sort_type *sorting,
-                         enum mail_thread_type threading,
-			 struct ostream *output, int uid_result)
-{
-	struct index_mailbox *ibox = (struct index_mailbox *) box;
-	struct mail_sort_context *sort_ctx;
-	struct mail_thread_context *thread_ctx;
-	struct index_sort_context index_sort_ctx;
-	int failed;
+		ctx->mail->seq = msgset_mail->client_seq;
+		ctx->mail->uid = msgset_mail->rec->uid;
+		ret = index_mail_next(&ctx->imail, msgset_mail->rec);
 
-	if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED))
-		return FALSE;
+		if (ret < 0)
+			return NULL;
 
-	if (sorting != NULL) {
-		memset(&index_sort_ctx, 0, sizeof(index_sort_ctx));
-		index_sort_ctx.ibox = ibox;
-		index_sort_ctx.output = output;
-		index_sort_ctx.id_is_uid = uid_result;
+		if (ret == 0)
+			found = FALSE;
+		else {
+			mail_search_args_reset(ctx->args);
 
-		thread_ctx = NULL;
-		sort_ctx = mail_sort_init(sort_unsorted, sorting, output,
-					  &index_sort_callbacks,
-					  &index_sort_ctx);
-		o_stream_send_str(output, "* SORT");
-	} else if (threading != MAIL_THREAD_NONE) {
-		memset(&index_sort_ctx, 0, sizeof(index_sort_ctx));
-		index_sort_ctx.ibox = ibox;
-		index_sort_ctx.id_is_uid = uid_result;
+			t_push();
 
-		sort_ctx = NULL;
-		thread_ctx = mail_thread_init(threading, output,
-					      &index_sort_callbacks,
-					      &index_sort_ctx);
-		o_stream_send_str(output, "* THREAD");
-	} else {
-		memset(&index_sort_ctx, 0, sizeof(index_sort_ctx));
-		sort_ctx = NULL;
-		thread_ctx = NULL;
-		o_stream_send_str(output, "* SEARCH");
-	}
+			mail_search_args_foreach(ctx->args, search_index_arg,
+						 ctx);
+			mail_search_args_foreach(ctx->args, search_cached_arg,
+						 ctx);
+			mail_search_args_foreach(ctx->args, search_envelope_arg,
+						 ctx);
+			found = search_arg_match_text(ctx->args, ctx);
 
-	failed = !search_messages(ibox, charset, args, sort_ctx, thread_ctx,
-				  &index_sort_ctx, output, uid_result);
-	if (sort_ctx != NULL)
-		mail_sort_deinit(sort_ctx);
-	if (thread_ctx != NULL)
-		mail_thread_finish(thread_ctx);
+			t_pop();
 
-	o_stream_send(output, "\r\n", 2);
+			if (ctx->error != NULL)
+				return NULL;
+		}
 
-	if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
-		return FALSE;
+		if (found) {
+			for (arg = ctx->args; arg != NULL; arg = arg->next) {
+				if (arg->result != 1) {
+					found = FALSE;
+					break;
+				}
+			}
+		}
+	} while (!found);
 
-	return !failed;
+	return ctx->mail;
 }

Index: index-storage.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-storage.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- index-storage.c	10 Jan 2003 11:29:24 -0000	1.25
+++ index-storage.c	20 Jan 2003 14:52:51 -0000	1.26
@@ -227,7 +227,6 @@
 		ibox->box.allow_custom_flags = TRUE;
 
 		ibox->index = index;
-		ibox->cache = imap_msgcache_alloc(&index_msgcache_iface);
 
 		ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
 		index->set_lock_notify_callback(index, lock_notify, ibox);
@@ -266,7 +265,6 @@
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
 
 	index_mailbox_check_remove(ibox);
-	imap_msgcache_free(ibox->cache);
 	if (ibox->index != NULL)
 		index_storage_unref(ibox->index);
 
@@ -316,13 +314,14 @@
 
 int index_mailbox_fix_custom_flags(struct index_mailbox *ibox,
 				   enum mail_flags *flags,
-                                   const char *custom_flags[])
+				   const char *custom_flags[],
+				   unsigned int custom_flags_count)
 {
 	int ret;
 
 	ret = mail_custom_flags_fix_list(ibox->index->custom_flags,
 					 flags, custom_flags,
-					 MAIL_CUSTOM_FLAGS_COUNT);
+					 custom_flags_count);
 	switch (ret) {
 	case 1:
 		return TRUE;

Index: index-storage.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-storage.h,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- index-storage.h	10 Jan 2003 11:29:24 -0000	1.28
+++ index-storage.h	20 Jan 2003 14:52:51 -0000	1.29
@@ -3,7 +3,7 @@
 
 #include "mail-storage.h"
 #include "mail-index.h"
-#include "imap-message-cache.h"
+#include "index-mail.h"
 
 struct index_mailbox {
 	struct mailbox box;
@@ -13,13 +13,13 @@
 	int (*expunge_locked)(struct index_mailbox *ibox, int notify);
 
 	struct mail_index *index;
-	struct imap_message_cache *cache;
 
 	char *check_path;
 	struct timeout *check_to;
 	time_t check_file_stamp;
 	time_t last_check;
 
+	struct index_mail fetch_mail; /* fetch_uid() or fetch_seq() */
 	unsigned int synced_messages_count;
 
 	time_t next_lock_notify; /* temporary */
@@ -28,8 +28,6 @@
 	unsigned int delay_save_unlocking:1; /* For COPYing inside mailbox */
 };
 
-extern struct imap_message_cache_iface index_msgcache_iface;
-
 int mail_storage_set_index_error(struct index_mailbox *ibox);
 void index_storage_init_lock_notify(struct index_mailbox *ibox);
 int index_storage_lock(struct index_mailbox *ibox,
@@ -51,7 +49,8 @@
 
 int index_mailbox_fix_custom_flags(struct index_mailbox *ibox,
 				   enum mail_flags *flags,
-                                   const char *custom_flags[]);
+				   const char *custom_flags[],
+				   unsigned int custom_flags_count);
 
 unsigned int index_storage_get_recent_count(struct mail_index *index);
 
@@ -65,10 +64,6 @@
 		       struct istream *input, struct ostream *output,
 		       uoff_t data_size);
 
-int index_msgcache_open(struct imap_message_cache *cache,
-			struct mail_index *index, struct mail_index_record *rec,
-			enum imap_cache_field fields);
-
 void index_mailbox_check_add(struct index_mailbox *ibox, const char *path);
 void index_mailbox_check_remove(struct index_mailbox *ibox);
 
@@ -84,16 +79,31 @@
 			     struct mailbox_status *status);
 int index_storage_sync(struct mailbox *box, int sync_expunges);
 int index_storage_update_flags(struct mailbox *box, const char *messageset,
-			       int uidset, enum mail_flags flags,
-			       const char *custom_flags[],
+			       int uidset, const struct mail_full_flags *flags,
 			       enum modify_type modify_type, int notify,
 			       int *all_found);
-int index_storage_fetch(struct mailbox *box, struct mail_fetch_data *fetch_data,
-			struct ostream *output, int *all_found);
-int index_storage_search(struct mailbox *box, const char *charset,
-			 struct mail_search_arg *args,
-			 enum mail_sort_type *sorting,
-                         enum mail_thread_type threading,
-			 struct ostream *output, int uid_result);
+
+struct mail_fetch_context *
+index_storage_fetch_init(struct mailbox *box,
+			 enum mail_fetch_field wanted_fields, int *update_seen,
+			 const char *messageset, int uidset);
+int index_storage_fetch_deinit(struct mail_fetch_context *ctx, int *all_found);
+struct mail *index_storage_fetch_next(struct mail_fetch_context *ctx);
+
+struct mail *index_storage_fetch_uid(struct mailbox *box, unsigned int uid,
+				     enum mail_fetch_field wanted_fields);
+struct mail *index_storage_fetch_seq(struct mailbox *box, unsigned int seq,
+				     enum mail_fetch_field wanted_fields);
+
+int index_storage_search_get_sorting(struct mailbox *box,
+				     enum mail_sort_type *sort_program);
+struct mail_search_context *
+index_storage_search_init(struct mailbox *box, const char *charset,
+			  struct mail_search_arg *args,
+			  const enum mail_sort_type *sort_program,
+			  enum mail_fetch_field wanted_fields,
+			  const char *const wanted_headers[]);
+int index_storage_search_deinit(struct mail_search_context *ctx);
+struct mail *index_storage_search_next(struct mail_search_context *ctx);
 
 #endif

Index: index-update-flags.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-update-flags.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- index-update-flags.c	11 Jan 2003 19:55:57 -0000	1.17
+++ index-update-flags.c	20 Jan 2003 14:52:51 -0000	1.18
@@ -5,78 +5,76 @@
 #include "index-messageset.h"
 #include "mail-custom-flags.h"
 
-struct update_context {
-	struct index_mailbox *ibox;
-	enum mail_flags flags;
-	enum modify_type modify_type;
-	int notify;
-};
-
-static int update_cb(struct mail_index *index, struct mail_index_record *rec,
-		     unsigned int client_seq, unsigned int idx_seq,
-		     void *context)
+static int update_messageset(struct messageset_context *ctx,
+			     struct index_mailbox *ibox, enum mail_flags flags,
+			     enum modify_type modify_type, int notify)
 {
-	struct update_context *ctx = context;
 	struct mail_storage *storage;
-	enum mail_flags flags;
+	const struct messageset_mail *mail;
 	const char **custom_flags;
+	enum mail_flags new_flags;
 
-	switch (ctx->modify_type) {
-	case MODIFY_ADD:
-		flags = rec->msg_flags | ctx->flags;
-		break;
-	case MODIFY_REMOVE:
-		flags = rec->msg_flags & ~ctx->flags;
-		break;
-	case MODIFY_REPLACE:
-		flags = ctx->flags;
-		break;
-	default:
-                i_unreached();
-	}
+	storage = ibox->box.storage;
+	custom_flags = mail_custom_flags_list_get(ibox->index->custom_flags);
 
-	if (!index->update_flags(index, rec, idx_seq, flags, FALSE))
-		return FALSE;
+	while ((mail = index_messageset_next(ctx)) != NULL) {
+		switch (modify_type) {
+		case MODIFY_ADD:
+			new_flags = mail->rec->msg_flags | flags;
+			break;
+		case MODIFY_REMOVE:
+			new_flags = mail->rec->msg_flags & ~flags;
+			break;
+		case MODIFY_REPLACE:
+			new_flags = flags;
+			break;
+		default:
+			i_unreached();
+		}
 
-	storage = ctx->ibox->box.storage;
-	if (mail_custom_flags_has_changes(index->custom_flags)) {
-		storage->callbacks->new_custom_flags(&ctx->ibox->box,
-			mail_custom_flags_list_get(index->custom_flags),
-			MAIL_CUSTOM_FLAGS_COUNT, storage->callback_context);
-	}
+		if (!ibox->index->update_flags(ibox->index, mail->rec,
+					       mail->idx_seq, new_flags, FALSE))
+			return -1;
 
-	if (ctx->notify) {
-		if (rec->uid >= index->first_recent_uid)
-			flags |= MAIL_RECENT;
+		if (mail_custom_flags_has_changes(ibox->index->custom_flags)) {
+			storage->callbacks->new_custom_flags(&ibox->box,
+				custom_flags, MAIL_CUSTOM_FLAGS_COUNT,
+				storage->callback_context);
+		}
 
-                custom_flags = mail_custom_flags_list_get(index->custom_flags);
-		storage->callbacks->update_flags(&ctx->ibox->box,
-						 client_seq, rec->uid,
-						 flags, custom_flags,
-						 MAIL_CUSTOM_FLAGS_COUNT,
-						 storage->callback_context);
+		if (notify) {
+			if (mail->rec->uid >= ibox->index->first_recent_uid)
+				new_flags |= MAIL_RECENT;
+
+			storage->callbacks->update_flags(&ibox->box,
+				mail->client_seq, mail->rec->uid, new_flags,
+				custom_flags, MAIL_CUSTOM_FLAGS_COUNT,
+				storage->callback_context);
+		}
 	}
 
-	return TRUE;
+	return 1;
 }
 
-int index_storage_update_flags(struct mailbox *box,
-			       const char *messageset, int uidset,
-			       enum mail_flags flags,
-			       const char *custom_flags[],
+int index_storage_update_flags(struct mailbox *box, const char *messageset,
+			       int uidset, const struct mail_full_flags *flags,
 			       enum modify_type modify_type, int notify,
 			       int *all_found)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
-        struct update_context ctx;
-	int ret;
+        struct messageset_context *ctx;
+	enum mail_flags mail_flags;
+	int ret, ret2;
 
 	if (box->readonly) {
 		mail_storage_set_error(box->storage, "Mailbox is read-only");
 		return FALSE;
 	}
 
-	if (!index_mailbox_fix_custom_flags(ibox, &flags, custom_flags))
+	mail_flags = flags->flags;
+	if (!index_mailbox_fix_custom_flags(ibox, &mail_flags,
+					    flags->custom_flags,
+					    flags->custom_flags_count))
 		return FALSE;
 
 	if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
@@ -85,18 +83,16 @@
 	if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_UNLOCK))
 		return FALSE;
 
-	ctx.ibox = ibox;
-	ctx.flags = flags & ~MAIL_RECENT; /* \Recent can't be changed */
-	ctx.modify_type = modify_type;
-	ctx.notify = notify;
+	mail_flags &= ~MAIL_RECENT; /* \Recent can't be changed */
 
-	ret = index_messageset_foreach(ibox, messageset, uidset,
-				       update_cb, &ctx);
+	ctx = index_messageset_init(ibox, messageset, uidset);
+	ret = update_messageset(ctx, ibox, mail_flags, modify_type, notify);
+	ret2 = index_messageset_deinit(ctx);
 
 	if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
 		return FALSE;
 
 	if (all_found != NULL)
-		*all_found = ret == 1;
-	return ret >= 0;
+		*all_found = ret2 > 0;
+	return ret >= 0 && ret2 >= 0;
 }

--- index-fetch-section.c DELETED ---

--- index-msgcache.c DELETED ---

--- index-sort.c DELETED ---

--- index-sort.h DELETED ---




More information about the dovecot-cvs mailing list