diff src/lib-storage/index/index-sync.c @ 453:0f6fd6802265 HEAD

Modify log now stores the changes in ranges, so store 1:100 doesn't generate 100 entries but just one. For single message changes this takes 8 bytes unneededly though, that could be fixed but for extra complexity so I don't think it's worth it. Also a change in sync-interface, expunge event no longer gets UID. It's not currently needed and I don't see any rfcs/drafts wanting it either. It's removed mostly because the log ranges makes it impossible to get it.
author Timo Sirainen <tss@iki.fi>
date Sun, 20 Oct 2002 02:09:56 +0300
parents b5d9ce840177
children 7b140cb09a2e
line wrap: on
line diff
--- a/src/lib-storage/index/index-sync.c	Sat Oct 19 19:40:17 2002 +0300
+++ b/src/lib-storage/index/index-sync.c	Sun Oct 20 02:09:56 2002 +0300
@@ -6,18 +6,35 @@
 #include "mail-modifylog.h"
 #include "mail-custom-flags.h"
 
-/* may leave the index locked */
-int index_storage_sync_index_if_possible(IndexMailbox *ibox)
+static void index_storage_sync_size(IndexMailbox *ibox)
 {
 	unsigned int messages, recent;
 
-	if (ibox->index->sync(ibox->index)) {
+	messages = ibox->index->get_header(ibox->index)->messages_count;
+	messages += mail_modifylog_get_expunge_count(ibox->index->modifylog);
+
+	if (messages != ibox->synced_messages_count) {
+		i_assert(messages > ibox->synced_messages_count);
+
+		/* new messages in mailbox */
+		recent = index_storage_get_recent_count(ibox->index);
+		ibox->sync_callbacks.new_messages(&ibox->box, messages, recent,
+						  ibox->sync_context);
+		ibox->synced_messages_count = messages;
+	}
+}
+
+/* may leave the index locked */
+int index_storage_sync_index_if_possible(IndexMailbox *ibox, int sync_size)
+{
+	MailIndex *index = ibox->index;
+
+	if (index->sync(index)) {
 		/* reset every time it has worked */
 		ibox->sent_diskspace_warning = FALSE;
 	} else {
-		if (!ibox->index->is_diskspace_error(ibox->index)) {
-			(void)ibox->index->set_lock(ibox->index,
-						    MAIL_LOCK_UNLOCK);
+		if (!index->is_diskspace_error(index)) {
+			(void)index->set_lock(index, MAIL_LOCK_UNLOCK);
 			return mail_storage_set_index_error(ibox);
 		}
 
@@ -28,29 +45,20 @@
 						&ibox->box, ibox->sync_context);
 		}
 
-		index_reset_error(ibox->index);
+		index_reset_error(index);
 	}
 
 	/* notify about changes in mailbox size. */
-	if (ibox->index->lock_type == MAIL_LOCK_UNLOCK)
+	if (index->lock_type == MAIL_LOCK_UNLOCK)
 		return TRUE; /* no changes - must be no new mail either */
 
-	messages = ibox->index->get_header(ibox->index)->messages_count;
-	messages += mail_modifylog_get_expunge_count(ibox->index->modifylog);
-	if (messages != ibox->synced_messages_count) {
-		i_assert(messages > ibox->synced_messages_count);
-
-		/* new messages in mailbox */
-		recent = index_storage_get_recent_count(ibox->index);
-		ibox->sync_callbacks.new_messages(&ibox->box, messages, recent,
-						  ibox->sync_context);
-		ibox->synced_messages_count = messages;
-	}
+	if (sync_size)
+		index_storage_sync_size(ibox);
 
 	/* notify changes in custom flags */
-	if (mail_custom_flags_has_changes(ibox->index->custom_flags)) {
+	if (mail_custom_flags_has_changes(index->custom_flags)) {
 		ibox->sync_callbacks.new_custom_flags(&ibox->box,
-                	mail_custom_flags_list_get(ibox->index->custom_flags),
+                	mail_custom_flags_list_get(index->custom_flags),
 			MAIL_CUSTOM_FLAGS_COUNT, ibox->sync_context);
 	}
 
@@ -59,13 +67,13 @@
 
 int index_storage_sync_modifylog(IndexMailbox *ibox)
 {
-	ModifyLogRecord *log;
+	const ModifyLogRecord *log;
 	MailIndexRecord *rec;
 	MailFlags flags;
         MailboxSyncCallbacks *sc;
 	void *sc_context;
 	const char **custom_flags;
-	unsigned int count, seq;
+	unsigned int count, seq, seq_count, i, first_flag_change, messages;
 
 	/* show the log */
 	log = mail_modifylog_get_nonsynced(ibox->index->modifylog, &count);
@@ -75,37 +83,69 @@
 	sc = &ibox->sync_callbacks;
 	sc_context = ibox->sync_context;
 
-	custom_flags = mail_custom_flags_list_get(ibox->index->custom_flags);
-	for (; count > 0; count--, log++) {
-		if (log->seq > ibox->synced_messages_count) {
+	/* first show expunges. this makes it easier to deal with sequence
+	   numbers. */
+	messages = ibox->synced_messages_count;
+	first_flag_change = count;
+	for (i = 0; i < count; i++) {
+		if (log[i].seq1 > messages) {
 			/* client doesn't know about this message yet */
 			continue;
 		}
 
-		switch (log->type) {
+		switch (log[i].type) {
 		case RECORD_TYPE_EXPUNGE:
-			sc->expunge(&ibox->box, log->seq,
-				    log->uid, sc_context);
-                        ibox->synced_messages_count--;
+			seq_count = (log[i].seq2 - log[i].seq1) + 1;
+			messages -= seq_count;
+
+			for (; seq_count > 0; seq_count--) {
+				sc->expunge(&ibox->box, log[i].seq1,
+					    sc_context);
+			}
+			break;
+		case RECORD_TYPE_FLAGS_CHANGED:
+			if (first_flag_change == count)
+				first_flag_change = i;
+			break;
+		}
+	}
+
+	/* now show the flags */
+	messages = ibox->synced_messages_count;
+	custom_flags = mail_custom_flags_list_get(ibox->index->custom_flags);
+	for (i = first_flag_change; i < count; i++) {
+		if (log[i].seq1 > messages) {
+			/* client doesn't know about this message yet */
+			continue;
+		}
+
+		switch (log[i].type) {
+		case RECORD_TYPE_EXPUNGE:
+			messages -= (log[i].seq2 - log[i].seq1) + 1;
 			break;
 		case RECORD_TYPE_FLAGS_CHANGED:
 			rec = ibox->index->lookup_uid_range(ibox->index,
-							    log->uid, log->uid,
-							    &seq);
-			if (rec == NULL)
-				break;
+							    log[i].uid1,
+							    log[i].uid2, &seq);
+			while (rec != NULL && rec->uid <= log[i].uid2) {
+				flags = rec->msg_flags;
+				if (rec->uid >= ibox->index->first_recent_uid)
+					flags |= MAIL_RECENT;
 
-			flags = rec->msg_flags;
-			if (rec->uid >= ibox->index->first_recent_uid)
-				flags |= MAIL_RECENT;
+				sc->update_flags(&ibox->box, seq, rec->uid,
+						 flags, custom_flags,
+						 MAIL_CUSTOM_FLAGS_COUNT,
+						 sc_context);
 
-			sc->update_flags(&ibox->box, log->seq, log->uid, flags,
-					 custom_flags, MAIL_CUSTOM_FLAGS_COUNT,
-					 sc_context);
+                                seq++;
+				rec = ibox->index->next(ibox->index, rec);
+			}
 			break;
 		}
 	}
 
+	ibox->synced_messages_count = messages;
+
 	/* mark synced */
 	if (!mail_modifylog_mark_synced(ibox->index->modifylog))
 		return mail_storage_set_index_error(ibox);
@@ -118,7 +158,7 @@
 	IndexMailbox *ibox = (IndexMailbox *) box;
 	int failed;
 
-	if (!index_storage_sync_index_if_possible(ibox))
+	if (!index_storage_sync_index_if_possible(ibox, FALSE))
 		return FALSE;
 
 	if (!sync_expunges) {
@@ -131,6 +171,10 @@
 		failed = !index_storage_sync_modifylog(ibox);
 	}
 
+	/* check size only if we're locked (== at least something changed) */
+	if (ibox->index->lock_type != MAIL_LOCK_UNLOCK)
+		index_storage_sync_size(ibox);
+
 	if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK))
 		return mail_storage_set_index_error(ibox);