[evolution-data-server] Keep better track of server-side UNREAD count.



commit 77b29a6e456f01e0a4241ca767233f77ab03a802
Author: David Woodhouse <David Woodhouse intel com>
Date:   Fri Jul 2 10:00:02 2010 +0100

    Keep better track of server-side UNREAD count.
    
    There are various circumstances in which the UNREAD count will change --
    new unseen messages arriving, flags changes from the client, unseen
    messages being expunged, etc. Keep track of those to improve the
    accuracy of the unread count, to avoid the QRESYNC sanity check
    triggering so often on minor issues that weren't the bug I was looking
    for. For this, we have to keep track of whether a FETCH or VANISHED response
    was solicited or unsolicited in certain cases.

 camel/providers/imapx/camel-imapx-server.c |   38 +++++++++++++++++++--------
 camel/providers/imapx/camel-imapx-utils.c  |   17 +++++++++---
 camel/providers/imapx/camel-imapx-utils.h  |    4 +-
 3 files changed, 41 insertions(+), 18 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 10ffd3c..5f8c79c 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -252,6 +252,7 @@ struct _CamelIMAPXJob {
 			guint32 off_set;
 			GArray *on_user; /* imapx_flag_change */
 			GArray *off_user;
+			gint unread_change;
 		} sync_changes;
 		struct {
 			gchar *path;
@@ -1134,12 +1135,12 @@ imapx_is_job_in_queue (CamelIMAPXServer *is, CamelFolder *folder, guint32 type,
 }
 
 static void
-imapx_expunge_uid_from_summary(CamelIMAPXServer *imap, gchar *uid)
+imapx_expunge_uid_from_summary(CamelIMAPXServer *imap, gchar *uid, gboolean unsolicited)
 {
 	CamelMessageInfo *mi;
 	CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *)imap->select_folder;
 
-	if (ifolder->exists_on_server)
+	if (unsolicited && ifolder->exists_on_server)
 		ifolder->exists_on_server--;
 
 	if (imap->changes == NULL)
@@ -1147,7 +1148,7 @@ imapx_expunge_uid_from_summary(CamelIMAPXServer *imap, gchar *uid)
 
 	mi = camel_folder_summary_uid (imap->select_folder->summary, uid);
 	if (mi) {
-		imapx_update_summary_for_removed_message (mi, imap->select_folder);
+		imapx_update_summary_for_removed_message (mi, imap->select_folder, unsolicited);
 		camel_message_info_free (mi);
 	}
 
@@ -1224,13 +1225,14 @@ imapx_untagged(CamelIMAPXServer *imap, CamelException *ex)
 			if (!uid)
 				break;
 
-			imapx_expunge_uid_from_summary(imap, uid);
+			imapx_expunge_uid_from_summary(imap, uid, TRUE);
 		}
 
 		break;
 	}
 	case IMAPX_VANISHED: {
 		GPtrArray *uids;
+		gboolean unsolicited = TRUE;
 		int i;
 		guint len;
 		guchar *token;
@@ -1240,6 +1242,7 @@ imapx_untagged(CamelIMAPXServer *imap, CamelException *ex)
 		if (camel_exception_is_set(ex))
 			return -1;
 		if (tok == '(') {
+			unsolicited = FALSE;
 			while (tok != ')') {
 				/* We expect this to be 'EARLIER' */
 				tok = camel_imapx_stream_token(imap->stream, &token, &len, ex);
@@ -1255,7 +1258,7 @@ imapx_untagged(CamelIMAPXServer *imap, CamelException *ex)
 		for (i = 0; i < uids->len; i++) {
 			gchar *uid = g_strdup_printf("%u", GPOINTER_TO_UINT(g_ptr_array_index (uids, i)));
 			c(printf("vanished: %s\n", uid));
-			imapx_expunge_uid_from_summary(imap, uid);
+			imapx_expunge_uid_from_summary(imap, uid, unsolicited);
 		}
 		g_ptr_array_free (uids, FALSE);
 		break;
@@ -1363,9 +1366,11 @@ imapx_untagged(CamelIMAPXServer *imap, CamelException *ex)
 
 				if (uid) {
 					mi = camel_folder_summary_uid (folder->summary, uid);
-					if (mi)
-						changed = imapx_update_message_info_flags (mi, finfo->flags, finfo->user_flags, folder);
-					else {
+					if (mi) {
+						/* It's unsolicited _unless_ imap->select_pending (i.e. during
+						   a QRESYNC SELECT */
+						changed = imapx_update_message_info_flags (mi, finfo->flags, finfo->user_flags, folder, !imap->select_pending);
+					} else {
 						/* This (UID + FLAGS for previously unknown message) might
 						   happen during a SELECT (QRESYNC). We should use it. */
 						c(printf("flags changed for unknown uid %s\n.", uid));
@@ -3495,7 +3500,7 @@ imapx_job_scan_changes_done(CamelIMAPXServer *is, CamelIMAPXCommand *ic)
 			if (s_minfo && uid_cmp(s_minfo->uid, r->uid, s) == 0) {
 				info = (CamelIMAPXMessageInfo *)s_minfo;
 
-				if (imapx_update_message_info_flags ((CamelMessageInfo *) info, r->server_flags, r->server_user_flags, job->folder))
+				if (imapx_update_message_info_flags ((CamelMessageInfo *) info, r->server_flags, r->server_user_flags, job->folder, FALSE))
 					camel_folder_change_info_change_uid (job->u.refresh_info.changes, camel_message_info_uid (s_minfo));
 				r->exists = TRUE;
 			} else
@@ -3537,7 +3542,7 @@ imapx_job_scan_changes_done(CamelIMAPXServer *is, CamelIMAPXCommand *ic)
 
 			mi = camel_folder_summary_uid (job->folder->summary, uid);
 			if (mi) {
-				imapx_update_summary_for_removed_message (mi, job->folder);
+				imapx_update_summary_for_removed_message (mi, job->folder, FALSE);
 				camel_message_info_free (mi);
 			}
 
@@ -3879,7 +3884,7 @@ imapx_command_expunge_done (CamelIMAPXServer *is, CamelIMAPXCommand *ic)
 				CamelMessageInfo *mi = camel_folder_summary_uid (folder->summary, uid);
 
 				if (mi) {
-					imapx_update_summary_for_removed_message (mi, folder);
+					imapx_update_summary_for_removed_message (mi, folder, FALSE);
 					camel_message_info_free (mi);
 				}
 
@@ -4222,6 +4227,9 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is, CamelIMAPXCommand *ic)
 
 			/* FIXME: move over user flags too */
 		}
+		/* Apply the changes to server-side unread count; it won't tell
+		   us of these changes, of course. */
+		((CamelIMAPXFolder *)job->folder)->unread_on_server += job->u.sync_changes.unread_change;
 	}
 
 	if (job->commands == 0) {
@@ -4300,6 +4308,14 @@ imapx_job_sync_changes_start(CamelIMAPXServer *is, CamelIMAPXJob *job)
 					imapx_command_queue(is, ic);
 					ic = NULL;
 				}
+				if (flag == CAMEL_MESSAGE_SEEN) {
+					/* Remember how the server's unread count will change if this
+					   command succeeds */
+					if (on)
+						job->u.sync_changes.unread_change--;
+					else
+						job->u.sync_changes.unread_change++;
+				}
 				camel_message_info_free (info);
 			}
 		}
diff --git a/camel/providers/imapx/camel-imapx-utils.c b/camel/providers/imapx/camel-imapx-utils.c
index e6e9480..dc9c2e8 100644
--- a/camel/providers/imapx/camel-imapx-utils.c
+++ b/camel/providers/imapx/camel-imapx-utils.c
@@ -229,9 +229,10 @@ imapx_update_user_flags (CamelMessageInfo *info, CamelFlag *server_user_flags)
 }
 
 gboolean
-imapx_update_message_info_flags (CamelMessageInfo *info, guint32 server_flags, CamelFlag *server_user_flags, CamelFolder *folder)
+imapx_update_message_info_flags (CamelMessageInfo *info, guint32 server_flags, CamelFlag *server_user_flags, CamelFolder *folder, gboolean unsolicited)
 {
 	gboolean changed = FALSE;
+	CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *)folder;
 	CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) info;
 
 	if (server_flags != xinfo->server_flags)
@@ -261,8 +262,11 @@ imapx_update_message_info_flags (CamelMessageInfo *info, guint32 server_flags, C
 					deleted == 1 ? "deleted" : ( deleted == -1 ? "undeleted" : ""),
 					junk == 1 ? "junk" : ( junk == -1 ? "unjunked" : "")));
 
-		if (read)
+		if (read) {
 			folder->summary->unread_count -= read;
+			if (unsolicited)
+				ifolder->unread_on_server -= read;
+		}
 		if (deleted)
 			folder->summary->deleted_count += deleted;
 		if (junk)
@@ -334,9 +338,10 @@ imapx_set_message_info_flags_for_new_message (CamelMessageInfo *info, guint32 se
 }
 
 void
-imapx_update_summary_for_removed_message (CamelMessageInfo *info, CamelFolder *folder)
+imapx_update_summary_for_removed_message (CamelMessageInfo *info, CamelFolder *folder, gboolean unsolicited)
 {
 	CamelMessageInfoBase *dinfo = (CamelMessageInfoBase *) info;
+	CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *)folder;
 	gint unread=0, deleted=0, junk=0;
 	guint32 flags;
 
@@ -350,9 +355,11 @@ imapx_update_summary_for_removed_message (CamelMessageInfo *info, CamelFolder *f
 	if (flags & CAMEL_MESSAGE_JUNK)
 		junk = 1;
 
-	if (unread)
+	if (unread) {
 		folder->summary->unread_count--;
-
+		if (unsolicited)
+			ifolder->unread_on_server--;
+	}
 	if (deleted)
 		folder->summary->deleted_count--;
 	if (junk)
diff --git a/camel/providers/imapx/camel-imapx-utils.h b/camel/providers/imapx/camel-imapx-utils.h
index 859f296..77d8979 100644
--- a/camel/providers/imapx/camel-imapx-utils.h
+++ b/camel/providers/imapx/camel-imapx-utils.h
@@ -69,10 +69,10 @@ enum {
 GPtrArray *imapx_parse_uids (CamelIMAPXStream *is, CamelException *ex);
 void imapx_parse_flags(struct _CamelIMAPXStream *stream, guint32 *flagsp, struct _CamelFlag **user_flagsp, CamelException *ex);
 void imapx_write_flags(CamelStream *stream, guint32 flags, struct _CamelFlag *user_flags, CamelException *ex);
-gboolean imapx_update_message_info_flags (CamelMessageInfo *info, guint32 server_flags, CamelFlag *server_user_flags, CamelFolder *folder);
+gboolean imapx_update_message_info_flags (CamelMessageInfo *info, guint32 server_flags, CamelFlag *server_user_flags, CamelFolder *folder, gboolean unsolicited);
 void imapx_set_message_info_flags_for_new_message (CamelMessageInfo *info, guint32 server_flags, CamelFlag *server_user_flags,
 							CamelFolder *folder);
-void imapx_update_summary_for_removed_message (CamelMessageInfo *info, CamelFolder *folder);
+void imapx_update_summary_for_removed_message (CamelMessageInfo *info, CamelFolder *folder, gboolean unsolicited);
 void imapx_update_store_summary (CamelFolder *folder);
 
 /* ********************************************************************** */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]