[evolution-ews] Bug 764976 - Failed message move processed as successful
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] Bug 764976 - Failed message move processed as successful
- Date: Thu, 14 Apr 2016 12:19:46 +0000 (UTC)
commit d88d6b39711762e1e1d5de178407d7807906d299
Author: Milan Crha <mcrha redhat com>
Date: Thu Apr 14 14:18:23 2016 +0200
Bug 764976 - Failed message move processed as successful
src/camel/camel-ews-folder.c | 57 +++++++++++++++++++++++---------
src/server/e-ews-connection.c | 72 +++++++++++++++++++++++++++++++++++++++++
src/server/e-ews-connection.h | 9 +++++
3 files changed, 122 insertions(+), 16 deletions(-)
---
diff --git a/src/camel/camel-ews-folder.c b/src/camel/camel-ews-folder.c
index 9c82222..5b770ea 100644
--- a/src/camel/camel-ews-folder.c
+++ b/src/camel/camel-ews-folder.c
@@ -1166,7 +1166,7 @@ ews_move_to_junk_folder (CamelFolder *folder,
folder_id = camel_ews_store_summary_get_folder_id_from_folder_type (
ews_store->summary, CAMEL_FOLDER_TYPE_JUNK);
- status = e_ews_connection_move_items_sync (
+ status = e_ews_connection_move_items_in_chunks_sync (
cnc, EWS_PRIORITY_MEDIUM, folder_id, FALSE,
junk_uids, &moved_items, cancellable, &local_error);
@@ -1178,17 +1178,20 @@ ews_move_to_junk_folder (CamelFolder *folder,
status = ews_refresh_info_sync (folder, cancellable, &local_error);
}
- g_slist_free_full (moved_items, g_object_unref);
- g_free (folder_id);
-
- if (status) {
+ /* Messages could be moved partially only, like when
+ the user cancels the operation in the middle */
+ if (status || moved_items) {
CamelFolderChangeInfo *changes;
- const GSList *iter;
+ const GSList *iter, *items_iter;
changes = camel_folder_change_info_new ();
- for (iter = junk_uids; iter; iter = g_slist_next (iter)) {
+ for (iter = junk_uids, items_iter = moved_items; iter && items_iter; iter =
g_slist_next (iter), items_iter = g_slist_next (items_iter)) {
const gchar *uid = iter->data;
+ EEwsItem *item = items_iter->data;
+
+ if (!item || e_ews_item_get_item_type (item) == E_EWS_ITEM_TYPE_ERROR)
+ continue;
camel_folder_summary_lock (folder->summary);
@@ -1206,6 +1209,9 @@ ews_move_to_junk_folder (CamelFolder *folder,
camel_folder_change_info_free (changes);
}
+ g_slist_free_full (moved_items, g_object_unref);
+ g_free (folder_id);
+
if (local_error) {
camel_ews_store_maybe_disconnect (ews_store, local_error);
g_propagate_error (error, local_error);
@@ -1801,6 +1807,8 @@ ews_refresh_info_sync (CamelFolder *folder,
id = camel_ews_store_summary_get_folder_id_from_name (
ews_store->summary, full_name);
+ camel_operation_push_message (cancellable, _("Refreshing folder '%s'"), camel_folder_get_display_name
(folder));
+
/* Sync folder items does not return the fields ToRecipients,
* CCRecipients. With the item_type unknown, its not possible
* to fetch the right properties which are valid for an item type.
@@ -1877,6 +1885,8 @@ ews_refresh_info_sync (CamelFolder *folder,
}
} while (!local_error && !includes_last_item && !g_cancellable_is_cancelled (cancellable));
+ camel_operation_pop_message (cancellable);
+
if (camel_folder_change_info_changed (change_info)) {
camel_folder_summary_touch (folder->summary);
camel_folder_summary_save_to_db (folder->summary, NULL);
@@ -2046,13 +2056,17 @@ ews_transfer_messages_to_sync (CamelFolder *source,
ids = g_slist_reverse (ids);
- if (success && e_ews_connection_move_items_sync (
+ success = success && e_ews_connection_move_items_in_chunks_sync (
cnc, EWS_PRIORITY_MEDIUM,
dst_id, !delete_originals,
ids, &ret_items,
- cancellable, &local_error)) {
+ cancellable, &local_error);
+
+ /* Messages could be copied/moved partially only, like when
+ the user cancels the operation in the middle */
+ if (success || ret_items) {
CamelFolderChangeInfo *changes;
- GSList *l;
+ GSList *l, *processed_items = NULL;
changes = camel_folder_change_info_new ();
@@ -2063,10 +2077,14 @@ ews_transfer_messages_to_sync (CamelFolder *source,
CamelMessageInfo *clone;
const EwsId *id;
- if (e_ews_item_get_item_type (l->data) == E_EWS_ITEM_TYPE_ERROR)
+ if (e_ews_item_get_item_type (l->data) == E_EWS_ITEM_TYPE_ERROR) {
+ if (!local_error)
+ local_error = g_error_copy (e_ews_item_get_error (l->data));
continue;
+ }
id = e_ews_item_get_id (l->data);
+ processed_items = g_slist_prepend (processed_items, uids->pdata[i]);
message = ews_folder_get_message_cached (source, uids->pdata[i], cancellable);
if (message == NULL)
@@ -2110,10 +2128,12 @@ ews_transfer_messages_to_sync (CamelFolder *source,
if (delete_originals) {
changes = camel_folder_change_info_new ();
- for (i = 0; i < uids->len; i++) {
- camel_folder_summary_remove_uid (source->summary, uids->pdata[i]);
- camel_folder_change_info_remove_uid (changes, uids->pdata[i]);
- ews_data_cache_remove (CAMEL_EWS_FOLDER (source)->cache, "cur",
uids->pdata[i], NULL);
+ for (l = processed_items; l; l = g_slist_next (l)) {
+ const gchar *uid = l->data;
+
+ camel_folder_summary_remove_uid (source->summary, uid);
+ camel_folder_change_info_remove_uid (changes, uid);
+ ews_data_cache_remove (CAMEL_EWS_FOLDER (source)->cache, "cur", uid, NULL);
}
if (camel_folder_change_info_changed (changes)) {
camel_folder_summary_touch (source->summary);
@@ -2126,8 +2146,13 @@ ews_transfer_messages_to_sync (CamelFolder *source,
/* update destination folder only if not frozen, to not update
for each single message transfer during filtering
*/
- if (!camel_folder_is_frozen (destination))
+ if (!camel_folder_is_frozen (destination)) {
+ camel_operation_progress (cancellable, -1);
+
ews_refresh_info_sync (destination, cancellable, NULL);
+ }
+
+ g_slist_free (processed_items);
}
g_free (dst_id);
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index 3c11a3e..41116ca 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -57,6 +57,9 @@
/* For the number of connections */
#define EWS_CONNECTION_MAX_REQUESTS 1
+/* A chunk size limit when moving items in chunks. */
+#define EWS_MOVE_ITEMS_CHUNK_SIZE 500
+
#define QUEUE_LOCK(x) (g_rec_mutex_lock(&(x)->priv->queue_lock))
#define QUEUE_UNLOCK(x) (g_rec_mutex_unlock(&(x)->priv->queue_lock))
@@ -6229,6 +6232,75 @@ e_ews_connection_move_items_sync (EEwsConnection *cnc,
return success;
}
+gboolean
+e_ews_connection_move_items_in_chunks_sync (EEwsConnection *cnc,
+ gint pri,
+ const gchar *folder_id,
+ gboolean docopy,
+ const GSList *ids,
+ GSList **items,
+ GCancellable *cancellable,
+ GError **error)
+{
+ const GSList *iter;
+ guint total_ids = 0, done_ids = 0;
+ gboolean success = TRUE;
+
+ g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (items != NULL, FALSE);
+
+ g_object_ref (cnc);
+
+ *items = NULL;
+ iter = ids;
+
+ while (success && iter) {
+ guint n_ids;
+ const GSList *tmp_iter;
+ GSList *processed_items = NULL;
+
+ for (tmp_iter = iter, n_ids = 0; tmp_iter && n_ids < EWS_MOVE_ITEMS_CHUNK_SIZE; tmp_iter =
g_slist_next (tmp_iter), n_ids++) {
+ /* Only check bounds first, to avoid unnecessary allocations */
+ }
+
+ if (tmp_iter) {
+ GSList *shorter = NULL;
+
+ if (total_ids == 0)
+ total_ids = g_slist_length ((GSList *) ids);
+
+ for (n_ids = 0; iter && n_ids < EWS_MOVE_ITEMS_CHUNK_SIZE; iter = g_slist_next
(iter), n_ids++) {
+ shorter = g_slist_prepend (shorter, iter->data);
+ }
+
+ shorter = g_slist_reverse (shorter);
+
+ success = e_ews_connection_move_items_sync (cnc, pri, folder_id, docopy,
+ shorter, &processed_items, cancellable, error);
+
+ g_slist_free (shorter);
+
+ done_ids += n_ids;
+ } else {
+ success = e_ews_connection_move_items_sync (cnc, pri, folder_id, docopy,
+ iter, &processed_items, cancellable, error);
+
+ iter = NULL;
+ done_ids = total_ids;
+ }
+
+ if (processed_items)
+ *items = g_slist_concat (*items, processed_items);
+
+ if (total_ids > 0)
+ camel_operation_progress (cancellable, 100 * (gdouble) done_ids / (gdouble)
total_ids);
+ }
+
+ g_object_unref (cnc);
+
+ return success;
+}
+
static void
delete_folder_response_cb (ESoapResponse *response,
GSimpleAsyncResult *simple)
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index c759856..f46bb54 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -908,6 +908,15 @@ gboolean e_ews_connection_move_items_sync
GSList **items_ret,
GCancellable *cancellable,
GError **error);
+gboolean e_ews_connection_move_items_in_chunks_sync
+ (EEwsConnection *cnc,
+ gint pri,
+ const gchar *folder_id,
+ gboolean docopy,
+ const GSList *ids,
+ GSList **items,
+ GCancellable *cancellable,
+ GError **error);
void e_ews_connection_create_attachments
(EEwsConnection *cnc,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]