[evolution-data-server] Bug 789147 - [IMAPx] Slow message move with UID MOVE
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug 789147 - [IMAPx] Slow message move with UID MOVE
- Date: Thu, 2 Nov 2017 19:01:43 +0000 (UTC)
commit 60231bcf0cf4a108ec4a67443e00c20f2dfd3f20
Author: Milan Crha <mcrha redhat com>
Date: Thu Nov 2 20:01:08 2017 +0100
Bug 789147 - [IMAPx] Slow message move with UID MOVE
src/camel/camel-folder-summary.c | 1 +
src/camel/providers/imapx/camel-imapx-command.c | 2 +
src/camel/providers/imapx/camel-imapx-command.h | 4 +
src/camel/providers/imapx/camel-imapx-server.c | 166 +++++++++++------------
src/camel/providers/imapx/camel-imapx-utils.c | 34 +++--
5 files changed, 106 insertions(+), 101 deletions(-)
---
diff --git a/src/camel/camel-folder-summary.c b/src/camel/camel-folder-summary.c
index fb54663..f966e8e 100644
--- a/src/camel/camel-folder-summary.c
+++ b/src/camel/camel-folder-summary.c
@@ -1241,6 +1241,7 @@ camel_folder_summary_get_array (CamelFolderSummary *summary)
camel_folder_summary_lock (summary);
+ /* Do not set free_func on the array, it would break IMAPx code */
res = g_ptr_array_sized_new (g_hash_table_size (summary->priv->uids));
g_hash_table_foreach (summary->priv->uids, folder_summary_dupe_uids_to_array, res);
diff --git a/src/camel/providers/imapx/camel-imapx-command.c b/src/camel/providers/imapx/camel-imapx-command.c
index 74a72ac..e76f38e 100644
--- a/src/camel/providers/imapx/camel-imapx-command.c
+++ b/src/camel/providers/imapx/camel-imapx-command.c
@@ -71,6 +71,7 @@ camel_imapx_command_new (CamelIMAPXServer *is,
real_ic->public.job_kind = job_kind;
real_ic->public.status = NULL;
real_ic->public.completed = FALSE;
+ real_ic->public.copy_move_expunged = NULL;
g_queue_init (&real_ic->public.parts);
if (format != NULL && *format != '\0') {
@@ -131,6 +132,7 @@ camel_imapx_command_unref (CamelIMAPXCommand *ic)
/* Free the private stuff. */
g_string_free (real_ic->buffer, TRUE);
+ g_slist_free (real_ic->public.copy_move_expunged);
g_clear_error (&real_ic->error);
diff --git a/src/camel/providers/imapx/camel-imapx-command.h b/src/camel/providers/imapx/camel-imapx-command.h
index 836ac45..1300c25 100644
--- a/src/camel/providers/imapx/camel-imapx-command.h
+++ b/src/camel/providers/imapx/camel-imapx-command.h
@@ -74,6 +74,10 @@ struct _CamelIMAPXCommand {
GQueue parts;
GList *current_part;
+
+ /* list of expunged indexes, not UID-s,
+ received during copy/move operation, in reverse order */
+ GSList *copy_move_expunged;
};
CamelIMAPXCommand *
diff --git a/src/camel/providers/imapx/camel-imapx-server.c b/src/camel/providers/imapx/camel-imapx-server.c
index c1ef70d..ba968db 100644
--- a/src/camel/providers/imapx/camel-imapx-server.c
+++ b/src/camel/providers/imapx/camel-imapx-server.c
@@ -738,56 +738,6 @@ imapx_server_set_connection_timeout (GIOStream *connection,
return previous_timeout;
}
-static void
-imapx_expunge_uid_from_summary (CamelIMAPXServer *is,
- const gchar *uid,
- gboolean unsolicited)
-{
- CamelFolder *folder;
- CamelIMAPXMailbox *mailbox;
- guint32 messages;
-
- mailbox = camel_imapx_server_ref_pending_or_selected (is);
-
- g_return_if_fail (mailbox != NULL);
-
- folder = imapx_server_ref_folder (is, mailbox);
- g_return_if_fail (folder != NULL);
-
- messages = camel_imapx_mailbox_get_messages (mailbox);
-
- if (unsolicited && messages > 0)
- camel_imapx_mailbox_set_messages (mailbox, messages - 1);
-
- g_return_if_fail (is->priv->changes != NULL);
-
- camel_folder_summary_remove_uid (camel_folder_get_folder_summary (folder), uid);
-
- g_mutex_lock (&is->priv->changes_lock);
-
- camel_folder_change_info_remove_uid (is->priv->changes, uid);
-
- if (camel_imapx_server_is_in_idle (is)) {
- CamelFolderChangeInfo *changes;
-
- changes = is->priv->changes;
- is->priv->changes = camel_folder_change_info_new ();
-
- g_mutex_unlock (&is->priv->changes_lock);
-
- camel_folder_summary_save (camel_folder_get_folder_summary (folder), NULL);
- imapx_update_store_summary (folder);
- camel_folder_changed (folder, changes);
-
- camel_folder_change_info_free (changes);
- } else {
- g_mutex_unlock (&is->priv->changes_lock);
- }
-
- g_object_unref (folder);
- g_object_unref (mailbox);
-}
-
/* untagged response handler functions */
static gboolean
@@ -835,12 +785,11 @@ imapx_untagged_expunge (CamelIMAPXServer *is,
GCancellable *cancellable,
GError **error)
{
- CamelIMAPXMailbox *mailbox;
- gulong expunge = 0;
+ gulong expunged_idx;
g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE);
- expunge = is->priv->context->id;
+ expunged_idx = is->priv->context->id;
COMMAND_LOCK (is);
@@ -849,33 +798,16 @@ imapx_untagged_expunge (CamelIMAPXServer *is,
is->priv->current_command->job_kind != CAMEL_IMAPX_JOB_MOVE_MESSAGE)) {
COMMAND_UNLOCK (is);
- c (is->priv->tagprefix, "ignoring untagged expunge: %lu\n", expunge);
+ c (is->priv->tagprefix, "ignoring untagged expunge: %lu\n", expunged_idx);
return TRUE;
}
- COMMAND_UNLOCK (is);
-
- c (is->priv->tagprefix, "expunged: %lu\n", expunge);
-
- mailbox = camel_imapx_server_ref_pending_or_selected (is);
-
- if (mailbox != NULL) {
- CamelFolder *folder;
- gchar *uid;
-
- folder = imapx_server_ref_folder (is, mailbox);
- g_return_val_if_fail (folder != NULL, FALSE);
-
- uid = camel_imapx_dup_uid_from_summary_index (folder, expunge - 1);
+ c (is->priv->tagprefix, "expunged: %lu\n", expunged_idx);
- if (uid != NULL)
- imapx_expunge_uid_from_summary (is, uid, TRUE);
+ is->priv->current_command->copy_move_expunged = g_slist_prepend (
+ is->priv->current_command->copy_move_expunged, GUINT_TO_POINTER (expunged_idx));
- g_object_unref (folder);
- g_free (uid);
- }
-
- g_clear_object (&mailbox);
+ COMMAND_UNLOCK (is);
return TRUE;
}
@@ -4296,6 +4228,7 @@ camel_imapx_server_copy_message_sync (CamelIMAPXServer *is,
gboolean use_move_command = FALSE;
CamelIMAPXCommand *ic;
CamelFolder *folder;
+ CamelFolderChangeInfo *changes = NULL;
GHashTable *source_infos;
gboolean remove_junk_flags;
gboolean success = TRUE;
@@ -4377,6 +4310,61 @@ camel_imapx_server_copy_message_sync (CamelIMAPXServer *is,
use_move_command ? _("Error moving messages") : _("Error copying messages"),
cancellable, error);
+ if (ic->copy_move_expunged) {
+ CamelFolderSummary *summary;
+
+ ic->copy_move_expunged = g_slist_reverse (ic->copy_move_expunged);
+
+ summary = camel_folder_get_folder_summary (folder);
+ if (summary) {
+ GPtrArray *array;
+
+ array = camel_folder_summary_get_array (summary);
+ if (array) {
+ GSList *slink;
+ GList *removed_uids = NULL, *llink;
+
+ camel_folder_sort_uids (folder, array);
+
+ for (slink = ic->copy_move_expunged; slink; slink = g_slist_next
(slink)) {
+ guint expunged_idx = GPOINTER_TO_UINT (slink->data) - 1;
+
+ if (expunged_idx < array->len) {
+ const gchar *uid = g_ptr_array_index (array,
expunged_idx);
+
+ if (uid) {
+ removed_uids = g_list_prepend (removed_uids,
(gpointer) uid);
+ g_ptr_array_remove_index (array,
expunged_idx);
+ }
+ }
+ }
+
+ if (removed_uids) {
+ CamelFolderSummary *summary;
+
+ summary = camel_folder_get_folder_summary (folder);
+
+ camel_folder_summary_remove_uids (summary, removed_uids);
+
+ for (llink = removed_uids; llink; llink = g_list_next
(llink)) {
+ const gchar *uid = llink->data;
+
+ if (!changes)
+ changes = camel_folder_change_info_new ();
+
+ camel_folder_change_info_remove_uid (changes, uid);
+
+ g_ptr_array_add (array, (gpointer) uid);
+ }
+
+ g_list_free (removed_uids);
+ }
+
+ camel_folder_summary_free_array (array);
+ }
+ }
+ }
+
if (success) {
struct _status_info *copyuid_status = is->priv->copyuid_status;
@@ -4467,8 +4455,6 @@ camel_imapx_server_copy_message_sync (CamelIMAPXServer *is,
CamelFolderChangeInfo *changes = NULL;
gint jj;
- camel_folder_freeze (folder);
-
for (jj = last_index; jj < ii; jj++) {
const gchar *uid = uids->pdata[jj];
@@ -4483,17 +4469,6 @@ camel_imapx_server_copy_message_sync (CamelIMAPXServer *is,
}
}
}
-
- if (changes && camel_folder_change_info_changed (changes)) {
- camel_folder_summary_touch (camel_folder_get_folder_summary (folder));
- camel_folder_summary_save (camel_folder_get_folder_summary (folder),
NULL);
- camel_folder_changed (folder, changes);
- }
-
- camel_folder_thaw (folder);
-
- if (changes)
- camel_folder_change_info_free (changes);
}
}
@@ -4501,6 +4476,21 @@ camel_imapx_server_copy_message_sync (CamelIMAPXServer *is,
is->priv->copyuid_status = NULL;
camel_imapx_command_unref (ic);
+
+ camel_operation_progress (cancellable, ii * 100 / data_uids->len);
+ }
+
+ if (changes) {
+ if (camel_folder_change_info_changed (changes)) {
+ camel_folder_summary_touch (camel_folder_get_folder_summary (folder));
+ camel_folder_summary_save (camel_folder_get_folder_summary (folder), NULL);
+
+ imapx_update_store_summary (folder);
+
+ camel_folder_changed (folder, changes);
+ }
+
+ camel_folder_change_info_free (changes);
}
g_hash_table_destroy (source_infos);
diff --git a/src/camel/providers/imapx/camel-imapx-utils.c b/src/camel/providers/imapx/camel-imapx-utils.c
index 478bf53..cc861d5 100644
--- a/src/camel/providers/imapx/camel-imapx-utils.c
+++ b/src/camel/providers/imapx/camel-imapx-utils.c
@@ -2653,6 +2653,7 @@ camel_imapx_command_add_qresync_parameter (CamelIMAPXCommand *ic,
CamelIMAPXFolder *imapx_folder;
CamelIMAPXSummary *imapx_summary;
CamelIMAPXMailbox *mailbox;
+ GPtrArray *summary_array;
guint64 last_known_uidvalidity;
guint64 last_known_modsequence;
guint32 last_known_message_cnt;
@@ -2667,9 +2668,16 @@ camel_imapx_command_add_qresync_parameter (CamelIMAPXCommand *ic,
imapx_folder = CAMEL_IMAPX_FOLDER (folder);
imapx_summary = CAMEL_IMAPX_SUMMARY (camel_folder_get_folder_summary (folder));
+ summary_array = camel_folder_summary_get_array (CAMEL_FOLDER_SUMMARY (imapx_summary));
+ g_return_val_if_fail (summary_array != NULL, FALSE);
+
+ camel_folder_sort_uids (folder, summary_array);
+
mailbox = camel_imapx_folder_ref_mailbox (imapx_folder);
- if (!mailbox)
+ if (!mailbox) {
+ camel_folder_summary_free_array (summary_array);
return FALSE;
+ }
last_known_uidvalidity = camel_imapx_mailbox_get_uidvalidity (mailbox);
last_known_modsequence = imapx_summary->modseq;
@@ -2682,16 +2690,16 @@ camel_imapx_command_add_qresync_parameter (CamelIMAPXCommand *ic,
if (summary_total > 0) {
guint last = summary_total - 1;
- gchar *begin, *end;
- begin = camel_imapx_dup_uid_from_summary_index (folder, 0);
- end = camel_imapx_dup_uid_from_summary_index (folder, last);
+ if (0 < summary_array->len && last < summary_array->len) {
+ const gchar *begin, *end;
- if (begin != NULL && end != NULL)
- known_uid_set = g_strconcat (begin, ":", end, NULL);
+ begin = g_ptr_array_index (summary_array, 0);
+ end = g_ptr_array_index (summary_array, last);
- g_free (begin);
- g_free (end);
+ if (begin && end)
+ known_uid_set = g_strconcat (begin, ":", end, NULL);
+ }
}
/* Make sure we have valid QRESYNC arguments. */
@@ -2736,7 +2744,7 @@ camel_imapx_command_add_qresync_parameter (CamelIMAPXCommand *ic,
do {
guint32 summary_index;
gchar buf[10];
- gchar *uid;
+ const gchar *uid;
ii = MIN (ii * 3, sequence_limit);
summary_index = sequence_limit - ii;
@@ -2754,12 +2762,12 @@ camel_imapx_command_add_qresync_parameter (CamelIMAPXCommand *ic,
"%" G_GUINT32_FORMAT,
summary_index + 1);
- uid = camel_imapx_dup_uid_from_summary_index (
- folder, summary_index);
+ uid = NULL;
+ if (summary_index < summary_array->len)
+ uid = g_ptr_array_index (summary_array, summary_index);
if (uid != NULL) {
g_string_prepend (seqs, buf);
g_string_prepend (uids, uid);
- g_free (uid);
}
} while (ii < sequence_limit);
@@ -2776,7 +2784,7 @@ camel_imapx_command_add_qresync_parameter (CamelIMAPXCommand *ic,
exit:
g_free (known_uid_set);
-
+ camel_folder_summary_free_array (summary_array);
g_object_unref (mailbox);
return parameter_added;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]