[dovecot-cvs] dovecot/src/lib-storage/index index-transaction.c, NONE, 1.1 Makefile.am, 1.12, 1.13 index-fetch.c, 1.52, 1.53 index-mail-headers.c, 1.17, 1.18 index-mail.c, 1.24, 1.25 index-mail.h, 1.10, 1.11 index-mailbox-check.c, 1.7, 1.8 index-search.c, 1.82, 1.83 index-status.c, 1.26, 1.27 index-storage.c, 1.41, 1.42 index-storage.h, 1.53, 1.54 index-sync.c, 1.27, 1.28 index-copy.c, 1.29, NONE index-expunge.c, 1.20, NONE index-expunge.h, 1.1, NONE index-messageset.c, 1.21, NONE index-messageset.h, 1.8, NONE index-update-flags.c, 1.26, NONE

cras at procontrol.fi cras at procontrol.fi
Tue Apr 27 23:25:57 EEST 2004


Update of /home/cvs/dovecot/src/lib-storage/index
In directory talvi:/tmp/cvs-serv29236/src/lib-storage/index

Modified Files:
	Makefile.am index-fetch.c index-mail-headers.c index-mail.c 
	index-mail.h index-mailbox-check.c index-search.c 
	index-status.c index-storage.c index-storage.h index-sync.c 
Added Files:
	index-transaction.c 
Removed Files:
	index-copy.c index-expunge.c index-expunge.h 
	index-messageset.c index-messageset.h index-update-flags.c 
Log Message:
importing new index code. mbox still broken.



--- NEW FILE: index-transaction.c ---
/* Copyright (C) 2003 Timo Sirainen */

#include "lib.h"
#include "index-storage.h"

static void index_transaction_free(struct index_transaction_context *t)
{
	mail_index_view_unlock(t->ibox->view);

	if (t->fetch_mail.pool != NULL)
		index_mail_deinit(&t->fetch_mail);
	i_free(t);
}

int index_transaction_commit(struct mailbox_transaction_context *_t)
{
	struct index_transaction_context *t =
		(struct index_transaction_context *)_t;
	uint32_t seq;
	uoff_t offset;
	int ret;

	if (t->cache_trans != NULL) 
		(void)mail_cache_transaction_commit(t->cache_trans);

	ret = mail_index_transaction_commit(t->trans, &seq, &offset);
	if (ret < 0)
		mail_storage_set_index_error(t->ibox);

	t->ibox->commit_log_file_seq = seq;
	t->ibox->commit_log_file_offset = offset;

	index_transaction_free(t);
	return ret;
}

void index_transaction_rollback(struct mailbox_transaction_context *_t)
{
	struct index_transaction_context *t =
		(struct index_transaction_context *)_t;

	mail_index_transaction_rollback(t->trans);
	index_transaction_free(t);
}

Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/Makefile.am,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- Makefile.am	18 Aug 2003 03:24:37 -0000	1.12
+++ Makefile.am	27 Apr 2004 20:25:54 -0000	1.13
@@ -10,21 +10,16 @@
 	-I$(top_srcdir)/src/lib-storage
 
 libstorage_index_a_SOURCES = \
-	index-copy.c \
-	index-expunge.c \
 	index-fetch.c \
 	index-mail.c \
 	index-mail-headers.c \
 	index-mailbox-check.c \
-	index-messageset.c \
 	index-search.c \
 	index-status.c \
 	index-storage.c \
 	index-sync.c \
-	index-update-flags.c
+	index-transaction.c
 
 noinst_HEADERS = \
-	index-expunge.h \
 	index-mail.h \
-	index-messageset.h \
 	index-storage.h

Index: index-fetch.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-fetch.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- index-fetch.c	26 Oct 2003 20:13:15 -0000	1.52
+++ index-fetch.c	27 Apr 2004 20:25:54 -0000	1.53
@@ -1,62 +1,46 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2003 Timo Sirainen */
 
 #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-messageset.h"
 #include "index-mail.h"
 
-static struct mail *
-fetch_record(struct index_mailbox *ibox, struct mail_index_record *rec,
-	     unsigned int idx_seq, enum mail_fetch_field wanted_fields)
+struct mail *
+index_storage_fetch(struct mailbox_transaction_context *_t, uint32_t seq,
+		    enum mail_fetch_field wanted_fields)
 {
-	if (ibox->fetch_mail.pool != NULL)
-		index_mail_deinit(&ibox->fetch_mail);
+	struct index_transaction_context *t =
+		(struct index_transaction_context *)_t;
+        const struct mail_index_record *rec;
 
-	index_mail_init(ibox, &ibox->fetch_mail, wanted_fields, NULL);
-	if (index_mail_next(&ibox->fetch_mail, rec, idx_seq, FALSE) <= 0)
+	if (mail_index_lookup(t->ibox->view, seq, &rec) < 0) {
+		mail_storage_set_index_error(t->ibox);
 		return NULL;
+	}
 
-	return &ibox->fetch_mail.mail;
-}
-
-struct mail *index_storage_fetch_uid(struct mailbox *box, unsigned int uid,
-				     enum mail_fetch_field wanted_fields)
-{
-	struct index_mailbox *ibox = (struct index_mailbox *) box;
-	struct mail_index_record *rec;
-	unsigned int seq;
+	if (rec == NULL)
+		return NULL;
 
-	i_assert(ibox->index->lock_type != MAIL_LOCK_UNLOCK);
+	if (t->fetch_mail.pool != NULL)
+		index_mail_deinit(&t->fetch_mail);
 
-	rec = ibox->index->lookup_uid_range(ibox->index, uid, uid, &seq);
-	if (rec == NULL)
+	index_mail_init(t, &t->fetch_mail, wanted_fields, NULL);
+	if (index_mail_next(&t->fetch_mail, rec, seq, FALSE) <= 0)
 		return NULL;
 
-	return fetch_record(ibox, rec, seq, wanted_fields);
+	return &t->fetch_mail.mail;
 }
 
-struct mail *index_storage_fetch_seq(struct mailbox *box, unsigned int seq,
-				     enum mail_fetch_field wanted_fields)
+int index_storage_get_uids(struct mailbox *box,
+			   uint32_t uid1, uint32_t uid2,
+			   uint32_t *seq1_r, uint32_t *seq2_r)
 {
-	struct index_mailbox *ibox = (struct index_mailbox *) box;
-        struct mail_index_record *rec;
-	unsigned int expunges_before;
-
-	i_assert(ibox->index->lock_type != MAIL_LOCK_UNLOCK);
-
-	if (mail_modifylog_seq_get_expunges(ibox->index->modifylog, seq, seq,
-					    &expunges_before) == NULL)
-		return NULL;
+	struct index_mailbox *ibox = (struct index_mailbox *)box;
 
-	seq -= expunges_before;
-	rec = ibox->index->lookup(ibox->index, seq);
-	if (rec == NULL)
-		return NULL;
+	if (mail_index_lookup_uid_range(ibox->view, uid1, uid2,
+					seq1_r, seq2_r) < 0) {
+		mail_storage_set_index_error(ibox);
+		return -1;
+	}
 
-	return fetch_record(ibox, rec, seq, wanted_fields);
+	return 0;
 }

Index: index-mail-headers.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mail-headers.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- index-mail-headers.c	21 Oct 2003 13:50:09 -0000	1.17
+++ index-mail-headers.c	27 Apr 2004 20:25:54 -0000	1.18
@@ -39,6 +39,7 @@
 #include "buffer.h"
 #include "str.h"
 #include "message-date.h"
+#include "message-parser.h"
 #include "imap-envelope.h"
 #include "imap-bodystructure.h"
 #include "index-storage.h"
@@ -140,7 +141,7 @@
 	return data;
 }
 
-static int find_wanted_headers(struct mail_cache *cache,
+static int find_wanted_headers(struct mail_cache_view *cache_view,
 			       const char *const wanted_headers[])
 {
 	const char *const *headers, *const *tmp;
@@ -154,7 +155,7 @@
 
 	ret = -1;
 	for (i = MAIL_CACHE_HEADERS_COUNT-1; i >= 0; i--) {
-		headers = mail_cache_get_header_fields(cache, i);
+		headers = mail_cache_get_header_fields(cache_view, i);
 		if (headers == NULL)
 			continue;
 
@@ -185,7 +186,7 @@
 {
 	int idx;
 
-	idx = find_wanted_headers(mail->ibox->index->cache, wanted_headers);
+	idx = find_wanted_headers(mail->ibox->cache_view, wanted_headers);
 	if (idx < 0)
 		return -1;
 
@@ -433,7 +434,7 @@
 		data->header_stream = istream;
 	} else {
 		str = mail_cache_lookup_string_field(
-			mail->ibox->index->cache, data->rec,
+			mail->ibox->cache_view, data->seq,
 			mail_cache_header_fields[idx]);
 		if (str == NULL) {
 			/* broken - we expected the header to exist */
@@ -446,10 +447,10 @@
 						    str, strlen(str));
 	}
 
-	idx_headers = mail_cache_get_header_fields(mail->ibox->index->cache,
+	idx_headers = mail_cache_get_header_fields(mail->ibox->cache_view,
 						   idx);
 	if (idx_headers == NULL) {
-		mail_cache_set_corrupted(mail->ibox->index->cache,
+		mail_cache_set_corrupted(mail->ibox->cache,
 			"Headers %d names not found", idx);
 		t_pop();
 		return FALSE;
@@ -485,13 +486,14 @@
 
 int index_mail_parse_headers(struct index_mail *mail)
 {
-	struct mail_cache *cache = mail->ibox->index->cache;
 	struct index_mail_data *data = &mail->data;
 	const char *str, *const *headers;
 	int idx, max;
 
-	if (!index_mail_open_stream(mail, 0))
-		return FALSE;
+	if (data->stream == NULL) {
+		if (mail->mail.get_stream(&mail->mail, NULL, NULL) == NULL)
+			return FALSE;
+	}
 
 	if (mail->data.header_data == NULL)
 		mail->data.header_data = str_new(mail->pool, 4096);
@@ -508,8 +510,9 @@
 		/* add all cached headers to beginning of header_data */
                 idx = data->header_data_cached; max = idx-1;
 		for (; idx < MAIL_CACHE_HEADERS_COUNT; idx++) {
-			str = mail_cache_lookup_string_field(cache, data->rec,
-						mail_cache_header_fields[idx]);
+			str = mail_cache_lookup_string_field(
+				mail->ibox->cache_view, mail->data.seq,
+				mail_cache_header_fields[idx]);
 			if (str == NULL)
 				continue;
 
@@ -522,7 +525,8 @@
 
 		/* make sure we cache everything */
 		for (idx = MAIL_CACHE_HEADERS_COUNT-1; idx >= 0; idx--) {
-			headers = mail_cache_get_header_fields(cache, idx);
+			headers = mail_cache_get_header_fields(
+					mail->ibox->cache_view, idx);
 			if (headers != NULL)
 				break;
 		}
@@ -537,8 +541,10 @@
 		if (max >= 0) {
 			/* now we'll have to set value_idx for all headers that
 			   are already cached */
-			if (!parse_cached_headers(mail, max))
+			if (!parse_cached_headers(mail, max)) {
+				/* FIXME: handle better */
 				return FALSE;
+			}
 		}
 
 		/* it's possible that we're parsing headers without wanting
@@ -593,8 +599,10 @@
 			idx = mail_find_wanted_headers(mail, arr);
 
 			if (idx >= 0) {
-				if (!parse_cached_headers(mail, idx))
-					return NULL;
+				if (!parse_cached_headers(mail, idx)) {
+					/* broken cache, parse again */
+					idx = -1;
+				}
 			}
 		}
 
@@ -647,7 +655,7 @@
 		}
 		for (i = data->header_data_cached; i <= idx; i++) {
 			str = mail_cache_lookup_string_field(
-					mail->ibox->index->cache, data->rec,
+					mail->ibox->cache_view, data->seq,
 					mail_cache_header_fields[i]);
 			if (str == NULL)
 				continue;
@@ -679,14 +687,14 @@
 
 void index_mail_headers_init(struct index_mail *mail)
 {
-	struct mail_cache *cache = mail->ibox->index->cache;
+	struct mail_cache_view *cache_view = mail->ibox->cache_view;
 	int idx = -2, idx2 = -2;
 
 	if (mail->wanted_headers != NULL && *mail->wanted_headers != NULL)
-		idx = find_wanted_headers(cache, mail->wanted_headers);
+		idx = find_wanted_headers(cache_view, mail->wanted_headers);
 
 	if (idx != -1 && (mail->wanted_fields & MAIL_FETCH_IMAP_ENVELOPE))
-		idx2 = find_wanted_headers(cache, imap_envelope_headers);
+		idx2 = find_wanted_headers(cache_view, imap_envelope_headers);
 
 	mail->wanted_headers_idx = idx == -1 || idx2 == -1 ? -1 :
 		idx > idx2 ? idx : idx2;
@@ -735,12 +743,12 @@
 	}
 }
 
-static int find_unused_header_idx(struct mail_cache *cache)
+static int find_unused_header_idx(struct mail_cache_view *cache_view)
 {
 	int i;
 
 	for (i = 0; i < MAIL_CACHE_HEADERS_COUNT; i++) {
-		if (mail_cache_get_header_fields(cache, i) == NULL)
+		if (mail_cache_get_header_fields(cache_view, i) == NULL)
 			return i;
 	}
 
@@ -761,21 +769,21 @@
 	   accessing headers from same message. index_mails should probably be
 	   shared.. */
 	headers = cached_header_get_names(mail);
-	idx = find_wanted_headers(mail->ibox->index->cache, headers);
+	idx = find_wanted_headers(mail->ibox->cache_view, headers);
 	if (idx >= 0) {
 		/* all headers found */
 		if (idx != mail->data.header_save_idx) {
-			mail_cache_set_corrupted(mail->ibox->index->cache,
+			mail_cache_set_corrupted(mail->ibox->cache,
 				"Duplicated header names list (%d and %d)",
 				idx, mail->data.header_save_idx);
 		}
 	} else {
 		/* there's some new headers */
-		idx = find_unused_header_idx(mail->ibox->index->cache);
+		idx = find_unused_header_idx(mail->ibox->cache_view);
 		if (idx < 0)
 			return;
 
-		if (!mail_cache_set_header_fields(mail->ibox->trans_ctx,
+		if (!mail_cache_set_header_fields(mail->trans->cache_trans,
 						  idx, headers))
 			return;
 	}
@@ -784,7 +792,7 @@
 	len = str_len(mail->data.header_data) -
 		data->header_data_uncached_offset;
 
-	mail_cache_add(mail->ibox->trans_ctx, data->rec,
+	mail_cache_add(mail->trans->cache_trans, data->seq,
 		       mail_cache_header_fields[idx], str, len+1);
 	data->header_save = FALSE;
 }

Index: index-mail.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mail.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- index-mail.c	26 Oct 2003 18:05:42 -0000	1.24
+++ index-mail.c	27 Apr 2004 20:25:54 -0000	1.25
@@ -6,15 +6,14 @@
 #include "str.h"
 #include "message-date.h"
 #include "message-part-serialize.h"
+#include "message-parser.h"
 #include "imap-bodystructure.h"
 #include "imap-envelope.h"
-#include "mail-custom-flags.h"
 #include "mail-cache.h"
 #include "index-storage.h"
-#include "index-expunge.h"
 #include "index-mail.h"
 
-static int index_mail_parse_body(struct index_mail *mail);
+static void index_mail_parse_body(struct index_mail *mail);
 
 static struct message_part *get_cached_parts(struct index_mail *mail)
 {
@@ -24,12 +23,12 @@
 	size_t part_size;
 
 	if ((mail->data.cached_fields & MAIL_CACHE_MESSAGEPART) == 0) {
-		mail_cache_mark_missing(mail->ibox->index->cache,
+		mail_cache_mark_missing(mail->ibox->cache_view,
 					MAIL_CACHE_MESSAGEPART);
 		return NULL;
 	}
 
-	if (!mail_cache_lookup_field(mail->ibox->index->cache, mail->data.rec,
+	if (!mail_cache_lookup_field(mail->ibox->cache_view, mail->data.seq,
 				     MAIL_CACHE_MESSAGEPART,
 				     &part_data, &part_size)) {
 		/* unexpected - must be an error */
@@ -39,7 +38,7 @@
 	part = message_part_deserialize(mail->pool, part_data, part_size,
 					&error);
 	if (part == NULL) {
-		mail_cache_set_corrupted(mail->ibox->index->cache,
+		mail_cache_set_corrupted(mail->ibox->cache,
 			"Corrupted cached message_part data (%s)", error);
 		return NULL;
 	}
@@ -56,50 +55,48 @@
 	return part;
 }
 
-static char *get_cached_string(struct index_mail *mail,
-			       enum mail_cache_field field)
+char *index_mail_get_cached_string(struct index_mail *mail,
+				   enum mail_cache_field field)
 {
 	const char *ret;
 
 	if ((mail->data.cached_fields & field) == 0) {
-		mail_cache_mark_missing(mail->ibox->index->cache, field);
+		mail_cache_mark_missing(mail->ibox->cache_view, field);
 		return NULL;
 	}
 
-	ret = mail_cache_lookup_string_field(mail->ibox->index->cache,
-					     mail->data.rec, field);
+	ret = mail_cache_lookup_string_field(mail->ibox->cache_view,
+					     mail->data.seq, field);
 	return p_strdup(mail->pool, ret);
 }
 
-static uoff_t get_cached_uoff_t(struct index_mail *mail,
-				enum mail_cache_field field)
+uoff_t index_mail_get_cached_uoff_t(struct index_mail *mail,
+				    enum mail_cache_field field)
 {
 	uoff_t uoff;
 
-	if (!mail_cache_copy_fixed_field(mail->ibox->index->cache,
-					 mail->data.rec, field,
-					 &uoff, sizeof(uoff))) {
-		mail_cache_mark_missing(mail->ibox->index->cache, field);
+	if (!mail_cache_copy_fixed_field(mail->ibox->cache_view, mail->data.seq,
+					 field, &uoff, sizeof(uoff))) {
+		mail_cache_mark_missing(mail->ibox->cache_view, field);
 		uoff = (uoff_t)-1;
 	}
 
 	return uoff;
 }
 
-static uoff_t get_cached_virtual_size(struct index_mail *mail)
+uoff_t index_mail_get_cached_virtual_size(struct index_mail *mail)
 {
-	return get_cached_uoff_t(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE);
+	return index_mail_get_cached_uoff_t(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE);
 }
 
-static time_t get_cached_received_date(struct index_mail *mail)
+time_t index_mail_get_cached_received_date(struct index_mail *mail)
 {
 	time_t t;
 
-	if (!mail_cache_copy_fixed_field(mail->ibox->index->cache,
-					 mail->data.rec,
+	if (!mail_cache_copy_fixed_field(mail->ibox->cache_view, mail->data.seq,
 					 MAIL_CACHE_RECEIVED_DATE,
 					 &t, sizeof(t))) {
-		mail_cache_mark_missing(mail->ibox->index->cache,
+		mail_cache_mark_missing(mail->ibox->cache_view,
 					MAIL_CACHE_RECEIVED_DATE);
 		t = (time_t)-1;
 	}
@@ -110,10 +107,10 @@
 static void get_cached_sent_date(struct index_mail *mail,
 				 struct mail_sent_date *sent_date)
 {
-	if (!mail_cache_copy_fixed_field(mail->ibox->index->cache,
-					 mail->data.rec, MAIL_CACHE_SENT_DATE,
+	if (!mail_cache_copy_fixed_field(mail->ibox->cache_view, mail->data.seq,
+					 MAIL_CACHE_SENT_DATE,
 					 sent_date, sizeof(*sent_date))) {
-		mail_cache_mark_missing(mail->ibox->index->cache,
+		mail_cache_mark_missing(mail->ibox->cache_view,
 					MAIL_CACHE_SENT_DATE);
 
 		sent_date->time = (time_t)-1;
@@ -123,16 +120,16 @@
 
 int index_mail_cache_transaction_begin(struct index_mail *mail)
 {
-	if (mail->ibox->trans_ctx != NULL)
+	if (mail->trans->cache_trans != NULL)
 		return TRUE;
 
-	if (mail_cache_transaction_begin(mail->ibox->index->cache, TRUE,
-					 &mail->ibox->trans_ctx) <= 0)
+	if (mail_cache_transaction_begin(mail->ibox->cache_view, TRUE,
+					 mail->trans->trans,
+					 &mail->trans->cache_trans) <= 0)
 		return FALSE;
 
-	mail->data.cached_fields =
-		mail_cache_get_fields(mail->ibox->index->cache,
-				      mail->data.rec);
+	mail->data.cached_fields = mail_cache_get_fields(mail->ibox->cache_view,
+							 mail->data.seq);
 	return TRUE;
 }
 
@@ -157,60 +154,33 @@
 void index_mail_cache_add(struct index_mail *mail, enum mail_cache_field field,
 			  const void *data, size_t size)
 {
-	struct index_mailbox *ibox = mail->ibox;
-
         if (!index_mail_cache_can_add(mail, field))
 		return;
 
-	if (!mail_cache_add(ibox->trans_ctx, mail->data.rec,
+	if (!mail_cache_add(mail->trans->cache_trans, mail->data.seq,
 			    field, data, size))
-		mail_cache_transaction_rollback(ibox->trans_ctx);
+		mail_cache_transaction_rollback(mail->trans->cache_trans);
 
 	mail->data.cached_fields |= field;
 }
 
-int index_mail_open_stream(struct index_mail *mail, uoff_t position)
-{
-	struct index_mail_data *data = &mail->data;
-	int deleted;
-
-	if (data->stream == NULL) {
-		data->stream = mail->ibox->index->
-			open_mail(mail->ibox->index, data->rec,
-				  &data->received_date, &deleted);
-		data->deleted = deleted;
-
-		if (data->stream == NULL)
-			return FALSE;
-
-		if (data->received_date != (time_t)-1) {
-			index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE,
-					     &data->received_date,
-					     sizeof(data->received_date));
-		}
-	}
-
-	i_stream_seek(mail->data.stream, position);
-	return TRUE;
-}
-
-static const struct mail_full_flags *get_flags(struct mail *_mail)
+const struct mail_full_flags *index_mail_get_flags(struct mail *_mail)
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
 	struct index_mail_data *data = &mail->data;
 
-	data->flags.flags = data->rec->msg_flags;
-	data->flags.custom_flags =
+	data->flags.flags = data->rec->flags;
+	/*FIXME:data->flags.custom_flags =
 		mail_custom_flags_list_get(mail->ibox->index->custom_flags);
 	data->flags.custom_flags_count = MAIL_CUSTOM_FLAGS_COUNT;
 
 	if (data->rec->uid >= mail->ibox->index->first_recent_uid)
-		data->flags.flags |= MAIL_RECENT;
+		data->flags.flags |= MAIL_RECENT;*/
 
 	return &data->flags;
 }
 
-static const struct message_part *get_parts(struct mail *_mail)
+const struct message_part *index_mail_get_parts(struct mail *_mail)
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
 	struct index_mail_data *data = &mail->data;
@@ -228,37 +198,12 @@
 		if (!index_mail_parse_headers(mail))
 			return NULL;
 	}
-	if (!index_mail_parse_body(mail))
-		return NULL;
+	index_mail_parse_body(mail);
 
 	return data->parts;
 }
 
-static time_t get_received_date(struct mail *_mail)
-{
-	struct index_mail *mail = (struct index_mail *) _mail;
-	struct index_mail_data *data = &mail->data;
-
-	if (data->received_date != (time_t)-1)
-		return data->received_date;
-
-	if ((mail->wanted_fields & MAIL_FETCH_RECEIVED_DATE) == 0) {
-		data->received_date = get_cached_received_date(mail);
-		if (data->received_date != (time_t)-1)
-			return data->received_date;
-	}
-
-	data->received_date = mail->ibox->index->
-		get_received_date(mail->ibox->index, mail->data.rec);
-	if (data->received_date != (time_t)-1) {
-		index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE,
-				     &data->received_date,
-				     sizeof(data->received_date));
-	}
-	return data->received_date;
-}
-
-static time_t get_date(struct mail *_mail, int *timezone)
+time_t index_mail_get_date(struct mail *_mail, int *timezone)
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
 	struct index_mail_data *data = &mail->data;
@@ -302,7 +247,7 @@
 
 	if (data->parts == NULL) {
 		if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) != 0)
-			(void)get_parts(&mail->mail);
+			(void)index_mail_get_parts(&mail->mail);
 		else
 			data->parts = get_cached_parts(mail);
 	}
@@ -319,7 +264,7 @@
 	return data->parts != NULL;
 }
 
-static uoff_t get_size(struct mail *_mail)
+uoff_t index_mail_get_size(struct mail *_mail)
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
 	struct index_mail_data *data = &mail->data;
@@ -329,7 +274,7 @@
 		return data->size;
 
 	if ((mail->wanted_fields & MAIL_FETCH_SIZE) == 0) {
-		data->size = get_cached_virtual_size(mail);
+		data->size = index_mail_get_cached_virtual_size(mail);
 		if (data->size != (uoff_t)-1)
 			return data->size;
 	}
@@ -352,7 +297,7 @@
 	imap_bodystructure_parse_header(pool, part, hdr);
 }
 
-static int index_mail_parse_body(struct index_mail *mail)
+static void index_mail_parse_body(struct index_mail *mail)
 {
 	struct index_mail_data *data = &mail->data;
         enum mail_index_record_flag index_flags;
@@ -379,7 +324,7 @@
 	data->body_size_set = TRUE;
 
 	if (mail->mail.has_nuls || mail->mail.has_no_nuls)
-		return TRUE;
+		return;
 
 	/* we know the NULs now, update them */
 	if ((data->parts->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) {
@@ -391,19 +336,19 @@
 	}
 
 	if (!index_mail_cache_transaction_begin(mail))
-		return TRUE;
+		return;
 
 	/* update index_flags */
-	index_flags = mail_cache_get_index_flags(mail->ibox->index->cache,
-						 mail->data.rec);
+	index_flags = mail_cache_get_index_flags(mail->ibox->cache_view,
+						 mail->data.seq);
 	if (mail->mail.has_nuls)
 		index_flags |= MAIL_INDEX_FLAG_HAS_NULS;
 	else
 		index_flags |= MAIL_INDEX_FLAG_HAS_NO_NULS;
 
-	if (!mail_cache_update_index_flags(mail->ibox->index->cache,
-					   mail->data.rec, index_flags))
-		return FALSE;
+	if (!mail_cache_update_index_flags(mail->ibox->cache_view,
+					   mail->data.seq, index_flags))
+		return;
 
 	if (index_mail_cache_can_add(mail, MAIL_CACHE_MESSAGEPART)) {
 		t_push();
@@ -416,19 +361,15 @@
 				     buf_data, buf_size);
 		t_pop();
 	}
-	return TRUE;
 }
 
-static struct istream *get_stream(struct mail *_mail,
-				  struct message_size *hdr_size,
-				  struct message_size *body_size)
+struct istream *index_mail_init_stream(struct index_mail *_mail,
+				       struct message_size *hdr_size,
+				       struct message_size *body_size)
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
 	struct index_mail_data *data = &mail->data;
 
-	if (!index_mail_open_stream(mail, 0))
-		return NULL;
-
 	if (hdr_size != NULL || body_size != NULL)
 		(void)get_msgpart_sizes(mail);
 
@@ -442,10 +383,8 @@
 	}
 
 	if (body_size != NULL) {
-		if (!data->body_size_set) {
-			if (!index_mail_parse_body(mail))
-				return NULL;
-		}
+		if (!data->body_size_set)
+			index_mail_parse_body(mail);
 
 		*body_size = data->body_size;
 	}
@@ -459,28 +398,30 @@
 	return data->stream;
 }
 
-static const char *get_special(struct mail *_mail, enum mail_fetch_field field)
+const char *index_mail_get_special(struct mail *_mail,
+				   enum mail_fetch_field field)
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
 	struct index_mail_data *data = &mail->data;
-	struct mail_cache *cache = mail->ibox->index->cache;
+	struct mail_cache *cache = mail->ibox->cache;
 	enum mail_cache_field cache_field;
 	char *str;
 
 	switch (field) {
 	case MAIL_FETCH_IMAP_BODY:
 		if ((data->cached_fields & MAIL_CACHE_BODY) &&
-		    data->body == NULL)
-			data->body = get_cached_string(mail, MAIL_CACHE_BODY);
+		    data->body == NULL) {
+			data->body = index_mail_get_cached_string(mail,
+					MAIL_CACHE_BODY);
+		}
 		if (data->body != NULL)
 			return data->body;
 		/* fall through */
 	case MAIL_FETCH_IMAP_BODYSTRUCTURE:
 		if ((data->cached_fields & MAIL_CACHE_BODYSTRUCTURE) &&
 		    data->bodystructure == NULL) {
-			data->bodystructure =
-				get_cached_string(mail,
-						  MAIL_CACHE_BODYSTRUCTURE);
+			data->bodystructure = index_mail_get_cached_string(mail,
+						MAIL_CACHE_BODYSTRUCTURE);
 		}
 
 		if (data->bodystructure != NULL) {
@@ -514,8 +455,7 @@
 						 parse_bodystructure_header,
 						 mail->pool);
 		} else {
-			if (!index_mail_parse_body(mail))
-				return NULL;
+			index_mail_parse_body(mail);
 		}
 
 		t_push();
@@ -548,39 +488,21 @@
 	}
 }
 
-static struct mail index_mail = {
-	0, 0, 0, 0, 0,
-
-	get_flags,
-	get_parts,
-	get_received_date,
-	get_date,
-	get_size,
-	index_mail_get_header,
-	index_mail_get_headers,
-	get_stream,
-	get_special,
-	index_storage_update_flags,
-	index_storage_expunge
-};
-
-void index_mail_init(struct index_mailbox *ibox, struct index_mail *mail,
+void index_mail_init(struct index_transaction_context *t,
+		     struct index_mail *mail,
 		     enum mail_fetch_field wanted_fields,
 		     const char *const wanted_headers[])
 {
-	mail->mail = index_mail;
-	mail->mail.box = &ibox->box;
+	mail->mail = *t->ibox->mail_interface;
+	mail->mail.box = &t->ibox->box;
 
 	mail->pool = pool_alloconly_create("index_mail", 16384);
-	mail->ibox = ibox;
+	mail->ibox = t->ibox;
+	mail->trans = t;
 	mail->wanted_fields = wanted_fields;
 	mail->wanted_headers = wanted_headers;
-	mail->expunge_counter = ibox->index->expunge_counter;
 
 	index_mail_headers_init(mail);
-
-	if (ibox->mail_init != NULL)
-		ibox->mail_init(mail);
 }
 
 static void index_mail_close(struct index_mail *mail)
@@ -591,48 +513,49 @@
 	index_mail_headers_close(mail);
 }
 
-int index_mail_next(struct index_mail *mail, struct mail_index_record *rec,
-		    unsigned int idx_seq, int delay_open)
+int index_mail_next(struct index_mail *mail,
+		    const struct mail_index_record *rec,
+		    uint32_t seq, int delay_open)
 {
-	struct mail_index *index = mail->ibox->index;
 	struct index_mail_data *data = &mail->data;
         enum mail_index_record_flag index_flags;
 	int ret, open_mail;
 
-	i_assert(mail->expunge_counter == index->expunge_counter);
-
 	t_push();
 
 	index_mail_close(mail);
 	memset(data, 0, sizeof(*data));
 	p_clear(mail->pool);
 
-        data->cached_fields = mail_cache_get_fields(index->cache, rec);
+	data->cached_fields =
+		mail_cache_get_fields(mail->ibox->cache_view, seq);
 	index_flags = (data->cached_fields & MAIL_CACHE_INDEX_FLAGS) == 0 ? 0 :
-		mail_cache_get_index_flags(index->cache, rec);
+		mail_cache_get_index_flags(mail->ibox->cache_view, seq);
 
 	mail->mail.has_nuls = (index_flags & MAIL_INDEX_FLAG_HAS_NULS) != 0;
 	mail->mail.has_no_nuls =
 		(index_flags & MAIL_INDEX_FLAG_HAS_NO_NULS) != 0;
 
 	data->rec = rec;
-	data->idx_seq = idx_seq;
+	data->seq = seq;
 	data->size = (uoff_t)-1;
 	data->received_date = data->sent_date.time = (time_t)-1;
 
 	/* if some wanted fields are cached, get them */
 	if (mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS)
 		data->parts = get_cached_parts(mail);
-	if (mail->wanted_fields & MAIL_FETCH_IMAP_BODY)
-		data->body = get_cached_string(mail, MAIL_CACHE_BODY);
+	if (mail->wanted_fields & MAIL_FETCH_IMAP_BODY) {
+		data->body =
+			index_mail_get_cached_string(mail, MAIL_CACHE_BODY);
+	}
 	if ((mail->wanted_fields & MAIL_FETCH_IMAP_BODYSTRUCTURE) ||
 	    ((mail->wanted_fields & MAIL_FETCH_IMAP_BODY) &&
 	     data->body == NULL)) {
-		data->bodystructure =
-			get_cached_string(mail, MAIL_CACHE_BODYSTRUCTURE);
+		data->bodystructure = index_mail_get_cached_string(mail,
+					MAIL_CACHE_BODYSTRUCTURE);
 	}
 	if (mail->wanted_fields & MAIL_FETCH_SIZE)
-		data->size = get_cached_virtual_size(mail);
+		data->size = index_mail_get_cached_virtual_size(mail);
 	if (mail->wanted_fields & MAIL_FETCH_DATE)
 		get_cached_sent_date(mail, &data->sent_date);
 
@@ -662,14 +585,15 @@
         index_mail_headers_init_next(mail);
 
 	if ((open_mail || data->parse_header) && !delay_open) {
-		if (!index_mail_open_stream(mail, 0))
+		if (mail->mail.get_stream(&mail->mail, NULL, NULL) == NULL)
 			ret = data->deleted ? 0 : -1;
 		else
 			ret = 1;
 	} else {
 		if (mail->wanted_fields & MAIL_FETCH_RECEIVED_DATE) {
 			/* check this only after open_mail() */
-			data->received_date = get_cached_received_date(mail);
+			data->received_date =
+				index_mail_get_cached_received_date(mail);
 		}
 		ret = 1;
 	}
@@ -694,3 +618,40 @@
 	pool_unref(mail->pool);
 	memset(mail, 0, sizeof(*mail));
 }
+
+int index_mail_update_flags(struct mail *mail,
+			    const struct mail_full_flags *flags,
+			    enum modify_type modify_type)
+{
+	struct index_mail *imail = (struct index_mail *)mail;
+	enum mail_flags modify_flags;
+	custom_flags_mask_t custom_flags;
+
+	/* \Recent can't be changed */
+	modify_flags = flags->flags & ~MAIL_RECENT;
+
+	/*if (!index_mailbox_fix_custom_flags(ibox, &modify_flags,
+					    flags->custom_flags,
+					    flags->custom_flags_count))
+		return FALSE;*/
+
+	memset(custom_flags, 0, sizeof(custom_flags));
+	mail_index_update_flags(imail->trans->trans, mail->seq, modify_type,
+				flags->flags, custom_flags);
+
+	/*if (mail_custom_flags_has_changes(ibox->index->custom_flags)) {
+		storage->callbacks->new_custom_flags(&ibox->box,
+			mail_custom_flags_list_get(ibox->index->custom_flags),
+			MAIL_CUSTOM_FLAGS_COUNT, storage->callback_context);
+	}*/
+
+	return 0;
+}
+
+int index_mail_expunge(struct mail *mail)
+{
+	struct index_mail *imail = (struct index_mail *)mail;
+
+	mail_index_expunge(imail->trans->trans, mail->seq);
+	return 0;
+}

Index: index-mail.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mail.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- index-mail.h	8 Sep 2003 02:24:29 -0000	1.10
+++ index-mail.h	27 Apr 2004 20:25:54 -0000	1.11
@@ -3,6 +3,7 @@
 
 #include "message-size.h"
 #include "mail-cache.h"
+#include "mail-storage-private.h"
 
 struct message_header_line;
 
@@ -25,8 +26,8 @@
 	const char *envelope, *body, *bodystructure;
 	struct message_part_envelope_data *envelope_data;
 
-	struct mail_index_record *rec;
-	unsigned int idx_seq;
+	uint32_t seq;
+	const struct mail_index_record *rec;
 
 	struct istream *stream;
 	struct message_size hdr_size, body_size;
@@ -53,6 +54,7 @@
 
 	pool_t pool;
 	struct index_mailbox *ibox;
+	struct index_transaction_context *trans;
 	unsigned int expunge_counter;
 	buffer_t *header_buf;
 
@@ -61,11 +63,13 @@
 	int wanted_headers_idx;
 };
 
-void index_mail_init(struct index_mailbox *ibox, struct index_mail *mail,
+void index_mail_init(struct index_transaction_context *t,
+		     struct index_mail *mail,
 		     enum mail_fetch_field wanted_fields,
 		     const char *const wanted_headers[]);
-int index_mail_next(struct index_mail *mail, struct mail_index_record *rec,
-		    unsigned int idx_seq, int delay_open);
+int index_mail_next(struct index_mail *mail,
+		    const struct mail_index_record *rec,
+		    uint32_t seq, int delay_open);
 void index_mail_deinit(struct index_mail *mail);
 
 void index_mail_parse_header_init(struct index_mail *mail,
@@ -78,7 +82,6 @@
 void index_mail_cache_add(struct index_mail *mail, enum mail_cache_field field,
 			  const void *data, size_t size);
 
-int index_mail_open_stream(struct index_mail *mail, uoff_t position);
 int index_mail_parse_headers(struct index_mail *mail);
 
 void index_mail_headers_init(struct index_mail *mail);
@@ -89,4 +92,26 @@
 struct istream *index_mail_get_headers(struct mail *_mail,
 				       const char *const minimum_fields[]);
 
+const struct mail_full_flags *index_mail_get_flags(struct mail *_mail);
+const struct message_part *index_mail_get_parts(struct mail *_mail);
+time_t index_mail_get_date(struct mail *_mail, int *timezone);
+uoff_t index_mail_get_size(struct mail *_mail);
+struct istream *index_mail_init_stream(struct index_mail *mail,
+				       struct message_size *hdr_size,
+				       struct message_size *body_size);
+const char *index_mail_get_special(struct mail *_mail,
+				   enum mail_fetch_field field);
+
+int index_mail_update_flags(struct mail *mail,
+			    const struct mail_full_flags *flags,
+			    enum modify_type modify_type);
+int index_mail_expunge(struct mail *mail);
+
+char *index_mail_get_cached_string(struct index_mail *mail,
+				   enum mail_cache_field field);
+uoff_t index_mail_get_cached_uoff_t(struct index_mail *mail,
+				    enum mail_cache_field field);
+uoff_t index_mail_get_cached_virtual_size(struct index_mail *mail);
+time_t index_mail_get_cached_received_date(struct index_mail *mail);
+
 #endif

Index: index-mailbox-check.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mailbox-check.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- index-mailbox-check.c	24 Aug 2003 12:59:08 -0000	1.7
+++ index-mailbox-check.c	27 Apr 2004 20:25:54 -0000	1.8
@@ -5,6 +5,8 @@
 #include "index-storage.h"
 
 #include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 
 static void check_timeout(void *context)

Index: index-search.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-search.c,v
retrieving revision 1.82
retrieving revision 1.83
diff -u -d -r1.82 -r1.83
--- index-search.c	26 Oct 2003 20:13:15 -0000	1.82
+++ index-search.c	27 Apr 2004 20:25:54 -0000	1.83
@@ -7,12 +7,10 @@
 #include "message-date.h"
 #include "message-body-search.h"
 #include "message-header-search.h"
+#include "message-parser.h"
 #include "imap-date.h"
 #include "index-storage.h"
-#include "index-messageset.h"
 #include "index-mail.h"
-#include "mail-custom-flags.h"
-#include "mail-modifylog.h"
 #include "mail-search.h"
 
 #include <stdlib.h>
@@ -21,12 +19,14 @@
 #define TXT_UNKNOWN_CHARSET "[BADCHARSET] Unknown charset"
 #define TXT_INVALID_SEARCH_KEY "Invalid search key"
 
-struct mail_search_context {
+struct index_search_context {
+        struct mail_search_context mail_ctx;
+	struct index_transaction_context *trans;
 	struct index_mailbox *ibox;
 	char *charset;
 	struct mail_search_arg *args;
 
-	struct messageset_context *msgset_ctx;
+	uint32_t seq1, seq2;
 	struct index_mail imail;
 	struct mail *mail;
 
@@ -37,7 +37,7 @@
 };
 
 struct search_header_context {
-        struct mail_search_context *index_context;
+        struct index_search_context *index_context;
 	struct mail_search_arg *args;
 
         struct message_header_line *hdr;
@@ -47,70 +47,17 @@
 };
 
 struct search_body_context {
-        struct mail_search_context *index_ctx;
+        struct index_search_context *index_ctx;
 	struct istream *input;
 	const struct message_part *part;
 };
 
-static int msgset_contains(const char *set, unsigned int match_num,
-			   unsigned int max_num)
+static int seqset_contains(struct mail_search_seqset *set, uint32_t seq)
 {
-	unsigned int num, num2;
-
-	while (*set != '\0') {
-		if (*set == '*') {
-			set++;
-			num = max_num;
-		} else {
-			num = 0;
-			while (*set >= '0' && *set <= '9') {
-				num = num*10 + (*set-'0');
-				set++;
-			}
-
-			if (num == 0)
-				return FALSE;
-		}
-
-		if (*set == ',' || *set == '\0') {
-			if (num == match_num)
-				return TRUE;
-			if (*set == '\0')
-				return FALSE;
-		} else if (*set == ':') {
-			set++;
-
-			if (*set == '*') {
-				set++;
-
-				if (match_num >= num && num <= max_num)
-					return TRUE;
-			} else {
-				num2 = 0;
-				while (*set >= '0' && *set <= '9') {
-					num2 = num2*10 + (*set-'0');
-					set++;
-				}
-
-				if (num2 == 0)
-					return FALSE;
-
-				if (num > num2) {
-					/* swap, as specified by RFC-3501 */
-					unsigned int temp = num;
-					num = num2;
-					num2 = temp;
-				}
-
-				if (match_num >= num && match_num <= num2)
-					return TRUE;
-			}
-
-			if (*set != ',')
-				return FALSE;
-		}
-
-		set++;
+	while (set != NULL) {
+		if (seq >= set->seq1 && seq <= set->seq2)
+			return TRUE;
+		set = set->next;
 	}
 
 	return FALSE;
@@ -133,56 +80,56 @@
 }
 
 static int search_keyword(struct mail_index *index,
-			  struct mail_index_record *rec, const char *value)
+			  const struct mail_index_record *rec,
+			  const char *value)
 {
 	const char **custom_flags;
 	int i;
 
-	if ((rec->msg_flags & MAIL_CUSTOM_FLAGS_MASK) == 0)
-		return FALSE;
+	for (i = 0; i < INDEX_CUSTOM_FLAGS_BYTE_COUNT; i++) {
+		if (rec->custom_flags[i] != 0)
+			break;
+	}
 
-	custom_flags = mail_custom_flags_list_get(index->custom_flags);
+	if (i == INDEX_CUSTOM_FLAGS_BYTE_COUNT)
+		return FALSE; /* no custom flags set */
+
+	/*FIXME:custom_flags = mail_custom_flags_list_get(index->custom_flags);
 	for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) {
 		if (custom_flags[i] != NULL &&
 		    strcasecmp(custom_flags[i], value) == 0) {
 			return rec->msg_flags &
 				(1 << (MAIL_CUSTOM_FLAG_1_BIT+i));
 		}
-	}
+	}*/
 
 	return FALSE;
 }
 
 /* Returns >0 = matched, 0 = not matched, -1 = unknown */
 static int search_arg_match_index(struct index_mailbox *ibox,
-				  struct mail_index_record *rec,
-				  unsigned int client_seq,
+				  const struct mail_index_record *rec,
 				  enum mail_search_arg_type type,
 				  const char *value)
 {
 	switch (type) {
 	case SEARCH_ALL:
 		return 1;
-	case SEARCH_SET:
-		return msgset_contains(value, client_seq,
-				       ibox->synced_messages_count);
-	case SEARCH_UID:
-		return msgset_contains(value, rec->uid,
-				       ibox->index->header->next_uid-1);
 
 	/* flags */
 	case SEARCH_ANSWERED:
-		return rec->msg_flags & MAIL_ANSWERED;
+		return rec->flags & MAIL_ANSWERED;
 	case SEARCH_DELETED:
-		return rec->msg_flags & MAIL_DELETED;
+		return rec->flags & MAIL_DELETED;
 	case SEARCH_DRAFT:
-		return rec->msg_flags & MAIL_DRAFT;
+		return rec->flags & MAIL_DRAFT;
 	case SEARCH_FLAGGED:
-		return rec->msg_flags & MAIL_FLAGGED;
+		return rec->flags & MAIL_FLAGGED;
 	case SEARCH_SEEN:
-		return rec->msg_flags & MAIL_SEEN;
+		return rec->flags & MAIL_SEEN;
 	case SEARCH_RECENT:
-		return rec->uid >= ibox->index->first_recent_uid;
+		//FIXME:return rec->uid >= ibox->index->first_recent_uid;
+		return FALSE;
 	case SEARCH_KEYWORD:
 		return search_keyword(ibox->index, rec, value);
 
@@ -193,10 +140,22 @@
 
 static void search_index_arg(struct mail_search_arg *arg, void *context)
 {
-	struct mail_search_context *ctx = context;
+	struct index_search_context *ctx = context;
+	int found;
+
+	if (arg->type == SEARCH_SEQSET) {
+		found = seqset_contains(arg->value.seqset, ctx->mail->seq);
+		ARG_SET_RESULT(arg, found);
+		return;
+	}
+
+	if (ctx->imail.data.rec == NULL) {
+		/* expunged message */
+		ARG_SET_RESULT(arg, 0);
+		return;
+	}
 
 	switch (search_arg_match_index(ctx->ibox, ctx->imail.data.rec,
-				       ctx->mail->seq,
 				       arg->type, arg->value.str)) {
 	case -1:
 		/* unknown */
@@ -211,7 +170,7 @@
 }
 
 /* Returns >0 = matched, 0 = not matched, -1 = unknown */
-static int search_arg_match_cached(struct mail_search_context *ctx,
+static int search_arg_match_cached(struct index_search_context *ctx,
 				   enum mail_search_arg_type type,
 				   const char *value)
 {
@@ -291,7 +250,7 @@
 
 static void search_cached_arg(struct mail_search_arg *arg, void *context)
 {
-	struct mail_search_context *ctx = context;
+	struct index_search_context *ctx = context;
 
 	switch (search_arg_match_cached(ctx, arg->type,
 					arg->value.str)) {
@@ -340,7 +299,7 @@
 }
 
 static struct header_search_context *
-search_header_context(struct mail_search_context *ctx,
+search_header_context(struct index_search_context *ctx,
 		      struct mail_search_arg *arg)
 {
 	int unknown_charset;
@@ -517,7 +476,7 @@
 }
 
 static int search_arg_match_text(struct mail_search_arg *args,
-				 struct mail_search_context *ctx)
+				 struct index_search_context *ctx)
 {
 	struct istream *input;
 	const char *const *headers;
@@ -571,249 +530,180 @@
 	return TRUE;
 }
 
-static int seq_update(const char *set, unsigned int *first_seq,
-		      unsigned int *last_seq, unsigned int max_value)
+static int search_msgset_fix(struct index_mailbox *ibox,
+                             const struct mail_index_header *hdr,
+			     struct mail_search_seqset *set,
+			     uint32_t *seq1_r, uint32_t *seq2_r)
 {
-	unsigned int seq;
-	int first = TRUE;
+	for (; set != NULL; set = set->next) {
+		if (set->seq1 == (uint32_t)-1)
+			set->seq1 = hdr->messages_count;
+		if (set->seq2 == (uint32_t)-1)
+			set->seq2 = hdr->messages_count;
 
-	while (*set != '\0') {
-		if (*set == '*') {
-			seq = max_value;
-			set++;
-		} else {
-			seq = 0;
-			while (*set >= '0' && *set <= '9') {
-				seq = seq*10 + (*set-'0');
-				set++;
-			}
+		if (set->seq1 == 0 || set->seq2 == 0 ||
+		    set->seq1 > hdr->messages_count ||
+		    set->seq2 > hdr->messages_count) {
+			mail_storage_set_syntax_error(ibox->box.storage,
+						      "Invalid messageset");
+			return -1;
 		}
 
-		if (seq == 0)
-			return FALSE;
-
-		if (*first_seq == 0 || seq < *first_seq)
-			*first_seq = seq;
-		if (*last_seq == 0 || seq > *last_seq)
-			*last_seq = seq;
-
-		if (*set != '\0') {
-			if (*set == ',')
-				first = TRUE;
-			else if (*set == ':' && first)
-				first = FALSE;
-			else
-				return FALSE;
-			set++;
-		}
+		if (*seq1_r > set->seq1 || *seq1_r == 0)
+			*seq1_r = set->seq1;
+		if (*seq2_r < set->seq2)
+			*seq2_r = set->seq2;
 	}
-
-	return TRUE;
+	return 0;
 }
 
-struct search_msgset_context {
-	struct index_mailbox *ibox;
-
-	unsigned int first_seq, last_seq;
-	unsigned int first_uid, last_uid;
-
-	struct mail_search_arg *msgset_arg;
-	unsigned int msgset_arg_count;
-};
-
-static int search_parse_msgset_args(struct search_msgset_context *ctx,
-				    struct mail_search_arg *args)
+static int search_parse_msgset_args(struct index_mailbox *ibox,
+				    struct mail_search_arg *args,
+				    uint32_t *seq1_r, uint32_t *seq2_r)
 {
-	struct index_mailbox *ibox = ctx->ibox;
+	const struct mail_index_header *hdr;
 
+	*seq1_r = *seq2_r = 0;
+
+	hdr = mail_index_get_header(ibox->view);
 	for (; args != NULL; args = args->next) {
-		/* FIXME: we don't check if OR condition can limit the range.
-		   It's a bit tricky and unlikely to affect performance much. */
 		if (args->type == SEARCH_SUB) {
-			if (!search_parse_msgset_args(ctx, args->value.subargs))
-				return FALSE;
-		} else if (args->type == SEARCH_SET) {
-			ctx->msgset_arg = args;
-			ctx->msgset_arg_count++;
-			if (!seq_update(args->value.str,
-					&ctx->first_seq, &ctx->last_seq,
-					ibox->synced_messages_count)) {
-				mail_storage_set_syntax_error(ibox->box.storage,
-					"Invalid messageset: %s",
-					args->value.str);
-				return FALSE;
-			}
-		} else if (args->type == SEARCH_UID) {
-			ctx->msgset_arg = args;
-			ctx->msgset_arg_count++;
-			if (!seq_update(args->value.str,
-					&ctx->first_uid, &ctx->last_uid,
-					ibox->index->header->next_uid-1)) {
-				mail_storage_set_syntax_error(ibox->box.storage,
-					"Invalid messageset: %s",
-					args->value.str);
-				return FALSE;
-			}
+			if (search_parse_msgset_args(ibox, args->value.subargs,
+						     seq1_r, seq2_r) < 0)
+				return -1;
+		} else if (args->type == SEARCH_OR) {
+			/* FIXME: in cases like "SEEN OR 5 7" we shouldn't
+			   limit the range, but in cases like "1 OR 5 7" we
+			   should expand the range. A bit tricky, we'll
+			   just go through everything now to make it work
+			   right. */
+			*seq1_r = 1;
+			*seq2_r = hdr->messages_count;
+
+                        /* We still have to fix potential seqsets though */
+			if (search_parse_msgset_args(ibox, args->value.subargs,
+						     seq1_r, seq2_r) < 0)
+				return -1;
+		} else if (args->type == SEARCH_SEQSET) {
+			if (search_msgset_fix(ibox, hdr, args->value.seqset,
+					      seq1_r, seq2_r) < 0)
+				return -1;
 		} else if (args->type == SEARCH_ALL) {
-			/* go through everything */
-			ctx->first_seq = 1;
-			ctx->last_seq = ibox->synced_messages_count;
-			ctx->msgset_arg_count++;
-			return TRUE;
+			/* go through everything. don't stop, have to fix
+			   seqsets. */
+			*seq1_r = 1;
+			*seq2_r = hdr->messages_count;
 		}
 	}
+	return 0;
+}
 
-	return TRUE;
+static int search_limit_lowwater(struct index_mailbox *ibox,
+				 uint32_t uid_lowwater, uint32_t *first_seq)
+{
+        const struct mail_index_header *hdr;
+	uint32_t seq1, seq2;
+
+	if (uid_lowwater == 0)
+		return 0;
+
+	hdr = mail_index_get_header(ibox->view);
+	if (mail_index_lookup_uid_range(ibox->view, uid_lowwater,
+					hdr->next_uid-1,
+					&seq1, &seq2) < 0) {
+		mail_storage_set_index_error(ibox);
+		return -1;
+	}
+
+	if (*first_seq < seq1)
+		*first_seq = seq1;
+	return 0;
 }
 
 static int search_limit_by_flags(struct index_mailbox *ibox,
 				 struct mail_search_arg *args,
-				 unsigned int *first_uid,
-				 unsigned int *last_uid)
+				 uint32_t *seq1, uint32_t *seq2)
 {
-	struct mail_index_header *hdr;
-	unsigned int uid;
+	const struct mail_index_header *hdr;
 
-	hdr = ibox->index->header;
+	hdr = mail_index_get_header(ibox->view);
 	for (; args != NULL; args = args->next) {
 		if (args->type == SEARCH_SEEN) {
 			/* SEEN with 0 seen? */
 			if (!args->not && hdr->seen_messages_count == 0)
-				return FALSE;
+				return 0;
 
 			if (hdr->seen_messages_count == hdr->messages_count) {
 				/* UNSEEN with all seen? */
 				if (args->not)
-					return FALSE;
+					return 0;
 
 				/* SEEN with all seen */
 				args->match_always = TRUE;
-			} else {
+			} else if (args->not) {
 				/* UNSEEN with lowwater limiting */
-				uid = hdr->first_unseen_uid_lowwater;
-				if (args->not && *first_uid < uid)
-					*first_uid = uid;
+				if (search_limit_lowwater(ibox,
+                                		hdr->first_unseen_uid_lowwater,
+						seq1) < 0)
+					return -1;
 			}
 		}
 
 		if (args->type == SEARCH_DELETED) {
 			/* DELETED with 0 deleted? */
 			if (!args->not && hdr->deleted_messages_count == 0)
-				return FALSE;
+				return 0;
 
 			if (hdr->deleted_messages_count ==
 			    hdr->messages_count) {
 				/* UNDELETED with all deleted? */
 				if (args->not)
-					return FALSE;
+					return 0;
 
 				/* DELETED with all deleted */
 				args->match_always = TRUE;
-			} else {
+			} else if (!args->not) {
 				/* DELETED with lowwater limiting */
-				uid = hdr->first_deleted_uid_lowwater;
-				if (!args->not && *first_uid < uid)
-					*first_uid = uid;
+				if (search_limit_lowwater(ibox,
+                                		hdr->first_deleted_uid_lowwater,
+						seq1) < 0)
+					return -1;
 			}
 		}
 
-		if (args->type == SEARCH_RECENT) {
+		/*FIXME:if (args->type == SEARCH_RECENT) {
 			uid = ibox->index->first_recent_uid;
 			if (!args->not && *first_uid < uid)
 				*first_uid = ibox->index->first_recent_uid;
 			else if (args->not && *last_uid >= uid)
 				*last_uid = uid-1;
-		}
-	}
-
-	return *first_uid <= *last_uid;
-}
-
-static int client_seq_to_uid(struct index_mailbox *ibox,
-			     unsigned int seq, unsigned int *uid)
-{
-	struct mail_index_record *rec;
-	unsigned int expunges_before;
-
-	if (seq > ibox->synced_messages_count) {
-		mail_storage_set_syntax_error(ibox->box.storage,
-					      "Sequence out of range: %u", seq);
-		return FALSE;
+		}*/
 	}
 
-	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);
-	*uid = rec == NULL ? 0 : rec->uid;
-	return TRUE;
+	return *seq1 <= *seq2;
 }
 
-static int search_get_msgset(struct index_mailbox *ibox,
-			     struct mail_search_arg *args,
-			     struct messageset_context **msgset_r)
+static int search_get_seqset(struct index_search_context *ctx,
+			     struct mail_search_arg *args)
 {
-        struct search_msgset_context ctx;
-	unsigned int uid;
-
-	memset(&ctx, 0, sizeof(ctx));
-	ctx.ibox = ibox;
+        const struct mail_index_header *hdr;
 
-	if (!search_parse_msgset_args(&ctx, args))
+	if (search_parse_msgset_args(ctx->ibox, args,
+				     &ctx->seq1, &ctx->seq2) < 0)
 		return -1;
 
-	/* seq_update() should make sure that these can't happen */
-	i_assert(ctx.first_seq <= ctx.last_seq);
-	i_assert(ctx.first_uid <= ctx.last_uid);
-
-	if (ctx.first_seq > 1) {
-		if (!client_seq_to_uid(ibox, ctx.first_seq, &uid))
-			return -1;
-		if (uid == 0)
-			return 0;
-
-		if (ctx.first_uid == 0 || uid < ctx.first_uid)
-			ctx.first_uid = uid;
-	}
-
-	if (ctx.last_seq > 1 && ctx.last_seq != ibox->synced_messages_count) {
-		if (!client_seq_to_uid(ibox, ctx.last_seq, &uid))
-			return -1;
-		if (uid == 0)
-			return 0;
-
-		if (ctx.last_uid == 0 || uid > ctx.last_uid)
-			ctx.last_uid = uid;
+	if (ctx->seq1 == 0) {
+		hdr = mail_index_get_header(ctx->ibox->view);
+		ctx->seq1 = 1;
+		ctx->seq2 = hdr->messages_count;
 	}
 
-	if (ctx.first_uid == 0)
-		ctx.first_uid = 1;
-	if (ctx.last_uid == 0 || ctx.last_seq == ibox->synced_messages_count)
-		ctx.last_uid = ibox->index->header->next_uid-1;
+	i_assert(ctx->seq1 <= ctx->seq2);
 
 	/* UNSEEN and DELETED in root search level may limit the range */
-	if (!search_limit_by_flags(ibox, args, &ctx.first_uid, &ctx.last_uid))
-		return 0;
-
-	i_assert(ctx.first_uid <= ctx.last_uid);
-
-	if (ctx.msgset_arg != NULL && ctx.msgset_arg_count == 1) {
-		/* one messageset argument, we can use it */
-		*msgset_r = index_messageset_init(ibox,
-				ctx.msgset_arg->value.str,
-				ctx.msgset_arg->type == SEARCH_UID, TRUE);
-		/* we might be able to limit it some more */
-		index_messageset_limit_range(*msgset_r,
-					     ctx.first_uid, ctx.last_uid);
-		ctx.msgset_arg->match_always = TRUE;
-	} else {
-		*msgset_r = index_messageset_init_range(ibox, ctx.first_uid,
-							ctx.last_uid, TRUE);
-	}
-	return 1;
+	if (search_limit_by_flags(ctx->ibox, args, &ctx->seq1, &ctx->seq2) < 0)
+		return -1;
+	return 0;
 }
 
 int index_storage_search_get_sorting(struct mailbox *box __attr_unused__,
@@ -821,80 +711,58 @@
 {
 	/* currently we don't support sorting */
 	*sort_program = MAIL_SORT_END;
-	return TRUE;
+	return 0;
 }
 
 struct mail_search_context *
-index_storage_search_init(struct mailbox *box, const char *charset,
-			  struct mail_search_arg *args,
+index_storage_search_init(struct mailbox_transaction_context *_t,
+			  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;
+	struct index_transaction_context *t =
+		(struct index_transaction_context *)_t;
+	struct index_search_context *ctx;
 
 	if (sort_program != NULL && *sort_program != MAIL_SORT_END) {
-		i_error("BUG: index_storage_search_init(): "
-			"invalid sort_program");
-		return NULL;
+		i_fatal("BUG: index_storage_search_init(): "
+			 "invalid sort_program");
 	}
 
-	if (!index_storage_sync_and_lock(ibox, TRUE, TRUE, MAIL_LOCK_SHARED))
-		return NULL;
+	/*FIXME:if (!index_storage_sync_and_lock(ibox, TRUE, TRUE, MAIL_LOCK_SHARED))
+		return NULL;*/
 
-	ctx = i_new(struct mail_search_context, 1);
-	ctx->ibox = ibox;
+	ctx = i_new(struct index_search_context, 1);
+	ctx->mail_ctx.box = &t->ibox->box;
+	ctx->trans = t;
+	ctx->ibox = t->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 ctx;
+	ctx->mail = &ctx->imail.mail;
+	index_mail_init(t, &ctx->imail, wanted_fields, wanted_headers);
 
 	mail_search_args_reset(ctx->args, TRUE);
 
-	/* see if we can limit the records we look at */
-	switch (search_get_msgset(ibox, args, &ctx->msgset_ctx)) {
-	case -1:
-		/* error */
+	if (search_get_seqset(ctx, args) < 0) {
 		ctx->failed = TRUE;
-		return ctx;
-	case 0:
-		/* nothing found */
-		return ctx;
+		ctx->seq1 = 1;
+		ctx->seq2 = 0;
 	}
-
-	return ctx;
+	return &ctx->mail_ctx;
 }
 
-int index_storage_search_deinit(struct mail_search_context *ctx, int *all_found)
+int index_storage_search_deinit(struct mail_search_context *_ctx)
 {
-	int ret, msgset_ret;
-
-	ret = !ctx->failed && ctx->error == NULL;
+        struct index_search_context *ctx = (struct index_search_context *)_ctx;
+	int ret;
 
-	if (ctx->msgset_ctx != NULL) {
-		msgset_ret = index_messageset_deinit(ctx->msgset_ctx);
-		if (msgset_ret < 0)
-			ret = FALSE;
-		if (all_found != NULL)
-			*all_found = msgset_ret > 0;
-	} else {
-		if (all_found != NULL)
-			*all_found = !ctx->failed;
-	}
+	ret = ctx->failed || ctx->error != NULL ? -1 : 0;
 
-	if (ctx->ibox->fetch_mail.pool != NULL)
-		index_mail_deinit(&ctx->ibox->fetch_mail);
 	if (ctx->imail.pool != NULL)
 		index_mail_deinit(&ctx->imail);
 
-	if (!index_storage_lock(ctx->ibox, MAIL_LOCK_UNLOCK))
-		ret = FALSE;
-
 	if (ctx->error != NULL) {
 		mail_storage_set_error(ctx->ibox->box.storage,
 				       "%s", ctx->error);
@@ -907,7 +775,7 @@
 	return ret;
 }
 
-static int search_match_next(struct mail_search_context *ctx)
+static int search_match_next(struct index_search_context *ctx)
 {
         struct mail_search_arg *arg;
 	int ret;
@@ -918,6 +786,12 @@
 	if (ret >= 0)
 		return ret > 0;
 
+	if (ctx->imail.data.rec == NULL) {
+		/* expunged message, no way to check if the rest would have
+		   matched */
+		return FALSE;
+	}
+
 	/* next search only from cached arguments */
 	ret = mail_search_args_foreach(ctx->args, search_cached_arg, ctx);
 	if (ret >= 0)
@@ -935,33 +809,27 @@
 	return TRUE;
 }
 
-struct mail *index_storage_search_next(struct mail_search_context *ctx)
+struct mail *index_storage_search_next(struct mail_search_context *_ctx)
 {
-	const struct messageset_mail *msgset_mail;
+        struct index_search_context *ctx = (struct index_search_context *)_ctx;
+	const struct mail_index_record *rec;
 	int ret;
 
-	if (ctx->msgset_ctx == NULL) {
-		/* initialization failed or didn't found any messages */
-		return NULL;
-	}
-
-	do {
-		msgset_mail = index_messageset_next(ctx->msgset_ctx);
-		if (msgset_mail == NULL) {
-			ret = -1;
-			break;
+	ret = 0;
+	while (ctx->seq1 <= ctx->seq2) {
+		if (mail_index_lookup(ctx->ibox->view, ctx->seq1, &rec) < 0) {
+			ctx->failed = TRUE;
+			mail_storage_set_index_error(ctx->ibox);
+			return NULL;
 		}
 
-		ctx->mail->seq = msgset_mail->client_seq;
-		ctx->mail->uid = msgset_mail->rec->uid;
+		ctx->imail.data.rec = rec;
+		ctx->mail->seq = ctx->seq1++;
+		ctx->mail->uid = rec == NULL ? 0 : rec->uid;
 
-		ret = index_mail_next(&ctx->imail, msgset_mail->rec,
-				      msgset_mail->idx_seq, TRUE);
-		if (ret <= 0) {
-			if (ret < 0)
-				break;
-			continue;
-		}
+		ret = index_mail_next(&ctx->imail, rec, ctx->mail->seq, TRUE);
+		if (ret < 0)
+			break;
 
 		t_push();
 		ret = search_match_next(ctx);
@@ -969,11 +837,12 @@
 
 		if (ctx->error != NULL)
 			ret = -1;
-	} while (ret == 0);
+		if (ret != 0)
+			break;
+	}
 
-	if (ret < 0) {
+	if (ret <= 0) {
 		/* error or last record */
-		index_mail_deinit(&ctx->imail);
 		return NULL;
 	}
 

Index: index-status.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-status.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- index-status.c	15 Jun 2003 03:42:29 -0000	1.26
+++ index-status.c	27 Apr 2004 20:25:54 -0000	1.27
@@ -1,69 +1,13 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "mail-custom-flags.h"
-#include "mail-index-util.h"
 #include "index-storage.h"
 
 #define STATUS_MESSAGE_COUNTS \
 	(STATUS_MESSAGES | STATUS_RECENT | STATUS_UIDNEXT | \
 	 STATUS_UIDVALIDITY | STATUS_UNSEEN | STATUS_FIRST_UNSEEN_SEQ)
 
-static unsigned int get_first_unseen_seq(struct mail_index *index)
-{
-	struct mail_index_header *hdr;
-	struct mail_index_record *rec;
-	unsigned int seq, lowwater_uid;
-
-	hdr = mail_index_get_header(index);
-	if (hdr->seen_messages_count == hdr->messages_count) {
-		/* no unseen messages */
-		return 0;
-	}
-
-	lowwater_uid = hdr->first_unseen_uid_lowwater;
-	if (lowwater_uid == hdr->next_uid) {
-		/* no unseen messages */
-		rec = NULL;
-	} else if (lowwater_uid > hdr->next_uid) {
-		index_set_corrupted(index, "first_unseen_uid_lowwater %u >= "
-				    "next_uid %u", lowwater_uid, hdr->next_uid);
-		return 0;
-	} else if (lowwater_uid != 0) {
-		/* begin scanning from the low water mark */
-		rec = index->lookup_uid_range(index, lowwater_uid,
-					      hdr->next_uid - 1, &seq);
-	} else {
-		/* begin scanning from the beginning */
-		rec = index->lookup(index, 1);
-		seq = 1;
-	}
-
-	while (rec != NULL && (rec->msg_flags & MAIL_SEEN)) {
-		rec = index->next(index, rec);
-		seq++;
-	}
-
-	if (rec == NULL) {
-		index_set_corrupted(index, "No unseen messages found with "
-				    "first_unseen_uid_lowwater %u, "
-				    "seen_messages_count %u, messages_count %u",
-				    lowwater_uid, hdr->seen_messages_count,
-				    hdr->messages_count);
-		return 0;
-	}
-
-	if (rec->uid != lowwater_uid) {
-		/* update the low water mark if we can get exclusive
-		   lock immediately. */
-		if (index->try_lock(index, MAIL_LOCK_EXCLUSIVE))
-			hdr->first_unseen_uid_lowwater = rec->uid;
-	}
-
-	return seq;
-}
-
-static void
+/*static void
 get_custom_flags(struct mail_custom_flags *mcf, struct mailbox_status *status)
 {
 	const char **flags;
@@ -75,55 +19,47 @@
 	flags = mail_custom_flags_list_get(mcf);
 	for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++)
 		status->custom_flags[i] = t_strdup(flags[i]);
-}
+}*/
 
 int index_storage_get_status(struct mailbox *box,
 			     enum mailbox_status_items items,
 			     struct mailbox_status *status)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
-	struct mail_index_header *hdr;
+	const struct mail_index_header *hdr;
 
 	memset(status, 0, sizeof(struct mailbox_status));
 
 	if ((items & STATUS_MESSAGE_COUNTS) != 0) {
-		/* if we're doing STATUS for selected mailbox, we have to sync
-		   it first or STATUS reply may give different data */
-		if (!index_storage_sync_and_lock(ibox, TRUE, FALSE,
-						 MAIL_LOCK_UNLOCK))
-			return FALSE;
-
-		if (!index_storage_sync_modifylog(ibox, FALSE)) {
-			(void)index_storage_lock(ibox, MAIL_LOCK_UNLOCK);
-			return FALSE;
-		}
-	} else {
-		if (!index_storage_lock(ibox, MAIL_LOCK_SHARED))
-			return FALSE;
+		/* sync mailbox to update message counts */
+		if (mailbox_sync(box, 0) < 0)
+			return -1;
 	}
 
 	/* we can get most of the status items without any trouble */
-	hdr = mail_index_get_header(ibox->index);
+	hdr = mail_index_get_header(ibox->view);
 	if ((items & STATUS_MESSAGE_COUNTS) != 0) {
 		status->messages = hdr->messages_count;
 		status->unseen = hdr->messages_count - hdr->seen_messages_count;
 		status->uidvalidity = hdr->uid_validity;
 		status->uidnext = hdr->next_uid;
 	}
-	status->diskspace_full = ibox->index->nodiskspace;
+	//FIXME:status->diskspace_full = ibox->nodiskspace;
 
 	if (items & STATUS_FIRST_UNSEEN_SEQ) {
-		status->first_unseen_seq =
-			get_first_unseen_seq(ibox->index);
+		if (mail_index_lookup_first(ibox->view, 0, MAIL_SEEN,
+					    &status->first_unseen_seq) < 0) {
+			mail_storage_set_index_error(ibox);
+			return -1;
+		}
 	}
 
-	if (items & STATUS_RECENT)
-		status->recent = index_storage_get_recent_count(ibox->index);
+	/*FIXME:if (items & STATUS_RECENT)
+		status->recent = index_storage_get_recent_count(view);*/
 
-	if (items & STATUS_CUSTOM_FLAGS)
-		get_custom_flags(ibox->index->custom_flags, status);
+	/*FIXME:if (items & STATUS_CUSTOM_FLAGS)
+		get_custom_flags(ibox, status);*/
 
-	if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
-		return FALSE;
-	return TRUE;
+	mail_index_view_unlock(ibox->view);
+	return 0;
 }

Index: index-storage.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-storage.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- index-storage.c	20 Oct 2003 04:15:18 -0000	1.41
+++ index-storage.c	27 Apr 2004 20:25:54 -0000	1.42
@@ -1,10 +1,8 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2003 Timo Sirainen */
 
 #include "lib.h"
 #include "ioloop.h"
 #include "mail-index.h"
-#include "mail-index-util.h"
-#include "mail-custom-flags.h"
 #include "index-storage.h"
 
 #include <stdlib.h>
@@ -23,8 +21,12 @@
 	struct index_list *next;
 
 	struct mail_index *index;
+	char *mailbox_path;
 	int refcount;
 
+	dev_t index_dir_dev;
+	ino_t index_dir_ino;
+
 	time_t destroy_time;
 };
 
@@ -32,12 +34,12 @@
 static struct timeout *to_index = NULL;
 static int index_storage_refcount = 0;
 
-void index_storage_init(struct mail_storage *storage __attr_unused__)
+void index_storage_init(struct index_storage *storage __attr_unused__)
 {
 	index_storage_refcount++;
 }
 
-void index_storage_deinit(struct mail_storage *storage __attr_unused__)
+void index_storage_deinit(struct index_storage *storage __attr_unused__)
 {
 	if (--index_storage_refcount > 0)
 		return;
@@ -45,7 +47,8 @@
         index_storage_destroy_unrefed();
 }
 
-void index_storage_add(struct mail_index *index)
+static void index_storage_add(struct mail_index *index,
+			      const char *mailbox_path, struct stat *st)
 {
 	struct index_list *list;
 
@@ -53,43 +56,56 @@
 	list->refcount = 1;
 	list->index = index;
 
+	list->mailbox_path = i_strdup(mailbox_path);
+	list->index_dir_dev = st->st_dev;
+	list->index_dir_ino = st->st_ino;
+
 	list->next = indexes;
 	indexes = list;
 }
 
+static void index_list_free(struct index_list *list)
+{
+	mail_index_free(list->index);
+	i_free(list->mailbox_path);
+	i_free(list);
+}
+
 struct mail_index *
-index_storage_lookup_ref(const char *index_dir, const char *path)
+index_storage_alloc(const char *index_dir, const char *mailbox_path,
+		    const char *prefix)
 {
 	struct index_list **list, *rec;
-	struct mail_index *match;
-	struct stat st1, st2;
+	struct mail_index *index;
+	struct stat st;
 	int destroy_count;
 
 	if (index_dir != NULL) {
-		if (stat(index_dir, &st1) < 0)
+		if (stat(index_dir, &st) < 0)
 			return NULL;
+	} else {
+		memset(&st, 0, sizeof(st));
 	}
 
 	/* compare index_dir inodes so we don't break even with symlinks.
 	   for in-memory indexes compare just mailbox paths */
-	destroy_count = 0; match = NULL;
+	destroy_count = 0; index = NULL;
 	for (list = &indexes; *list != NULL;) {
 		rec = *list;
 
-		if ((index_dir != NULL && stat(rec->index->dir, &st2) == 0 &&
-		     st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev) ||
-		    (index_dir == NULL &&
-		     strcmp(path, rec->index->mailbox_path) == 0)) {
+		if ((index_dir != NULL && st.st_ino == rec->index_dir_ino &&
+		     st.st_dev == rec->index_dir_dev) ||
+		    (index_dir == NULL && st.st_ino == 0 &&
+		     strcmp(mailbox_path, rec->mailbox_path) == 0)) {
 			rec->refcount++;
-			match = rec->index;
+			index = rec->index;
 		}
 
 		if (rec->refcount == 0) {
 			if (rec->destroy_time <= ioloop_time ||
 			    destroy_count >= INDEX_CACHE_MAX) {
-				rec->index->free(rec->index);
 				*list = rec->next;
-				i_free(rec);
+				index_list_free(rec);
 				continue;
 			} else {
 				destroy_count++;
@@ -99,7 +115,12 @@
                 list = &(*list)->next;
 	}
 
-	return match;
+	if (index == NULL) {
+		index = mail_index_alloc(index_dir, prefix);
+		index_storage_add(index, mailbox_path, &st);
+	}
+
+	return index;
 }
 
 static void destroy_unrefed(int all)
@@ -111,9 +132,8 @@
 
 		if (rec->refcount == 0 &&
 		    (all || rec->destroy_time <= ioloop_time)) {
-			rec->index->free(rec->index);
 			*list = rec->next;
-			i_free(rec);
+			index_list_free(rec);
 		} else {
 			list = &(*list)->next;
 		}
@@ -223,11 +243,11 @@
 	return ret;
 }
 
-static void lock_notify(enum mail_lock_notify_type notify_type,
+static void lock_notify(enum mailbox_lock_notify_type notify_type,
 			unsigned int secs_left, void *context)
 {
 	struct index_mailbox *ibox = context;
-	struct mail_storage *storage = ibox->box.storage;
+	struct index_storage *storage = ibox->storage;
 	const char *str;
 	time_t now;
 
@@ -241,10 +261,10 @@
 
 	/* if notify type changes, print the message immediately */
 	now = time(NULL);
-	if (ibox->last_notify_type == (enum mail_lock_notify_type)-1 ||
+	if (ibox->last_notify_type == MAILBOX_LOCK_NOTIFY_NONE ||
 	    ibox->last_notify_type == notify_type) {
-		if (ibox->last_notify_type == (enum mail_lock_notify_type)-1 &&
-		    notify_type == MAIL_LOCK_NOTIFY_MAILBOX_OVERRIDE) {
+		if (ibox->last_notify_type == MAILBOX_LOCK_NOTIFY_NONE &&
+		    notify_type == MAILBOX_LOCK_NOTIFY_MAILBOX_OVERRIDE) {
 			/* first override notification, show it */
 		} else {
 			if (now < ibox->next_lock_notify || secs_left < 15)
@@ -256,73 +276,31 @@
         ibox->last_notify_type = notify_type;
 
 	switch (notify_type) {
-	case MAIL_LOCK_NOTIFY_MAILBOX_ABORT:
+	case MAILBOX_LOCK_NOTIFY_NONE:
+		break;
+	case MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT:
 		str = t_strdup_printf("Mailbox is locked, will abort in "
 				      "%u seconds", secs_left);
 		storage->callbacks->notify_no(&ibox->box, str,
 					      storage->callback_context);
 		break;
-	case MAIL_LOCK_NOTIFY_MAILBOX_OVERRIDE:
+	case MAILBOX_LOCK_NOTIFY_MAILBOX_OVERRIDE:
 		str = t_strdup_printf("Stale mailbox lock file detected, "
 				      "will override in %u seconds", secs_left);
 		storage->callbacks->notify_ok(&ibox->box, str,
 					      storage->callback_context);
 		break;
-	case MAIL_LOCK_NOTIFY_INDEX_ABORT:
-		str = t_strdup_printf("Mailbox index is locked, will abort in "
-				      "%u seconds", secs_left);
-		storage->callbacks->notify_no(&ibox->box, str,
-					      storage->callback_context);
-		break;
 	}
 }
 
-void index_storage_init_lock_notify(struct index_mailbox *ibox)
+void index_storage_reset_lock_notify(struct index_mailbox *ibox)
 {
-	if (ibox->index->mailbox_readonly)
-		ibox->readonly = TRUE;
-
 	ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
-	ibox->last_notify_type = (enum mail_lock_notify_type)-1;
-
-	ibox->index->set_lock_notify_callback(ibox->index, lock_notify, ibox);
-}
-
-int index_storage_lock(struct index_mailbox *ibox,
-		       enum mail_lock_type lock_type)
-{
-	int ret = TRUE;
-
-	if (lock_type == MAIL_LOCK_UNLOCK) {
-		if (ibox->trans_ctx != NULL) {
-			if (!mail_cache_transaction_commit(ibox->trans_ctx))
-				ret = FALSE;
-			if (!mail_cache_transaction_end(ibox->trans_ctx))
-				ret = FALSE;
-			ibox->trans_ctx = NULL;
-		}
-		if (ibox->lock_type != MAILBOX_LOCK_UNLOCK)
-			return TRUE;
-	} else {
-		if (ibox->lock_type == MAIL_LOCK_EXCLUSIVE)
-			return TRUE;
-	}
-
-	/* we have to set/reset this every time, because the same index
-	   may be used by multiple IndexMailboxes. */
-        index_storage_init_lock_notify(ibox);
-	if (!ibox->index->set_lock(ibox->index, lock_type))
-		ret = FALSE;
-	ibox->index->set_lock_notify_callback(ibox->index, NULL, NULL);
-
-	if (!ret)
-		return mail_storage_set_index_error(ibox);
-
-	return TRUE;
+	ibox->last_notify_type = MAILBOX_LOCK_NOTIFY_NONE;
 }
 
 struct index_mailbox *
-index_storage_mailbox_init(struct mail_storage *storage, struct mailbox *box,
+index_storage_mailbox_init(struct index_storage *storage, struct mailbox *box,
 			   struct mail_index *index, const char *name,
 			   enum mailbox_open_flags flags)
 {
@@ -334,52 +312,38 @@
 	index_flags = MAIL_INDEX_OPEN_FLAG_CREATE;
 	if ((flags & MAILBOX_OPEN_FAST) != 0)
 		index_flags |= MAIL_INDEX_OPEN_FLAG_FAST;
-	if ((flags & MAILBOX_OPEN_READONLY) != 0)
-		index_flags |= MAIL_INDEX_OPEN_FLAG_UPDATE_RECENT;
-	if ((flags & MAILBOX_OPEN_MMAP_INVALIDATE) != 0)
-		index_flags |= MAIL_INDEX_OPEN_FLAG_MMAP_INVALIDATE;
 
 	do {
 		ibox = i_new(struct index_mailbox, 1);
 		ibox->box = *box;
+		ibox->storage = storage;
 
-		ibox->box.storage = storage;
+		ibox->box.storage = &storage->storage;
 		ibox->box.name = i_strdup(name);
 		ibox->readonly = (flags & MAILBOX_OPEN_READONLY) != 0;
 
 		ibox->index = index;
 
 		ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
-		index->set_lock_notify_callback(index, lock_notify, ibox);
-
-		if (!index->opened) {
-			/* open the index first */
-			if (!index->open(index, index_flags))
-				break;
-
-			mail_cache_set_defaults(index->cache,
-						get_default_cache_fields(),
-						get_never_cache_fields());
-
-			if (INDEX_IS_IN_MEMORY(index) &&
-			    storage->index_dir != NULL) {
-				storage->callbacks->notify_no(&ibox->box,
-					"Couldn't use index files",
-					storage->callback_context);
-			}
-		}
+		ibox->commit_log_file_seq = 0;
+		ibox->mail_read_mmaped = getenv("MAIL_READ_MMAPED") != NULL;
 
-		if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_SHARED))
+		if (mail_index_open(index, index_flags) < 0)
 			break;
 
-		ibox->synced_messages_count =
-			mail_index_get_header(index)->messages_count;
-
-		if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK))
-			break;
+		ibox->cache = mail_index_get_cache(index);
+		mail_cache_set_defaults(ibox->cache,
+					get_default_cache_fields(),
+					get_never_cache_fields());
 
-		index->set_lock_notify_callback(index, NULL, NULL);
+		if (mail_index_is_in_memory(index) &&
+		    storage->index_dir != NULL) {
+			storage->callbacks->notify_no(&ibox->box,
+				"Couldn't use index files",
+				storage->callback_context);
+		}
 
+		ibox->view = mail_index_view_open(index);
 		return ibox;
 	} while (0);
 
@@ -388,21 +352,21 @@
 	return NULL;
 }
 
-int index_storage_mailbox_free(struct mailbox *box)
+void index_storage_mailbox_free(struct mailbox *box)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
 
 	/* make sure we're unlocked */
-	(void)ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK);
+	mail_index_view_unlock(ibox->view);
 
 	index_mailbox_check_remove_all(ibox);
 	if (ibox->index != NULL)
 		index_storage_unref(ibox->index);
+	i_free(ibox->path);
+	i_free(ibox->control_dir);
 
 	i_free(box->name);
 	i_free(box);
-
-	return TRUE;
 }
 
 int index_storage_is_readonly(struct mailbox *box)
@@ -416,51 +380,41 @@
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
 
-	return ibox->index->allow_new_custom_flags;
+	/* FIXME: return FALSE if we're full */
+	return !ibox->readonly;
 }
 
-int index_storage_is_inconsistency_error(struct mailbox *box)
+int index_storage_is_inconsistent(struct mailbox *box)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
 
-	return ibox->inconsistent;
+	return mail_index_view_is_inconsistent(ibox->view);
 }
 
-void index_storage_set_callbacks(struct mail_storage *storage,
+void index_storage_set_callbacks(struct mail_storage *_storage,
 				 struct mail_storage_callbacks *callbacks,
 				 void *context)
 {
-	memcpy(storage->callbacks, callbacks,
-	       sizeof(struct mail_storage_callbacks));
+	struct index_storage *storage = (struct index_storage *) _storage;
+
+	*storage->callbacks = *callbacks;
 	storage->callback_context = context;
 }
 
 int mail_storage_set_index_error(struct index_mailbox *ibox)
 {
-	switch (ibox->index->get_last_error(ibox->index)) {
+	switch (mail_index_get_last_error(ibox->index)) {
 	case MAIL_INDEX_ERROR_NONE:
 	case MAIL_INDEX_ERROR_INTERNAL:
 		mail_storage_set_internal_error(ibox->box.storage);
 		break;
-	case MAIL_INDEX_ERROR_INCONSISTENT:
-		ibox->inconsistent = TRUE;
-		break;
 	case MAIL_INDEX_ERROR_DISKSPACE:
 		mail_storage_set_error(ibox->box.storage, "Out of disk space");
 		break;
-	case MAIL_INDEX_ERROR_INDEX_LOCK_TIMEOUT:
-		mail_storage_set_error(ibox->box.storage,
-			"Timeout while waiting for lock to index of mailbox %s",
-			ibox->box.name);
-		break;
-	case MAIL_INDEX_ERROR_MAILBOX_LOCK_TIMEOUT:
-		mail_storage_set_error(ibox->box.storage,
-			"Timeout while waiting for lock to mailbox %s",
-			ibox->box.name);
-		break;
 	}
 
-	index_reset_error(ibox->index);
+	mail_index_view_unlock(ibox->view);
+	mail_index_reset_error(ibox->index);
 	return FALSE;
 }
 
@@ -469,9 +423,9 @@
 				   const char *custom_flags[],
 				   unsigned int custom_flags_count)
 {
-	int ret;
+	/*FIXME:int ret;
 
-	ret = mail_custom_flags_fix_list(ibox->index->custom_flags,
+	ret = mail_custom_flags_fix_list(ibox->index,
 					 flags, custom_flags,
 					 custom_flags_count);
 	switch (ret) {
@@ -483,16 +437,17 @@
 		return FALSE;
 	default:
 		return mail_storage_set_index_error(ibox);
-	}
+	}*/
 }
 
-unsigned int index_storage_get_recent_count(struct mail_index *index)
+unsigned int index_storage_get_recent_count(struct mail_index_view *view)
 {
+#if 0
 	struct mail_index_header *hdr;
 	struct mail_index_record *rec;
 	unsigned int seq;
 
-	hdr = mail_index_get_header(index);
+	hdr = mail_index_get_header(view);
 	if (index->first_recent_uid <= 1) {
 		/* all are recent */
 		return hdr->messages_count;
@@ -502,7 +457,9 @@
 	if (index->first_recent_uid >= hdr->next_uid)
 		return 0;
 
-	rec = index->lookup_uid_range(index, index->first_recent_uid,
-				      hdr->next_uid - 1, &seq);
+	rec = mail_index_lookup_uid_range(view, index->first_recent_uid,
+					  hdr->next_uid - 1, &seq);
 	return rec == NULL ? 0 : hdr->messages_count+1 - seq;
+#endif
+	return 0;
 }

Index: index-storage.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-storage.h,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -d -r1.53 -r1.54
--- index-storage.h	26 Oct 2003 20:13:15 -0000	1.53
+++ index-storage.h	27 Apr 2004 20:25:54 -0000	1.54
@@ -1,10 +1,26 @@
 #ifndef __INDEX_STORAGE_H
 #define __INDEX_STORAGE_H
 
-#include "mail-storage.h"
+#include "mail-storage-private.h"
 #include "mail-index.h"
 #include "index-mail.h"
 
+/* Max. mmap()ed size for a message */
+#define MAIL_MMAP_BLOCK_SIZE (1024*256)
+/* Block size when read()ing message. */
+#define MAIL_READ_BLOCK_SIZE (1024*8)
+
+#define MAILBOX_FULL_SYNC_INTERVAL 5
+
+enum mailbox_lock_notify_type {
+	MAILBOX_LOCK_NOTIFY_NONE,
+
+	/* Mailbox is locked, will abort in secs_left */
+	MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT,
+	/* Mailbox lock looks stale, will override in secs_left */
+	MAILBOX_LOCK_NOTIFY_MAILBOX_OVERRIDE
+};
+
 struct index_autosync_file {
 	struct index_autosync_file *next;
 
@@ -18,16 +34,30 @@
 	int fd;
 };
 
+struct index_storage {
+	struct mail_storage storage;
+
+	char *dir; /* root directory */
+	char *index_dir;
+	char *control_dir;
+	char *inbox_path; /* INBOX location */
+
+	char *user; /* name of user accessing the storage */
+
+	struct mail_storage_callbacks *callbacks;
+	void *callback_context;
+};
+
 struct index_mailbox {
 	struct mailbox box;
-
-	/* expunge messages marked as deleted, requires index to be
-	   exclusively locked */
-	void (*mail_init)(struct index_mail *mail);
+	struct index_storage *storage;
+	char *path, *control_dir;
 
 	struct mail_index *index;
-        enum mailbox_lock_type lock_type;
-	struct mail_cache_transaction_ctx *trans_ctx;
+	struct mail_index_view *view;
+	struct mail_cache *cache;
+	struct mail_cache_view *cache_view;
+	struct mail *mail_interface;
 
 	struct timeout *autosync_to;
 	struct index_autosync_file *autosync_files;
@@ -36,59 +66,72 @@
 	time_t sync_last_check, sync_last_notify;
 	unsigned int min_newmail_notify_interval;
 
-	struct index_mail fetch_mail; /* fetch_uid() or fetch_seq() */
-	unsigned int synced_messages_count;
-
 	time_t next_lock_notify; /* temporary */
-	enum mail_lock_notify_type last_notify_type;
+	enum mailbox_lock_notify_type last_notify_type;
+
+	uint32_t commit_log_file_seq;
+	uoff_t commit_log_file_offset;
+
+	/* sync: */
+	struct maildir_uidlist *uidlist;
+	time_t last_new_mtime, last_cur_mtime, last_sync;
+
+        mode_t mail_create_mode;
+	unsigned int private_flags_mask;
 
 	unsigned int readonly:1;
-	unsigned int inconsistent:1;
 	unsigned int sent_diskspace_warning:1;
 	unsigned int sent_readonly_flags_warning:1;
 	unsigned int autosync_pending:1;
+	unsigned int mail_read_mmaped:1;
+
+	unsigned int maildir_keep_new:1;
+};
+
+struct index_transaction_context {
+	struct mailbox_transaction_context mailbox_ctx;
+	struct index_mailbox *ibox;
+	struct mail_index_transaction *trans;
+	struct mail_cache_transaction_ctx *cache_trans;
+
+	struct index_mail fetch_mail; /* for index_storage_fetch() */
 };
 
 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,
-		       enum mail_lock_type lock_type);
+void index_storage_reset_lock_notify(struct index_mailbox *ibox);
 
-void index_storage_add(struct mail_index *index);
 struct mail_index *
-index_storage_lookup_ref(const char *index_dir, const char *path);
+index_storage_alloc(const char *index_dir,
+		    const char *mailbox_path, const char *prefix);
 void index_storage_unref(struct mail_index *index);
 void index_storage_destroy_unrefed(void);
 
-void index_storage_init(struct mail_storage *storage);
-void index_storage_deinit(struct mail_storage *storage);
+void index_storage_init(struct index_storage *storage);
+void index_storage_deinit(struct index_storage *storage);
 
 struct index_mailbox *
-index_storage_mailbox_init(struct mail_storage *storage, struct mailbox *box,
+index_storage_mailbox_init(struct index_storage *storage, struct mailbox *box,
 			   struct mail_index *index, const char *name,
 			   enum mailbox_open_flags flags);
-int index_storage_mailbox_free(struct mailbox *box);
+void index_storage_mailbox_free(struct mailbox *box);
 
 int index_storage_is_readonly(struct mailbox *box);
 int index_storage_allow_new_custom_flags(struct mailbox *box);
-int index_storage_is_inconsistency_error(struct mailbox *box);
-
-int index_storage_sync_and_lock(struct index_mailbox *ibox,
-				int sync_size, int minimal_sync,
-				enum mail_lock_type data_lock_type);
-int index_storage_sync_modifylog(struct index_mailbox *ibox, int hide_deleted);
+int index_storage_is_inconsistent(struct mailbox *box);
 
 int index_mailbox_fix_custom_flags(struct index_mailbox *ibox,
 				   enum mail_flags *flags,
 				   const char *custom_flags[],
 				   unsigned int custom_flags_count);
 
-unsigned int index_storage_get_recent_count(struct mail_index *index);
+unsigned int index_storage_get_recent_count(struct mail_index_view *view);
 
 void index_mailbox_check_add(struct index_mailbox *ibox,
 			     const char *path, int dir);
 void index_mailbox_check_remove_all(struct index_mailbox *ibox);
 
+int index_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags);
+
 /* mailbox methods: */
 void index_storage_set_callbacks(struct mail_storage *storage,
 				 struct mail_storage_callbacks *callbacks,
@@ -96,31 +139,27 @@
 int index_storage_get_status(struct mailbox *box,
 			     enum mailbox_status_items items,
 			     struct mailbox_status *status);
-int index_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags);
 
-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);
+struct mail *
+index_storage_fetch(struct mailbox_transaction_context *t, uint32_t seq,
+		    enum mail_fetch_field wanted_fields);
+int index_storage_get_uids(struct mailbox *box, uint32_t uid1, uint32_t uid2,
+			   uint32_t *seq1_r, uint32_t *seq2_r);
 
 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,
+index_storage_search_init(struct mailbox_transaction_context *t,
+			  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,
-				int *all_found);
+int index_storage_search_deinit(struct mail_search_context *ctx);
 struct mail *index_storage_search_next(struct mail_search_context *ctx);
 
-struct mail_copy_context *index_storage_copy_init(struct mailbox *box);
-int index_storage_copy_deinit(struct mail_copy_context *ctx, int rollback);
-int index_storage_copy(struct mail *mail, struct mail_copy_context *ctx);
-
-int index_storage_update_flags(struct mail *mail,
-			       const struct mail_full_flags *flags,
-			       enum modify_type modify_type);
+struct mailbox_transaction_context *
+index_transaction_begin(struct mailbox *box);
+int index_transaction_commit(struct mailbox_transaction_context *t);
+void index_transaction_rollback(struct mailbox_transaction_context *t);
 
 #endif

Index: index-sync.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-sync.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- index-sync.c	24 Aug 2003 12:45:33 -0000	1.27
+++ index-sync.c	27 Apr 2004 20:25:54 -0000	1.28
@@ -1,250 +1,89 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ioloop.h"
 #include "index-storage.h"
-#include "mail-index-util.h"
-#include "mail-modifylog.h"
-#include "mail-custom-flags.h"
 
-/* How often to do full sync when fast sync flag is set. */
-#define MAILBOX_FULL_SYNC_INTERVAL 5
-
-static void index_storage_sync_size(struct index_mailbox *ibox)
+int index_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags)
 {
-	struct mail_storage *storage = ibox->box.storage;
-	unsigned int messages, recent;
-
-	if (storage->callbacks->new_messages == NULL)
-		return;
-
-	messages = ibox->index->get_header(ibox->index)->messages_count;
-	messages += mail_modifylog_get_expunge_count(ibox->index->modifylog);
+	struct index_mailbox *ibox = (struct index_mailbox *)box;
+	struct mail_index_view_sync_ctx *ctx;
+        struct mail_full_flags full_flags;
+	const struct mail_index_record *rec;
+	struct mail_index_sync_rec sync;
+	struct mail_storage_callbacks *sc;
+	const uint32_t *expunges;
+	size_t i, expunges_count;
+	void *sc_context;
+	enum mail_index_sync_type sync_mask;
+	uint32_t seq, new_count;
+	int ret, appends;
 
-	if (messages != ibox->synced_messages_count) {
-		i_assert(messages > ibox->synced_messages_count);
+	sync_mask = MAIL_INDEX_SYNC_MASK_ALL;
+	if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) != 0)
+		sync_mask &= ~MAIL_INDEX_SYNC_TYPE_EXPUNGE;
 
-		/* new messages in mailbox */
-		recent = index_storage_get_recent_count(ibox->index);
-		storage->callbacks->new_messages(&ibox->box, messages, recent,
-						 storage->callback_context);
-		ibox->synced_messages_count = messages;
+	if (mail_index_view_sync_begin(ibox->view, sync_mask, &ctx) < 0) {
+                mail_storage_set_index_error(ibox);
+		return -1;
 	}
-}
-
-int index_storage_sync_and_lock(struct index_mailbox *ibox,
-				int sync_size, int minimal_sync,
-				enum mail_lock_type data_lock_type)
-{
-	struct mail_storage *storage = ibox->box.storage;
-	struct mail_index *index = ibox->index;
-	int failed, changes, set_shared_lock;
-
-        set_shared_lock = ibox->index->lock_type != MAIL_LOCK_EXCLUSIVE;
 
-        index_storage_init_lock_notify(ibox);
-	failed = !index->sync_and_lock(index, minimal_sync,
-				       data_lock_type, &changes);
-	ibox->index->set_lock_notify_callback(ibox->index, NULL, NULL);
-
-	if (!failed) {
-		/* reset every time it has worked */
-		ibox->sent_diskspace_warning = FALSE;
+	if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) != 0) {
+		expunges_count = 0;
+		expunges = NULL;
 	} else {
-		if (index->get_last_error(index) !=
-		    MAIL_INDEX_ERROR_DISKSPACE) {
-			(void)index_storage_lock(ibox, MAIL_LOCK_UNLOCK);
-			return mail_storage_set_index_error(ibox);
-		}
-
-		/* notify client once about it */
-		if (!ibox->sent_diskspace_warning &&
-		    storage->callbacks->alert_no_diskspace != NULL) {
-			ibox->sent_diskspace_warning = TRUE;
-			storage->callbacks->alert_no_diskspace(
-				&ibox->box, storage->callback_context);
-		}
-
-		index_reset_error(index);
-	}
-
-	if (set_shared_lock) {
-		/* just make sure we are locked, and that we drop our
-		   exclusive lock if it wasn't wanted originally */
-		if (!index_storage_lock(ibox, MAIL_LOCK_SHARED)) {
-			(void)index_storage_lock(ibox, MAIL_LOCK_UNLOCK);
-			return FALSE;
-		}
-	}
-
-	/* notify about changes in mailbox size. */
-	if (!changes)
-		return TRUE; /* no changes - must be no new mail either */
-
-	if (sync_size)
-		index_storage_sync_size(ibox);
-
-	/* notify changes in custom flags */
-	if (mail_custom_flags_has_changes(index->custom_flags) &&
-	    storage->callbacks->new_custom_flags != NULL) {
-		storage->callbacks->new_custom_flags(&ibox->box,
-                	mail_custom_flags_list_get(index->custom_flags),
-			MAIL_CUSTOM_FLAGS_COUNT, storage->callback_context);
+		expunges =
+			mail_index_view_sync_get_expunges(ctx, &expunges_count);
 	}
 
-	return TRUE;
-}
-
-int index_storage_sync_modifylog(struct index_mailbox *ibox, int hide_deleted)
-{
-	const struct modify_log_record *log1, *log2, *log, *first_flag_log;
-	struct mail_index_record *rec;
-	struct mail_full_flags flags;
-        struct mail_storage_callbacks *sc;
-	void *sc_context;
-	unsigned int count1, count2, total_count, seq, seq_count, i, messages;
-	unsigned int first_flag_change, first_flag_messages_count;
-
-	/* show the log */
-	if (!mail_modifylog_get_nonsynced(ibox->index->modifylog,
-					  &log1, &count1, &log2, &count2))
-		return mail_storage_set_index_error(ibox);
-
-	sc = ibox->box.storage->callbacks;
-	sc_context = ibox->box.storage->callback_context;
-
-	/* first show expunges. this makes it easier to deal with sequence
-	   numbers. */
-	total_count = count1 + count2;
-	messages = ibox->synced_messages_count;
-	first_flag_change = total_count;
-	first_flag_log = NULL;
-        first_flag_messages_count = 0;
-
-	for (i = 0, log = log1; i < total_count; i++, log++) {
-		if (i == count1)
-			log = log2;
-
-		if (log->seq1 > messages) {
-			/* client doesn't know about this message yet */
-			continue;
-		}
-
-		switch (log->type) {
-		case RECORD_TYPE_EXPUNGE:
-			seq_count = (log->seq2 - log->seq1) + 1;
-			messages -= seq_count;
-
-			if (sc->expunge == NULL)
-				break;
+	sc = ibox->storage->callbacks;
+	sc_context = ibox->storage->callback_context;
+	appends = FALSE;
 
-			for (; seq_count > 0; seq_count--) {
-				sc->expunge(&ibox->box, log->seq1,
-					    sc_context);
-			}
-			break;
-		case RECORD_TYPE_FLAGS_CHANGED:
-			if (first_flag_change == total_count) {
-				first_flag_change = i;
-				first_flag_log = log;
-				first_flag_messages_count = messages;
-			}
+	memset(&full_flags, 0, sizeof(full_flags));
+	while ((ret = mail_index_view_sync_next(ctx, &sync)) > 0) {
+		switch (sync.type) {
+		case MAIL_INDEX_SYNC_TYPE_APPEND:
+			appends = TRUE;
 			break;
-		}
-	}
-
-	/* set synced messages count before flag changes break it */
-	ibox->synced_messages_count = messages;
-
-	/* now show the flags */
-	messages = first_flag_messages_count;
-	flags.custom_flags =
-		mail_custom_flags_list_get(ibox->index->custom_flags);
-	flags.custom_flags_count = MAIL_CUSTOM_FLAGS_COUNT;
-
-	if (sc->update_flags == NULL) {
-		/* don't bother going through, we're not printing them anyway */
-		total_count = 0;
-	}
-
-	log = first_flag_log;
-	for (i = first_flag_change; i < total_count; i++, log++) {
-		if (i == count1)
-			log = log2;
-
-		if (log->seq1 > messages) {
-			/* client doesn't know about this message yet */
-			continue;
-		}
-
-		switch (log->type) {
-		case RECORD_TYPE_EXPUNGE:
-			messages -= (log->seq2 - log->seq1) + 1;
+		case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
+			/* later */
 			break;
-		case RECORD_TYPE_FLAGS_CHANGED:
-			rec = ibox->index->lookup_uid_range(ibox->index,
-							    log->uid1,
-							    log->uid2, &seq);
-			while (rec != NULL && rec->uid <= log->uid2) {
-				flags.flags = rec->msg_flags;
-				if (rec->uid >= ibox->index->first_recent_uid)
-					flags.flags |= MAIL_RECENT;
+		case MAIL_INDEX_SYNC_TYPE_FLAGS:
+			if (sc->update_flags == NULL)
+				break;
 
-				/* \Deleted-hiding is useful when syncing just
-				   before doing EXPUNGE. */
-				if ((flags.flags & MAIL_DELETED) == 0 ||
-				    !hide_deleted) {
-					sc->update_flags(&ibox->box, seq,
-							 rec->uid, &flags,
-							 sc_context);
+			/* FIXME: hide the flag updates for expunged messages */
+			for (seq = sync.seq1; seq <= sync.seq2; seq++) {
+				if (mail_index_lookup(ibox->view,
+						      seq, &rec) < 0) {
+					ret = -1;
+					break;
 				}
-
-                                seq++;
-				rec = ibox->index->next(ibox->index, rec);
+				full_flags.flags = rec->flags; // FIXME
+				sc->update_flags(&ibox->box, seq,
+						 &full_flags, sc_context);
 			}
 			break;
 		}
 	}
 
-	/* mark synced */
-	if (!mail_modifylog_mark_synced(ibox->index->modifylog))
-		return mail_storage_set_index_error(ibox);
-
-	return TRUE;
-}
-
-int index_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags)
-{
-	struct index_mailbox *ibox = (struct index_mailbox *) box;
-	int ret;
-
-	if ((flags & MAILBOX_SYNC_FAST) == 0 ||
-	    ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= ioloop_time) {
-		ibox->sync_last_check = ioloop_time;
-
-		if (!index_storage_sync_and_lock(ibox, FALSE, FALSE,
-						 MAIL_LOCK_UNLOCK))
-			return FALSE;
-	} else {
-		/* check only modify log */
-		if (!index_storage_lock(ibox, MAIL_LOCK_SHARED)) {
-			(void)index_storage_lock(ibox, MAIL_LOCK_UNLOCK);
-			return FALSE;
+	if (sc->expunge != NULL) {
+		for (i = expunges_count*2; i > 0; i -= 2) {
+			for (seq = expunges[i-1]; seq >= expunges[i-2]; seq--)
+				sc->expunge(&ibox->box, seq, sc_context);
 		}
 	}
 
-	/* FIXME: we could sync flags always, but expunges in the middle
-	   could make it a bit more difficult and slower */
-	if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) == 0 ||
-	    mail_modifylog_get_expunge_count(ibox->index->modifylog) == 0)
-		ret = index_storage_sync_modifylog(ibox, FALSE);
-	else
-		ret = TRUE;
+	mail_index_view_sync_end(ctx);
 
-	index_storage_sync_size(ibox);
+	if (appends) {
+		new_count = mail_index_view_get_message_count(ibox->view);
+		sc->new_messages(&ibox->box, new_count, 0, sc_context);
+	}
 
-	if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
-		return FALSE;
+	if (ret < 0)
+		mail_storage_set_index_error(ibox);
 
+	mail_index_view_unlock(ibox->view);
 	return ret;
 }

--- index-copy.c DELETED ---

--- index-expunge.c DELETED ---

--- index-expunge.h DELETED ---

--- index-messageset.c DELETED ---

--- index-messageset.h DELETED ---

--- index-update-flags.c DELETED ---



More information about the dovecot-cvs mailing list