diff -up evolution-data-server-3.8.5/camel/camel-imapx-conn-manager.c.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-conn-manager.c
--- evolution-data-server-3.8.5/camel/camel-imapx-conn-manager.c.imapx-conn-manager-ext 2013-07-23 13:57:46.000000000 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-conn-manager.c 2014-05-13 14:17:43.115983665 +0200
@@ -47,6 +47,7 @@ struct _CamelIMAPXConnManagerPrivate {
GList *connections;
GWeakRef store;
GRWLock rw_lock;
+ guint limit_max_connections;
};
struct _ConnectionInfo {
@@ -54,6 +55,7 @@ struct _ConnectionInfo {
CamelIMAPXServer *is;
GHashTable *folder_names;
gchar *selected_folder;
+ GError *shutdown_error;
volatile gint ref_count;
};
@@ -68,7 +70,9 @@ G_DEFINE_TYPE (
CAMEL_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,
@@ -91,6 +95,7 @@ connection_info_new (CamelIMAPXServer *i
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;
@@ -114,11 +119,15 @@ connection_info_unref (ConnectionInfo *c
g_return_if_fail (cinfo->ref_count > 0);
if (g_atomic_int_dec_and_test (&cinfo->ref_count)) {
- camel_imapx_server_connect (cinfo->is, NULL, NULL);
+ 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_mutex_clear (&cinfo->lock);
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);
}
@@ -132,6 +141,7 @@ connection_info_cancel_and_unref (Connec
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);
+ camel_imapx_server_shutdown (cinfo->is, cinfo->shutdown_error);
g_cancellable_cancel (cinfo->is->cancellable);
connection_info_unref (cinfo);
}
@@ -145,8 +155,9 @@ connection_info_is_available (Connection
g_mutex_lock (&cinfo->lock);
- /* Available means it's not tracking any folder names. */
- available = (g_hash_table_size (cinfo->folder_names) == 0);
+ /* Available means it's not tracking any folder names or no jobs are running. */
+ available = (g_hash_table_size (cinfo->folder_names) == 0) ||
+ camel_imapx_server_get_command_count (cinfo->is) == 0;
g_mutex_unlock (&cinfo->lock);
@@ -234,6 +245,23 @@ connection_info_set_selected_folder (Con
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)
{
@@ -416,11 +444,9 @@ camel_imapx_conn_manager_init (CamelIMAP
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;
@@ -432,6 +458,14 @@ imapx_conn_shutdown (CamelIMAPXServer *i
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
@@ -451,14 +485,10 @@ imapx_conn_update_select (CamelIMAPXServ
old_selected_folder = connection_info_dup_selected_folder (cinfo);
if (old_selected_folder != NULL) {
- IMAPXJobQueueInfo *jinfo;
-
- jinfo = camel_imapx_server_get_job_queue_info (is);
- if (!g_hash_table_lookup (jinfo->folders, old_selected_folder)) {
+ if (!camel_imapx_server_folder_name_in_jobs (is, old_selected_folder)) {
connection_info_remove_folder_name (cinfo, old_selected_folder);
c (is->tagprefix, "Removed folder %s from connection folder list - select changed \n", old_selected_folder);
}
- camel_imapx_destroy_job_queue_info (jinfo);
g_free (old_selected_folder);
}
@@ -471,14 +501,15 @@ imapx_conn_update_select (CamelIMAPXServ
/* This should find a connection if the slots are full, returns NULL if there are slots available for a new connection for a folder */
static CamelIMAPXServer *
imapx_find_connection_unlocked (CamelIMAPXConnManager *con_man,
- const gchar *folder_name)
+ const gchar *folder_name,
+ gboolean for_expensive_job)
{
CamelStore *store;
CamelSettings *settings;
CamelIMAPXServer *is = NULL;
ConnectionInfo *cinfo = NULL;
GList *list, *link;
- guint concurrent_connections;
+ guint concurrent_connections, opened_connections, expensive_connections = 0;
guint min_jobs = G_MAXUINT;
/* Caller must be holding CON_WRITE_LOCK. */
@@ -492,24 +523,85 @@ imapx_find_connection_unlocked (CamelIMA
camel_imapx_settings_get_concurrent_connections (
CAMEL_IMAPX_SETTINGS (settings));
+ if (con_man->priv->limit_max_connections > 0 &&
+ con_man->priv->limit_max_connections < concurrent_connections)
+ concurrent_connections = con_man->priv->limit_max_connections;
+
g_object_unref (settings);
/* XXX Have a dedicated connection for INBOX ? */
+ opened_connections = g_list_length (con_man->priv->connections);
list = con_man->priv->connections;
/* If a folder was not given, find the least-busy connection. */
- if (folder_name == NULL)
+ if (folder_name == NULL) {
goto least_busy;
+ }
/* First try to find a connection already handling this folder. */
for (link = list; link != NULL; link = g_list_next (link)) {
ConnectionInfo *candidate = link->data;
- if (connection_info_has_folder_name (candidate, folder_name)) {
+ if (camel_imapx_server_has_expensive_command (candidate->is))
+ expensive_connections++;
+
+ if (connection_info_has_folder_name (candidate, folder_name) &&
+ (opened_connections >= concurrent_connections || for_expensive_job || !camel_imapx_server_has_expensive_command (candidate->is))) {
+ if (cinfo) {
+ /* group expensive jobs into one connection */
+ if (for_expensive_job && camel_imapx_server_has_expensive_command (cinfo->is))
+ continue;
+
+ if (!for_expensive_job && camel_imapx_server_get_command_count (cinfo->is) < camel_imapx_server_get_command_count (candidate->is))
+ continue;
+
+ connection_info_unref (cinfo);
+ }
+
cinfo = connection_info_ref (candidate);
+ if (for_expensive_job && camel_imapx_server_has_expensive_command (cinfo->is))
+ goto exit;
+ }
+ }
+
+ least_busy:
+ if (for_expensive_job) {
+ /* allow only half connections being with expensive operations */
+ if (expensive_connections > 0 &&
+ expensive_connections < concurrent_connections / 2 &&
+ opened_connections < concurrent_connections)
goto exit;
+
+ /* cinfo here doesn't have any expensive command, thus ignore it */
+ if (cinfo) {
+ connection_info_unref (cinfo);
+ cinfo = NULL;
}
+
+ /* Pick the connection with the least number of jobs in progress among those with expensive jobs. */
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ ConnectionInfo *candidate = link->data;
+ guint jobs;
+
+ if (!camel_imapx_server_has_expensive_command (candidate->is))
+ continue;
+
+ jobs = camel_imapx_server_get_command_count (candidate->is);
+
+ if (cinfo == NULL) {
+ cinfo = connection_info_ref (candidate);
+ min_jobs = jobs;
+
+ } else if (jobs < min_jobs) {
+ connection_info_unref (cinfo);
+ cinfo = connection_info_ref (candidate);
+ min_jobs = jobs;
+ }
+ }
+
+ if (cinfo)
+ goto exit;
}
/* Next try to find a connection not handling any folders. */
@@ -517,44 +609,59 @@ imapx_find_connection_unlocked (CamelIMA
ConnectionInfo *candidate = link->data;
if (connection_info_is_available (candidate)) {
+ if (cinfo)
+ connection_info_unref (cinfo);
cinfo = connection_info_ref (candidate);
goto exit;
}
}
-least_busy:
+ /* open a new connection, if there is a room for it */
+ if (opened_connections < concurrent_connections && (!for_expensive_job || opened_connections < concurrent_connections / 2)) {
+ if (cinfo && camel_imapx_server_get_command_count (cinfo->is) != 0) {
+ connection_info_unref (cinfo);
+ cinfo = NULL;
+ }
+ goto exit;
+ } else {
+ if (cinfo)
+ min_jobs = camel_imapx_server_get_command_count (cinfo->is);
+ }
+
/* Pick the connection with the least number of jobs in progress. */
for (link = list; link != NULL; link = g_list_next (link)) {
ConnectionInfo *candidate = link->data;
- IMAPXJobQueueInfo *jinfo = NULL;
-
- jinfo = camel_imapx_server_get_job_queue_info (candidate->is);
+ gint n_commands = camel_imapx_server_get_command_count (candidate->is);
if (cinfo == NULL) {
cinfo = connection_info_ref (candidate);
- min_jobs = jinfo->queue_len;
+ min_jobs = n_commands;
- } else if (jinfo->queue_len < min_jobs) {
+ } else if (n_commands < min_jobs) {
connection_info_unref (cinfo);
cinfo = connection_info_ref (candidate);
- min_jobs = jinfo->queue_len;
+ min_jobs = n_commands;
}
-
- camel_imapx_destroy_job_queue_info (jinfo);
}
exit:
if (cinfo != NULL && folder_name != NULL)
connection_info_insert_folder_name (cinfo, folder_name);
+ if (camel_debug_flag (conman)) {
+ printf ("%s: for-expensive:%d will return:%p cmd-count:%d has-expensive:%d found:%d; connections opened:%d max:%d\n", G_STRFUNC, for_expensive_job, cinfo, cinfo ? camel_imapx_server_get_command_count (cinfo->is) : -2, cinfo ? camel_imapx_server_has_expensive_command (cinfo->is) : -2, expensive_connections, g_list_length (list), concurrent_connections);
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ ConnectionInfo *candidate = link->data;
+
+ printf (" cmds:%d has-expensive:%d avail:%d cinfo:%p server:%p\n", camel_imapx_server_get_command_count (candidate->is), camel_imapx_server_has_expensive_command (candidate->is), connection_info_is_available (candidate), candidate, candidate->is);
+ }
+ }
+
if (cinfo != NULL) {
is = g_object_ref (cinfo->is);
connection_info_unref (cinfo);
}
- if (camel_debug_flag (conman))
- g_assert (!(concurrent_connections == g_list_length (con_man->priv->connections) && is == NULL));
-
g_object_unref (store);
return is;
@@ -601,9 +708,11 @@ imapx_create_new_connection_unlocked (Ca
* authenticate at once, so this should be thread-safe.
*/
imapx_store->authenticating_server = g_object_ref (is);
+ camel_imapx_store_set_authenticating_concurrent_connection (imapx_store, con_man->priv->connections != NULL);
success = camel_imapx_server_connect (is, cancellable, error);
g_object_unref (imapx_store->authenticating_server);
imapx_store->authenticating_server = NULL;
+ camel_imapx_store_set_authenticating_concurrent_connection (imapx_store, FALSE);
if (!success) {
g_clear_object (&is);
@@ -626,7 +735,7 @@ imapx_create_new_connection_unlocked (Ca
con_man->priv->connections = g_list_prepend (
con_man->priv->connections, cinfo);
- c (is->tagprefix, "Created new connection for %s and total connections %d \n", folder_name, g_list_length (con_man->priv->connections));
+ c (is->tagprefix, "Created new connection %p (server:%p) for %s; total connections %d\n", cinfo, cinfo->is, folder_name, g_list_length (con_man->priv->connections));
exit:
g_object_unref (store);
@@ -656,6 +765,7 @@ camel_imapx_conn_manager_ref_store (Came
CamelIMAPXServer *
camel_imapx_conn_manager_get_connection (CamelIMAPXConnManager *con_man,
const gchar *folder_name,
+ gboolean for_expensive_job,
GCancellable *cancellable,
GError **error)
{
@@ -669,10 +779,36 @@ camel_imapx_conn_manager_get_connection
/* Check if we got cancelled while waiting for the lock. */
if (!g_cancellable_set_error_if_cancelled (cancellable, error)) {
- is = imapx_find_connection_unlocked (con_man, folder_name);
- if (is == NULL)
- is = imapx_create_new_connection_unlocked (
- con_man, folder_name, cancellable, error);
+ is = imapx_find_connection_unlocked (con_man, folder_name, for_expensive_job);
+ if (is == NULL) {
+ GError *local_error = NULL;
+
+ is = imapx_create_new_connection_unlocked (con_man, folder_name, cancellable, &local_error);
+
+ if (!is) {
+ gboolean limit_connections =
+ g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR,
+ CAMEL_IMAPX_SERVER_ERROR_CONCURRENT_CONNECT_FAILED) &&
+ con_man->priv->connections;
+
+ c ('*', "Failed to open a new connection, while having %d opened, with error: %s; will limit connections: %s\n",
+ g_list_length (con_man->priv->connections),
+ local_error ? local_error->message : "Unknown error",
+ limit_connections ? "yes" : "no");
+
+ if (limit_connections) {
+ /* limit to one-less than current connection count - be nice to the server */
+ con_man->priv->limit_max_connections = g_list_length (con_man->priv->connections) - 1;
+ if (!con_man->priv->limit_max_connections)
+ con_man->priv->limit_max_connections = 1;
+
+ g_clear_error (&local_error);
+ is = imapx_find_connection_unlocked (con_man, folder_name, for_expensive_job);
+ } else if (local_error) {
+ g_propagate_error (error, local_error);
+ }
+ }
+ }
}
CON_WRITE_UNLOCK (con_man);
@@ -706,7 +842,6 @@ camel_imapx_conn_manager_update_con_info
const gchar *folder_name)
{
ConnectionInfo *cinfo;
- IMAPXJobQueueInfo *jinfo;
g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (con_man));
@@ -716,28 +851,35 @@ camel_imapx_conn_manager_update_con_info
if (cinfo == NULL)
return;
- jinfo = camel_imapx_server_get_job_queue_info (cinfo->is);
- if (!g_hash_table_lookup (jinfo->folders, folder_name)) {
+ if (camel_imapx_server_folder_name_in_jobs (is, folder_name)) {
connection_info_remove_folder_name (cinfo, folder_name);
c (is->tagprefix, "Removed folder %s from connection folder list - op done \n", folder_name);
}
- camel_imapx_destroy_job_queue_info (jinfo);
connection_info_unref (cinfo);
}
void
-camel_imapx_conn_manager_close_connections (CamelIMAPXConnManager *con_man)
+camel_imapx_conn_manager_close_connections (CamelIMAPXConnManager *con_man,
+ const GError *error)
{
+ GList *iter, *connections;
+
g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (con_man));
CON_WRITE_LOCK (con_man);
- g_list_free_full (
- con_man->priv->connections,
- (GDestroyNotify) connection_info_cancel_and_unref);
+ c('*', "Closing all %d connections, with propagated error: %s\n", g_list_length (con_man->priv->connections), error ? error->message : "none");
+
+ connections = con_man->priv->connections;
con_man->priv->connections = NULL;
CON_WRITE_UNLOCK (con_man);
+
+ for (iter = connections; iter; iter = g_list_next (iter)) {
+ connection_info_set_shutdown_error (iter->data, error);
+ }
+
+ g_list_free_full (connections, (GDestroyNotify) connection_info_cancel_and_unref);
}
diff -up evolution-data-server-3.8.5/camel/camel-imapx-conn-manager.h.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-conn-manager.h
--- evolution-data-server-3.8.5/camel/camel-imapx-conn-manager.h.imapx-conn-manager-ext 2013-07-23 13:57:56.000000000 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-conn-manager.h 2014-05-13 14:17:43.116983665 +0200
@@ -71,10 +71,12 @@ CamelIMAPXServer *
camel_imapx_conn_manager_get_connection
(CamelIMAPXConnManager *con_man,
const gchar *folder_name,
+ gboolean for_expensive_job,
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 -up evolution-data-server-3.8.5/camel/camel-imapx-folder.c.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-folder.c
--- evolution-data-server-3.8.5/camel/camel-imapx-folder.c.imapx-conn-manager-ext 2013-07-23 14:01:51.000000000 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-folder.c 2014-05-13 14:17:43.116983665 +0200
@@ -303,47 +303,27 @@ imapx_search_by_uids (CamelFolder *folde
{
CamelIMAPXFolder *ifolder;
CamelIMAPXSearch *isearch;
- CamelIMAPXServer *server = NULL;
- CamelStore *parent_store;
GPtrArray *matches;
- const gchar *folder_name;
- gboolean online;
if (uids->len == 0)
return g_ptr_array_new ();
ifolder = CAMEL_IMAPX_FOLDER (folder);
- folder_name = camel_folder_get_full_name (folder);
- parent_store = camel_folder_get_parent_store (folder);
-
- online = camel_offline_store_get_online (
- CAMEL_OFFLINE_STORE (parent_store));
-
- if (online) {
- /* do not panic when the server cannot be reached for whatever reason,
- * show offline data at least */
- server = camel_imapx_store_get_server (
- CAMEL_IMAPX_STORE (parent_store),
- folder_name, cancellable, NULL);
- }
g_mutex_lock (&ifolder->search_lock);
isearch = CAMEL_IMAPX_SEARCH (ifolder->search);
- camel_imapx_search_set_server (isearch, server);
camel_folder_search_set_folder (ifolder->search, folder);
+ camel_imapx_search_set_cancellable_and_error (isearch, cancellable, error);
matches = camel_folder_search_search (
ifolder->search, expression, uids, cancellable, error);
- camel_imapx_search_set_server (isearch, NULL);
+ camel_imapx_search_set_cancellable_and_error (isearch, NULL, NULL);
g_mutex_unlock (&ifolder->search_lock);
- if (server != NULL)
- g_object_unref (server);
-
return matches;
}
@@ -355,44 +335,24 @@ imapx_count_by_expression (CamelFolder *
{
CamelIMAPXFolder *ifolder;
CamelIMAPXSearch *isearch;
- CamelIMAPXServer *server = NULL;
- CamelStore *parent_store;
- const gchar *folder_name;
- gboolean online;
guint32 matches;
ifolder = CAMEL_IMAPX_FOLDER (folder);
- folder_name = camel_folder_get_full_name (folder);
- parent_store = camel_folder_get_parent_store (folder);
-
- online = camel_offline_store_get_online (
- CAMEL_OFFLINE_STORE (parent_store));
-
- if (online) {
- /* do not panic when the server cannot be reached for whatever reason,
- * show offline data at least */
- server = camel_imapx_store_get_server (
- CAMEL_IMAPX_STORE (parent_store),
- folder_name, cancellable, NULL);
- }
g_mutex_lock (&ifolder->search_lock);
isearch = CAMEL_IMAPX_SEARCH (ifolder->search);
- camel_imapx_search_set_server (isearch, server);
camel_folder_search_set_folder (ifolder->search, folder);
+ camel_imapx_search_set_cancellable_and_error (isearch, cancellable, error);
matches = camel_folder_search_count (
ifolder->search, expression, cancellable, error);
- camel_imapx_search_set_server (isearch, NULL);
+ camel_imapx_search_set_cancellable_and_error (isearch, NULL, NULL);
g_mutex_unlock (&ifolder->search_lock);
- if (server != NULL)
- g_object_unref (server);
-
return matches;
}
@@ -404,44 +364,24 @@ imapx_search_by_expression (CamelFolder
{
CamelIMAPXFolder *ifolder;
CamelIMAPXSearch *isearch;
- CamelIMAPXServer *server = NULL;
- CamelStore *parent_store;
GPtrArray *matches;
- const gchar *folder_name;
- gboolean online;
ifolder = CAMEL_IMAPX_FOLDER (folder);
- folder_name = camel_folder_get_full_name (folder);
- parent_store = camel_folder_get_parent_store (folder);
-
- online = camel_offline_store_get_online (
- CAMEL_OFFLINE_STORE (parent_store));
-
- if (online) {
- /* do not panic when the server cannot be reached for whatever reason,
- * show offline data at least */
- server = camel_imapx_store_get_server (
- CAMEL_IMAPX_STORE (parent_store),
- folder_name, cancellable, NULL);
- }
g_mutex_lock (&ifolder->search_lock);
isearch = CAMEL_IMAPX_SEARCH (ifolder->search);
- camel_imapx_search_set_server (isearch, server);
camel_folder_search_set_folder (ifolder->search, folder);
+ camel_imapx_search_set_cancellable_and_error (isearch, cancellable, error);
matches = camel_folder_search_search (
ifolder->search, expression, NULL, cancellable, error);
- camel_imapx_search_set_server (isearch, NULL);
+ camel_imapx_search_set_cancellable_and_error (isearch, NULL, NULL);
g_mutex_unlock (&ifolder->search_lock);
- if (server != NULL)
- g_object_unref (server);
-
return matches;
}
@@ -466,8 +406,11 @@ imapx_append_message_sync (CamelFolder *
CamelStore *parent_store;
CamelIMAPXStore *istore;
CamelIMAPXServer *server;
+ const gchar *folder_name;
+ GError *local_error = NULL;
gboolean success = FALSE;
+ folder_name = camel_folder_get_full_name (folder);
parent_store = camel_folder_get_parent_store (folder);
istore = CAMEL_IMAPX_STORE (parent_store);
@@ -482,11 +425,27 @@ imapx_append_message_sync (CamelFolder *
if (appended_uid)
*appended_uid = NULL;
- server = camel_imapx_store_get_server (istore, NULL, cancellable, error);
+ server = camel_imapx_store_get_server (istore, folder_name, FALSE, cancellable, error);
if (server) {
success = camel_imapx_server_append_message (
- server, folder, message, info, appended_uid, cancellable, error);
+ server, folder, message, info, appended_uid, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, folder_name);
g_object_unref (server);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, folder_name, FALSE, cancellable, &local_error);
+ if (server) {
+ success = camel_imapx_server_append_message (
+ server, folder, message, info, appended_uid, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, folder_name);
+ g_object_unref (server);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
}
return success;
@@ -501,6 +460,7 @@ imapx_expunge_sync (CamelFolder *folder,
CamelIMAPXStore *istore;
CamelIMAPXServer *server;
const gchar *folder_name;
+ GError *local_error = NULL;
gboolean success = FALSE;
folder_name = camel_folder_get_full_name (folder);
@@ -515,13 +475,25 @@ imapx_expunge_sync (CamelFolder *folder,
return FALSE;
}
- server = camel_imapx_store_get_server (
- istore, folder_name, cancellable, error);
+ server = camel_imapx_store_get_server (istore, folder_name, FALSE, cancellable, error);
if (server != NULL) {
- success = camel_imapx_server_expunge (
- server, folder, cancellable, error);
+ success = camel_imapx_server_expunge (server, folder, cancellable, &local_error);
camel_imapx_store_op_done (istore, server, folder_name);
g_object_unref (server);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, folder_name, FALSE, cancellable, &local_error);
+ if (server != NULL) {
+ success = camel_imapx_server_expunge (server, folder, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, folder_name);
+ g_object_unref (server);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
}
return success;
@@ -539,6 +511,7 @@ imapx_fetch_messages_sync (CamelFolder *
CamelIMAPXStore *istore;
CamelIMAPXServer *server;
const gchar *folder_name;
+ GError *local_error = NULL;
gboolean success = FALSE;
folder_name = camel_folder_get_full_name (folder);
@@ -557,19 +530,66 @@ imapx_fetch_messages_sync (CamelFolder *
if (!camel_service_connect_sync (service, cancellable, error))
return FALSE;
- server = camel_imapx_store_get_server (
- istore, folder_name, cancellable, error);
+ server = camel_imapx_store_get_server (istore, folder_name, TRUE, cancellable, error);
if (server != NULL) {
- success = camel_imapx_server_fetch_messages (
- server, folder, type, limit, cancellable, error);
+ success = camel_imapx_server_fetch_messages (server, folder, type, limit, cancellable, &local_error);
camel_imapx_store_op_done (istore, server, folder_name);
g_object_unref (server);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, folder_name, TRUE, cancellable, &local_error);
+ if (server != NULL) {
+ success = camel_imapx_server_fetch_messages (server, folder, type, limit, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, folder_name);
+ g_object_unref (server);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
}
return success;
}
static CamelMimeMessage *
+imapx_get_message_cached (CamelFolder *folder,
+ const gchar *message_uid,
+ GCancellable *cancellable)
+{
+ CamelIMAPXFolder *imapx_folder;
+ CamelMimeMessage *msg = NULL;
+ CamelStream *stream = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_FOLDER (folder), NULL);
+ g_return_val_if_fail (message_uid != NULL, NULL);
+
+ imapx_folder = CAMEL_IMAPX_FOLDER (folder);
+
+ stream = camel_data_cache_get (imapx_folder->cache, "cur", message_uid, NULL);
+ if (stream != NULL) {
+ gboolean success;
+
+ msg = camel_mime_message_new ();
+
+ g_mutex_lock (&imapx_folder->stream_lock);
+ success = camel_data_wrapper_construct_from_stream_sync (
+ CAMEL_DATA_WRAPPER (msg), stream, cancellable, NULL);
+ if (!success) {
+ g_object_unref (msg);
+ msg = NULL;
+ }
+ g_mutex_unlock (&imapx_folder->stream_lock);
+ g_object_unref (stream);
+ }
+
+ return msg;
+}
+
+static CamelMimeMessage *
imapx_get_message_sync (CamelFolder *folder,
const gchar *uid,
GCancellable *cancellable,
@@ -583,6 +603,7 @@ imapx_get_message_sync (CamelFolder *fol
CamelIMAPXServer *server;
const gchar *folder_name;
const gchar *path = NULL;
+ GError *local_error = NULL;
gboolean offline_message = FALSE;
folder_name = camel_folder_get_full_name (folder);
@@ -615,14 +636,27 @@ imapx_get_message_sync (CamelFolder *fol
}
server = camel_imapx_store_get_server (
- istore, folder_name, cancellable, error);
+ istore, folder_name, FALSE, cancellable, error);
if (server == NULL)
return NULL;
- stream = camel_imapx_server_get_message (
- server, folder, uid, cancellable, error);
+ stream = camel_imapx_server_get_message (server, folder, uid, cancellable, &local_error);
camel_imapx_store_op_done (istore, server, folder_name);
g_object_unref (server);
+
+ while (!stream && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, folder_name, FALSE, cancellable, &local_error);
+ if (server) {
+ stream = camel_imapx_server_get_message (server, folder, uid, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, folder_name);
+ g_object_unref (server);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
}
if (stream != NULL) {
@@ -675,6 +709,7 @@ imapx_get_quota_info_sync (CamelFolder *
CamelFolderQuotaInfo *quota_info = NULL;
const gchar *folder_name;
gchar **quota_root_names;
+ GError *local_error = NULL;
gboolean success = FALSE;
folder_name = camel_folder_get_full_name (folder);
@@ -682,14 +717,29 @@ imapx_get_quota_info_sync (CamelFolder *
server = camel_imapx_store_get_server (
CAMEL_IMAPX_STORE (parent_store),
- folder_name, cancellable, error);
+ folder_name, FALSE, cancellable, error);
if (server != NULL) {
- success = camel_imapx_server_update_quota_info (
- server, folder_name, cancellable, error);
+ success = camel_imapx_server_update_quota_info (server, folder_name, cancellable, &local_error);
+ camel_imapx_store_op_done (CAMEL_IMAPX_STORE (parent_store), server, folder_name);
g_object_unref (server);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (CAMEL_IMAPX_STORE (parent_store), folder_name, FALSE, cancellable, &local_error);
+ if (server) {
+ success = camel_imapx_server_update_quota_info (server, folder_name, cancellable, &local_error);
+ camel_imapx_store_op_done (CAMEL_IMAPX_STORE (parent_store), server, folder_name);
+ g_object_unref (server);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
}
+
if (!success)
return NULL;
@@ -734,6 +784,7 @@ imapx_refresh_info_sync (CamelFolder *fo
CamelIMAPXStore *istore;
CamelIMAPXServer *server;
const gchar *folder_name;
+ GError *local_error = NULL;
gboolean success = FALSE;
folder_name = camel_folder_get_full_name (folder);
@@ -752,13 +803,25 @@ imapx_refresh_info_sync (CamelFolder *fo
if (!camel_service_connect_sync (service, cancellable, error))
return FALSE;
- server = camel_imapx_store_get_server (
- istore, folder_name, cancellable, error);
+ server = camel_imapx_store_get_server (istore, folder_name, TRUE, cancellable, error);
if (server != NULL) {
- success = camel_imapx_server_refresh_info (
- server, folder, cancellable, error);
+ success = camel_imapx_server_refresh_info (server, folder, cancellable, &local_error);
camel_imapx_store_op_done (istore, server, folder_name);
g_object_unref (server);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, folder_name, TRUE, cancellable, &local_error);
+ if (server != NULL) {
+ success = camel_imapx_server_refresh_info (server, folder, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, folder_name);
+ g_object_unref (server);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
}
return success;
@@ -920,6 +983,7 @@ imapx_synchronize_sync (CamelFolder *fol
CamelIMAPXStore *istore;
CamelIMAPXServer *server;
const gchar *folder_name;
+ GError *local_error = NULL;
gboolean success = FALSE;
folder_name = camel_folder_get_full_name (folder);
@@ -934,13 +998,25 @@ imapx_synchronize_sync (CamelFolder *fol
return FALSE;
}
+ /* while it can be expensive job, do not treat it as such, to avoid a blockage
+ by really expensive jobs */
server = camel_imapx_store_get_server (
- istore, folder_name, cancellable, error);
+ istore, folder_name, FALSE, cancellable, error);
if (server != NULL) {
gboolean need_to_expunge;
- success = camel_imapx_server_sync_changes (
- server, folder, cancellable, error);
+ success = camel_imapx_server_sync_changes (server, folder, cancellable, &local_error);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ camel_imapx_store_op_done (istore, server, folder_name);
+
+ g_clear_error (&local_error);
+ g_clear_object (&server);
+
+ server = camel_imapx_store_get_server (istore, folder_name, FALSE, cancellable, &local_error);
+ if (server) {
+ success = camel_imapx_server_sync_changes (server, folder, cancellable, &local_error);
+ }
+ }
if (success) {
success = imapx_move_to_real_junk (
@@ -959,12 +1035,29 @@ imapx_synchronize_sync (CamelFolder *fol
/* Sync twice - make sure deleted flags are written out,
* then sync again incase expunge changed anything */
- if (success && expunge)
- success = camel_imapx_server_expunge (
- server, folder, cancellable, error);
+ if (success && expunge) {
+ success = camel_imapx_server_expunge (server, folder, cancellable, &local_error);
- camel_imapx_store_op_done (istore, server, folder_name);
- g_object_unref (server);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ camel_imapx_store_op_done (istore, server, folder_name);
+
+ g_clear_error (&local_error);
+ g_clear_object (&server);
+
+ server = camel_imapx_store_get_server (istore, folder_name, FALSE, cancellable, &local_error);
+ if (server) {
+ success = camel_imapx_server_expunge (server, folder, cancellable, &local_error);
+ }
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
+ if (server) {
+ camel_imapx_store_op_done (istore, server, folder_name);
+ g_object_unref (server);
+ }
}
return success;
@@ -980,6 +1073,7 @@ imapx_synchronize_message_sync (CamelFol
CamelIMAPXStore *istore;
CamelIMAPXServer *server;
const gchar *folder_name;
+ GError *local_error = NULL;
gboolean success = FALSE;
folder_name = camel_folder_get_full_name (folder);
@@ -995,14 +1089,27 @@ imapx_synchronize_message_sync (CamelFol
}
server = camel_imapx_store_get_server (
- istore, folder_name, cancellable, error);
+ istore, folder_name, FALSE, cancellable, error);
if (server != NULL) {
- success = camel_imapx_server_sync_message (
- server, folder, uid, cancellable, error);
+ success = camel_imapx_server_sync_message (server, folder, uid, cancellable, &local_error);
camel_imapx_store_op_done (istore, server, folder_name);
g_object_unref (server);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, folder_name, FALSE, cancellable, &local_error);
+ if (server != NULL) {
+ success = camel_imapx_server_sync_message (server, folder, uid, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, folder_name);
+ g_object_unref (server);
+ }
+ }
}
+ if (local_error)
+ g_propagate_error (error, local_error);
+
return success;
}
@@ -1019,6 +1126,7 @@ imapx_transfer_messages_to_sync (CamelFo
CamelIMAPXStore *istore;
CamelIMAPXServer *server;
const gchar *folder_name;
+ GError *local_error = NULL;
gboolean success = FALSE;
folder_name = camel_folder_get_full_name (source);
@@ -1034,15 +1142,31 @@ imapx_transfer_messages_to_sync (CamelFo
}
server = camel_imapx_store_get_server (
- istore, folder_name, cancellable, error);
+ istore, folder_name, FALSE, cancellable, error);
if (server != NULL) {
success = camel_imapx_server_copy_message (
server, source, dest, uids,
- delete_originals, cancellable, error);
+ delete_originals, cancellable, &local_error);
camel_imapx_store_op_done (istore, server, folder_name);
g_object_unref (server);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, folder_name, FALSE, cancellable, &local_error);
+ if (server != NULL) {
+ success = camel_imapx_server_copy_message (
+ server, source, dest, uids,
+ delete_originals, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, folder_name);
+ g_object_unref (server);
+ }
+ }
}
+ if (local_error)
+ g_propagate_error (error, local_error);
+
/* update destination folder only if not frozen, to not update
* for each single message transfer during filtering
*/
@@ -1102,6 +1226,7 @@ camel_imapx_folder_class_init (CamelIMAP
folder_class->append_message_sync = imapx_append_message_sync;
folder_class->expunge_sync = imapx_expunge_sync;
folder_class->fetch_messages_sync = imapx_fetch_messages_sync;
+ folder_class->get_message_cached = imapx_get_message_cached;
folder_class->get_message_sync = imapx_get_message_sync;
folder_class->get_quota_info_sync = imapx_get_quota_info_sync;
folder_class->purge_message_cache_sync = imapx_purge_message_cache_sync;
@@ -1238,12 +1363,17 @@ camel_imapx_folder_new (CamelStore *stor
return NULL;
}
+ /* Ensure cache will never expire, otherwise
+ * it causes redownload of messages. */
+ camel_data_cache_set_expire_age (ifolder->cache, -1);
+ camel_data_cache_set_expire_access (ifolder->cache, -1);
+
state_file = g_build_filename (folder_dir, "cmeta", NULL);
camel_object_set_state_filename (CAMEL_OBJECT (folder), state_file);
g_free (state_file);
camel_object_state_read (CAMEL_OBJECT (folder));
- ifolder->search = camel_imapx_search_new ();
+ ifolder->search = camel_imapx_search_new (CAMEL_IMAPX_STORE (store));
g_mutex_init (&ifolder->search_lock);
g_mutex_init (&ifolder->stream_lock);
ifolder->ignore_recent = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
diff -up evolution-data-server-3.8.5/camel/camel-imapx-search.c.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-search.c
--- evolution-data-server-3.8.5/camel/camel-imapx-search.c.imapx-conn-manager-ext 2014-05-13 14:17:43.103983666 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-search.c 2014-05-13 14:17:43.116983665 +0200
@@ -16,6 +16,7 @@
*
*/
+#include "camel-imapx-store.h"
#include "camel-imapx-search.h"
#include "camel-offline-store.h"
@@ -26,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 (
@@ -47,8 +51,8 @@ imapx_search_set_property (GObject *obje
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;
@@ -64,10 +68,10 @@ imapx_search_get_property (GObject *obje
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;
}
@@ -82,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);
@@ -136,31 +140,51 @@ imapx_search_result_match_none (CamelSEx
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);
GPtrArray *uids = NULL;
- GError *error = NULL;
+ GError *local_error = NULL;
+ CamelIMAPXServer *imapx_server;
+ const gchar *folder_name;
+
+ /* 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_get_server (imapx_store, folder_name, TRUE, imapx_search->priv->cancellable, &local_error);
+ if (imapx_server) {
+ uids = camel_imapx_server_uid_search (imapx_server, search->folder, criteria->str, imapx_search->priv->cancellable, &local_error);
+ camel_imapx_store_op_done (imapx_store, imapx_server, folder_name);
+
+ 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_get_server (imapx_store, folder_name, TRUE, imapx_search->priv->cancellable, &local_error);
+ if (imapx_server) {
+ uids = camel_imapx_server_uid_search (imapx_server, search->folder, criteria->str, imapx_search->priv->cancellable, &local_error);
+ camel_imapx_store_op_done (imapx_store, imapx_server, folder_name);
+ }
+ }
+ }
- uids = camel_imapx_server_uid_search (
- server, search->folder, criteria->str, NULL, &error);
+ g_clear_object (&imapx_server);
/* Sanity check. */
g_return_val_if_fail (
- ((uids != NULL) && (error == NULL)) ||
- ((uids == NULL) && (error != NULL)), NULL);
+ ((uids != NULL) && (local_error == NULL)) ||
+ ((uids == NULL) && (local_error != NULL)), NULL);
+
+ if (local_error != NULL) {
+ g_propagate_error (imapx_search->priv->error, local_error);
- /* 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);
+ /* Make like we've got an empty result */
uids = g_ptr_array_new ();
- g_error_free (error);
}
if (search->current != NULL) {
@@ -183,7 +207,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;
@@ -191,9 +215,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)->
@@ -224,7 +248,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)->
@@ -235,7 +259,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_clear_object (&imapx_store);
g_return_val_if_fail (result != NULL, result);
g_return_val_if_fail (result->type == CAMEL_SEXP_RES_ARRAY_PTR, result);
@@ -250,7 +274,7 @@ imapx_search_body_contains (CamelSExp *s
CamelFolderSearch *search)
{
CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
- CamelIMAPXServer *server;
+ CamelIMAPXStore *imapx_store;
CamelSExpResult *result;
GString *criteria;
gint ii, jj;
@@ -269,10 +293,10 @@ imapx_search_body_contains (CamelSExp *s
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);
@@ -320,10 +344,10 @@ imapx_search_body_contains (CamelSExp *s
}
}
- 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;
}
@@ -344,7 +368,7 @@ imapx_search_header_contains (CamelSExp
CamelFolderSearch *search)
{
CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
- CamelIMAPXServer *server;
+ CamelIMAPXStore *imapx_store;
CamelSExpResult *result;
const gchar *headername, *command = NULL;
GString *criteria;
@@ -373,10 +397,10 @@ imapx_search_header_contains (CamelSExp
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);
@@ -440,10 +464,10 @@ imapx_search_header_contains (CamelSExp
}
}
- 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;
}
@@ -455,7 +479,7 @@ imapx_search_header_exists (CamelSExp *s
CamelFolderSearch *search)
{
CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
- CamelIMAPXServer *server;
+ CamelIMAPXStore *imapx_store;
CamelSExpResult *result;
GString *criteria;
gint ii;
@@ -490,10 +514,10 @@ imapx_search_header_exists (CamelSExp *s
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);
@@ -525,10 +549,10 @@ imapx_search_header_exists (CamelSExp *s
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;
}
@@ -554,12 +578,12 @@ camel_imapx_search_class_init (CamelIMAP
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));
}
@@ -573,67 +597,105 @@ camel_imapx_search_init (CamelIMAPXSearc
/**
* 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 -up evolution-data-server-3.8.5/camel/camel-imapx-search.h.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-search.h
--- evolution-data-server-3.8.5/camel/camel-imapx-search.h.imapx-conn-manager-ext 2013-07-23 13:57:45.000000000 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-search.h 2014-05-13 14:17:43.116983665 +0200
@@ -24,7 +24,7 @@
#define CAMEL_IMAPX_SEARCH_H
#include <camel/camel-folder-search.h>
-#include <camel/camel-imapx-server.h>
+#include <camel/camel-imapx-store.h>
/* Standard GObject macros */
#define CAMEL_TYPE_IMAPX_SEARCH \
@@ -47,6 +47,9 @@
G_BEGIN_DECLS
+/* Avoid a circular reference. */
+struct _CamelIMAPXStore;
+
typedef struct _CamelIMAPXSearch CamelIMAPXSearch;
typedef struct _CamelIMAPXSearchClass CamelIMAPXSearchClass;
typedef struct _CamelIMAPXSearchPrivate CamelIMAPXSearchPrivate;
@@ -70,11 +73,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 (struct _CamelIMAPXStore *imapx_store);
+struct _CamelIMAPXStore *
+ camel_imapx_search_ref_store (CamelIMAPXSearch *search);
+void camel_imapx_search_set_store (CamelIMAPXSearch *search,
+ struct _CamelIMAPXStore *imapx_store);
+void camel_imapx_search_set_cancellable_and_error
+ (CamelIMAPXSearch *search,
+ GCancellable *cancellable,
+ GError **error);
G_END_DECLS
diff -up evolution-data-server-3.8.5/camel/camel-imapx-server.c.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-server.c
--- evolution-data-server-3.8.5/camel/camel-imapx-server.c.imapx-conn-manager-ext 2014-05-13 14:17:43.110983665 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-server.c 2014-05-13 14:17:43.118983665 +0200
@@ -73,6 +73,8 @@
#define MAX_COMMAND_LEN 1000
+G_DEFINE_QUARK (camel-imapx-server-error-quark, camel_imapx_server_error)
+
extern gint camel_application_is_exiting;
/* Job-specific structs */
@@ -343,6 +345,14 @@ struct _CamelIMAPXServerPrivate {
GHashTable *known_alerts;
GMutex known_alerts_lock;
+
+ GMutex jobs_prop_lock;
+ GHashTable *jobs_prop_folder_paths;
+ gint jobs_prop_command_count; /* without IDLE command */
+ gint jobs_prop_expensive_command_count;
+
+ GMutex shutdown_error_lock;
+ GError *shutdown_error;
};
enum {
@@ -377,7 +387,6 @@ static gboolean imapx_continuation (Cam
gboolean litplus,
GCancellable *cancellable,
GError **error);
-static gboolean imapx_disconnect (CamelIMAPXServer *is);
static gboolean imapx_is_command_queue_empty (CamelIMAPXServer *is);
static gint imapx_uid_cmp (gconstpointer ap,
gconstpointer bp,
@@ -560,6 +569,159 @@ replace_untagged_descriptor (GHashTable
}
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)
+{
+ CamelIMAPXJob *job;
+
+ g_return_if_fail (command != NULL);
+
+ g_mutex_lock (&imapx_server->priv->jobs_prop_lock);
+
+ job = camel_imapx_command_get_job (command);
+
+ if (job) {
+ /* without IDLE commands */
+ if (!(job->type & IMAPX_JOB_IDLE))
+ imapx_server->priv->jobs_prop_command_count++;
+
+ if ((job->type & (IMAPX_JOB_FETCH_NEW_MESSAGES | IMAPX_JOB_REFRESH_INFO)) != 0)
+ imapx_server->priv->jobs_prop_expensive_command_count++;
+ }
+
+ g_mutex_unlock (&imapx_server->priv->jobs_prop_lock);
+}
+
+static void
+imapx_server_command_removed (CamelIMAPXServer *imapx_server,
+ CamelIMAPXCommand *command)
+{
+ CamelIMAPXJob *job;
+
+ g_return_if_fail (command != NULL);
+
+ g_mutex_lock (&imapx_server->priv->jobs_prop_lock);
+
+ job = camel_imapx_command_get_job (command);
+
+ if (job) {
+ /* without IDLE commands */
+ if (!(job->type & IMAPX_JOB_IDLE)) {
+ imapx_server->priv->jobs_prop_command_count--;
+ g_warn_if_fail (imapx_server->priv->jobs_prop_command_count >= 0);
+ }
+
+ if ((job->type & (IMAPX_JOB_FETCH_NEW_MESSAGES | IMAPX_JOB_REFRESH_INFO)) != 0) {
+ imapx_server->priv->jobs_prop_expensive_command_count--;
+ g_warn_if_fail (imapx_server->priv->jobs_prop_expensive_command_count >= 0);
+ }
+ }
+
+ g_mutex_unlock (&imapx_server->priv->jobs_prop_lock);
+}
+
+static void
+imapx_server_add_job_mailbox (CamelIMAPXServer *imapx_server,
+ const gchar *folder_path)
+{
+ gint n_stored;
+
+ g_return_if_fail (folder_path != NULL);
+
+ g_mutex_lock (&imapx_server->priv->jobs_prop_lock);
+
+ n_stored = GPOINTER_TO_INT (g_hash_table_lookup (imapx_server->priv->jobs_prop_folder_paths, folder_path));
+ g_hash_table_insert (imapx_server->priv->jobs_prop_folder_paths, g_strdup (folder_path), GINT_TO_POINTER (n_stored + 1));
+
+ g_mutex_unlock (&imapx_server->priv->jobs_prop_lock);
+}
+
+static void
+imapx_server_remove_job_mailbox (CamelIMAPXServer *imapx_server,
+ const gchar *folder_path)
+{
+ gint n_stored;
+
+ g_return_if_fail (folder_path != NULL);
+
+ g_mutex_lock (&imapx_server->priv->jobs_prop_lock);
+
+ n_stored = GPOINTER_TO_INT (g_hash_table_lookup (imapx_server->priv->jobs_prop_folder_paths, folder_path));
+ g_warn_if_fail (n_stored >= 1);
+
+ n_stored--;
+ if (n_stored > 0) {
+ g_hash_table_insert (imapx_server->priv->jobs_prop_folder_paths, g_strdup (folder_path), GINT_TO_POINTER (n_stored));
+ } else {
+ g_hash_table_remove (imapx_server->priv->jobs_prop_folder_paths, folder_path);
+ }
+
+ g_mutex_unlock (&imapx_server->priv->jobs_prop_lock);
+}
+
+static void
+imapx_server_job_added (CamelIMAPXServer *imapx_server,
+ CamelIMAPXJob *job)
+{
+ CamelFolder *folder;
+
+ g_return_if_fail (job != NULL);
+
+ folder = camel_imapx_job_ref_folder (job);
+
+ if (folder != NULL) {
+ imapx_server_add_job_mailbox (imapx_server, camel_folder_get_full_name (folder));
+ g_object_unref (folder);
+ }
+}
+
+static void
+imapx_server_job_removed (CamelIMAPXServer *imapx_server,
+ CamelIMAPXJob *job)
+{
+ CamelFolder *folder;
+
+ g_return_if_fail (job != NULL);
+
+ folder = camel_imapx_job_ref_folder (job);
+
+ if (folder != NULL) {
+ imapx_server_remove_job_mailbox (imapx_server, camel_folder_get_full_name (folder));
+ g_object_unref (folder);
+ }
+}
+
+static void
add_initial_untagged_descriptor (GHashTable *untagged_handlers,
guint untagged_id)
{
@@ -582,8 +744,8 @@ static GHashTable *
create_initial_untagged_handler_table (void)
{
GHashTable *uh = g_hash_table_new_full (
- g_str_hash,
- g_str_equal,
+ camel_strcase_hash,
+ camel_strcase_equal,
g_free,
NULL);
guint32 ii = 0;
@@ -833,12 +995,14 @@ imapx_command_start (CamelIMAPXServer *i
{
CamelIMAPXStream *stream = NULL;
CamelIMAPXCommandPart *cp;
+ CamelIMAPXJob *job;
gboolean cp_continuation;
gboolean cp_literal_plus;
GList *head;
gboolean success = FALSE;
gchar *string;
gint retval;
+ GError *local_error = NULL;
camel_imapx_command_close (ic);
@@ -857,6 +1021,14 @@ imapx_command_start (CamelIMAPXServer *i
is->literal = ic;
camel_imapx_command_queue_push_tail (is->active, ic);
+ imapx_server_command_added (is, ic);
+
+ job = camel_imapx_command_get_job (ic);
+ if (job && g_cancellable_set_error_if_cancelled (camel_imapx_job_get_cancellable (job), &local_error)) {
+ camel_imapx_job_set_error (job, local_error);
+ g_clear_error (&local_error);
+ goto err;
+ }
stream = camel_imapx_server_ref_stream (is);
@@ -898,6 +1070,7 @@ imapx_command_start (CamelIMAPXServer *i
err:
camel_imapx_command_queue_remove (is->active, ic);
+ imapx_server_command_removed (is, ic);
/* HACK: Since we're failing, make sure the command has a status
* structure and the result code indicates failure, so the
@@ -1016,6 +1189,7 @@ imapx_command_start_next (CamelIMAPXServ
ic = camel_imapx_command_ref (link->data);
camel_imapx_command_queue_delete_link (is->queue, link);
+ imapx_server_command_removed (is, ic);
success = imapx_command_start (
is, ic, cancellable, error);
@@ -1150,6 +1324,7 @@ imapx_command_start_next (CamelIMAPXServ
ic = camel_imapx_command_ref (link->data);
camel_imapx_command_queue_delete_link (is->queue, link);
+ imapx_server_command_removed (is, ic);
success = imapx_command_start (
is, ic, cancellable, error);
@@ -1223,6 +1398,7 @@ imapx_command_start_next (CamelIMAPXServ
ic = camel_imapx_command_ref (link->data);
camel_imapx_command_queue_delete_link (is->queue, link);
+ imapx_server_command_removed (is, ic);
success = imapx_command_start (
is, ic, cancellable, error);
@@ -1279,7 +1455,7 @@ imapx_command_queue (CamelIMAPXServer *i
if (is->state == IMAPX_SHUTDOWN) {
c (is->tagprefix, "refuse to queue job on disconnected server\n");
g_set_error (
- error, CAMEL_IMAPX_ERROR, 1,
+ error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT,
"%s", _("Server disconnected"));
QUEUE_UNLOCK (is);
@@ -1294,6 +1470,7 @@ imapx_command_queue (CamelIMAPXServer *i
}
camel_imapx_command_queue_insert_sorted (is->queue, ic);
+ imapx_server_command_added (is, ic);
success = imapx_command_start_next (is, cancellable, error);
@@ -1376,38 +1553,34 @@ imapx_match_active_job (CamelIMAPXServer
return match;
}
+/* Do *not* call this when the queue_lock is held, it can cause
+ deadlock when searching between multiple servers */
static CamelIMAPXJob *
-imapx_is_job_in_queue (CamelIMAPXServer *is,
- CamelFolder *folder,
- guint32 type,
- const gchar *uid)
+imapx_server_ref_job (CamelIMAPXServer *imapx_server,
+ CamelFolder *folder,
+ guint32 job_type,
+ const gchar *uid)
{
- GList *head, *link;
- CamelIMAPXJob *job = NULL;
- gboolean found = FALSE;
-
- QUEUE_LOCK (is);
+ CamelIMAPXStore *imapx_store;
+ CamelIMAPXJob *job;
- head = g_queue_peek_head_link (&is->jobs);
+ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (imapx_server), NULL);
- for (link = head; link != NULL; link = g_list_next (link)) {
- job = (CamelIMAPXJob *) link->data;
+ /* first try its own queue */
+ job = camel_imapx_server_ref_job (imapx_server, folder, job_type, uid);
+ if (job)
+ return job;
- if (!job || !(job->type & type))
- continue;
+ /* then try queue for all the opened servers */
+ imapx_store = camel_imapx_server_ref_store (imapx_server);
+ if (!imapx_store)
+ return NULL;
- if (camel_imapx_job_matches (job, folder, uid)) {
- found = TRUE;
- break;
- }
- }
+ job = camel_imapx_store_ref_job (imapx_store, folder, job_type, uid);
- QUEUE_UNLOCK (is);
+ g_object_unref (imapx_store);
- if (found)
- return job;
- else
- return NULL;
+ return job;
}
static void
@@ -1867,8 +2040,8 @@ imapx_untagged_fetch (CamelIMAPXServer *
is->changes = camel_folder_change_info_new ();
camel_folder_change_info_change_uid (is->changes, uid);
- g_free (uid);
}
+ g_free (uid);
if (imapx_idle_supported (is) && changed && imapx_in_idle (is)) {
camel_folder_summary_save_to_db (
@@ -2313,9 +2486,6 @@ imapx_untagged_bye (CamelIMAPXServer *is
GCancellable *cancellable,
GError **error)
{
- CamelIMAPXStore *imapx_store;
- CamelService *service;
- CamelServiceConnectionStatus status;
guchar *token = NULL;
g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE);
@@ -2325,7 +2495,7 @@ imapx_untagged_bye (CamelIMAPXServer *is
if (camel_imapx_stream_text (stream, &token, cancellable, NULL)) {
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);
}
@@ -2333,19 +2503,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;
}
@@ -2399,10 +2556,16 @@ imapx_untagged_ok_no_bad (CamelIMAPXServ
select_folder = g_weak_ref_get (&is->select_folder);
select_pending = g_weak_ref_get (&is->select_pending);
- if (select_folder == NULL)
+ if (select_folder)
+ imapx_server_remove_job_mailbox (is, camel_folder_get_full_name (select_folder));
+
+ if (select_folder == NULL) {
g_weak_ref_set (
&is->select_folder,
select_pending);
+ if (select_pending)
+ imapx_server_add_job_mailbox (is, camel_folder_get_full_name (select_pending));
+ }
g_clear_object (&select_folder);
g_clear_object (&select_pending);
@@ -2849,6 +3012,7 @@ imapx_completion (CamelIMAPXServer *is,
camel_imapx_command_ref (ic);
camel_imapx_command_queue_remove (is->active, ic);
+ imapx_server_command_removed (is, ic);
camel_imapx_command_queue_push_tail (is->done, ic);
camel_imapx_command_unref (ic);
@@ -3058,10 +3222,18 @@ imapx_register_job (CamelIMAPXServer *is
if (is->state >= IMAPX_INITIALISED) {
QUEUE_LOCK (is);
g_queue_push_head (&is->jobs, camel_imapx_job_ref (job));
+ imapx_server_job_added (is, job);
QUEUE_UNLOCK (is);
+ } else if (is->state <= IMAPX_SHUTDOWN) {
+ e (is->tagprefix, "Server is shutdown/disconnected, try reconnect.");
+ g_set_error (error,
+ CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT,
+ _("Not authenticated"));
+ return FALSE;
+
} else {
- e (is->tagprefix, "NO connection yet, maybe user cancelled jobs earlier ?");
+ e (is->tagprefix, "Not connected yet, maybe user cancelled jobs earlier?");
g_set_error (
error, CAMEL_SERVICE_ERROR,
CAMEL_SERVICE_ERROR_NOT_CONNECTED,
@@ -3080,8 +3252,10 @@ imapx_unregister_job (CamelIMAPXServer *
camel_imapx_job_done (job);
QUEUE_LOCK (is);
- if (g_queue_remove (&is->jobs, job))
+ if (g_queue_remove (&is->jobs, job)) {
+ imapx_server_job_removed (is, job);
camel_imapx_job_unref (job);
+ }
QUEUE_UNLOCK (is);
}
@@ -3152,6 +3326,7 @@ imapx_command_idle_done (CamelIMAPXServe
IDLE_UNLOCK (idle);
imapx_unregister_job (is, job);
+
camel_imapx_command_unref (ic);
return success;
@@ -3347,8 +3522,11 @@ imapx_idle_thread (gpointer data)
break;
}
+ IDLE_LOCK (is->idle);
g_clear_error (&local_error);
is->idle->idle_thread = NULL;
+ IDLE_UNLOCK (is->idle);
+
return NULL;
}
@@ -3521,6 +3699,11 @@ imapx_command_select_done (CamelIMAPXSer
c (is->tagprefix, "Select failed\n");
g_mutex_lock (&is->select_lock);
+ folder = g_weak_ref_get (&is->select_folder);
+ if (folder) {
+ imapx_server_remove_job_mailbox (is, camel_folder_get_full_name (folder));
+ g_object_unref (folder);
+ }
folder = g_weak_ref_get (&is->select_pending);
g_weak_ref_set (&is->select_folder, NULL);
g_weak_ref_set (&is->select_pending, NULL);
@@ -3548,7 +3731,9 @@ imapx_command_select_done (CamelIMAPXSer
while ((link = g_queue_pop_head (&trash)) != NULL) {
CamelIMAPXCommand *cw = link->data;
+ camel_imapx_command_ref (cw);
camel_imapx_command_queue_delete_link (is->queue, link);
+ imapx_server_command_removed (is, cw);
g_queue_push_tail (&failed, cw);
}
@@ -3563,6 +3748,7 @@ imapx_command_select_done (CamelIMAPXSer
if (!CAMEL_IS_IMAPX_JOB (job)) {
g_warn_if_reached ();
+ camel_imapx_command_unref (cw);
continue;
}
@@ -3572,6 +3758,7 @@ imapx_command_select_done (CamelIMAPXSer
cw->status = imapx_copy_status (ic->status);
cw->complete (is, cw, NULL, NULL);
+ camel_imapx_command_unref (cw);
}
g_propagate_error (error, local_error);
@@ -3601,22 +3788,16 @@ imapx_command_select_done (CamelIMAPXSer
/* We don't want to fetch new messages if the command we selected this
* folder for is *already* fetching all messages (i.e. scan_changes).
* Bug #667725. */
- CamelIMAPXJob *job = imapx_is_job_in_queue (
+ CamelIMAPXJob *job = imapx_server_ref_job (
is, folder, IMAPX_JOB_REFRESH_INFO, NULL);
if (job) {
- RefreshInfoData *data = camel_imapx_job_get_data (job);
-
- if (data->scan_changes) {
- c (is->tagprefix, "Will not fetch_new_messages when already in scan_changes\n");
- goto no_fetch_new;
- }
+ camel_imapx_job_unref (job);
+ c (
+ is->tagprefix,
+ "Will not fetch_new_messages when already refreshing information\n");
+ } else {
+ imapx_server_fetch_new_messages (is, folder, TRUE, TRUE, NULL, NULL);
}
- imapx_server_fetch_new_messages (is, folder, TRUE, TRUE, NULL, NULL);
- /* We don't do this right now because we want the new messages to
- * update the unseen count. */
- //ifolder->uidnext_on_server = is->uidnext;
- no_fetch_new:
- ;
}
ifolder->uidvalidity_on_server = is->uidvalidity;
selected_folder = camel_folder_get_full_name (folder);
@@ -3638,6 +3819,9 @@ imapx_command_select_done (CamelIMAPXSer
camel_imapx_command_unref (ic);
+ if (selected_folder)
+ imapx_server_add_job_mailbox (is, selected_folder);
+
g_signal_emit (is, signals[SELECT_CHANGED], 0, selected_folder);
return success;
@@ -4132,7 +4316,7 @@ camel_imapx_server_authenticate (CamelIM
g_return_val_if_fail (
CAMEL_IS_IMAPX_SERVER (is),
- CAMEL_AUTHENTICATION_REJECTED);
+ CAMEL_AUTHENTICATION_ERROR);
store = camel_imapx_server_ref_store (is);
@@ -4202,8 +4386,27 @@ camel_imapx_server_authenticate (CamelIM
result = CAMEL_AUTHENTICATION_ERROR;
else if (ic->status->result == IMAPX_OK)
result = CAMEL_AUTHENTICATION_ACCEPTED;
- else
- result = CAMEL_AUTHENTICATION_REJECTED;
+ else if (ic->status->result == IMAPX_NO) {
+ if (camel_imapx_store_get_authenticating_concurrent_connection (store)) {
+ /* At least one connection succeeded, probably max connection limit
+ set on the server had been reached, thus use special error code
+ for it, to instruct the connection manager to decrease the limit
+ and use already created connection. */
+ g_set_error_literal (
+ error, CAMEL_IMAPX_SERVER_ERROR,
+ CAMEL_IMAPX_SERVER_ERROR_CONCURRENT_CONNECT_FAILED,
+ ic->status->text ? ic->status->text : _("Unknown error"));
+ result = CAMEL_AUTHENTICATION_ERROR;
+ } else {
+ result = CAMEL_AUTHENTICATION_REJECTED;
+ }
+ } else {
+ g_set_error_literal (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ ic->status->text ? ic->status->text : _("Unknown error"));
+ result = CAMEL_AUTHENTICATION_ERROR;
+ }
/* Forget old capabilities after login. */
if (result == CAMEL_AUTHENTICATION_ACCEPTED) {
@@ -4348,7 +4551,7 @@ imapx_reconnect (CamelIMAPXServer *is,
exception:
- imapx_disconnect (is);
+ camel_imapx_server_disconnect (is);
if (is->cinfo) {
imapx_free_capability (is->cinfo);
@@ -4457,6 +4660,13 @@ imapx_command_fetch_message_done (CamelI
_("Failed to close the tmp stream"));
}
+ if (success && g_cancellable_set_error_if_cancelled (cancellable, error)) {
+ success = FALSE;
+ g_prefix_error (
+ error, "%s: ",
+ _("Error fetching message"));
+ }
+
if (success) {
gchar *cur_filename;
gchar *tmp_filename;
@@ -5488,7 +5698,6 @@ imapx_job_fetch_new_messages_start (Came
_("Fetching summary information for new messages in '%s'"),
camel_folder_get_display_name (folder));
- //printf ("Fetch order: %d/%d\n", fetch_order, CAMEL_SORT_DESCENDING);
if (diff > uidset_size || fetch_order == CAMEL_SORT_DESCENDING) {
ic = camel_imapx_command_new (
is, "FETCH", folder,
@@ -6837,7 +7046,7 @@ imapx_job_sync_changes_matches (CamelIMA
/* we cancel all the commands and their jobs, so associated jobs will be notified */
static void
cancel_all_jobs (CamelIMAPXServer *is,
- GError *error)
+ const GError *error)
{
CamelIMAPXCommandQueue *queue;
GList *head, *link;
@@ -6847,11 +7056,21 @@ cancel_all_jobs (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);
camel_imapx_command_queue_transfer (is->active, queue);
+ head = camel_imapx_command_queue_peek_head_link (queue);
+ for (link = head; link != NULL; link = g_list_next (link)) {
+ CamelIMAPXCommand *ic = link->data;
+
+ if (ic)
+ imapx_server_command_removed (is, ic);
+ }
+
QUEUE_UNLOCK (is);
head = camel_imapx_command_queue_peek_head_link (queue);
@@ -6871,7 +7090,14 @@ cancel_all_jobs (CamelIMAPXServer *is,
if (!CAMEL_IS_IMAPX_JOB (job))
continue;
- camel_imapx_job_cancel (job);
+ if (error) {
+ /* Insert an error into the CamelIMAPXCommand to be
+ * propagated when the completion callback function
+ * calls camel_imapx_command_set_error_if_failed(). */
+ camel_imapx_job_set_error (job, error);
+ } else {
+ camel_imapx_job_cancel (job);
+ }
/* Send a NULL GError since we already cancelled
* the job and we're not interested in individual
@@ -6916,6 +7142,7 @@ imapx_parser_thread (gpointer d)
GCancellable *cancellable;
gboolean have_stream;
GError *local_error = NULL;
+ GError *shutdown_error;
QUEUE_LOCK (is);
/* Do not use CamelOperation here, because it can be cancelled at
@@ -6991,8 +7218,28 @@ imapx_parser_thread (gpointer d)
}
/* Jump out of the loop if an error occurred. */
- if (local_error != NULL)
+ 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);
+
break;
+ }
stream = camel_imapx_server_ref_stream (is);
if (stream != NULL) {
@@ -7020,7 +7267,12 @@ imapx_parser_thread (gpointer d)
QUEUE_UNLOCK (is);
is->parser_quit = FALSE;
- 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);
@@ -7103,7 +7355,7 @@ imapx_server_dispose (GObject *object)
if (server->cinfo && imapx_idle_supported (server))
imapx_exit_idle (server);
- imapx_disconnect (server);
+ camel_imapx_server_disconnect (server);
g_weak_ref_set (&server->priv->store, NULL);
@@ -7141,6 +7393,12 @@ imapx_server_finalize (GObject *object)
g_hash_table_destroy (is->priv->known_alerts);
g_mutex_clear (&is->priv->known_alerts_lock);
+ 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);
}
@@ -7216,6 +7474,7 @@ camel_imapx_server_class_init (CamelIMAP
/**
* 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",
@@ -7223,8 +7482,8 @@ camel_imapx_server_class_init (CamelIMAP
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';
}
@@ -7239,6 +7498,12 @@ camel_imapx_server_init (CamelIMAPXServe
g_mutex_init (&is->priv->stream_lock);
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;
+ is->priv->jobs_prop_expensive_command_count = 0;
is->queue = camel_imapx_command_queue_new ();
is->active = camel_imapx_command_queue_new ();
@@ -7259,6 +7524,8 @@ camel_imapx_server_init (CamelIMAPXServe
is->changes = camel_folder_change_info_new ();
is->parser_quit = FALSE;
+ is->priv->shutdown_error = NULL;
+
is->priv->known_alerts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
}
@@ -7312,11 +7579,23 @@ camel_imapx_server_ref_stream (CamelIMAP
return stream;
}
-static gboolean
-imapx_disconnect (CamelIMAPXServer *is)
+gboolean
+camel_imapx_server_disconnect (CamelIMAPXServer *is)
{
gboolean ret = TRUE;
+ /*QUEUE_LOCK (is);
+ is->state = IMAPX_SHUTDOWN;
+
+ is->parser_quit = TRUE;
+
+ if (is->cancellable != NULL) {
+ g_cancellable_cancel (is->cancellable);
+ g_object_unref (is->cancellable);
+ is->cancellable = NULL;
+ }
+ QUEUE_UNLOCK (is);*/
+
g_mutex_lock (&is->priv->stream_lock);
if (is->priv->stream != NULL) {
@@ -7387,18 +7666,15 @@ imapx_server_get_message (CamelIMAPXServ
gboolean registered;
gboolean success;
- QUEUE_LOCK (is);
-
- if ((job = imapx_is_job_in_queue (is, folder, IMAPX_JOB_GET_MESSAGE, uid))) {
+ if ((job = imapx_server_ref_job (is, folder, IMAPX_JOB_GET_MESSAGE, uid))) {
/* Promote the existing GET_MESSAGE
* job's priority if ours is higher. */
if (pri > job->pri)
job->pri = pri;
- QUEUE_UNLOCK (is);
-
/* Wait for the job to finish. */
camel_imapx_job_wait (job);
+ camel_imapx_job_unref (job);
/* Disregard errors here. If we failed to retreive the
* message from cache (implying the job we were waiting
@@ -7407,10 +7683,10 @@ imapx_server_get_message (CamelIMAPXServ
ifolder->cache, "cur", uid, NULL);
if (stream != NULL)
return stream;
-
- QUEUE_LOCK (is);
}
+ QUEUE_LOCK (is);
+
mi = camel_folder_summary_get (folder->summary, uid);
if (!mi) {
g_set_error (
@@ -7700,15 +7976,17 @@ camel_imapx_server_refresh_info (CamelIM
full_name = camel_folder_get_full_name (folder);
- QUEUE_LOCK (is);
-
/* Both RefreshInfo and Fetch messages can't operate simultaneously */
- if (imapx_is_job_in_queue (is, folder, IMAPX_JOB_REFRESH_INFO, NULL) ||
- imapx_is_job_in_queue (is, folder, IMAPX_JOB_FETCH_MESSAGES, NULL)) {
- QUEUE_UNLOCK (is);
+ job = imapx_server_ref_job (is, folder, IMAPX_JOB_REFRESH_INFO, NULL);
+ if (!job)
+ job = imapx_server_ref_job (is, folder, IMAPX_JOB_FETCH_MESSAGES, NULL);
+ if (job) {
+ camel_imapx_job_unref (job);
return TRUE;
}
+ QUEUE_LOCK (is);
+
data = g_slice_new0 (RefreshInfoData);
data->changes = camel_folder_change_info_new ();
@@ -7963,13 +8241,11 @@ imapx_server_sync_changes (CamelIMAPXSer
/* TODO above code should go into changes_start */
- QUEUE_LOCK (is);
-
- if ((job = imapx_is_job_in_queue (is, folder, IMAPX_JOB_SYNC_CHANGES, NULL))) {
+ if ((job = imapx_server_ref_job (is, folder, IMAPX_JOB_SYNC_CHANGES, NULL))) {
if (pri > job->pri)
job->pri = pri;
- QUEUE_UNLOCK (is);
+ camel_imapx_job_unref (job);
imapx_sync_free_user (on_user);
imapx_sync_free_user (off_user);
@@ -7977,6 +8253,8 @@ imapx_server_sync_changes (CamelIMAPXSer
return TRUE;
}
+ QUEUE_LOCK (is);
+
data = g_slice_new0 (SyncChangesData);
data->folder = g_object_ref (folder);
data->changed_uids = changed_uids; /* takes ownership */
@@ -8036,13 +8314,15 @@ camel_imapx_server_expunge (CamelIMAPXSe
gboolean success;
/* Do we really care to wait for this one to finish? */
- QUEUE_LOCK (is);
- if (imapx_is_job_in_queue (is, folder, IMAPX_JOB_EXPUNGE, NULL)) {
- QUEUE_UNLOCK (is);
+ job = imapx_server_ref_job (is, folder, IMAPX_JOB_EXPUNGE, NULL);
+ if (job) {
+ camel_imapx_job_unref (job);
return TRUE;
}
+ QUEUE_LOCK (is);
+
job = camel_imapx_job_new (cancellable);
job->type = IMAPX_JOB_EXPUNGE;
job->start = imapx_job_expunge_start;
@@ -8270,15 +8550,17 @@ camel_imapx_server_fetch_messages (Camel
firstuid = strtoull (uid, NULL, 10);
g_free (uid);
- QUEUE_LOCK (is);
-
/* Both RefreshInfo and Fetch messages can't operate simultaneously */
- if (imapx_is_job_in_queue (is, folder, IMAPX_JOB_REFRESH_INFO, NULL) ||
- imapx_is_job_in_queue (is, folder, IMAPX_JOB_FETCH_MESSAGES, NULL)) {
- QUEUE_UNLOCK (is);
+ job = imapx_server_ref_job (is, folder, IMAPX_JOB_REFRESH_INFO, NULL);
+ if (!job)
+ job = imapx_server_ref_job (is, folder, IMAPX_JOB_FETCH_MESSAGES, NULL);
+ if (job) {
+ camel_imapx_job_unref (job);
return TRUE;
}
+ QUEUE_LOCK (is);
+
data = g_slice_new0 (RefreshInfoData);
data->changes = camel_folder_change_info_new ();
data->fetch_msg_limit = limit;
@@ -8450,55 +8732,54 @@ camel_imapx_server_uid_search (CamelIMAP
return results;
}
-IMAPXJobQueueInfo *
-camel_imapx_server_get_job_queue_info (CamelIMAPXServer *is)
+gboolean
+camel_imapx_server_folder_name_in_jobs (CamelIMAPXServer *imapx_server,
+ const gchar *folder_path)
{
- IMAPXJobQueueInfo *jinfo = g_new0 (IMAPXJobQueueInfo, 1);
- CamelFolder *select_folder;
- CamelIMAPXJob *job = NULL;
- GList *head, *link;
+ gboolean res;
- QUEUE_LOCK (is);
+ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (imapx_server), FALSE);
+ g_return_val_if_fail (folder_path != NULL, FALSE);
- jinfo->queue_len = g_queue_get_length (&is->jobs);
- jinfo->folders = g_hash_table_new_full (
- (GHashFunc) g_str_hash,
- (GEqualFunc) g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) NULL);
+ g_mutex_lock (&imapx_server->priv->jobs_prop_lock);
- head = g_queue_peek_head_link (&is->jobs);
+ res = GPOINTER_TO_INT (g_hash_table_lookup (imapx_server->priv->jobs_prop_folder_paths, folder_path)) > 0;
- for (link = head; link != NULL; link = g_list_next (link)) {
- CamelFolder *folder;
+ g_mutex_unlock (&imapx_server->priv->jobs_prop_lock);
- job = (CamelIMAPXJob *) link->data;
- folder = camel_imapx_job_ref_folder (job);
+ return res;
+}
- if (folder != NULL) {
- gchar *folder_name;
+gboolean
+camel_imapx_server_has_expensive_command (CamelIMAPXServer *imapx_server)
+{
+ gboolean res;
- folder_name = camel_folder_dup_full_name (folder);
- g_hash_table_add (jinfo->folders, folder_name);
+ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (imapx_server), FALSE);
- g_object_unref (folder);
- }
- }
+ g_mutex_lock (&imapx_server->priv->jobs_prop_lock);
- select_folder = g_weak_ref_get (&is->select_folder);
+ res = imapx_server->priv->jobs_prop_expensive_command_count > 0;
- if (select_folder != NULL) {
- gchar *folder_name;
+ g_mutex_unlock (&imapx_server->priv->jobs_prop_lock);
- folder_name = camel_folder_dup_full_name (select_folder);
- g_hash_table_add (jinfo->folders, folder_name);
+ return res;
+}
- g_object_unref (select_folder);
- }
+gint
+camel_imapx_server_get_command_count (CamelIMAPXServer *imapx_server)
+{
+ guint32 res;
- QUEUE_UNLOCK (is);
+ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (imapx_server), -1);
+
+ g_mutex_lock (&imapx_server->priv->jobs_prop_lock);
- return jinfo;
+ res = imapx_server->priv->jobs_prop_command_count;
+
+ g_mutex_unlock (&imapx_server->priv->jobs_prop_lock);
+
+ return res;
}
/**
@@ -8575,3 +8856,108 @@ camel_imapx_server_command_run (CamelIMA
return ok;
}
+
+/**
+ * camel_imapx_server_is_job_in_queue:
+ * @imapx_server: a #CamelIMAPXServer instance
+ * @folder: a folder to search job for
+ * @job_type: a job type specifier to search for
+ * @uid: optional message UID for which the job might be searched
+ *
+ * Searches queue of jobs for the particular job. The returned job
+ * is referenced for thread safety, unref it with camel_imapx_job_unref().
+ *
+ * Returns: %NULL, if such job could not be found, or a referenced job.
+ **/
+CamelIMAPXJob *
+camel_imapx_server_ref_job (CamelIMAPXServer *imapx_server,
+ CamelFolder *folder,
+ guint32 job_type,
+ const gchar *uid)
+{
+ GList *head, *link;
+ CamelIMAPXJob *job = NULL;
+ gboolean found = FALSE;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (imapx_server), NULL);
+
+ QUEUE_LOCK (imapx_server);
+
+ head = g_queue_peek_head_link (&imapx_server->jobs);
+
+ for (link = head; link != NULL; link = g_list_next (link)) {
+ job = (CamelIMAPXJob *) link->data;
+
+ if (!job || !(job->type & job_type))
+ continue;
+
+ if (camel_imapx_job_matches (job, folder, uid)) {
+ found = TRUE;
+ camel_imapx_job_ref (job);
+ break;
+ }
+ }
+
+ QUEUE_UNLOCK (imapx_server);
+
+ return found ? job : NULL;
+}
+
+/**
+ * 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->parser_quit = TRUE;
+ is->state = IMAPX_SHUTDOWN;
+
+ if (is->cancellable)
+ cancellable = g_object_ref (is->cancellable);
+ else
+ cancellable = NULL;
+
+ QUEUE_UNLOCK (is);
+
+ if (!error) {
+ shutdown_error_copy = imapx_server_dup_shutdown_error (is);
+ error = shutdown_error_copy;
+ }
+
+ if (error) {
+ cancel_all_jobs (is, error);
+ } else {
+ GError *local_error = NULL;
+
+ g_set_error (
+ &local_error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_UNAVAILABLE,
+ "Shutting down");
+
+ cancel_all_jobs (is, local_error);
+
+ g_clear_error (&local_error);
+ }
+
+ if (cancellable)
+ g_cancellable_cancel (cancellable);
+ g_clear_object (&cancellable);
+ g_clear_error (&shutdown_error_copy);
+}
diff -up evolution-data-server-3.8.5/camel/camel-imapx-server.h.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-server.h
--- evolution-data-server-3.8.5/camel/camel-imapx-server.h.imapx-conn-manager-ext 2013-07-23 13:57:54.000000000 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-server.h 2014-05-13 14:17:43.118983665 +0200
@@ -53,18 +53,27 @@
#define IMAPX_MODE_READ (1 << 0)
#define IMAPX_MODE_WRITE (1 << 1)
+#define CAMEL_IMAPX_SERVER_ERROR (camel_imapx_server_error_quark ())
+
G_BEGIN_DECLS
+typedef enum {
+ CAMEL_IMAPX_SERVER_ERROR_CONCURRENT_CONNECT_FAILED,
+ CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT
+} CamelIMAPXServerError;
+
+GQuark camel_imapx_server_error_quark (void) G_GNUC_CONST;
+
/* Avoid a circular reference. */
struct _CamelIMAPXStore;
struct _CamelIMAPXSettings;
+struct _CamelIMAPXJob;
typedef struct _CamelIMAPXServer CamelIMAPXServer;
typedef struct _CamelIMAPXServerClass CamelIMAPXServerClass;
typedef struct _CamelIMAPXServerPrivate CamelIMAPXServerPrivate;
typedef struct _CamelIMAPXIdle CamelIMAPXIdle;
-struct _IMAPXJobQueueInfo;
/* untagged response handling */
typedef gboolean
@@ -167,7 +176,8 @@ struct _CamelIMAPXServerClass {
/* Signals */
void (*select_changed) (CamelIMAPXServer *is,
const gchar *selected_folder);
- void (*shutdown) (CamelIMAPXServer *is);
+ void (*shutdown) (CamelIMAPXServer *is,
+ const GError *error);
gchar tagprefix;
};
@@ -184,6 +194,9 @@ CamelIMAPXStream *
gboolean camel_imapx_server_connect (CamelIMAPXServer *is,
GCancellable *cancellable,
GError **error);
+gboolean camel_imapx_server_disconnect (CamelIMAPXServer *is);
+void camel_imapx_server_shutdown (CamelIMAPXServer *is,
+ const GError *error);
gboolean imapx_connect_to_server (CamelIMAPXServer *is,
GCancellable *cancellable,
GError **error);
@@ -278,9 +291,13 @@ GPtrArray * camel_imapx_server_uid_searc
const gchar *criteria,
GCancellable *cancellable,
GError **error);
-struct _IMAPXJobQueueInfo *
- camel_imapx_server_get_job_queue_info
- (CamelIMAPXServer *is);
+gboolean camel_imapx_server_folder_name_in_jobs
+ (CamelIMAPXServer *imapx_server,
+ const gchar *folder_path);
+gboolean camel_imapx_server_has_expensive_command
+ (CamelIMAPXServer *imapx_server);
+gint camel_imapx_server_get_command_count
+ (CamelIMAPXServer *imapx_server);
const CamelIMAPXUntaggedRespHandlerDesc *
camel_imapx_server_register_untagged_handler
(CamelIMAPXServer *is,
@@ -290,6 +307,11 @@ gboolean camel_imapx_server_command_run
CamelIMAPXCommand *ic,
GCancellable *cancellable,
GError **error);
+struct _CamelIMAPXJob *
+ camel_imapx_server_ref_job (CamelIMAPXServer *imapx_server,
+ CamelFolder *folder,
+ guint32 job_type,
+ const gchar *uid);
G_END_DECLS
diff -up evolution-data-server-3.8.5/camel/camel-imapx-settings.c.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-settings.c
--- evolution-data-server-3.8.5/camel/camel-imapx-settings.c.imapx-conn-manager-ext 2013-07-23 13:57:50.000000000 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-settings.c 2014-05-13 14:17:43.118983665 +0200
@@ -516,7 +516,7 @@ camel_imapx_settings_class_init (CamelIM
"Number of concurrent IMAP connections to use",
MIN_CONCURRENT_CONNECTIONS,
MAX_CONCURRENT_CONNECTIONS,
- 5,
+ 3,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
diff -up evolution-data-server-3.8.5/camel/camel-imapx-store.c.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-store.c
--- evolution-data-server-3.8.5/camel/camel-imapx-store.c.imapx-conn-manager-ext 2014-05-13 14:17:43.114983665 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-store.c 2014-05-13 14:17:43.119983665 +0200
@@ -40,6 +40,7 @@
#include <glib/gi18n-lib.h>
#include "camel-imapx-folder.h"
+#include "camel-imapx-job.h"
#include "camel-imapx-server.h"
#include "camel-imapx-settings.h"
#include "camel-imapx-store.h"
@@ -59,6 +60,7 @@
struct _CamelIMAPXStorePrivate {
GHashTable *quota_info;
GMutex quota_info_lock;
+ gboolean is_concurrent_connection;
};
enum {
@@ -260,11 +262,12 @@ imapx_get_name (CamelService *service,
CamelIMAPXServer *
camel_imapx_store_get_server (CamelIMAPXStore *istore,
const gchar *folder_name,
+ gboolean for_expensive_job,
GCancellable *cancellable,
GError **error)
{
return camel_imapx_conn_manager_get_connection (
- istore->con_man, folder_name, cancellable, error);
+ istore->con_man, folder_name, for_expensive_job, cancellable, error);
}
void
@@ -286,7 +289,7 @@ imapx_connect_sync (CamelService *servic
CamelIMAPXStore *istore = (CamelIMAPXStore *) service;
CamelIMAPXServer *server;
- server = camel_imapx_store_get_server (istore, NULL, cancellable, error);
+ server = camel_imapx_store_get_server (istore, NULL, FALSE, cancellable, error);
if (server) {
g_object_unref (server);
return TRUE;
@@ -309,7 +312,7 @@ imapx_disconnect_sync (CamelService *ser
res = service_class->disconnect_sync (service, clean, cancellable, error);
if (istore->con_man != NULL)
- camel_imapx_conn_manager_close_connections (istore->con_man);
+ camel_imapx_conn_manager_close_connections (istore->con_man, NULL);
return res;
}
@@ -333,7 +336,7 @@ imapx_authenticate_sync (CamelService *s
g_return_val_if_fail (
CAMEL_IS_IMAPX_SERVER (server),
- CAMEL_AUTHENTICATION_REJECTED);
+ CAMEL_AUTHENTICATION_ERROR);
return camel_imapx_server_authenticate (
server, mechanism, cancellable, error);
@@ -657,22 +660,35 @@ imapx_subscribe_folder (CamelStore *stor
{
CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
CamelIMAPXServer *server;
+ GError *local_error = NULL;
gboolean success;
if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
return TRUE;
- server = camel_imapx_store_get_server (istore, NULL, cancellable, error);
+ server = camel_imapx_store_get_server (istore, NULL, FALSE, cancellable, error);
if (!server)
return FALSE;
if (folder_name && *folder_name == '/')
folder_name++;
- success = camel_imapx_server_manage_subscription (
- server, folder_name, TRUE, cancellable, error);
+ success = camel_imapx_server_manage_subscription (server, folder_name, TRUE, cancellable, &local_error);
g_object_unref (server);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, NULL, FALSE, cancellable, &local_error);
+ if (server) {
+ success = camel_imapx_server_manage_subscription (server, folder_name, TRUE, cancellable, &local_error);
+ g_object_unref (server);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
if (success)
imapx_mark_folder_subscribed (istore, folder_name, emit_signal);
@@ -688,22 +704,35 @@ imapx_unsubscribe_folder (CamelStore *st
{
CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
CamelIMAPXServer *server;
+ GError *local_error = NULL;
gboolean success;
if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
return TRUE;
- server = camel_imapx_store_get_server (istore, NULL, cancellable, error);
+ server = camel_imapx_store_get_server (istore, NULL, FALSE, cancellable, error);
if (!server)
return FALSE;
if (folder_name && *folder_name == '/')
folder_name++;
- success = camel_imapx_server_manage_subscription (
- server, folder_name, FALSE, cancellable, error);
+ success = camel_imapx_server_manage_subscription (server, folder_name, FALSE, cancellable, &local_error);
g_object_unref (server);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, NULL, FALSE, cancellable, &local_error);
+ if (server) {
+ success = camel_imapx_server_manage_subscription (server, folder_name, FALSE, cancellable, &local_error);
+ g_object_unref (server);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
if (success)
imapx_unmark_folder_subscribed (istore, folder_name, emit_signal);
@@ -1012,9 +1041,23 @@ fetch_folders_for_pattern (CamelIMAPXSto
GPtrArray *folders;
GError *local_error = NULL;
+ g_object_ref (server);
+
folders = camel_imapx_server_list (
server, pattern, flags, ext, cancellable, &local_error);
- if (folders == NULL || local_error) {
+
+ while (!folders && 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_get_server (istore, NULL, FALSE, cancellable, &local_error);
+ if (server)
+ folders = camel_imapx_server_list (server, pattern, flags, ext, cancellable, &local_error);
+ }
+
+ if (folders == NULL || local_error || !server) {
+ g_clear_object (&server);
+
if (local_error)
g_propagate_error (error, local_error);
return FALSE;
@@ -1022,6 +1065,8 @@ fetch_folders_for_pattern (CamelIMAPXSto
add_folders_to_summary (istore, server, folders, table, (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED));
+ g_clear_object (&server);
+
g_ptr_array_foreach (folders, free_list, folders);
g_ptr_array_free (folders, TRUE);
@@ -1057,7 +1102,7 @@ fetch_folders_for_namespaces (CamelIMAPX
GHashTable *folders = NULL;
GList *namespaces = NULL, *l;
- server = camel_imapx_store_get_server (istore, NULL, cancellable, error);
+ server = camel_imapx_store_get_server (istore, NULL, FALSE, cancellable, error);
if (!server)
return NULL;
@@ -1581,6 +1626,7 @@ imapx_store_create_folder_sync (CamelSto
gchar *real_name, *full_name, *parent_real;
CamelFolderInfo *fi = NULL;
gchar dir_sep = 0;
+ GError *local_error = NULL;
gboolean success;
if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store))) {
@@ -1591,7 +1637,7 @@ imapx_store_create_folder_sync (CamelSto
return NULL;
}
- server = camel_imapx_store_get_server (istore, NULL, cancellable, error);
+ server = camel_imapx_store_get_server (istore, NULL, FALSE, cancellable, error);
if (!server)
return NULL;
@@ -1642,10 +1688,22 @@ imapx_store_create_folder_sync (CamelSto
full_name = imapx_concat (istore, parent_real, real_name);
g_free (real_name);
- success = camel_imapx_server_create_folder (
- server, full_name, cancellable, error);
+ success = camel_imapx_server_create_folder (server, full_name, cancellable, &local_error);
g_object_unref (server);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, NULL, FALSE, cancellable, &local_error);
+ if (server) {
+ success = camel_imapx_server_create_folder (server, full_name, cancellable, &local_error);
+ g_object_unref (server);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
if (success) {
CamelIMAPXStoreInfo *si;
@@ -1670,6 +1728,7 @@ imapx_store_delete_folder_sync (CamelSto
{
CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
CamelIMAPXServer *server;
+ GError *local_error = NULL;
gboolean success;
if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store))) {
@@ -1681,14 +1740,28 @@ imapx_store_delete_folder_sync (CamelSto
}
/* Use INBOX connection as the implementation would try to select inbox to ensure
* we are not selected on the folder being deleted */
- server = camel_imapx_store_get_server (istore, "INBOX", cancellable, error);
+ server = camel_imapx_store_get_server (istore, "INBOX", FALSE, cancellable, error);
if (!server)
return FALSE;
- success = camel_imapx_server_delete_folder (
- server, folder_name, cancellable, error);
+ success = camel_imapx_server_delete_folder (server, folder_name, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, "INBOX");
g_object_unref (server);
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, "INBOX", FALSE, cancellable, &local_error);
+ if (server) {
+ success = camel_imapx_server_delete_folder (server, folder_name, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, "INBOX");
+ g_object_unref (server);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
if (success)
imapx_delete_folder_from_cache (istore, folder_name);
@@ -1734,11 +1807,28 @@ imapx_store_rename_folder_sync (CamelSto
/* Use INBOX connection as the implementation would try to select inbox to ensure
* we are not selected on the folder being renamed */
- server = camel_imapx_store_get_server (istore, "INBOX", cancellable, error);
+ server = camel_imapx_store_get_server (istore, "INBOX", FALSE, cancellable, error);
if (server) {
- success = camel_imapx_server_rename_folder (
- server, old, new, cancellable, error);
+ GError *local_error = NULL;
+
+ success = camel_imapx_server_rename_folder (server, old, new, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, "INBOX");
g_object_unref (server);
+
+ while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+
+ server = camel_imapx_store_get_server (istore, "INBOX", FALSE, cancellable, &local_error);
+ if (server) {
+ success = camel_imapx_server_rename_folder (server, old, new, cancellable, &local_error);
+ camel_imapx_store_op_done (istore, server, "INBOX");
+ g_object_unref (server);
+ }
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
}
if (!success) {
@@ -1787,9 +1877,18 @@ imapx_store_noop_sync (CamelStore *store
for (link = list; link != NULL; link = g_list_next (link)) {
CamelIMAPXServer *server = CAMEL_IMAPX_SERVER (link->data);
+ GError *local_error = NULL;
/* we just return last noops value, technically not correct though */
- success = camel_imapx_server_noop (server, NULL, cancellable, error);
+ success = camel_imapx_server_noop (server, NULL, cancellable, &local_error);
+
+ if (g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+ g_clear_error (&local_error);
+ break;
+ } else if (local_error) {
+ g_propagate_error (error, local_error);
+ }
+
if (!success)
break;
}
@@ -2081,3 +2180,49 @@ camel_imapx_store_set_quota_info (CamelI
g_mutex_unlock (&store->priv->quota_info_lock);
}
+void
+camel_imapx_store_set_authenticating_concurrent_connection (CamelIMAPXStore *store,
+ gboolean is_concurrent_connection)
+{
+ g_return_if_fail (CAMEL_IS_IMAPX_STORE (store));
+
+ store->priv->is_concurrent_connection = is_concurrent_connection;
+}
+
+gboolean
+camel_imapx_store_get_authenticating_concurrent_connection (CamelIMAPXStore *store)
+{
+ g_return_val_if_fail (CAMEL_IS_IMAPX_STORE (store), FALSE);
+
+ return store->priv->is_concurrent_connection;
+}
+
+/* Tries to find matching job among all active connections.
+ See camel_imapx_server_ref_job() for more information on parameters
+ and return values.
+*/
+CamelIMAPXJob *
+camel_imapx_store_ref_job (CamelIMAPXStore *imapx_store,
+ CamelFolder *folder,
+ guint32 job_type,
+ const gchar *uid)
+{
+ GList *servers, *siter;
+ CamelIMAPXJob *job = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_STORE (imapx_store), NULL);
+
+ servers = camel_imapx_conn_manager_get_connections (imapx_store->con_man);
+
+ for (siter = servers; siter; siter = g_list_next (siter)) {
+ CamelIMAPXServer *imapx_server = siter->data;
+
+ job = camel_imapx_server_ref_job (imapx_server, folder, job_type, uid);
+ if (job)
+ break;
+ }
+
+ g_list_free_full (servers, g_object_unref);
+
+ return job;
+}
diff -up evolution-data-server-3.8.5/camel/camel-imapx-store.h.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-store.h
--- evolution-data-server-3.8.5/camel/camel-imapx-store.h.imapx-conn-manager-ext 2013-07-23 13:57:56.000000000 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-store.h 2014-05-13 14:17:43.119983665 +0200
@@ -55,6 +55,9 @@
G_BEGIN_DECLS
+/* Avoid a circular reference. */
+struct _CamelIMAPXJob;
+
typedef struct _CamelIMAPXStore CamelIMAPXStore;
typedef struct _CamelIMAPXStoreClass CamelIMAPXStoreClass;
typedef struct _CamelIMAPXStorePrivate CamelIMAPXStorePrivate;
@@ -93,6 +96,7 @@ GType camel_imapx_store_get_type (void)
CamelIMAPXServer *
camel_imapx_store_get_server (CamelIMAPXStore *store,
const gchar *folder_name,
+ gboolean for_expensive_job,
GCancellable *cancellable,
GError **error);
void camel_imapx_store_op_done (CamelIMAPXStore *istore,
@@ -106,6 +110,16 @@ void camel_imapx_store_set_quota_info
(CamelIMAPXStore *store,
const gchar *quota_root_name,
const CamelFolderQuotaInfo *info);
+void camel_imapx_store_set_authenticating_concurrent_connection
+ (CamelIMAPXStore *store,
+ gboolean is_concurrent_connection);
+gboolean camel_imapx_store_get_authenticating_concurrent_connection
+ (CamelIMAPXStore *store);
+struct _CamelIMAPXJob *
+ camel_imapx_store_ref_job (CamelIMAPXStore *imapx_store,
+ CamelFolder *folder,
+ guint32 job_type,
+ const gchar *uid);
G_END_DECLS
diff -up evolution-data-server-3.8.5/camel/camel-imapx-stream.c.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-stream.c
--- evolution-data-server-3.8.5/camel/camel-imapx-stream.c.imapx-conn-manager-ext 2013-07-23 13:57:55.000000000 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-stream.c 2014-05-13 14:17:43.119983665 +0200
@@ -34,6 +34,7 @@
#include <camel/camel-stream-mem.h>
#include "camel-imapx-utils.h"
+#include "camel-imapx-server.h"
#include "camel-imapx-stream.h"
#define CAMEL_IMAPX_STREAM_GET_PRIVATE(obj) \
@@ -92,10 +93,14 @@ imapx_stream_fill (CamelIMAPXStream *is,
* that to be an error. But we do -- we should only be here
* if we *know* there are data to receive. So set the error
* accordingly */
- if (!left)
+ if (!left) {
+ io (is->tagprefix, "Failed to read any bytes into buffer of size %d (from buffer size %d, last read:'%.20s')\n", (gint) (is->priv->bufsize - (is->priv->end - is->priv->buf)), is->priv->bufsize, (const gchar *) is->priv->buf);
+
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 -up evolution-data-server-3.8.5/camel/camel-imapx-utils.c.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-utils.c
--- evolution-data-server-3.8.5/camel/camel-imapx-utils.c.imapx-conn-manager-ext 2014-05-13 14:17:43.110983665 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-utils.c 2014-05-13 14:17:43.119983665 +0200
@@ -430,8 +430,8 @@ create_initial_capabilities_table (void)
* to free hash table
*/
capa_htable = g_hash_table_new_full (
- g_str_hash,
- g_str_equal,
+ camel_strcase_hash,
+ camel_strcase_equal,
g_free,
NULL);
@@ -456,7 +456,7 @@ imapx_parse_capability (CamelIMAPXStream
GError *local_error = NULL;
cinfo = g_malloc0 (sizeof (*cinfo));
- cinfo->auth_types = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
+ cinfo->auth_types = g_hash_table_new_full (camel_strcase_hash, camel_strcase_equal, (GDestroyNotify) g_free, NULL);
/* FIXME: handle auth types */
while ((tok = camel_imapx_stream_token (stream, &token, &len, cancellable, &local_error)) != '\n' &&
@@ -2607,10 +2607,3 @@ imapx_get_temp_uid (void)
return res;
}
-
-void
-camel_imapx_destroy_job_queue_info (IMAPXJobQueueInfo *jinfo)
-{
- g_hash_table_destroy (jinfo->folders);
- g_free (jinfo);
-}
diff -up evolution-data-server-3.8.5/camel/camel-imapx-utils.h.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-imapx-utils.h
--- evolution-data-server-3.8.5/camel/camel-imapx-utils.h.imapx-conn-manager-ext 2013-07-23 13:57:45.000000000 +0200
+++ evolution-data-server-3.8.5/camel/camel-imapx-utils.h 2014-05-13 14:17:43.119983665 +0200
@@ -365,17 +365,6 @@ gboolean camel_imapx_parse_quotaroot (st
GError **error);
/* ********************************************************************** */
-typedef struct _IMAPXJobQueueInfo {
- guint queue_len;
-
- /* list of folders for which jobs are in the queue */
- GHashTable *folders;
-} IMAPXJobQueueInfo;
-
-void camel_imapx_destroy_job_queue_info
- (IMAPXJobQueueInfo *jinfo);
-
-/* ********************************************************************** */
extern guchar imapx_specials[256];
diff -up evolution-data-server-3.8.5/camel/camel-service.c.imapx-conn-manager-ext evolution-data-server-3.8.5/camel/camel-service.c
--- evolution-data-server-3.8.5/camel/camel-service.c.imapx-conn-manager-ext 2013-07-23 14:01:51.000000000 +0200
+++ evolution-data-server-3.8.5/camel/camel-service.c 2014-05-13 14:17:43.120983665 +0200
@@ -934,7 +934,7 @@ service_authenticate_finish (CamelServic
g_return_val_if_fail (
g_simple_async_result_is_valid (
result, G_OBJECT (service), service_authenticate),
- CAMEL_AUTHENTICATION_REJECTED);
+ CAMEL_AUTHENTICATION_ERROR);
simple = G_SIMPLE_ASYNC_RESULT (result);
async_context = g_simple_async_result_get_op_res_gpointer (simple);
@@ -2007,12 +2007,12 @@ camel_service_authenticate_sync (CamelSe
g_return_val_if_fail (
CAMEL_IS_SERVICE (service),
- CAMEL_AUTHENTICATION_REJECTED);
+ CAMEL_AUTHENTICATION_ERROR);
class = CAMEL_SERVICE_GET_CLASS (service);
g_return_val_if_fail (
class->authenticate_sync != NULL,
- CAMEL_AUTHENTICATION_REJECTED);
+ CAMEL_AUTHENTICATION_ERROR);
result = class->authenticate_sync (
service, mechanism, cancellable, error);
@@ -2096,15 +2096,15 @@ camel_service_authenticate_finish (Camel
g_return_val_if_fail (
CAMEL_IS_SERVICE (service),
- CAMEL_AUTHENTICATION_REJECTED);
+ CAMEL_AUTHENTICATION_ERROR);
g_return_val_if_fail (
G_IS_ASYNC_RESULT (result),
- CAMEL_AUTHENTICATION_REJECTED);
+ CAMEL_AUTHENTICATION_ERROR);
class = CAMEL_SERVICE_GET_CLASS (service);
g_return_val_if_fail (
class->authenticate_finish,
- CAMEL_AUTHENTICATION_REJECTED);
+ CAMEL_AUTHENTICATION_ERROR);
return class->authenticate_finish (service, result, error);
}