changeset 327:276b7a53c264 HEAD

Modify log fixes. STORE and SEARCH didn't handle properly message sequence numbers when some in the middle were externally deleted.
author Timo Sirainen <tss@iki.fi>
date Sun, 29 Sep 2002 19:19:53 +0300
parents b79b6da2f84a
children a0abed892d11
files src/lib-index/mail-modifylog.c src/lib-index/mail-modifylog.h src/lib-storage/index/index-copy.c src/lib-storage/index/index-fetch.c src/lib-storage/index/index-messageset.c src/lib-storage/index/index-messageset.h src/lib-storage/index/index-search.c src/lib-storage/index/index-sync.c src/lib-storage/index/index-update-flags.c src/lib-storage/index/maildir/maildir-copy.c src/lib-storage/mail-storage.h
diffstat 11 files changed, 223 insertions(+), 113 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-modifylog.c	Sat Sep 28 13:29:10 2002 +0300
+++ b/src/lib-index/mail-modifylog.c	Sun Sep 29 19:19:53 2002 +0300
@@ -112,8 +112,10 @@
 	unsigned int extra;
 
 	if (!forced && log->header != NULL &&
-	    log->mmap_full_length >= log->header->used_file_size)
+	    log->mmap_full_length >= log->header->used_file_size) {
+		log->mmap_used_length = log->header->used_file_size;
 		return TRUE;
+	}
 
 	i_assert(!log->anon_mmap);
 
@@ -528,6 +530,9 @@
 		}
 	}
 
+	if (!mmap_update(log, FALSE))
+		return FALSE;
+
 	if (log->mmap_used_length == log->mmap_full_length) {
 		if (!mail_modifylog_grow(log))
 			return FALSE;
@@ -750,7 +755,8 @@
 const unsigned int *
 mail_modifylog_uid_get_expunges(MailModifyLog *log,
 				unsigned int first_uid,
-				unsigned int last_uid)
+				unsigned int last_uid,
+				unsigned int *expunges_before)
 {
 	/* pretty much copy&pasted from sequence code above ..
 	   kind of annoying */
@@ -759,6 +765,8 @@
 
 	i_assert(log->index->lock_type != MAIL_LOCK_UNLOCK);
 
+	*expunges_before = 0;
+
 	if (!mmap_update(log, FALSE))
 		return NULL;
 
@@ -793,8 +801,10 @@
 
 	before = 0;
 	while (rec < end_rec) {
-		if (rec->type == RECORD_TYPE_EXPUNGE &&
-		    rec->uid >= first_uid && rec->uid <= last_uid) {
+		if (rec->type != RECORD_TYPE_EXPUNGE)
+			continue;
+
+		if (rec->uid >= first_uid && rec->uid <= last_uid) {
 			/* within our range */
 			if (max_records-- == 0) {
 				/* log contains more data than it should
@@ -804,6 +814,9 @@
 				return NULL;
 			}
 			*arr++ = rec->uid;
+		} else if (rec->uid < first_uid) {
+			/* before our range */
+			before++;
 		}
 		rec++;
 	}
@@ -813,5 +826,32 @@
 	qsort(expunges, (unsigned int) (arr - expunges), sizeof(unsigned int),
 	      compare_uint);
 
+	*expunges_before = before;
 	return expunges;
 }
+
+unsigned int mail_modifylog_get_expunge_count(MailModifyLog *log)
+{
+	ModifyLogRecord *rec, *end_rec;
+	unsigned int expunges;
+
+	i_assert(log->index->lock_type != MAIL_LOCK_UNLOCK);
+
+	if (!mmap_update(log, FALSE))
+		return 0;
+
+	/* find the first expunged message that affects our range */
+	rec = (ModifyLogRecord *) ((char *) log->mmap_base +
+				   log->synced_position);
+	end_rec = (ModifyLogRecord *) ((char *) log->mmap_base +
+				       log->mmap_used_length);
+
+	expunges = 0;
+	while (rec < end_rec) {
+		if (rec->type == RECORD_TYPE_EXPUNGE)
+			expunges++;
+		rec++;
+	}
+
+	return expunges;
+}
--- a/src/lib-index/mail-modifylog.h	Sat Sep 28 13:29:10 2002 +0300
+++ b/src/lib-index/mail-modifylog.h	Sun Sep 29 19:19:53 2002 +0300
@@ -63,6 +63,10 @@
 const unsigned int *
 mail_modifylog_uid_get_expunges(MailModifyLog *log,
 				unsigned int first_uid,
-				unsigned int last_uid);
+				unsigned int last_uid,
+				unsigned int *expunges_before);
+
+/* Get number of non-synced expunges in modify log. */
+unsigned int mail_modifylog_get_expunge_count(MailModifyLog *log);
 
 #endif
--- a/src/lib-storage/index/index-copy.c	Sat Sep 28 13:29:10 2002 +0300
+++ b/src/lib-storage/index/index-copy.c	Sun Sep 29 19:19:53 2002 +0300
@@ -14,7 +14,8 @@
 } CopyContext;
 
 static int copy_func(MailIndex *index, MailIndexRecord *rec,
-		     unsigned int seq __attr_unused__, void *context)
+		     unsigned int client_seq __attr_unused__,
+		     unsigned int idx_seq __attr_unused__, void *context)
 {
 	CopyContext *ctx = context;
 	IOBuffer *inbuf;
--- a/src/lib-storage/index/index-fetch.c	Sat Sep 28 13:29:10 2002 +0300
+++ b/src/lib-storage/index/index-fetch.c	Sun Sep 29 19:19:53 2002 +0300
@@ -239,7 +239,9 @@
 }
 
 static int index_fetch_mail(MailIndex *index __attr_unused__,
-			    MailIndexRecord *rec, unsigned int seq,
+			    MailIndexRecord *rec,
+			    unsigned int client_seq,
+			    unsigned int idx_seq __attr_unused__,
 			    void *context)
 {
 	FetchContext *ctx = context;
@@ -249,7 +251,7 @@
 
 	ctx->str = t_string_new(2048);
 
-	t_string_printfa(ctx->str, "* %u FETCH (", seq);
+	t_string_printfa(ctx->str, "* %u FETCH (", client_seq);
 	orig_len = ctx->str->len;
 
 	/* first see what we need to do. this way we don't first do some
--- a/src/lib-storage/index/index-messageset.c	Sat Sep 28 13:29:10 2002 +0300
+++ b/src/lib-storage/index/index-messageset.c	Sun Sep 29 19:19:53 2002 +0300
@@ -30,7 +30,7 @@
 {
 	MailIndexRecord *rec;
 	const unsigned int *expunges;
-	unsigned int expunges_before;
+	unsigned int idx_seq, expunges_before;
 	int expunges_found;
 
 	if (seq > seq2) {
@@ -55,8 +55,9 @@
 
 	/* get the first non-expunged message. note that if all messages
 	   were expunged in the range, this points outside wanted range. */
-	rec = index->lookup(index, seq - expunges_before);
-	for (; rec != NULL; seq++) {
+	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);
 
@@ -70,7 +71,7 @@
 			break;
 
 		t_push();
-		if (!func(index, rec, seq, context)) {
+		if (!func(index, rec, seq, idx_seq, context)) {
 			t_pop();
 			return 0;
 		}
@@ -158,8 +159,10 @@
 		if (seq > messages_count) {
 			/* too large .. ignore silently */
 		} else {
+			t_push();
 			ret = mail_index_foreach(index, seq, seq2,
 						 func, context, error);
+			t_pop();
 			if (ret <= 0)
 				return ret;
 			if (ret == 2)
@@ -177,7 +180,7 @@
 {
 	MailIndexRecord *rec;
 	const unsigned int *expunges;
-	unsigned int seq;
+	unsigned int client_seq, idx_seq, expunges_before;
 	int expunges_found;
 
 	if (uid > uid2) {
@@ -188,7 +191,8 @@
 	}
 
 	/* get list of expunged messages in our range. */
-	expunges = mail_modifylog_uid_get_expunges(index->modifylog, uid, uid2);
+	expunges = mail_modifylog_uid_get_expunges(index->modifylog, uid, uid2,
+						   &expunges_before);
 	expunges_found = *expunges != '\0';
 
 	/* skip expunged messages at the beginning */
@@ -205,23 +209,25 @@
 	if (rec == NULL)
 		return expunges_found ? 2 : 1;
 
-	seq = index->get_sequence(index, rec);
+	idx_seq = index->get_sequence(index, rec);
+	client_seq = idx_seq + expunges_before;
+
 	while (rec != NULL && rec->uid <= uid2) {
 		uid = rec->uid;
 		while (*expunges != 0 && *expunges < rec->uid) {
 			expunges++;
-			seq++;
+			client_seq++;
 		}
 		i_assert(*expunges != rec->uid);
 
 		t_push();
-		if (!func(index, rec, seq, context)) {
+		if (!func(index, rec, client_seq, idx_seq, context)) {
 			t_pop();
 			return 0;
 		}
 		t_pop();
 
-		seq++;
+		client_seq++; idx_seq++;
 		rec = index->next(index, rec);
 	}
 
@@ -304,8 +310,10 @@
 		if (uid >= index->header->next_uid) {
 			/* too large .. ignore silently */
 		} else {
+			t_push();
 			ret = mail_index_uid_foreach(index, uid, uid2,
 						     func, context, error);
+			t_pop();
 			if (ret <= 0)
 				return ret;
 			if (ret == 2)
--- a/src/lib-storage/index/index-messageset.h	Sat Sep 28 13:29:10 2002 +0300
+++ b/src/lib-storage/index/index-messageset.h	Sun Sep 29 19:19:53 2002 +0300
@@ -5,7 +5,8 @@
 
 /* If FALSE is returned, the loop is stopped. */
 typedef int (*MsgsetForeachFunc)(MailIndex *index, MailIndexRecord *rec,
-				 unsigned int seq, void *context);
+				 unsigned int client_seq, unsigned int idx_seq,
+				 void *context);
 
 /* Returns 1 if all were found, 2 if some messages were deleted,
    0 func returned FALSE, -1 if internal error occured or -2 if messageset
--- a/src/lib-storage/index/index-search.c	Sat Sep 28 13:29:10 2002 +0300
+++ b/src/lib-storage/index/index-search.c	Sun Sep 29 19:19:53 2002 +0300
@@ -7,6 +7,7 @@
 #include "imap-date.h"
 #include "index-storage.h"
 #include "mail-index-util.h"
+#include "mail-modifylog.h"
 #include "mail-search.h"
 
 #include <stdlib.h>
@@ -20,7 +21,7 @@
 typedef struct {
 	IndexMailbox *ibox;
 	MailIndexRecord *rec;
-	unsigned int seq;
+	unsigned int client_seq;
 } SearchIndexContext;
 
 typedef struct {
@@ -107,8 +108,8 @@
 
 /* Returns >0 = matched, 0 = not matched, -1 = unknown */
 static int search_arg_match_index(IndexMailbox *ibox, MailIndexRecord *rec,
-				  unsigned int seq, MailSearchArgType type,
-				  const char *value)
+				  unsigned int client_seq,
+				  MailSearchArgType type, const char *value)
 {
 	time_t t;
 	uoff_t size;
@@ -117,7 +118,8 @@
 	case SEARCH_ALL:
 		return TRUE;
 	case SEARCH_SET:
-		return msgset_contains(value, seq, ibox->synced_messages_count);
+		return msgset_contains(value, client_seq,
+				       ibox->synced_messages_count);
 	case SEARCH_UID:
 		return msgset_contains(value, rec->uid,
 				       ibox->synced_messages_count);
@@ -185,7 +187,7 @@
 {
 	SearchIndexContext *ctx = context;
 
-	switch (search_arg_match_index(ctx->ibox, ctx->rec, ctx->seq,
+	switch (search_arg_match_index(ctx->ibox, ctx->rec, ctx->client_seq,
 				       arg->type, arg->value.str)) {
 	case -1:
 		/* unknown */
@@ -606,76 +608,104 @@
 	}
 }
 
-static void search_get_sequences(IndexMailbox *ibox, MailSearchArg *args,
-				 unsigned int *first_seq,
-				 unsigned int *last_seq)
+static unsigned int client_seq_to_uid(MailIndex *index, unsigned int seq)
 {
 	MailIndexRecord *rec;
-	unsigned int seq, first_uid, last_uid;
+	unsigned int expunges_before;
+
+	(void)mail_modifylog_seq_get_expunges(index->modifylog, seq, seq,
+					      &expunges_before);
+	seq -= expunges_before;
+
+	rec = index->lookup(index, seq);
+	return rec == NULL ? 0 : rec->uid;
+}
 
-	*first_seq = *last_seq = 0;
-	first_uid = last_uid = 0;
+static int search_get_uid_range(IndexMailbox *ibox, MailSearchArg *args,
+				unsigned int *first_uid,
+				unsigned int *last_uid)
+{
+	unsigned int first_seq, last_seq, uid;
 
-	search_get_sequid(ibox, args, first_seq, last_seq,
-			  &first_uid, &last_uid);
+	*first_uid = *last_uid = 0;
+	first_seq = last_seq = 0;
+
+	search_get_sequid(ibox, args, &first_seq, &last_seq,
+			  first_uid, last_uid);
 
 	/* seq_update() should make sure that these can't happen */
-	i_assert(*first_seq <= *last_seq);
-	i_assert(first_uid <= last_uid);
+	i_assert(first_seq <= last_seq);
+	i_assert(*first_uid <= *last_uid);
 
-	if (first_uid != 0 && (*first_seq != 1 ||
-			       *last_seq != ibox->synced_messages_count)) {
-		/* UIDs were used - see if they affect the sequences */
-		rec = ibox->index->lookup_uid_range(ibox->index,
-						    first_uid, last_uid);
-		if (rec != NULL) {
-			/* update lower UID */
-			seq = ibox->index->get_sequence(ibox->index, rec);
-			if (seq < *first_seq)
-				*first_seq = seq;
+	if (first_seq > 1) {
+		uid = client_seq_to_uid(ibox->index, first_seq);
+		if (uid == 0)
+			return FALSE;
 
-			/* update higher UID .. except we don't really
-			   know it and it'd be uselessly slow to find it.
-			   use a kludgy method which might limit the
-			   sequences. */
-			seq += last_uid-first_uid;
-			if (seq >= ibox->synced_messages_count)
-				seq = ibox->synced_messages_count;
-
-			if (seq > *last_seq)
-				*last_seq = seq;
-		}
+		if (*first_uid == 0 || uid < *first_uid)
+			*first_uid = uid;
 	}
 
-	if (*first_seq == 0)
-		*first_seq = 1;
-	if (*last_seq == 0)
-		*last_seq = ibox->synced_messages_count;
+	if (last_seq > 1 && last_seq != ibox->synced_messages_count) {
+		uid = client_seq_to_uid(ibox->index, last_seq);
+		if (uid == 0)
+			return FALSE;
 
-	i_assert(*first_seq <= *last_seq);
+		if (uid > *last_uid)
+			*last_uid = uid;
+	}
+
+	if (*first_uid == 0)
+		*first_uid = 1;
+	if (*last_uid == 0)
+		*last_uid = ibox->index->header->next_uid-1;
+
+	i_assert(*first_uid <= *last_uid);
+	return TRUE;
 }
 
-static void search_messages(IndexMailbox *ibox, MailSearchArg *args,
-			    IOBuffer *outbuf, int uid_result)
+static int search_messages(IndexMailbox *ibox, MailSearchArg *args,
+			   IOBuffer *outbuf, int uid_result)
 {
 	SearchIndexContext ctx;
 	MailIndexRecord *rec;
         MailSearchArg *arg;
-	unsigned int first_seq, last_seq, seq;
+	const unsigned int *expunges;
+	unsigned int first_uid, last_uid, client_seq, expunges_before;
 	char num[MAX_LARGEST_T_STRLEN+10];
 	int found;
 
 	if (ibox->synced_messages_count == 0)
-		return;
+		return TRUE;
 
 	/* see if we can limit the records we look at */
-	search_get_sequences(ibox, args, &first_seq, &last_seq);
+	if (!search_get_uid_range(ibox, args, &first_uid, &last_uid))
+		return TRUE;
+
+	rec = ibox->index->lookup_uid_range(ibox->index, first_uid, last_uid);
+	if (rec == NULL)
+		return TRUE;
+
+	expunges = mail_modifylog_uid_get_expunges(ibox->index->modifylog,
+						   rec->uid, last_uid,
+						   &expunges_before);
+
+	client_seq = ibox->index->get_sequence(ibox->index, rec);
+	if (client_seq == 0)
+		return mail_storage_set_index_error(ibox);
+
+	client_seq += expunges_before;
 
 	ctx.ibox = ibox;
-	rec = ibox->index->lookup(ibox->index, first_seq);
-	for (seq = first_seq; rec != NULL && seq <= last_seq; seq++) {
+	for (; rec != NULL && rec->uid <= last_uid; client_seq++) {
+		while (*expunges != 0 && *expunges < rec->uid) {
+			expunges++;
+			client_seq++;
+		}
+		i_assert(*expunges != rec->uid);
+
 		ctx.rec = rec;
-		ctx.seq = seq;
+		ctx.client_seq = client_seq;
 
 		mail_search_args_reset(args);
 
@@ -694,18 +724,22 @@
 
 			if (found) {
 				i_snprintf(num, sizeof(num), " %u",
-					   uid_result ? rec->uid : seq);
+					   uid_result ? rec->uid : client_seq);
 				io_buffer_send(outbuf, num, strlen(num));
 			}
 		}
+
 		rec = ibox->index->next(ibox->index, rec);
 	}
+
+	return TRUE;
 }
 
 int index_storage_search(Mailbox *box, MailSearchArg *args,
 			 IOBuffer *outbuf, int uid_result)
 {
 	IndexMailbox *ibox = (IndexMailbox *) box;
+	int failed;
 
 	if (!index_storage_sync_if_possible(ibox))
 		return FALSE;
@@ -714,11 +748,11 @@
 		return mail_storage_set_index_error(ibox);
 
 	io_buffer_send(outbuf, "* SEARCH", 8);
-	search_messages(ibox, args, outbuf, uid_result);
+	failed = !search_messages(ibox, args, outbuf, uid_result);
 	io_buffer_send(outbuf, "\r\n", 2);
 
 	if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK))
 		return mail_storage_set_index_error(ibox);
 
-	return TRUE;
+	return !failed;
 }
--- a/src/lib-storage/index/index-sync.c	Sat Sep 28 13:29:10 2002 +0300
+++ b/src/lib-storage/index/index-sync.c	Sun Sep 29 19:19:53 2002 +0300
@@ -25,6 +25,54 @@
 	return TRUE;
 }
 
+static int index_storage_sync_log(Mailbox *box, MailIndex *index,
+				  MailExpungeFunc expunge_func,
+				  MailFlagUpdateFunc flag_func,
+				  void *context)
+{
+	ModifyLogRecord *log;
+	MailIndexRecord *rec;
+	MailFlags flags;
+	const char **custom_flags;
+	unsigned int count;
+
+	/* show the log */
+	log = mail_modifylog_get_nonsynced(index->modifylog, &count);
+	if (log == NULL)
+		return FALSE;
+
+	custom_flags = mail_custom_flags_list_get(index->custom_flags);
+	for (; count > 0; count--, log++) {
+		switch (log->type) {
+		case RECORD_TYPE_EXPUNGE:
+			if (expunge_func != NULL) {
+				expunge_func(box, log->seq,
+					     log->uid, context);
+			}
+			break;
+		case RECORD_TYPE_FLAGS_CHANGED:
+			if (flag_func == NULL)
+				break;
+
+			rec = index->lookup_uid_range(index,
+						      log->uid, log->uid);
+			if (rec != NULL) {
+				flags = rec->msg_flags;
+				if (rec->uid >= index->first_recent_uid)
+					flags |= MAIL_RECENT;
+
+				flag_func(box, log->seq, log->uid, flags,
+					  custom_flags, context);
+			}
+			break;
+		}
+	}
+	mail_custom_flags_list_unref(index->custom_flags);
+
+	/* mark synced */
+	return mail_modifylog_mark_synced(index->modifylog);
+}
+
 int index_storage_sync(Mailbox *box, int expunge,
 		       unsigned int *messages, unsigned int *recent,
 		       MailExpungeFunc expunge_func,
@@ -32,10 +80,6 @@
 		       void *context)
 {
 	IndexMailbox *ibox = (IndexMailbox *) box;
-	ModifyLogRecord *log;
-	MailIndexRecord *rec;
-	MailFlags flags;
-	const char **custom_flags;
 	unsigned int count;
 	int failed;
 
@@ -53,41 +97,12 @@
 				   MAIL_LOCK_EXCLUSIVE : MAIL_LOCK_SHARED))
 		return mail_storage_set_index_error(ibox);
 
-	/* show the log */
-	log = mail_modifylog_get_nonsynced(ibox->index->modifylog, &count);
-	if (log == NULL)
-		failed = TRUE;
-
-	custom_flags = mail_custom_flags_list_get(ibox->index->custom_flags);
-	for (; count > 0; count--, log++) {
-		switch (log->type) {
-		case RECORD_TYPE_EXPUNGE:
-			if (expunge_func != NULL) {
-				expunge_func(box, log->seq,
-					     log->uid, context);
-			}
-			break;
-		case RECORD_TYPE_FLAGS_CHANGED:
-			if (flag_func == NULL)
-				break;
+	failed = FALSE;
 
-			rec = ibox->index->lookup_uid_range(ibox->index,
-							    log->uid, log->uid);
-			if (rec != NULL) {
-				flags = rec->msg_flags;
-				if (rec->uid >= ibox->index->first_recent_uid)
-					flags |= MAIL_RECENT;
-
-				flag_func(box, log->seq, log->uid, flags,
-					  custom_flags, context);
-			}
-			break;
-		}
+	if (expunge_func != NULL || flag_func != NULL) {
+		failed = !index_storage_sync_log(box, ibox->index, expunge_func,
+						 flag_func, context);
 	}
-	mail_custom_flags_list_unref(ibox->index->custom_flags);
-
-	/* mark synced */
-	failed = !mail_modifylog_mark_synced(ibox->index->modifylog);
 
 	if (!failed && expunge) {
 		/* expunge messages */
@@ -97,6 +112,7 @@
 	/* get the messages count even if there was some failures.
 	   also it must be done after expunging messages */
 	count = ibox->index->get_header(ibox->index)->messages_count;
+	count += mail_modifylog_get_expunge_count(ibox->index->modifylog);
 	if (count != ibox->synced_messages_count) {
 		if (count > ibox->synced_messages_count) {
 			/* new messages in mailbox */
--- a/src/lib-storage/index/index-update-flags.c	Sat Sep 28 13:29:10 2002 +0300
+++ b/src/lib-storage/index/index-update-flags.c	Sun Sep 29 19:19:53 2002 +0300
@@ -15,7 +15,8 @@
 } UpdateContext;
 
 static int update_func(MailIndex *index, MailIndexRecord *rec,
-		       unsigned int seq, void *context)
+		       unsigned int client_seq, unsigned int idx_seq,
+		       void *context)
 {
 	UpdateContext *ctx = context;
 	MailFlags flags;
@@ -35,14 +36,14 @@
 		i_assert(0);
 	}
 
-	if (!index->update_flags(index, rec, seq, flags, FALSE))
+	if (!index->update_flags(index, rec, idx_seq, flags, FALSE))
 		return FALSE;
 
 	if (rec->uid >= index->first_recent_uid)
 		flags |= MAIL_RECENT;
 
 	if (ctx->func != NULL) {
-		ctx->func(ctx->box, seq, rec->uid, flags,
+		ctx->func(ctx->box, client_seq, rec->uid, flags,
 			  mail_custom_flags_list_get(ctx->custom_flags),
 			  ctx->context);
 		mail_custom_flags_list_unref(ctx->custom_flags);
--- a/src/lib-storage/index/maildir/maildir-copy.c	Sat Sep 28 13:29:10 2002 +0300
+++ b/src/lib-storage/index/maildir/maildir-copy.c	Sun Sep 29 19:19:53 2002 +0300
@@ -14,7 +14,8 @@
 } CopyHardContext;
 
 static int copy_hard_func(MailIndex *index, MailIndexRecord *rec,
-			  unsigned int seq __attr_unused__, void *context)
+			  unsigned int client_seq __attr_unused__,
+			  unsigned int idx_seq __attr_unused__, void *context)
 {
 	CopyHardContext *ctx = context;
 	const char *fname;
--- a/src/lib-storage/mail-storage.h	Sat Sep 28 13:29:10 2002 +0300
+++ b/src/lib-storage/mail-storage.h	Sun Sep 29 19:19:53 2002 +0300
@@ -131,7 +131,9 @@
 	/* Synchronize the mailbox by reading all expunges and flag changes.
 	   If new mail has been added to mailbox, messages contains the total
 	   number of messages in mailbox and recent is set, otherwise 0.
-	   Functions may be NULL.
+
+	   If both functions are NULL, only the message counts are returned
+	   and mailbox isn't marked synchronized.
 
 	   If expunge is TRUE, deleted mails are expunged as well. Difference
 	   to expunge() function is that expunge_func is also called. */