[evolution-data-server/gnome-2-30] Keep better track of server-side UNREAD count.



commit f385e0c9c9bab26386873adf44bb6ce3174a4821
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.
    (cherry picked from commit 77b29a6e456f01e0a4241ca767233f77ab03a802)

 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 36ec812..ebd08af 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -274,6 +274,7 @@ struct _CamelIMAPXJob {
 			guint32 off_set;
 			GArray *on_user; /* imapx_flag_change */
 			GArray *off_user;
+			gint unread_change;
 		} sync_changes;
 		struct {
 			gchar *path;
@@ -1145,12 +1146,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)
@@ -1158,7 +1159,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);
 	}
 
@@ -1232,13 +1233,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;
@@ -1248,6 +1250,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);
@@ -1263,7 +1266,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;
@@ -1371,9 +1374,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));
@@ -3479,7 +3484,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
@@ -3521,7 +3526,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);
 			}
 
@@ -3848,7 +3853,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);
 				}
 
@@ -4186,6 +4191,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) {
@@ -4264,6 +4272,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 6c86d0b..d51c7be 100644
--- a/camel/providers/imapx/camel-imapx-utils.c
+++ b/camel/providers/imapx/camel-imapx-utils.c
@@ -236,9 +236,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)
@@ -268,8 +269,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)
@@ -341,9 +345,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;
 
@@ -357,9 +362,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 277ec7f..b6b47aa 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 (struct _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]