[evolution-data-server] Bug #720154 - [IMAPx] Silently recover from "Connection reset by peer" error
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug #720154 - [IMAPx] Silently recover from "Connection reset by peer" error
- Date: Wed, 30 Apr 2014 11:13:14 +0000 (UTC)
commit 8f9269309dd55de551ff1b4cae9ab987bde5361d
Author: Milan Crha <mcrha redhat com>
Date: Wed Apr 30 13:10:08 2014 +0200
Bug #720154 - [IMAPx] Silently recover from "Connection reset by peer" error
This is a partial commit for the bug, to address "Connection reset by peer"
errors, and even the BYE response from the server, more gracefully, like
reconnecting to the server and re-issue the job. There will be at least
one more commit for this bug report, for an NNTP provider.
camel/providers/imapx/camel-imapx-conn-manager.c | 53 ++++-
camel/providers/imapx/camel-imapx-conn-manager.h | 3 +-
camel/providers/imapx/camel-imapx-folder.c | 254 ++++++++++++++++------
camel/providers/imapx/camel-imapx-input-stream.c | 3 +-
camel/providers/imapx/camel-imapx-search.c | 216 ++++++++++++-------
camel/providers/imapx/camel-imapx-search.h | 16 +-
camel/providers/imapx/camel-imapx-server.c | 180 +++++++++++-----
camel/providers/imapx/camel-imapx-server.h | 9 +-
camel/providers/imapx/camel-imapx-store.c | 209 +++++++++++++++---
9 files changed, 688 insertions(+), 255 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-conn-manager.c
b/camel/providers/imapx/camel-imapx-conn-manager.c
index 02a52fd..75942dd 100644
--- a/camel/providers/imapx/camel-imapx-conn-manager.c
+++ b/camel/providers/imapx/camel-imapx-conn-manager.c
@@ -54,6 +54,7 @@ struct _ConnectionInfo {
CamelIMAPXServer *is;
GHashTable *folder_names;
gchar *selected_folder;
+ GError *shutdown_error;
volatile gint ref_count;
};
@@ -68,7 +69,9 @@ G_DEFINE_TYPE (
G_TYPE_OBJECT)
static void
-imapx_conn_shutdown (CamelIMAPXServer *is, CamelIMAPXConnManager *con_man);
+imapx_conn_shutdown (CamelIMAPXServer *is,
+ const GError *error,
+ CamelIMAPXConnManager *con_man);
static void
imapx_conn_update_select (CamelIMAPXServer *is,
@@ -95,6 +98,7 @@ connection_info_new (CamelIMAPXServer *is)
g_mutex_init (&cinfo->lock);
cinfo->is = g_object_ref (is);
cinfo->folder_names = folder_names;
+ cinfo->shutdown_error = NULL;
cinfo->ref_count = 1;
return cinfo;
@@ -118,7 +122,7 @@ connection_info_unref (ConnectionInfo *cinfo)
g_return_if_fail (cinfo->ref_count > 0);
if (g_atomic_int_dec_and_test (&cinfo->ref_count)) {
- camel_imapx_server_shutdown (cinfo->is);
+ camel_imapx_server_shutdown (cinfo->is, cinfo->shutdown_error);
g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
imapx_conn_shutdown, NULL);
g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
imapx_conn_update_select, NULL);
g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
imapx_conn_mailbox_closed, NULL);
@@ -127,6 +131,7 @@ connection_info_unref (ConnectionInfo *cinfo)
g_object_unref (cinfo->is);
g_hash_table_destroy (cinfo->folder_names);
g_free (cinfo->selected_folder);
+ g_clear_error (&cinfo->shutdown_error);
g_slice_free (ConnectionInfo, cinfo);
}
@@ -141,7 +146,7 @@ connection_info_cancel_and_unref (ConnectionInfo *cinfo)
g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
imapx_conn_shutdown, NULL);
g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
imapx_conn_update_select, NULL);
g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
imapx_conn_mailbox_closed, NULL);
- camel_imapx_server_shutdown (cinfo->is);
+ camel_imapx_server_shutdown (cinfo->is, cinfo->shutdown_error);
connection_info_unref (cinfo);
}
@@ -244,6 +249,23 @@ connection_info_set_selected_folder (ConnectionInfo *cinfo,
g_mutex_unlock (&cinfo->lock);
}
+static void
+connection_info_set_shutdown_error (ConnectionInfo *cinfo,
+ const GError *shutdown_error)
+{
+ g_return_if_fail (cinfo != NULL);
+
+ g_mutex_lock (&cinfo->lock);
+
+ if (cinfo->shutdown_error != shutdown_error) {
+ g_clear_error (&cinfo->shutdown_error);
+ if (shutdown_error)
+ cinfo->shutdown_error = g_error_copy (shutdown_error);
+ }
+
+ g_mutex_unlock (&cinfo->lock);
+}
+
static GList *
imapx_conn_manager_list_info (CamelIMAPXConnManager *con_man)
{
@@ -426,11 +448,9 @@ camel_imapx_conn_manager_init (CamelIMAPXConnManager *con_man)
g_rw_lock_init (&con_man->priv->rw_lock);
}
-/* Static functions go here */
-
-/* TODO destroy unused connections in a time-out loop */
static void
imapx_conn_shutdown (CamelIMAPXServer *is,
+ const GError *error,
CamelIMAPXConnManager *con_man)
{
ConnectionInfo *cinfo;
@@ -442,6 +462,14 @@ imapx_conn_shutdown (CamelIMAPXServer *is,
imapx_conn_manager_remove_info (con_man, cinfo);
connection_info_unref (cinfo);
}
+
+ /* If one connection ends with this error, then it means all
+ other opened connections also may end with the same error,
+ thus better to kill them all from the list of connections.
+ */
+ if (g_error_matches (error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ camel_imapx_conn_manager_close_connections (con_man, error);
+ }
}
static void
@@ -792,7 +820,7 @@ camel_imapx_conn_manager_get_connection (CamelIMAPXConnManager *con_man,
g_clear_error (&local_error);
is = imapx_find_connection_unlocked (con_man, folder_name,
for_expensive_job);
- } else {
+ } else if (local_error) {
g_propagate_error (error, local_error);
}
}
@@ -848,13 +876,20 @@ camel_imapx_conn_manager_update_con_info (CamelIMAPXConnManager *con_man,
}
void
-camel_imapx_conn_manager_close_connections (CamelIMAPXConnManager *con_man)
+camel_imapx_conn_manager_close_connections (CamelIMAPXConnManager *con_man,
+ const GError *error)
{
+ GList *iter;
+
g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (con_man));
CON_WRITE_LOCK (con_man);
- c('*', "Closing all %d connections\n", g_list_length (con_man->priv->connections));
+ c('*', "Closing all %d connections, with propagated error: %s\n", g_list_length
(con_man->priv->connections), error ? error->message : "none");
+
+ for (iter = con_man->priv->connections; iter; iter = g_list_next (iter)) {
+ connection_info_set_shutdown_error (iter->data, error);
+ }
g_list_free_full (
con_man->priv->connections,
diff --git a/camel/providers/imapx/camel-imapx-conn-manager.h
b/camel/providers/imapx/camel-imapx-conn-manager.h
index fc93a11..5ada11d 100644
--- a/camel/providers/imapx/camel-imapx-conn-manager.h
+++ b/camel/providers/imapx/camel-imapx-conn-manager.h
@@ -71,7 +71,8 @@ CamelIMAPXServer *
GCancellable *cancellable,
GError **error);
void camel_imapx_conn_manager_close_connections
- (CamelIMAPXConnManager *con_man);
+ (CamelIMAPXConnManager *con_man,
+ const GError *error);
GList * camel_imapx_conn_manager_get_connections
(CamelIMAPXConnManager *con_man);
void camel_imapx_conn_manager_update_con_info
diff --git a/camel/providers/imapx/camel-imapx-folder.c b/camel/providers/imapx/camel-imapx-folder.c
index a02eabc..af5b92f 100644
--- a/camel/providers/imapx/camel-imapx-folder.c
+++ b/camel/providers/imapx/camel-imapx-folder.c
@@ -300,44 +300,29 @@ imapx_search_by_uids (CamelFolder *folder,
GCancellable *cancellable,
GError **error)
{
- CamelIMAPXStore *imapx_store;
CamelIMAPXFolder *imapx_folder;
CamelIMAPXSearch *imapx_search;
- CamelIMAPXServer *imapx_server = NULL;
- const gchar *folder_name;
- CamelStore *store;
GPtrArray *matches;
if (uids->len == 0)
return g_ptr_array_new ();
imapx_folder = CAMEL_IMAPX_FOLDER (folder);
- store = camel_folder_get_parent_store (folder);
- folder_name = camel_folder_get_full_name (folder);
-
- imapx_store = CAMEL_IMAPX_STORE (store);
- if (camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
- imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable,
NULL);
g_mutex_lock (&imapx_folder->search_lock);
imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search);
- camel_imapx_search_set_server (imapx_search, imapx_server);
camel_folder_search_set_folder (imapx_folder->search, folder);
+ camel_imapx_search_set_cancellable_and_error (imapx_search, cancellable, error);
matches = camel_folder_search_search (
imapx_folder->search, expression, uids, cancellable, error);
- camel_imapx_search_set_server (imapx_search, NULL);
-
- if (imapx_server)
- camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ camel_imapx_search_set_cancellable_and_error (imapx_search, NULL, NULL);
g_mutex_unlock (&imapx_folder->search_lock);
- g_clear_object (&imapx_server);
-
return matches;
}
@@ -347,41 +332,26 @@ imapx_count_by_expression (CamelFolder *folder,
GCancellable *cancellable,
GError **error)
{
- CamelIMAPXStore *imapx_store;
CamelIMAPXFolder *imapx_folder;
CamelIMAPXSearch *imapx_search;
- CamelIMAPXServer *imapx_server = NULL;
- const gchar *folder_name;
- CamelStore *store;
guint32 matches;
imapx_folder = CAMEL_IMAPX_FOLDER (folder);
- store = camel_folder_get_parent_store (folder);
- folder_name = camel_folder_get_full_name (folder);
-
- imapx_store = CAMEL_IMAPX_STORE (store);
- if (camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
- imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable,
NULL);
g_mutex_lock (&imapx_folder->search_lock);
imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search);
- camel_imapx_search_set_server (imapx_search, imapx_server);
camel_folder_search_set_folder (imapx_folder->search, folder);
+ camel_imapx_search_set_cancellable_and_error (imapx_search, cancellable, error);
matches = camel_folder_search_count (
imapx_folder->search, expression, cancellable, error);
- camel_imapx_search_set_server (imapx_search, NULL);
-
- if (imapx_server)
- camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ camel_imapx_search_set_cancellable_and_error (imapx_search, NULL, NULL);
g_mutex_unlock (&imapx_folder->search_lock);
- g_clear_object (&imapx_server);
-
return matches;
}
@@ -391,41 +361,26 @@ imapx_search_by_expression (CamelFolder *folder,
GCancellable *cancellable,
GError **error)
{
- CamelIMAPXStore *imapx_store;
CamelIMAPXFolder *imapx_folder;
CamelIMAPXSearch *imapx_search;
- CamelIMAPXServer *imapx_server = NULL;
- const gchar *folder_name;
- CamelStore *store;
GPtrArray *matches;
imapx_folder = CAMEL_IMAPX_FOLDER (folder);
- store = camel_folder_get_parent_store (folder);
- folder_name = camel_folder_get_full_name (folder);
-
- imapx_store = CAMEL_IMAPX_STORE (store);
- if (camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
- imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable,
NULL);
g_mutex_lock (&imapx_folder->search_lock);
imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search);
- camel_imapx_search_set_server (imapx_search, imapx_server);
camel_folder_search_set_folder (imapx_folder->search, folder);
+ camel_imapx_search_set_cancellable_and_error (imapx_search, cancellable, error);
matches = camel_folder_search_search (
imapx_folder->search, expression, NULL, cancellable, error);
- camel_imapx_search_set_server (imapx_search, NULL);
-
- if (imapx_server)
- camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ camel_imapx_search_set_cancellable_and_error (imapx_search, NULL, NULL);
g_mutex_unlock (&imapx_folder->search_lock);
- g_clear_object (&imapx_server);
-
return matches;
}
@@ -455,6 +410,7 @@ imapx_append_message_sync (CamelFolder *folder,
CamelIMAPXServer *imapx_server;
CamelIMAPXMailbox *mailbox = NULL;
const gchar *folder_name;
+ GError *local_error = NULL;
gboolean success = FALSE;
if (appended_uid != NULL)
@@ -480,10 +436,28 @@ imapx_append_message_sync (CamelFolder *folder,
success = camel_imapx_server_append_message (
imapx_server, mailbox, folder->summary,
CAMEL_IMAPX_FOLDER (folder)->cache, message,
- info, appended_uid, cancellable, error);
+ info, appended_uid, cancellable, &local_error);
camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable,
&local_error);
+ if (imapx_server) {
+ success = camel_imapx_server_append_message (
+ imapx_server, mailbox, folder->summary,
+ CAMEL_IMAPX_FOLDER (folder)->cache, message,
+ info, appended_uid, cancellable, &local_error);
+
+ camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
exit:
g_clear_object (&mailbox);
g_clear_object (&imapx_server);
@@ -500,6 +474,7 @@ imapx_expunge_sync (CamelFolder *folder,
CamelIMAPXStore *imapx_store;
CamelIMAPXServer *imapx_server;
CamelIMAPXMailbox *mailbox = NULL;
+ GError *local_error = NULL;
const gchar *folder_name;
gboolean success = FALSE;
@@ -523,7 +498,6 @@ imapx_expunge_sync (CamelFolder *folder,
if ((store->flags & CAMEL_STORE_VTRASH) == 0) {
CamelFolder *trash;
const gchar *full_name;
- GError *local_error = NULL;
full_name = camel_folder_get_full_name (folder);
@@ -553,11 +527,25 @@ imapx_expunge_sync (CamelFolder *folder,
g_clear_error (&local_error);
}
- success = camel_imapx_server_expunge (
- imapx_server, mailbox, cancellable, error);
+ success = camel_imapx_server_expunge (imapx_server, mailbox, cancellable, &local_error);
camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable,
&local_error);
+ if (imapx_server) {
+ success = camel_imapx_server_expunge (imapx_server, mailbox, cancellable,
&local_error);
+
+ camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
exit:
g_clear_object (&mailbox);
g_clear_object (&imapx_server);
@@ -618,6 +606,7 @@ imapx_get_message_sync (CamelFolder *folder,
GIOStream *base_stream;
const gchar *path = NULL;
gboolean offline_message = FALSE;
+ GError *local_error = NULL;
imapx_folder = CAMEL_IMAPX_FOLDER (folder);
store = camel_folder_get_parent_store (folder);
@@ -666,10 +655,28 @@ imapx_get_message_sync (CamelFolder *folder,
stream = camel_imapx_server_get_message (
imapx_server, mailbox, folder->summary,
CAMEL_IMAPX_FOLDER (folder)->cache, uid,
- cancellable, error);
+ cancellable, &local_error);
camel_imapx_store_folder_op_done (CAMEL_IMAPX_STORE (store), imapx_server, folder_name);
+ while (!stream && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (CAMEL_IMAPX_STORE (store), folder_name,
FALSE, cancellable, &local_error);
+ if (imapx_server) {
+ stream = camel_imapx_server_get_message (
+ imapx_server, mailbox, folder->summary,
+ CAMEL_IMAPX_FOLDER (folder)->cache, uid,
+ cancellable, &local_error);
+
+ camel_imapx_store_folder_op_done (CAMEL_IMAPX_STORE (store), imapx_server,
folder_name);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
g_clear_object (&mailbox);
g_clear_object (&imapx_server);
}
@@ -727,6 +734,7 @@ imapx_get_quota_info_sync (CamelFolder *folder,
const gchar *folder_name;
gchar **quota_roots;
gboolean success = FALSE;
+ GError *local_error = NULL;
store = camel_folder_get_parent_store (folder);
folder_name = camel_folder_get_full_name (folder);
@@ -744,11 +752,25 @@ imapx_get_quota_info_sync (CamelFolder *folder,
goto exit;
}
- success = camel_imapx_server_update_quota_info (
- imapx_server, mailbox, cancellable, error);
+ success = camel_imapx_server_update_quota_info (imapx_server, mailbox, cancellable, &local_error);
camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable,
&local_error);
+ if (imapx_server) {
+ success = camel_imapx_server_update_quota_info (imapx_server, mailbox, cancellable,
&local_error);
+
+ camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
if (!success)
goto exit;
@@ -798,6 +820,7 @@ imapx_refresh_info_sync (CamelFolder *folder,
CamelFolderChangeInfo *changes;
const gchar *folder_name;
gboolean success = FALSE;
+ GError *local_error = NULL;
store = camel_folder_get_parent_store (folder);
folder_name = camel_folder_get_full_name (folder);
@@ -816,11 +839,25 @@ imapx_refresh_info_sync (CamelFolder *folder,
goto exit;
}
- changes = camel_imapx_server_refresh_info (
- imapx_server, mailbox, cancellable, error);
+ changes = camel_imapx_server_refresh_info (imapx_server, mailbox, cancellable, &local_error);
camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, TRUE, cancellable,
&local_error);
+ if (imapx_server) {
+ changes = camel_imapx_server_refresh_info (imapx_server, mailbox, cancellable,
&local_error);
+
+ camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
if (changes != NULL) {
if (camel_folder_change_info_changed (changes))
camel_folder_changed (folder, changes);
@@ -1034,6 +1071,7 @@ imapx_synchronize_sync (CamelFolder *folder,
const gchar *folder_name;
gboolean need_to_expunge;
gboolean success = FALSE;
+ GError *local_error = NULL;
store = camel_folder_get_parent_store (folder);
folder_name = camel_folder_get_full_name (folder);
@@ -1053,8 +1091,19 @@ imapx_synchronize_sync (CamelFolder *folder,
goto exit;
}
- success = camel_imapx_server_sync_changes (
- imapx_server, mailbox, cancellable, error);
+ success = camel_imapx_server_sync_changes (imapx_server, mailbox, cancellable, &local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable,
&local_error);
+ if (imapx_server) {
+ success = camel_imapx_server_sync_changes (imapx_server, mailbox, cancellable,
&local_error);
+ }
+ }
if (success) {
success = imapx_move_to_real_junk (
@@ -1074,11 +1123,26 @@ imapx_synchronize_sync (CamelFolder *folder,
* then sync again incase expunge changed anything */
if (success && expunge) {
- success = camel_imapx_server_expunge (
- imapx_server, mailbox, cancellable, error);
+ success = camel_imapx_server_expunge (imapx_server, mailbox, cancellable, &local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE,
cancellable, &local_error);
+ if (imapx_server) {
+ success = camel_imapx_server_expunge (imapx_server, mailbox, cancellable,
&local_error);
+ }
+ }
}
- camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ if (local_error)
+ g_propagate_error (error, local_error);
+
+ if (imapx_server)
+ camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
exit:
g_clear_object (&mailbox);
@@ -1099,6 +1163,7 @@ imapx_synchronize_message_sync (CamelFolder *folder,
CamelIMAPXMailbox *mailbox = NULL;
const gchar *folder_name;
gboolean success = FALSE;
+ GError *local_error = NULL;
store = camel_folder_get_parent_store (folder);
folder_name = camel_folder_get_full_name (folder);
@@ -1120,10 +1185,28 @@ imapx_synchronize_message_sync (CamelFolder *folder,
success = camel_imapx_server_sync_message (
imapx_server, mailbox, folder->summary,
CAMEL_IMAPX_FOLDER (folder)->cache, uid,
- cancellable, error);
+ cancellable, &local_error);
camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable,
&local_error);
+ if (imapx_server) {
+ success = camel_imapx_server_sync_message (
+ imapx_server, mailbox, folder->summary,
+ CAMEL_IMAPX_FOLDER (folder)->cache, uid,
+ cancellable, &local_error);
+
+ camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
exit:
g_clear_object (&mailbox);
g_clear_object (&imapx_server);
@@ -1147,6 +1230,7 @@ imapx_transfer_messages_to_sync (CamelFolder *source,
CamelIMAPXMailbox *dst_mailbox = NULL;
const gchar *folder_name;
gboolean success = FALSE;
+ GError *local_error = NULL;
store = camel_folder_get_parent_store (source);
folder_name = camel_folder_get_full_name (source);
@@ -1175,10 +1259,27 @@ imapx_transfer_messages_to_sync (CamelFolder *source,
success = camel_imapx_server_copy_message (
imapx_server, src_mailbox, dst_mailbox, uids,
- delete_originals, cancellable, error);
+ delete_originals, cancellable, &local_error);
camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable,
&local_error);
+ if (imapx_server) {
+ success = camel_imapx_server_copy_message (
+ imapx_server, src_mailbox, dst_mailbox, uids,
+ delete_originals, cancellable, &local_error);
+
+ camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
/* Update destination folder only if it's not frozen,
* to avoid updating for each "move" action on a single
* message while filtering. */
@@ -1380,7 +1481,7 @@ camel_imapx_folder_new (CamelStore *store,
g_free (state_file);
camel_object_state_read (CAMEL_OBJECT (folder));
- imapx_folder->search = camel_imapx_search_new ();
+ imapx_folder->search = camel_imapx_search_new (CAMEL_IMAPX_STORE (store));
g_mutex_init (&imapx_folder->search_lock);
g_mutex_init (&imapx_folder->stream_lock);
@@ -1500,6 +1601,7 @@ camel_imapx_folder_list_mailbox (CamelIMAPXFolder *folder,
gchar *mailbox_name = NULL;
gchar *pattern;
gboolean success;
+ GError *local_error = NULL;
g_return_val_if_fail (CAMEL_IS_IMAPX_FOLDER (folder), FALSE);
@@ -1552,8 +1654,20 @@ camel_imapx_folder_list_mailbox (CamelIMAPXFolder *folder,
pattern = camel_utf8_utf7 (mailbox_name);
/* This creates a mailbox instance from the LIST response. */
- success = camel_imapx_server_list (
- server, pattern, 0, cancellable, error);
+ success = camel_imapx_server_list (server, pattern, 0, cancellable, &local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&server);
+
+ server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, &local_error);
+ if (server) {
+ success = camel_imapx_server_list (server, pattern, 0, cancellable, &local_error);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
g_free (pattern);
diff --git a/camel/providers/imapx/camel-imapx-input-stream.c
b/camel/providers/imapx/camel-imapx-input-stream.c
index e5fbd15..ccc1542 100644
--- a/camel/providers/imapx/camel-imapx-input-stream.c
+++ b/camel/providers/imapx/camel-imapx-input-stream.c
@@ -27,6 +27,7 @@
#include <camel/camel.h>
+#include "camel-imapx-server.h"
#include "camel-imapx-utils.h"
#define CAMEL_IMAPX_INPUT_STREAM_GET_PRIVATE(obj) \
@@ -88,7 +89,7 @@ imapx_input_stream_fill (CamelIMAPXInputStream *is,
* accordingly */
if (!left)
g_set_error (
- error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+ error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT,
_("Source stream returned no data"));
return -1;
}
diff --git a/camel/providers/imapx/camel-imapx-search.c b/camel/providers/imapx/camel-imapx-search.c
index c8c4ebf..e99c7a4 100644
--- a/camel/providers/imapx/camel-imapx-search.c
+++ b/camel/providers/imapx/camel-imapx-search.c
@@ -27,13 +27,16 @@
((obj), CAMEL_TYPE_IMAPX_SEARCH, CamelIMAPXSearchPrivate))
struct _CamelIMAPXSearchPrivate {
- GWeakRef server;
+ GWeakRef imapx_store;
gint *local_data_search; /* not NULL, if testing whether all used headers are all locally available */
+
+ GCancellable *cancellable; /* not referenced */
+ GError **error; /* not referenced */
};
enum {
PROP_0,
- PROP_SERVER
+ PROP_STORE
};
G_DEFINE_TYPE (
@@ -48,8 +51,8 @@ imapx_search_set_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
- case PROP_SERVER:
- camel_imapx_search_set_server (
+ case PROP_STORE:
+ camel_imapx_search_set_store (
CAMEL_IMAPX_SEARCH (object),
g_value_get_object (value));
return;
@@ -65,10 +68,10 @@ imapx_search_get_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
- case PROP_SERVER:
+ case PROP_STORE:
g_value_take_object (
value,
- camel_imapx_search_ref_server (
+ camel_imapx_search_ref_store (
CAMEL_IMAPX_SEARCH (object)));
return;
}
@@ -83,7 +86,7 @@ imapx_search_dispose (GObject *object)
priv = CAMEL_IMAPX_SEARCH_GET_PRIVATE (object);
- g_weak_ref_set (&priv->server, NULL);
+ g_weak_ref_set (&priv->imapx_store, NULL);
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (camel_imapx_search_parent_class)->dispose (object);
@@ -137,43 +140,64 @@ imapx_search_result_match_none (CamelSExp *sexp,
static CamelSExpResult *
imapx_search_process_criteria (CamelSExp *sexp,
CamelFolderSearch *search,
- CamelIMAPXServer *server,
+ CamelIMAPXStore *imapx_store,
const GString *criteria,
const gchar *from_function)
{
CamelSExpResult *result;
+ CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
CamelIMAPXMailbox *mailbox;
GPtrArray *uids = NULL;
- GError *error = NULL;
+ GError *local_error = NULL;
mailbox = camel_imapx_folder_list_mailbox (
- CAMEL_IMAPX_FOLDER (search->folder), NULL, &error);
+ CAMEL_IMAPX_FOLDER (search->folder), imapx_search->priv->cancellable, &local_error);
/* Sanity check. */
g_return_val_if_fail (
- ((mailbox != NULL) && (error == NULL)) ||
- ((mailbox == NULL) && (error != NULL)), NULL);
+ ((mailbox != NULL) && (local_error == NULL)) ||
+ ((mailbox == NULL) && (local_error != NULL)), NULL);
if (mailbox != NULL) {
- uids = camel_imapx_server_uid_search (
- server, mailbox, criteria->str, NULL, &error);
+ CamelIMAPXStore *imapx_store;
+ CamelIMAPXServer *imapx_server;
+ const gchar *folder_name;
+
+ imapx_store = camel_imapx_search_ref_store (imapx_search);
+
+ /* there should always be one, held by one of the callers of this function */
+ g_warn_if_fail (imapx_store != NULL);
+
+ folder_name = camel_folder_get_full_name (search->folder);
+ imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, TRUE,
imapx_search->priv->cancellable, &local_error);
+ if (imapx_server) {
+ uids = camel_imapx_server_uid_search (imapx_server, mailbox, criteria->str,
imapx_search->priv->cancellable, &local_error);
+
+ while (!uids && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, TRUE,
imapx_search->priv->cancellable, &local_error);
+ if (imapx_server)
+ uids = camel_imapx_server_uid_search (imapx_server, mailbox,
criteria->str, imapx_search->priv->cancellable, &local_error);
+ }
+ }
+
+ g_clear_object (&imapx_server);
+ g_clear_object (&imapx_store);
g_object_unref (mailbox);
}
/* Sanity check. */
g_return_val_if_fail (
- ((uids != NULL) && (error == NULL)) ||
- ((uids == NULL) && (error != NULL)), NULL);
-
- /* XXX No allowance for errors in CamelSExp callbacks!
- * Dump the error to the console and make like we
- * got an empty result. */
- if (error != NULL) {
- g_warning (
- "%s: (UID SEARCH %s): %s",
- from_function, criteria->str, error->message);
+ ((uids != NULL) && (local_error == NULL)) ||
+ ((uids == NULL) && (local_error != NULL)), NULL);
+
+ if (local_error != NULL) {
+ g_propagate_error (imapx_search->priv->error, local_error);
+
+ /* Make like we've got an empty result */
uids = g_ptr_array_new ();
- g_error_free (error);
}
if (search->current != NULL) {
@@ -196,7 +220,7 @@ imapx_search_match_all (CamelSExp *sexp,
CamelFolderSearch *search)
{
CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
- CamelIMAPXServer *server;
+ CamelIMAPXStore *imapx_store;
CamelSExpResult *result;
GPtrArray *summary;
gint local_data_search = 0, *prev_local_data_search, ii;
@@ -204,9 +228,9 @@ imapx_search_match_all (CamelSExp *sexp,
if (argc != 1)
return imapx_search_result_match_none (sexp, search);
- server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
- if (!server || search->current || !search->summary) {
- g_clear_object (&server);
+ imapx_store = camel_imapx_search_ref_store (CAMEL_IMAPX_SEARCH (search));
+ if (!imapx_store || search->current || !search->summary) {
+ g_clear_object (&imapx_store);
/* Chain up to parent's method. */
return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
@@ -237,7 +261,7 @@ imapx_search_match_all (CamelSExp *sexp,
imapx_search->priv->local_data_search = prev_local_data_search;
if (local_data_search >= 0) {
- g_clear_object (&server);
+ g_clear_object (&imapx_store);
/* Chain up to parent's method. */
return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
@@ -248,7 +272,7 @@ imapx_search_match_all (CamelSExp *sexp,
* but here is expected GPtrArray of matched UIDs */
result = camel_sexp_term_eval (sexp, argv[0]);
- g_object_unref (server);
+ g_object_unref (imapx_store);
g_return_val_if_fail (result != NULL, result);
g_return_val_if_fail (result->type == CAMEL_SEXP_RES_ARRAY_PTR, result);
@@ -263,7 +287,7 @@ imapx_search_body_contains (CamelSExp *sexp,
CamelFolderSearch *search)
{
CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
- CamelIMAPXServer *server;
+ CamelIMAPXStore *imapx_store;
CamelSExpResult *result;
GString *criteria;
gint ii, jj;
@@ -282,10 +306,10 @@ imapx_search_body_contains (CamelSExp *sexp,
if (argc == 0 || search->summary->len == 0)
return imapx_search_result_match_none (sexp, search);
- server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
+ imapx_store = camel_imapx_search_ref_store (CAMEL_IMAPX_SEARCH (search));
- /* This will be NULL if we're offline. Search from cache. */
- if (server == NULL) {
+ /* This will be NULL if we're offline. Search from cache. */
+ if (imapx_store == NULL) {
/* Chain up to parent's method. */
return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
body_contains (sexp, argc, argv, search);
@@ -333,10 +357,10 @@ imapx_search_body_contains (CamelSExp *sexp,
}
}
- result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
+ result = imapx_search_process_criteria (sexp, search, imapx_store, criteria, G_STRFUNC);
g_string_free (criteria, TRUE);
- g_object_unref (server);
+ g_object_unref (imapx_store);
return result;
}
@@ -357,7 +381,7 @@ imapx_search_header_contains (CamelSExp *sexp,
CamelFolderSearch *search)
{
CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
- CamelIMAPXServer *server;
+ CamelIMAPXStore *imapx_store;
CamelSExpResult *result;
const gchar *headername, *command = NULL;
GString *criteria;
@@ -386,10 +410,10 @@ imapx_search_header_contains (CamelSExp *sexp,
return imapx_search_result_match_none (sexp, search);
}
- server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
+ imapx_store = camel_imapx_search_ref_store (CAMEL_IMAPX_SEARCH (search));
- /* This will be NULL if we're offline. Search from cache. */
- if (server == NULL) {
+ /* This will be NULL if we're offline. Search from cache. */
+ if (imapx_store == NULL) {
/* Chain up to parent's method. */
return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
header_contains (sexp, argc, argv, search);
@@ -453,10 +477,10 @@ imapx_search_header_contains (CamelSExp *sexp,
}
}
- result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
+ result = imapx_search_process_criteria (sexp, search, imapx_store, criteria, G_STRFUNC);
g_string_free (criteria, TRUE);
- g_object_unref (server);
+ g_object_unref (imapx_store);
return result;
}
@@ -468,7 +492,7 @@ imapx_search_header_exists (CamelSExp *sexp,
CamelFolderSearch *search)
{
CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
- CamelIMAPXServer *server;
+ CamelIMAPXStore *imapx_store;
CamelSExpResult *result;
GString *criteria;
gint ii;
@@ -503,10 +527,10 @@ imapx_search_header_exists (CamelSExp *sexp,
return imapx_search_result_match_none (sexp, search);
}
- server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
+ imapx_store = camel_imapx_search_ref_store (CAMEL_IMAPX_SEARCH (search));
- /* This will be NULL if we're offline. Search from cache. */
- if (server == NULL) {
+ /* This will be NULL if we're offline. Search from cache. */
+ if (imapx_store == NULL) {
/* Chain up to parent's method. */
return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
header_exists (sexp, argc, argv, search);
@@ -538,10 +562,10 @@ imapx_search_header_exists (CamelSExp *sexp,
g_string_append_printf (criteria, "HEADER \"%s\" \"\"", headername);
}
- result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
+ result = imapx_search_process_criteria (sexp, search, imapx_store, criteria, G_STRFUNC);
g_string_free (criteria, TRUE);
- g_object_unref (server);
+ g_object_unref (imapx_store);
return result;
}
@@ -567,12 +591,12 @@ camel_imapx_search_class_init (CamelIMAPXSearchClass *class)
g_object_class_install_property (
object_class,
- PROP_SERVER,
+ PROP_STORE,
g_param_spec_object (
- "server",
- "Server",
- "Server proxy for server-side searches",
- CAMEL_TYPE_IMAPX_SERVER,
+ "store",
+ "IMAPX Store",
+ "IMAPX Store for server-side searches",
+ CAMEL_TYPE_IMAPX_STORE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
}
@@ -586,67 +610,105 @@ camel_imapx_search_init (CamelIMAPXSearch *search)
/**
* camel_imapx_search_new:
+ * imapx_store: a #CamelIMAPXStore to which the search belongs
*
* Returns a new #CamelIMAPXSearch instance.
*
- * The #CamelIMAPXSearch must be given a #CamelIMAPXSearch:server before
- * it can issue server-side search requests. Otherwise it will fallback
- * to the default #CamelFolderSearch behavior.
- *
* Returns: a new #CamelIMAPXSearch
*
* Since: 3.8
**/
CamelFolderSearch *
-camel_imapx_search_new (void)
+camel_imapx_search_new (CamelIMAPXStore *imapx_store)
{
- return g_object_new (CAMEL_TYPE_IMAPX_SEARCH, NULL);
+ g_return_val_if_fail (CAMEL_IS_IMAPX_STORE (imapx_store), NULL);
+
+ return g_object_new (
+ CAMEL_TYPE_IMAPX_SEARCH,
+ "store", imapx_store,
+ NULL);
}
/**
- * camel_imapx_search_ref_server:
+ * camel_imapx_search_ref_store:
* @search: a #CamelIMAPXSearch
*
- * Returns a #CamelIMAPXServer to use for server-side searches,
- * or %NULL when the corresponding #CamelIMAPXStore is offline.
+ * Returns a #CamelIMAPXStore to use for server-side searches,
+ * or %NULL when the store is offline.
*
- * The returned #CamelIMAPXSearch is referenced for thread-safety and
+ * The returned #CamelIMAPXStore is referenced for thread-safety and
* must be unreferenced with g_object_unref() when finished with it.
*
- * Returns: a #CamelIMAPXServer, or %NULL
+ * Returns: a #CamelIMAPXStore, or %NULL
*
* Since: 3.8
**/
-CamelIMAPXServer *
-camel_imapx_search_ref_server (CamelIMAPXSearch *search)
+CamelIMAPXStore *
+camel_imapx_search_ref_store (CamelIMAPXSearch *search)
{
+ CamelIMAPXStore *imapx_store;
+
g_return_val_if_fail (CAMEL_IS_IMAPX_SEARCH (search), NULL);
- return g_weak_ref_get (&search->priv->server);
+ imapx_store = g_weak_ref_get (&search->priv->imapx_store);
+
+ if (imapx_store && !camel_offline_store_get_online (CAMEL_OFFLINE_STORE (imapx_store)))
+ g_clear_object (&imapx_store);
+
+ return imapx_store;
}
/**
- * camel_imapx_search_set_server:
+ * camel_imapx_search_set_store:
* @search: a #CamelIMAPXSearch
- * @server: a #CamelIMAPXServer, or %NULL
+ * @imapx_server: a #CamelIMAPXStore, or %NULL
*
- * Sets a #CamelIMAPXServer to use for server-side searches. Generally
+ * Sets a #CamelIMAPXStore to use for server-side searches. Generally
* this is set for the duration of a single search when online, and then
* reset to %NULL.
*
* Since: 3.8
**/
void
-camel_imapx_search_set_server (CamelIMAPXSearch *search,
- CamelIMAPXServer *server)
+camel_imapx_search_set_store (CamelIMAPXSearch *search,
+ CamelIMAPXStore *imapx_store)
{
g_return_if_fail (CAMEL_IS_IMAPX_SEARCH (search));
- if (server != NULL)
- g_return_if_fail (CAMEL_IS_IMAPX_SERVER (server));
+ if (imapx_store != NULL)
+ g_return_if_fail (CAMEL_IS_IMAPX_STORE (imapx_store));
- g_weak_ref_set (&search->priv->server, server);
+ g_weak_ref_set (&search->priv->imapx_store, imapx_store);
- g_object_notify (G_OBJECT (search), "server");
+ g_object_notify (G_OBJECT (search), "store");
}
+/**
+ * camel_imapx_search_set_cancellable_and_error:
+ * @search: a #CamelIMAPXSearch
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: a #GError, or %NULL
+ *
+ * Sets @cancellable and @error to use for server-side searches. This way
+ * the search can return accurate errors and be eventually cancelled by
+ * a user.
+ *
+ * Note: The caller is responsible to keep alive both @cancellable and @error
+ * for the whole run of the search and reset them both to NULL after
+ * the search is finished.
+ *
+ * Since: 3.14
+ **/
+void
+camel_imapx_search_set_cancellable_and_error (CamelIMAPXSearch *search,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_if_fail (CAMEL_IS_IMAPX_SEARCH (search));
+
+ if (cancellable)
+ g_return_if_fail (G_IS_CANCELLABLE (cancellable));
+
+ search->priv->cancellable = cancellable;
+ search->priv->error = error;
+}
diff --git a/camel/providers/imapx/camel-imapx-search.h b/camel/providers/imapx/camel-imapx-search.h
index 6fd9d05..acdba79 100644
--- a/camel/providers/imapx/camel-imapx-search.h
+++ b/camel/providers/imapx/camel-imapx-search.h
@@ -20,7 +20,7 @@
#include <camel/camel.h>
-#include "camel-imapx-server.h"
+#include "camel-imapx-store.h"
/* Standard GObject macros */
#define CAMEL_TYPE_IMAPX_SEARCH \
@@ -66,11 +66,15 @@ struct _CamelIMAPXSearchClass {
GType camel_imapx_search_get_type (void) G_GNUC_CONST;
CamelFolderSearch *
- camel_imapx_search_new (void);
-CamelIMAPXServer *
- camel_imapx_search_ref_server (CamelIMAPXSearch *search);
-void camel_imapx_search_set_server (CamelIMAPXSearch *search,
- CamelIMAPXServer *server);
+ camel_imapx_search_new (CamelIMAPXStore *imapx_store);
+CamelIMAPXStore *
+ camel_imapx_search_ref_store (CamelIMAPXSearch *search);
+void camel_imapx_search_set_store (CamelIMAPXSearch *search,
+ CamelIMAPXStore *imapx_store);
+void camel_imapx_search_set_cancellable_and_error
+ (CamelIMAPXSearch *search,
+ GCancellable *cancellable,
+ GError **error);
G_END_DECLS
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 44f886a..b9624ef 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -354,6 +354,9 @@ struct _CamelIMAPXServerPrivate {
GMainContext *parser_main_context;
GWeakRef parser_cancellable;
+ GMutex shutdown_error_lock;
+ GError *shutdown_error;
+
GSource *inactivity_timeout;
GMutex inactivity_timeout_lock;
@@ -576,6 +579,36 @@ imapx_weak_ref_free (GWeakRef *weak_ref)
}
static void
+imapx_server_set_shutdown_error (CamelIMAPXServer *imapx_server,
+ const GError *error)
+{
+ g_mutex_lock (&imapx_server->priv->shutdown_error_lock);
+
+ if (error != imapx_server->priv->shutdown_error) {
+ g_clear_error (&imapx_server->priv->shutdown_error);
+ if (error)
+ imapx_server->priv->shutdown_error = g_error_copy (error);
+ }
+
+ g_mutex_unlock (&imapx_server->priv->shutdown_error_lock);
+}
+
+static GError *
+imapx_server_dup_shutdown_error (CamelIMAPXServer *imapx_server)
+{
+ GError *error = NULL;
+
+ g_mutex_lock (&imapx_server->priv->shutdown_error_lock);
+
+ if (imapx_server->priv->shutdown_error)
+ error = g_error_copy (imapx_server->priv->shutdown_error);
+
+ g_mutex_unlock (&imapx_server->priv->shutdown_error_lock);
+
+ return error;
+}
+
+static void
imapx_server_command_added (CamelIMAPXServer *imapx_server,
CamelIMAPXCommand *command)
{
@@ -1696,7 +1729,7 @@ imapx_command_queue (CamelIMAPXServer *is,
c (is->tagprefix, "refuse to queue job on disconnected server\n");
local_error = g_error_new (
- CAMEL_IMAPX_ERROR, 1,
+ CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT,
"%s", _("Server disconnected"));
camel_imapx_command_failed (ic, local_error);
g_error_free (local_error);
@@ -2710,9 +2743,6 @@ imapx_untagged_bye (CamelIMAPXServer *is,
GCancellable *cancellable,
GError **error)
{
- CamelIMAPXStore *imapx_store;
- CamelService *service;
- CamelServiceConnectionStatus status;
guchar *token = NULL;
gboolean success;
@@ -2727,7 +2757,7 @@ imapx_untagged_bye (CamelIMAPXServer *is,
if (success) {
c (is->tagprefix, "BYE: %s\n", token);
g_set_error (
- error, CAMEL_IMAPX_ERROR, 1,
+ error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT,
"IMAP server said BYE: %s", token);
}
@@ -2735,19 +2765,6 @@ imapx_untagged_bye (CamelIMAPXServer *is,
is->state = IMAPX_SHUTDOWN;
- imapx_store = camel_imapx_server_ref_store (is);
- service = CAMEL_SERVICE (imapx_store);
- status = camel_service_get_connection_status (service);
-
- /* Do not disconnect the service if we're still connecting.
- * camel_service_disconnect_sync() will cancel the connect
- * operation and the server message will get replaced with
- * a generic "Operation was cancelled" message. */
- if (status == CAMEL_SERVICE_CONNECTED)
- camel_service_disconnect_sync (service, FALSE, NULL, NULL);
-
- g_object_unref (imapx_store);
-
return FALSE;
}
@@ -4904,39 +4921,6 @@ exit:
return success;
}
-/**
- * camel_imapx_server_shutdown:
- * @is: a #CamelIMAPXServer
- *
- * Signals the server to shut down command processing. #CamelIMAPXStore
- * should call this immediately before unreferencing its server instance.
- * Note, the server instance may linger a short time after this function
- * returns as its own worker threads finish.
- *
- * Since: 3.12
- **/
-void
-camel_imapx_server_shutdown (CamelIMAPXServer *is)
-{
- GCancellable *cancellable;
-
- g_return_if_fail (CAMEL_IS_IMAPX_SERVER (is));
-
- QUEUE_LOCK (is);
-
- is->state = IMAPX_SHUTDOWN;
-
- cancellable = g_weak_ref_get (&is->priv->parser_cancellable);
-
- QUEUE_UNLOCK (is);
-
- g_main_loop_quit (is->priv->idle_main_loop);
- g_main_loop_quit (is->priv->parser_main_loop);
-
- g_cancellable_cancel (cancellable);
- g_clear_object (&cancellable);
-}
-
/* ********************************************************************** */
static void
@@ -7447,6 +7431,8 @@ imapx_abort_all_commands (CamelIMAPXServer *is,
queue = camel_imapx_command_queue_new ();
+ imapx_server_set_shutdown_error (is, error);
+
QUEUE_LOCK (is);
camel_imapx_command_queue_transfer (is->queue, queue);
@@ -7538,6 +7524,25 @@ imapx_ready_to_read (GInputStream *input_stream,
g_clear_object (&cancellable);
if (local_error != NULL) {
+ camel_imapx_debug (io, is->tagprefix, "Data read failed with error '%s'\n",
local_error->message);
+
+ /* Sadly, G_IO_ERROR_FAILED is also used for 'Connection reset by peer' error */
+ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_FAILED)) {
+ local_error->domain = CAMEL_IMAPX_SERVER_ERROR;
+ local_error->code = CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT;
+ }
+
+ imapx_server_set_shutdown_error (is, local_error);
+
+ /* Call the signal early, certain thread interleaving can cause the closed connection
+ being reused on the following reconnect attempt. There is also re-setting
+ the shutdown_error above, because the signal handler in connection manager
+ also calls camel_imapx_server_shutdown(), but without the error, while we want
+ to have there propagated the "try reconnect" error instead. As there is no
+ guarantee that it'll be called, then we also quit the parser's mainloop and
+ call the imapx_abort_all_commands() below - just in case. */
+ g_signal_emit (is, signals[SHUTDOWN], 0, local_error);
+
g_main_loop_quit (is->priv->parser_main_loop);
imapx_abort_all_commands (is, local_error);
g_clear_error (&local_error);
@@ -7561,6 +7566,7 @@ imapx_parser_thread (gpointer user_data)
GInputStream *input_stream;
GCancellable *cancellable;
GSource *pollable_source;
+ GError *shutdown_error;
is = CAMEL_IMAPX_SERVER (user_data);
@@ -7600,7 +7606,11 @@ imapx_parser_thread (gpointer user_data)
g_main_context_pop_thread_default (is->priv->parser_main_context);
- g_signal_emit (is, signals[SHUTDOWN], 0);
+ shutdown_error = imapx_server_dup_shutdown_error (is);
+
+ g_signal_emit (is, signals[SHUTDOWN], 0, shutdown_error);
+
+ g_clear_error (&shutdown_error);
g_object_unref (is);
@@ -7736,6 +7746,9 @@ imapx_server_finalize (GObject *object)
g_mutex_clear (&is->priv->jobs_prop_lock);
g_hash_table_destroy (is->priv->jobs_prop_folder_paths);
+ g_mutex_clear (&is->priv->shutdown_error_lock);
+ g_clear_error (&is->priv->shutdown_error);
+
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (camel_imapx_server_parent_class)->finalize (object);
}
@@ -7831,6 +7844,7 @@ camel_imapx_server_class_init (CamelIMAPXServerClass *class)
/**
* CamelIMAPXServer::shutdown
* @server: the #CamelIMAPXServer which emitted the signal
+ * @error: a #GError, which caused the shutdown; can be %NULL
**/
signals[SHUTDOWN] = g_signal_new (
"shutdown",
@@ -7838,8 +7852,8 @@ camel_imapx_server_class_init (CamelIMAPXServerClass *class)
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (CamelIMAPXServerClass, shutdown),
NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, G_TYPE_ERROR);
class->tagprefix = 'A';
}
@@ -7859,6 +7873,7 @@ camel_imapx_server_init (CamelIMAPXServer *is)
g_mutex_init (&is->priv->search_results_lock);
g_mutex_init (&is->priv->known_alerts_lock);
g_mutex_init (&is->priv->jobs_prop_lock);
+ g_mutex_init (&is->priv->shutdown_error_lock);
is->priv->jobs_prop_folder_paths = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
is->priv->jobs_prop_command_count = 0;
@@ -7888,6 +7903,7 @@ camel_imapx_server_init (CamelIMAPXServer *is)
is->priv->parser_main_loop = g_main_loop_new (main_context, FALSE);
is->priv->parser_main_context = g_main_context_ref (main_context);
+ is->priv->shutdown_error = NULL;
g_main_context_unref (main_context);
@@ -9282,3 +9298,59 @@ camel_imapx_server_register_untagged_handler (CamelIMAPXServer *is,
return previous;
}
+/**
+ * camel_imapx_server_shutdown:
+ * @is: a #CamelIMAPXServer
+ * @error: a #GError with which cancel any pending jobs
+ *
+ * Signals the server to shut down command processing. A #CamelIMAPXStore
+ * should call this immediately before unreferencing its server instance.
+ * Note, the server instance may linger a short time after this function
+ * returns as its own worker threads finish.
+ *
+ * Since: 3.12
+ **/
+void
+camel_imapx_server_shutdown (CamelIMAPXServer *is,
+ const GError *error)
+{
+ GCancellable *cancellable;
+ GError *shutdown_error_copy = NULL;
+
+ g_return_if_fail (CAMEL_IS_IMAPX_SERVER (is));
+
+ QUEUE_LOCK (is);
+
+ is->state = IMAPX_SHUTDOWN;
+
+ cancellable = g_weak_ref_get (&is->priv->parser_cancellable);
+
+ QUEUE_UNLOCK (is);
+
+ if (!error) {
+ shutdown_error_copy = imapx_server_dup_shutdown_error (is);
+ error = shutdown_error_copy;
+ }
+
+ if (error) {
+ imapx_abort_all_commands (is, error);
+ } else {
+ GError *local_error = NULL;
+
+ g_set_error (
+ &local_error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_UNAVAILABLE,
+ "Shutting down");
+
+ imapx_abort_all_commands (is, local_error);
+
+ g_clear_error (&local_error);
+ }
+
+ g_main_loop_quit (is->priv->idle_main_loop);
+ g_main_loop_quit (is->priv->parser_main_loop);
+
+ g_cancellable_cancel (cancellable);
+ g_clear_object (&cancellable);
+ g_clear_error (&shutdown_error_copy);
+}
diff --git a/camel/providers/imapx/camel-imapx-server.h b/camel/providers/imapx/camel-imapx-server.h
index 3a61ba1..ceacc23 100644
--- a/camel/providers/imapx/camel-imapx-server.h
+++ b/camel/providers/imapx/camel-imapx-server.h
@@ -50,7 +50,8 @@
G_BEGIN_DECLS
typedef enum {
- CAMEL_IMAPX_SERVER_ERROR_CONCURRENT_CONNECT_FAILED
+ CAMEL_IMAPX_SERVER_ERROR_CONCURRENT_CONNECT_FAILED,
+ CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT
} CamelIMAPXServerError;
GQuark camel_imapx_server_error_quark (void) G_GNUC_CONST;
@@ -135,7 +136,8 @@ struct _CamelIMAPXServerClass {
CamelIMAPXMailbox *mailbox);
void (*mailbox_closed) (CamelIMAPXServer *is,
CamelIMAPXMailbox *mailbox);
- void (*shutdown) (CamelIMAPXServer *is);
+ void (*shutdown) (CamelIMAPXServer *is,
+ const GError *error);
};
GType camel_imapx_server_get_type (void);
@@ -162,7 +164,8 @@ CamelAuthenticationResult
const gchar *mechanism,
GCancellable *cancellable,
GError **error);
-void camel_imapx_server_shutdown (CamelIMAPXServer *is);
+void camel_imapx_server_shutdown (CamelIMAPXServer *is,
+ const GError *error);
gboolean camel_imapx_server_list (CamelIMAPXServer *is,
const gchar *pattern,
CamelStoreGetFolderInfoFlags flags,
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index 96c080f..6b577d3 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -794,7 +794,7 @@ imapx_disconnect_sync (CamelService *service,
priv = CAMEL_IMAPX_STORE_GET_PRIVATE (service);
if (priv->con_man != NULL)
- camel_imapx_conn_manager_close_connections (priv->con_man);
+ camel_imapx_conn_manager_close_connections (priv->con_man, NULL);
g_mutex_lock (&priv->server_lock);
@@ -1146,24 +1146,39 @@ fetch_folder_info_for_pattern (CamelIMAPXServer *server,
GError *local_error = NULL;
gboolean success;
- success = camel_imapx_server_list (
- server, pattern, flags, cancellable, &local_error);
+ g_object_ref (server);
+
+ imapx_store = camel_imapx_server_ref_store (server);
+
+ success = camel_imapx_server_list (server, pattern, flags, cancellable, &local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&server);
+
+ server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, &local_error);
+ if (server)
+ success = camel_imapx_server_list (server, pattern, flags, cancellable, &local_error);
+ }
+
+ g_clear_object (&server);
+
if (!success) {
+ g_clear_object (&imapx_store);
+
if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
camel_imapx_namespace_get_category (namespace) != CAMEL_IMAPX_NAMESPACE_PERSONAL) {
/* Ignore errors for non-personal namespaces; one such error can be:
"NO LIST failed: wildcards not permitted in username" */
g_clear_error (&local_error);
return TRUE;
- } else {
+ } else if (local_error) {
g_propagate_error (error, local_error);
}
return FALSE;
}
- imapx_store = camel_imapx_server_ref_store (server);
-
list = camel_imapx_store_list_mailboxes (imapx_store, namespace, pattern);
for (link = list; link != NULL; link = g_list_next (link)) {
@@ -1189,26 +1204,41 @@ fetch_folder_info_for_inbox (CamelIMAPXServer *server,
GCancellable *cancellable,
GError **error)
{
+ CamelIMAPXStore *imapx_store;
+ GError *local_error = NULL;
gboolean success;
- success = camel_imapx_server_list (
- server, "INBOX", flags, cancellable, error);
+ g_object_ref (server);
+ imapx_store = camel_imapx_server_ref_store (server);
+
+ success = camel_imapx_server_list (server, "INBOX", flags, cancellable, &local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&server);
+
+ server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, &local_error);
+ if (server)
+ success = camel_imapx_server_list (server, "INBOX", flags, cancellable, &local_error);
+ }
+
+ g_clear_object (&server);
+
+ if (local_error)
+ g_propagate_error (error, local_error);
if (success) {
- CamelIMAPXStore *imapx_store;
CamelIMAPXMailbox *mailbox;
- imapx_store = camel_imapx_server_ref_store (server);
-
mailbox = camel_imapx_store_ref_mailbox (imapx_store, "INBOX");
g_return_val_if_fail (mailbox != NULL, FALSE);
collect_folder_info_for_list (
imapx_store, mailbox, folder_info_results);
-
- g_object_unref (imapx_store);
}
+ g_object_unref (imapx_store);
+
return success;
}
@@ -1475,8 +1505,21 @@ discover_inbox (CamelIMAPXStore *imapx_store,
attribute = CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED;
if (!camel_imapx_mailbox_has_attribute (mailbox, attribute)) {
- camel_imapx_server_subscribe_mailbox (
- imapx_server, mailbox, cancellable, NULL);
+ GError *local_error = NULL;
+ gboolean success;
+
+ success = camel_imapx_server_subscribe_mailbox (imapx_server, mailbox, cancellable,
&local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable,
&local_error);
+ if (imapx_server)
+ success = camel_imapx_server_subscribe_mailbox (imapx_server, mailbox,
cancellable, &local_error);
+ }
+
+ g_clear_error (&local_error);
}
exit:
@@ -1808,6 +1851,7 @@ imapx_store_create_folder_sync (CamelStore *store,
gchar *mailbox_name = NULL;
gchar separator;
gboolean success;
+ GError *local_error = NULL;
imapx_store = CAMEL_IMAPX_STORE (store);
imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, error);
@@ -1884,8 +1928,19 @@ check_separator:
/* This also LISTs the mailbox after creating it, which
* triggers the CamelIMAPXStore::mailbox-created signal
* and all the local processing that goes along with it. */
- success = camel_imapx_server_create_mailbox (
- imapx_server, mailbox_name, cancellable, error);
+ success = camel_imapx_server_create_mailbox (imapx_server, mailbox_name, cancellable, &local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable,
&local_error);
+ if (imapx_server)
+ success = camel_imapx_server_create_mailbox (imapx_server, mailbox_name, cancellable,
&local_error);
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
if (success) {
fi = imapx_store_build_folder_info (
@@ -1912,6 +1967,7 @@ imapx_store_delete_folder_sync (CamelStore *store,
CamelIMAPXServer *imapx_server;
CamelIMAPXMailbox *mailbox = NULL;
gboolean success = FALSE;
+ GError *local_error = NULL;
folder = camel_store_get_folder_sync (
store, folder_name, 0, cancellable, error);
@@ -1930,8 +1986,19 @@ imapx_store_delete_folder_sync (CamelStore *store,
if (mailbox == NULL)
goto exit;
- success = camel_imapx_server_delete_mailbox (
- imapx_server, mailbox, cancellable, error);
+ success = camel_imapx_server_delete_mailbox (imapx_server, mailbox, cancellable, &local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable,
&local_error);
+ if (imapx_server)
+ success = camel_imapx_server_delete_mailbox (imapx_server, mailbox, cancellable,
&local_error);
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
if (success)
imapx_delete_folder_from_cache (imapx_store, folder_name);
@@ -1962,6 +2029,7 @@ imapx_store_rename_folder_sync (CamelStore *store,
gchar separator;
gboolean use_subscriptions;
gboolean success = FALSE;
+ GError *local_error = NULL;
service = CAMEL_SERVICE (store);
imapx_store = CAMEL_IMAPX_STORE (store);
@@ -1996,16 +2064,53 @@ imapx_store_rename_folder_sync (CamelStore *store,
separator = camel_imapx_mailbox_get_separator (mailbox);
new_mailbox_name = camel_imapx_folder_path_to_mailbox (new, separator);
- if (use_subscriptions)
- camel_imapx_server_unsubscribe_mailbox (
- imapx_server, mailbox, cancellable, NULL);
+ if (use_subscriptions) {
+ success = camel_imapx_server_unsubscribe_mailbox (imapx_server, mailbox, cancellable,
&local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable,
&local_error);
+ if (imapx_server)
+ success = camel_imapx_server_unsubscribe_mailbox (imapx_server, mailbox,
cancellable, &local_error);
+ }
+
+ g_clear_error (&local_error);
+ }
+
+ success = camel_imapx_server_rename_mailbox (imapx_server, mailbox, new_mailbox_name, cancellable,
&local_error);
- success = camel_imapx_server_rename_mailbox (
- imapx_server, mailbox, new_mailbox_name, cancellable, error);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable,
&local_error);
+ if (imapx_server)
+ success = camel_imapx_server_rename_mailbox (imapx_server, mailbox, new_mailbox_name,
cancellable, &local_error);
+ }
if (!success) {
- camel_imapx_server_subscribe_mailbox (
- imapx_server, mailbox, cancellable, NULL);
+ if (local_error)
+ g_propagate_error (error, local_error);
+ local_error = NULL;
+
+ if (use_subscriptions) {
+ gboolean success_2;
+
+ success_2 = camel_imapx_server_subscribe_mailbox (imapx_server, mailbox, cancellable,
&local_error);
+
+ while (!success_2 && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE,
cancellable, &local_error);
+ if (imapx_server)
+ success_2 = camel_imapx_server_subscribe_mailbox (imapx_server,
mailbox, cancellable, &local_error);
+ }
+
+ g_clear_error (&local_error);
+ }
goto exit;
}
@@ -2019,9 +2124,21 @@ imapx_store_rename_folder_sync (CamelStore *store,
camel_imapx_folder_set_mailbox (
CAMEL_IMAPX_FOLDER (folder), cloned_mailbox);
- if (use_subscriptions)
- success = camel_imapx_server_subscribe_mailbox (
- imapx_server, cloned_mailbox, cancellable, error);
+ if (use_subscriptions) {
+ success = camel_imapx_server_subscribe_mailbox (imapx_server, cloned_mailbox, cancellable,
&local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable,
&local_error);
+ if (imapx_server)
+ success = camel_imapx_server_subscribe_mailbox (imapx_server, cloned_mailbox,
cancellable, &local_error);
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+ }
g_clear_object (&cloned_mailbox);
@@ -2216,6 +2333,7 @@ imapx_store_subscribe_folder_sync (CamelSubscribable *subscribable,
CamelIMAPXServer *imapx_server;
CamelIMAPXMailbox *mailbox = NULL;
gboolean success = FALSE;
+ GError *local_error = NULL;
imapx_store = CAMEL_IMAPX_STORE (subscribable);
imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, error);
@@ -2236,8 +2354,19 @@ imapx_store_subscribe_folder_sync (CamelSubscribable *subscribable,
if (mailbox == NULL)
goto exit;
- success = camel_imapx_server_subscribe_mailbox (
- imapx_server, mailbox, cancellable, error);
+ success = camel_imapx_server_subscribe_mailbox (imapx_server, mailbox, cancellable, &local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable,
&local_error);
+ if (imapx_server)
+ success = camel_imapx_server_subscribe_mailbox (imapx_server, mailbox, cancellable,
&local_error);
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
if (success) {
CamelFolderInfo *fi;
@@ -2269,6 +2398,7 @@ imapx_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
CamelIMAPXServer *imapx_server;
CamelIMAPXMailbox *mailbox = NULL;
gboolean success = FALSE;
+ GError *local_error = NULL;
imapx_store = CAMEL_IMAPX_STORE (subscribable);
imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, error);
@@ -2289,8 +2419,19 @@ imapx_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
if (mailbox == NULL)
goto exit;
- success = camel_imapx_server_unsubscribe_mailbox (
- imapx_server, mailbox, cancellable, error);
+ success = camel_imapx_server_unsubscribe_mailbox (imapx_server, mailbox, cancellable, &local_error);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ g_clear_object (&imapx_server);
+
+ imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable,
&local_error);
+ if (imapx_server)
+ success = camel_imapx_server_unsubscribe_mailbox (imapx_server, mailbox, cancellable,
&local_error);
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
if (success) {
CamelFolderInfo *fi;
@@ -2526,7 +2667,7 @@ camel_imapx_store_ref_server (CamelIMAPXStore *store,
server = camel_imapx_conn_manager_get_connection (
store->priv->con_man, folder_name, for_expensive_job, cancellable, error);
- if (!server) {
+ if (!server && error && !*error) {
g_set_error (
error, CAMEL_SERVICE_ERROR,
CAMEL_SERVICE_ERROR_UNAVAILABLE,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]