[evolution-data-server] Bug 676403 - imapx: Syncing folder after server-side deletion of many messages is *very* slow



commit 23a77e1d521c34e04121395ffe5df9a567c22e77
Author: David Woodhouse <David Woodhouse intel com>
Date:   Sun May 20 00:40:53 2012 +0100

    Bug 676403 - imapx: Syncing folder after server-side deletion of many messages is *very* slow
    
    Fix this by introducing a new camel_folder_change_info_remove_uids()
    function, and using it for the 'vanished' code. This reduces the time taken
    from about 40ms per message, to about 50Âs.

 camel/camel-folder-summary.c |   48 ++++++++++++++++++++++++++++++++++++++++++
 camel/camel-folder-summary.h |    2 +
 camel/camel-imapx-server.c   |   24 +++++++++++++++++++-
 3 files changed, 72 insertions(+), 2 deletions(-)
---
diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c
index 43c7c98..8dad22c 100644
--- a/camel/camel-folder-summary.c
+++ b/camel/camel-folder-summary.c
@@ -3232,6 +3232,54 @@ camel_folder_summary_remove_uid (CamelFolderSummary *summary,
 	return res;
 }
 
+/**
+ * camel_folder_summary_remove_uids:
+ * @summary: a #CamelFolderSummary object
+ * @uids: a GList of uids
+ *
+ * Remove a specific info record from the summary, by @uid.
+ *
+ * Returns: Whether the @uid was found and removed from the @summary.
+ *
+ * Since: 3.4.3
+ **/
+gboolean
+camel_folder_summary_remove_uids (CamelFolderSummary *summary,
+				  GList *uids)
+{
+	CamelStore *parent_store;
+	const gchar *full_name;
+	GList *l;
+	gboolean res = TRUE;
+
+	g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary), FALSE);
+	g_return_val_if_fail (uids != NULL, FALSE);
+
+	camel_folder_summary_lock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	for (l = g_list_first(uids); l; l = g_list_next(l)) {
+		gpointer ptr_uid = NULL, ptr_flags = NULL;
+		if (g_hash_table_lookup_extended (summary->priv->uids, l->data, &ptr_uid, &ptr_flags)) {
+			const gchar *uid_copy = camel_pstring_strdup (l->data);
+			folder_summary_update_counts_by_flags (summary, GPOINTER_TO_UINT (ptr_flags), TRUE);
+			g_hash_table_remove (summary->priv->uids, uid_copy);
+			g_hash_table_remove (summary->priv->loaded_infos, uid_copy);
+			camel_pstring_free (uid_copy);
+		}
+	}
+
+	full_name = camel_folder_get_full_name (summary->priv->folder);
+	parent_store = camel_folder_get_parent_store (summary->priv->folder);
+	if (camel_db_delete_uids (parent_store->cdb_w, full_name, uids, NULL) != 0)
+		res = FALSE;
+
+	camel_folder_summary_touch (summary);
+	camel_folder_summary_unlock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	return res;
+}
+
+
 static struct _node *
 my_list_append (struct _node **list,
                 struct _node *n)
diff --git a/camel/camel-folder-summary.h b/camel/camel-folder-summary.h
index cb66520..dacacab 100644
--- a/camel/camel-folder-summary.h
+++ b/camel/camel-folder-summary.h
@@ -402,6 +402,8 @@ gboolean		camel_folder_summary_remove	(CamelFolderSummary *summary,
 
 gboolean		camel_folder_summary_remove_uid	(CamelFolderSummary *summary,
 							 const gchar *uid);
+gboolean		camel_folder_summary_remove_uids(CamelFolderSummary *summary,
+							 GList *uids);
 
 /* remove all items */
 gboolean		camel_folder_summary_clear	(CamelFolderSummary *summary,
diff --git a/camel/camel-imapx-server.c b/camel/camel-imapx-server.c
index 5afd519..a527aae 100644
--- a/camel/camel-imapx-server.c
+++ b/camel/camel-imapx-server.c
@@ -1140,6 +1140,7 @@ imapx_untagged (CamelIMAPXServer *is,
 	}
 	case IMAPX_VANISHED: {
 		GPtrArray *uids;
+		GList *uid_list = NULL;
 		gboolean unsolicited = TRUE;
 		gint i;
 		guint len;
@@ -1163,11 +1164,30 @@ imapx_untagged (CamelIMAPXServer *is,
 		uids = imapx_parse_uids (is->stream, cancellable, error);
 		if (uids == NULL)
 			return FALSE;
+
+		if (unsolicited) {
+			CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *)is->select_folder;
+
+			if (ifolder->exists_on_server < uids->len) {
+				c(is->tagprefix, "Error: exists_on_folder %d is fewer than vanished %d\n",
+				  ifolder->exists_on_server, uids->len);
+				ifolder->exists_on_server = 0;
+			} else
+				ifolder->exists_on_server -= uids->len;
+		}
+		if (is->changes == NULL)
+			is->changes = camel_folder_change_info_new ();
+
 		for (i = 0; i < uids->len; i++) {
 			gchar *uid = g_strdup_printf("%u", GPOINTER_TO_UINT(g_ptr_array_index (uids, i)));
+
 			c(is->tagprefix, "vanished: %s\n", uid);
-			imapx_expunge_uid_from_summary (is, uid, unsolicited);
+
+			uid_list = g_list_append(uid_list, uid);
+			camel_folder_change_info_remove_uid (is->changes, uid);
 		}
+		camel_folder_summary_remove_uids(is->select_folder->summary, uid_list);
+		is->expunged = g_list_concat(is->expunged, uid_list);
 		g_ptr_array_free (uids, FALSE);
 		break;
 	}
@@ -3940,10 +3960,10 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
 			gchar *uid = (gchar *) l->data;
 
 			camel_folder_change_info_remove_uid (data->changes, uid);
-			camel_folder_summary_remove_uid (s, uid);
 		}
 
 		if (removed != NULL) {
+			camel_folder_summary_remove_uids (s, removed);
 			camel_folder_summary_touch (s);
 
 			g_list_free_full (removed, (GDestroyNotify) g_free);



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