From: David Woodhouse Date: Sat, 19 May 2012 23:40:53 +0000 (+0100) Subject: Bug 676403 - imapx: Syncing folder after server-side deletion of many messages is... X-Git-Tag: upstream/3.7.4~905 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=23a77e1d521c34e04121395ffe5df9a567c22e77;p=platform%2Fupstream%2Fevolution-data-server.git 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. --- 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);