Blame SOURCES/evolution-data-server-3.8.5-imapx-conn-manager-ext.patch

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