Blob Blame History Raw
diff -up evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-job.c.imapx-empty-cache-file-temp-workaround evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-job.c
--- evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-job.c.imapx-empty-cache-file-temp-workaround	2014-06-16 15:00:03.000000000 +0200
+++ evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-job.c	2015-05-26 15:02:30.395243456 +0200
@@ -182,6 +182,7 @@ camel_imapx_job_wait (CamelIMAPXJob *job
 {
 	CamelIMAPXRealJob *real_job;
 	GCancellable *cancellable;
+	gulong cancel_id = 0;
 	gboolean success = TRUE;
 
 	g_return_val_if_fail (CAMEL_IS_IMAPX_JOB (job), FALSE);
@@ -189,13 +190,23 @@ camel_imapx_job_wait (CamelIMAPXJob *job
 	real_job = (CamelIMAPXRealJob *) job;
 	cancellable = camel_imapx_job_get_cancellable (job);
 
+	if (G_IS_CANCELLABLE (cancellable))
+		cancel_id = g_cancellable_connect (
+			cancellable,
+			G_CALLBACK (imapx_job_cancelled_cb),
+			camel_imapx_job_ref (job),
+			(GDestroyNotify) camel_imapx_job_unref);
+
 	g_mutex_lock (&real_job->done_mutex);
-	while (!real_job->done_flag)
+	while (!real_job->done_flag && !g_cancellable_is_cancelled (cancellable))
 		g_cond_wait (
 			&real_job->done_cond,
 			&real_job->done_mutex);
 	g_mutex_unlock (&real_job->done_mutex);
 
+	if (cancel_id > 0)
+		g_cancellable_disconnect (cancellable, cancel_id);
+
 	/* Cancellation takes priority over other errors. */
 	if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
 		success = FALSE;
@@ -233,7 +244,6 @@ camel_imapx_job_run (CamelIMAPXJob *job,
                      GError **error)
 {
 	GCancellable *cancellable;
-	gulong cancel_id = 0;
 	gboolean success;
 
 	g_return_val_if_fail (CAMEL_IS_IMAPX_JOB (job), FALSE);
@@ -245,21 +255,11 @@ camel_imapx_job_run (CamelIMAPXJob *job,
 	if (g_cancellable_set_error_if_cancelled (cancellable, error))
 		return FALSE;
 
-	if (G_IS_CANCELLABLE (cancellable))
-		cancel_id = g_cancellable_connect (
-			cancellable,
-			G_CALLBACK (imapx_job_cancelled_cb),
-			camel_imapx_job_ref (job),
-			(GDestroyNotify) camel_imapx_job_unref);
-
 	success = job->start (job, is, cancellable, error);
 
 	if (success && !job->noreply)
 		success = camel_imapx_job_wait (job, error);
 
-	if (cancel_id > 0)
-		g_cancellable_disconnect (cancellable, cancel_id);
-
 	return success;
 }
 
diff -up evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-server.c.imapx-empty-cache-file-temp-workaround evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-server.c
--- evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-server.c.imapx-empty-cache-file-temp-workaround	2015-05-26 15:02:30.390243457 +0200
+++ evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-server.c	2015-05-26 15:02:46.146242702 +0200
@@ -57,8 +57,8 @@
 #define c(...) camel_imapx_debug(command, __VA_ARGS__)
 #define e(...) camel_imapx_debug(extra, __VA_ARGS__)
 
-#define QUEUE_LOCK(x) (g_rec_mutex_lock(&(x)->queue_lock))
-#define QUEUE_UNLOCK(x) (g_rec_mutex_unlock(&(x)->queue_lock))
+#define QUEUE_LOCK(x) g_rec_mutex_lock (&(x)->queue_lock)
+#define QUEUE_UNLOCK(x) g_rec_mutex_unlock (&(x)->queue_lock)
 
 /* Try pipelining fetch requests, 'in bits' */
 #define MULTI_SIZE (32768 * 8)
@@ -5172,23 +5172,54 @@ imapx_command_fetch_message_done (CamelI
 		g_free (tmp_filename);
 	}
 
-	/* Delete the 'tmp' file only if the operation wasn't cancelled. It's because
+	/* Delete the 'tmp' file only if the operation succeeded. It's because
 	   cancelled operations end before they are properly finished (IMAP-protocol speaking),
 	   thus if any other GET_MESSAGE operation was waiting for this job, then it
 	   realized that the message was not downloaded and opened its own "tmp" file, but
 	   of the same name, thus this remove would drop file which could be used
 	   by a different GET_MESSAGE job. */
-	if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+	if (!local_error && !g_cancellable_is_cancelled (cancellable))
 		camel_data_cache_remove (data->message_cache, "tmp", data->uid, NULL);
 
 	/* Avoid possible use-after-free when the imapx_unregister_job() can
 	   also free the 'job' structure. */
+	camel_imapx_job_ref (job);
+
+	imapx_unregister_job (is, job);
+
 	if (local_error != NULL) {
-		camel_imapx_job_take_error (job, local_error);
-		local_error = NULL;
+		CamelIMAPXJob *pending_job;
+
+		/* Give a chance to other threads. */
+		g_thread_yield ();
+
+		pending_job = imapx_server_ref_job (is, mailbox, IMAPX_JOB_GET_MESSAGE, data->uid);
+		if (pending_job != NULL) {
+			GIOStream *cache_stream;
+
+			/* Wait for the job to finish. */
+			camel_imapx_job_wait (pending_job, NULL);
+			camel_imapx_job_unref (pending_job);
+
+			/* Disregard errors here.  If we failed to retrieve the
+			 * message from cache (implying the job we were waiting
+			 * on failed or got cancelled), we'll just re-fetch it. */
+			cache_stream = camel_data_cache_get (data->message_cache, "cur", data->uid, NULL);
+			if (cache_stream != NULL) {
+				g_clear_error (&local_error);
+
+				g_clear_object (&data->stream);
+				data->stream = cache_stream;
+			}
+		}
+
+		if (local_error) {
+			camel_imapx_job_take_error (job, local_error);
+			local_error = NULL;
+		}
 	}
 
-	imapx_unregister_job (is, job);
+	camel_imapx_job_unref (job);
 
 exit:
 	if (local_error != NULL)
@@ -8344,9 +8375,7 @@ imapx_server_get_message (CamelIMAPXServ
 	GetMessageData *data;
 	gboolean registered;
 
-	job = imapx_server_ref_job (is, mailbox, IMAPX_JOB_GET_MESSAGE, message_uid);
-
-	if (job != NULL) {
+	while (job = imapx_server_ref_job (is, mailbox, IMAPX_JOB_GET_MESSAGE, message_uid), job != NULL) {
 		/* Promote the existing GET_MESSAGE
 		 * job's priority if ours is higher. */
 		if (pri > job->pri)
@@ -8362,14 +8391,26 @@ imapx_server_get_message (CamelIMAPXServ
 		cache_stream = camel_data_cache_get (
 			message_cache, "cur", message_uid, NULL);
 		if (cache_stream != NULL) {
-			stream = camel_stream_new (cache_stream);
+			/* Return new file stream, instead of a DataCache's to not fight
+			   on its content and position with other jobs, if any. */
+			gchar *filename = camel_data_cache_get_filename (message_cache, "cur", message_uid);
+			stream = camel_stream_fs_new_with_name (filename, O_RDONLY, 0, NULL);
+			g_free (filename);
 			g_object_unref (cache_stream);
-			return stream;
+
+			if (stream)
+				return stream;
 		}
 	}
 
 	QUEUE_LOCK (is);
 
+	if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+		QUEUE_UNLOCK (is);
+
+		return NULL;
+	}
+
 	mi = camel_folder_summary_get (summary, message_uid);
 	if (mi == NULL) {
 		g_set_error (
diff -up evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-server.h.imapx-empty-cache-file-temp-workaround evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-server.h
diff -up evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-store.c.imapx-empty-cache-file-temp-workaround evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-store.c
--- evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-store.c.imapx-empty-cache-file-temp-workaround	2014-12-02 16:07:54.000000000 +0100
+++ evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-store.c	2015-05-26 15:02:46.148242702 +0200
@@ -704,7 +704,6 @@ imapx_store_finalize (GObject *object)
 	priv = CAMEL_IMAPX_STORE_GET_PRIVATE (object);
 
 	g_mutex_clear (&priv->get_finfo_lock);
-
 	g_mutex_clear (&priv->server_lock);
 
 	g_hash_table_destroy (priv->quota_info);
diff -up evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-store.h.imapx-empty-cache-file-temp-workaround evolution-data-server-3.12.11/camel/providers/imapx/camel-imapx-store.h