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