[evolution-data-server] Return a GError in camel_imapx_job_wait().
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Return a GError in camel_imapx_job_wait().
- Date: Thu, 15 Aug 2013 09:48:03 +0000 (UTC)
commit 3192936f5bc22c654cbb82db51a335e3cf1946b9
Author: Matthew Barnes <mbarnes redhat com>
Date: Tue Aug 13 15:21:29 2013 -0400
Return a GError in camel_imapx_job_wait().
Despite the improvements in commit dacf161, there is still a disconnect
in error propagation between CamelIMAPXCommand and CamelIMAPXJob in that
completed jobs are still not aware of whether they failed.
This commit lays the foundations for another attempt to bridge the gap,
this time by adding a means of setting an error on a CamelIMAPXJob with
camel_imapx_job_take_error(). We also break API in order to return the
error through camel_imapx_job_wait().
New functions:
camel_imapx_job_take_error()
camel/camel-imapx-job.c | 78 +++++++++++++++++++++++++++++--
camel/camel-imapx-job.h | 5 ++-
camel/camel-imapx-server.c | 5 +-
docs/reference/camel/camel-sections.txt | 1 +
4 files changed, 82 insertions(+), 7 deletions(-)
---
diff --git a/camel/camel-imapx-job.c b/camel/camel-imapx-job.c
index a91e0ae..49c3988 100644
--- a/camel/camel-imapx-job.c
+++ b/camel/camel-imapx-job.c
@@ -30,6 +30,10 @@ struct _CamelIMAPXRealJob {
GCancellable *cancellable;
+ /* This is set by camel_imapx_job_take_error(),
+ * and propagated through camel_imapx_job_wait(). */
+ GError *error;
+
/* Used for running some jobs synchronously. */
GCond done_cond;
GMutex done_mutex;
@@ -111,6 +115,8 @@ camel_imapx_job_unref (CamelIMAPXJob *job)
if (real_job->cancellable != NULL)
g_object_unref (real_job->cancellable);
+ g_clear_error (&real_job->error);
+
g_cond_clear (&real_job->done_cond);
g_mutex_clear (&real_job->done_mutex);
@@ -156,14 +162,32 @@ camel_imapx_job_cancel (CamelIMAPXJob *job)
g_cancellable_cancel (real_job->cancellable);
}
-void
-camel_imapx_job_wait (CamelIMAPXJob *job)
+/**
+ * camel_imapx_job_wait:
+ * @job: a #CamelIMAPXJob
+ * @error: return location for a #GError, or %NULL
+ *
+ * Blocks until @job completes by way of camel_imapx_job_done(). If @job
+ * completed successfully, the function returns %TRUE. If @job was given
+ * a #GError by way of camel_imapx_job_take_error(), or its #GCancellable
+ * was cancelled, the function sets @error and returns %FALSE.
+ *
+ * Returns: whether @job completed successfully
+ *
+ * Since: 3.10
+ **/
+gboolean
+camel_imapx_job_wait (CamelIMAPXJob *job,
+ GError **error)
{
CamelIMAPXRealJob *real_job;
+ GCancellable *cancellable;
+ gboolean success = TRUE;
- g_return_if_fail (CAMEL_IS_IMAPX_JOB (job));
+ g_return_val_if_fail (CAMEL_IS_IMAPX_JOB (job), FALSE);
real_job = (CamelIMAPXRealJob *) job;
+ cancellable = camel_imapx_job_get_cancellable (job);
g_mutex_lock (&real_job->done_mutex);
while (!real_job->done_flag)
@@ -171,6 +195,21 @@ camel_imapx_job_wait (CamelIMAPXJob *job)
&real_job->done_cond,
&real_job->done_mutex);
g_mutex_unlock (&real_job->done_mutex);
+
+ /* Cancellation takes priority over other errors. */
+ if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+ success = FALSE;
+ } else if (real_job->error != NULL) {
+ /* Copy the error, don't propagate it.
+ * We want our GError to remain intact. */
+ if (error != NULL) {
+ g_warn_if_fail (*error == NULL);
+ *error = g_error_copy (real_job->error);
+ }
+ success = FALSE;
+ }
+
+ return success;
}
void
@@ -216,7 +255,7 @@ camel_imapx_job_run (CamelIMAPXJob *job,
success = job->start (job, is, cancellable, error);
if (success && !job->noreply)
- camel_imapx_job_wait (job);
+ success = camel_imapx_job_wait (job, error);
if (cancel_id > 0)
g_cancellable_disconnect (cancellable, cancel_id);
@@ -348,3 +387,34 @@ camel_imapx_job_get_cancellable (CamelIMAPXJob *job)
return real_job->cancellable;
}
+
+/**
+ * camel_imapx_job_take_error:
+ * @job: a #CamelIMAPXJob
+ * @error: a #GError
+ *
+ * Takes over the caller's ownership of @error, so the caller does not
+ * need to free it any more. Call this when a #CamelIMAPXCommand fails
+ * and the @job is to be aborted.
+ *
+ * The @error will be returned to callers of camel_imapx_job_wait() or
+ * camel_imapx_job_run().
+ *
+ * Since: 3.10
+ **/
+void
+camel_imapx_job_take_error (CamelIMAPXJob *job,
+ GError *error)
+{
+ CamelIMAPXRealJob *real_job;
+
+ g_return_if_fail (CAMEL_IS_IMAPX_JOB (job));
+ g_return_if_fail (error != NULL);
+
+ real_job = (CamelIMAPXRealJob *) job;
+
+ g_clear_error (&real_job->error);
+
+ real_job->error = error; /* takes ownership */
+}
+
diff --git a/camel/camel-imapx-job.h b/camel/camel-imapx-job.h
index a6fbec8..4b57864 100644
--- a/camel/camel-imapx-job.h
+++ b/camel/camel-imapx-job.h
@@ -63,7 +63,8 @@ CamelIMAPXJob * camel_imapx_job_ref (CamelIMAPXJob *job);
void camel_imapx_job_unref (CamelIMAPXJob *job);
gboolean camel_imapx_job_check (CamelIMAPXJob *job);
void camel_imapx_job_cancel (CamelIMAPXJob *job);
-void camel_imapx_job_wait (CamelIMAPXJob *job);
+gboolean camel_imapx_job_wait (CamelIMAPXJob *job,
+ GError **error);
void camel_imapx_job_done (CamelIMAPXJob *job);
gboolean camel_imapx_job_run (CamelIMAPXJob *job,
CamelIMAPXServer *is,
@@ -81,6 +82,8 @@ CamelFolder * camel_imapx_job_ref_folder (CamelIMAPXJob *job);
void camel_imapx_job_set_folder (CamelIMAPXJob *job,
CamelFolder *folder);
GCancellable * camel_imapx_job_get_cancellable (CamelIMAPXJob *job);
+void camel_imapx_job_take_error (CamelIMAPXJob *job,
+ GError *error);
G_END_DECLS
diff --git a/camel/camel-imapx-server.c b/camel/camel-imapx-server.c
index 39cba6b..b3cccf1 100644
--- a/camel/camel-imapx-server.c
+++ b/camel/camel-imapx-server.c
@@ -7318,7 +7318,8 @@ imapx_server_get_message (CamelIMAPXServer *is,
QUEUE_LOCK (is);
- if ((job = imapx_is_job_in_queue (is, folder, IMAPX_JOB_GET_MESSAGE, uid))) {
+ job = imapx_is_job_in_queue (is, folder, IMAPX_JOB_GET_MESSAGE, uid);
+ if (job != NULL) {
/* Promote the existing GET_MESSAGE
* job's priority if ours is higher. */
if (pri > job->pri)
@@ -7327,7 +7328,7 @@ imapx_server_get_message (CamelIMAPXServer *is,
QUEUE_UNLOCK (is);
/* Wait for the job to finish. */
- camel_imapx_job_wait (job);
+ camel_imapx_job_wait (job, NULL);
/* Disregard errors here. If we failed to retreive the
* message from cache (implying the job we were waiting
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index 82881be..ae52d5a 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -814,6 +814,7 @@ camel_imapx_job_has_folder
camel_imapx_job_ref_folder
camel_imapx_job_set_folder
camel_imapx_job_get_cancellable
+camel_imapx_job_take_error
<SUBSECTION Private>
uidset_state
</SECTION>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]