[evolution-data-server] CamelSession: Make forward_to() method asynchronous.



commit 4006bb1335be48450243127799fd4210ce5fe5c2
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sun Aug 12 07:09:12 2012 -0400

    CamelSession: Make forward_to() method asynchronous.
    
    Missed this while converting the rest of Camel to GIO's async pattern,
    but came to realize Evolution's forward_to() implementation starts an
    asynchronous CamelFolder.append_to() operation and returns TRUE.
    
    So the return value from camel_session_forward_to() does not actually
    indicate whether the message was successfully forwarded.  In fact the
    caller has no way of knowing!
    
    This calls for an API break.
    
    Split the forward_to() method into synchronous and asynchronous
    variations:
    
      gboolean  (*forward_to_sync)    (CamelSession *session,
                                       CamelFolder *folder,
                                       CamelMimeMessage *message,
                                       const gchar *address,
                                       GCancellable *cancellable,
                                       GError **error);
    
      void      (*forward_to)         (CamelSession *session,
                                       CamelFolder *folder,
                                       CamelMimeMessage *message,
                                       const gchar *address,
                                       gint io_priority,
                                       GCancellable *cancellable,
                                       GAsyncReadyCallback callback,
                                       gpointer user_data);
    
      gboolean  (*forward_to_finish)  (CamelSession *session,
                                       GAsyncResult *result,
                                       GError **error);

 camel/camel-filter-driver.c             |    4 +-
 camel/camel-session.c                   |  257 ++++++++++++++++++++++++++-----
 camel/camel-session.h                   |   44 ++++--
 docs/reference/camel/camel-sections.txt |    4 +-
 4 files changed, 260 insertions(+), 49 deletions(-)
---
diff --git a/camel/camel-filter-driver.c b/camel/camel-filter-driver.c
index 07fe106..c3ab346 100644
--- a/camel/camel-filter-driver.c
+++ b/camel/camel-filter-driver.c
@@ -494,11 +494,13 @@ do_forward_to (struct _CamelSExp *f,
 		"Forward message to '%s'",
 		argv[0]->value.string);
 
-	camel_session_forward_to (
+	/* XXX Not cancellable. */
+	camel_session_forward_to_sync (
 		driver->priv->session,
 		driver->priv->source,
 		driver->priv->message,
 		argv[0]->value.string,
+		NULL,
 		&driver->priv->error);
 
 	return NULL;
diff --git a/camel/camel-session.c b/camel/camel-session.c
index 0fcbc30..4b479cd 100644
--- a/camel/camel-session.c
+++ b/camel/camel-session.c
@@ -79,7 +79,10 @@ struct _CamelSessionPrivate {
 };
 
 struct _AsyncContext {
+	CamelFolder *folder;
+	CamelMimeMessage *message;
 	CamelService *service;
+	gchar *address;
 	gchar *auth_mechanism;
 };
 
@@ -115,9 +118,16 @@ G_DEFINE_TYPE (CamelSession, camel_session, CAMEL_TYPE_OBJECT)
 static void
 async_context_free (AsyncContext *async_context)
 {
+	if (async_context->folder != NULL)
+		g_object_unref (async_context->folder);
+
+	if (async_context->message != NULL)
+		g_object_unref (async_context->message);
+
 	if (async_context->service != NULL)
 		g_object_unref (async_context->service);
 
+	g_free (async_context->address);
 	g_free (async_context->auth_mechanism);
 
 	g_slice_free (AsyncContext, async_context);
@@ -568,8 +578,10 @@ session_authenticate_thread (GSimpleAsyncResult *simple,
 	async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
 	camel_session_authenticate_sync (
-		CAMEL_SESSION (object), async_context->service,
-		async_context->auth_mechanism, cancellable, &error);
+		CAMEL_SESSION (object),
+		async_context->service,
+		async_context->auth_mechanism,
+		cancellable, &error);
 
 	if (error != NULL)
 		g_simple_async_result_take_error (simple, error);
@@ -622,6 +634,91 @@ session_authenticate_finish (CamelSession *session,
 	return !g_simple_async_result_propagate_error (simple, error);
 }
 
+static gboolean
+session_forward_to_sync (CamelSession *session,
+                         CamelFolder *folder,
+                         CamelMimeMessage *message,
+                         const gchar *address,
+                         GCancellable *cancellable,
+                         GError **error)
+{
+	g_set_error_literal (
+		error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+		_("Forwarding messages is not supported"));
+
+	return FALSE;
+}
+
+static void
+session_forward_to_thread (GSimpleAsyncResult *simple,
+                           GObject *object,
+                           GCancellable *cancellable)
+{
+	AsyncContext *async_context;
+	GError *error = NULL;
+
+	async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+	camel_session_forward_to_sync (
+		CAMEL_SESSION (object),
+		async_context->folder,
+		async_context->message,
+		async_context->address,
+		cancellable, &error);
+
+	if (error != NULL)
+		g_simple_async_result_take_error (simple, error);
+}
+
+static void
+session_forward_to (CamelSession *session,
+                    CamelFolder *folder,
+                    CamelMimeMessage *message,
+                    const gchar *address,
+                    gint io_priority,
+                    GCancellable *cancellable,
+                    GAsyncReadyCallback callback,
+                    gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	AsyncContext *async_context;
+
+	async_context = g_slice_new0 (AsyncContext);
+	async_context->folder = g_object_ref (folder);
+	async_context->message = g_object_ref (message);
+	async_context->address = g_strdup (address);
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (session), callback, user_data, session_forward_to);
+
+	g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+	g_simple_async_result_set_op_res_gpointer (
+		simple, async_context, (GDestroyNotify) async_context_free);
+
+	g_simple_async_result_run_in_thread (
+		simple, session_forward_to_thread, io_priority, cancellable);
+
+	g_object_unref (simple);
+}
+
+static gboolean
+session_forward_to_finish (CamelSession *session,
+                           GAsyncResult *result,
+                           GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (
+		g_simple_async_result_is_valid (
+		result, G_OBJECT (session), session_forward_to), FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	/* Assume success unless a GError is set. */
+	return !g_simple_async_result_propagate_error (simple, error);
+}
+
 static void
 camel_session_class_init (CamelSessionClass *class)
 {
@@ -640,9 +737,12 @@ camel_session_class_init (CamelSessionClass *class)
 	class->get_socks_proxy = session_get_socks_proxy;
 
 	class->authenticate_sync = session_authenticate_sync;
+	class->forward_to_sync = session_forward_to_sync;
 
 	class->authenticate = session_authenticate;
 	class->authenticate_finish = session_authenticate_finish;
+	class->forward_to = session_forward_to;
+	class->forward_to_finish = session_forward_to_finish;
 
 	g_object_class_install_property (
 		object_class,
@@ -1575,41 +1675,6 @@ camel_session_get_junk_headers (CamelSession *session)
 }
 
 /**
- * camel_session_forward_to:
- * Forwards message to some address(es) in a given type. The meaning of the forward_type defines session itself.
- * @session #CameSession.
- * @folder #CamelFolder where is @message located.
- * @message Message to forward.
- * @address Where forward to.
- * @ex Exception.
- *
- * Since: 2.26
- **/
-gboolean
-camel_session_forward_to (CamelSession *session,
-                          CamelFolder *folder,
-                          CamelMimeMessage *message,
-                          const gchar *address,
-                          GError **error)
-{
-	CamelSessionClass *class;
-	gboolean success;
-
-	g_return_val_if_fail (CAMEL_IS_SESSION (session), FALSE);
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
-	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
-	g_return_val_if_fail (address != NULL, FALSE);
-
-	class = CAMEL_SESSION_GET_CLASS (session);
-	g_return_val_if_fail (class->forward_to != NULL, FALSE);
-
-	success = class->forward_to (session, folder, message, address, error);
-	CAMEL_CHECK_GERROR (session, forward_to, success, error);
-
-	return success;
-}
-
-/**
  * camel_session_lock:
  * @session: a #CamelSession
  * @lock: lock type to lock
@@ -1740,6 +1805,49 @@ camel_session_authenticate_sync (CamelSession *session,
 }
 
 /**
+ * camel_session_forward_to_sync:
+ * @session: a #CamelSession
+ * @folder: the #CamelFolder where @message is located
+ * @message: the #CamelMimeMessage to forward
+ * @address: the recipient's email address
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Forwards @message in @folder to the email address(es) given by @address.
+ *
+ * If an error occurs, the function sets @error and returns %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.6
+ **/
+gboolean
+camel_session_forward_to_sync (CamelSession *session,
+                               CamelFolder *folder,
+                               CamelMimeMessage *message,
+                               const gchar *address,
+                               GCancellable *cancellable,
+                               GError **error)
+{
+	CamelSessionClass *class;
+	gboolean success;
+
+	g_return_val_if_fail (CAMEL_IS_SESSION (session), FALSE);
+	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
+	g_return_val_if_fail (address != NULL, FALSE);
+
+	class = CAMEL_SESSION_GET_CLASS (session);
+	g_return_val_if_fail (class->forward_to_sync != NULL, FALSE);
+
+	success = class->forward_to_sync (
+		session, folder, message, address, cancellable, error);
+	CAMEL_CHECK_GERROR (session, forward_to_sync, success, error);
+
+	return success;
+}
+
+/**
  * camel_session_authenticate:
  * @session: a #CamelSession
  * @service: a #CamelService
@@ -1814,3 +1922,78 @@ camel_session_authenticate_finish (CamelSession *session,
 	return class->authenticate_finish (session, result, error);
 }
 
+/**
+ * camel_session_forward_to:
+ * @session: a #CamelSession
+ * @folder: the #CamelFolder where @message is located
+ * @message: the #CamelMimeMessage to forward
+ * @address: the recipient's email address
+ * @io_priority: the I/O priority for the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously forwards @message in @folder to the email address(s)
+ * given by @address.
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_session_forward_to_finish() to get the result of the
+ * operation.
+ *
+ * Since: 3.6
+ **/
+void
+camel_session_forward_to (CamelSession *session,
+                          CamelFolder *folder,
+                          CamelMimeMessage *message,
+                          const gchar *address,
+                          gint io_priority,
+                          GCancellable *cancellable,
+                          GAsyncReadyCallback callback,
+                          gpointer user_data)
+{
+	CamelSessionClass *class;
+
+	g_return_if_fail (CAMEL_IS_SESSION (session));
+	g_return_if_fail (CAMEL_IS_FOLDER (folder));
+	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
+	g_return_if_fail (address != NULL);
+
+	class = CAMEL_SESSION_GET_CLASS (session);
+	g_return_if_fail (class->forward_to != NULL);
+
+	class->forward_to (
+		session, folder, message, address,
+		io_priority, cancellable, callback, user_data);
+}
+
+/**
+ * camel_session_forward_to_finish:
+ * @session: a #CamelSession
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_session_forward_to().
+ *
+ * If an error occurred, the function sets @error and returns %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.6
+ **/
+gboolean
+camel_session_forward_to_finish (CamelSession *session,
+                                 GAsyncResult *result,
+                                 GError **error)
+{
+	CamelSessionClass *class;
+
+	g_return_val_if_fail (CAMEL_IS_SESSION (session), FALSE);
+	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+	class = CAMEL_SESSION_GET_CLASS (session);
+	g_return_val_if_fail (class->forward_to_finish != NULL, FALSE);
+
+	return class->forward_to_finish (session, result, error);
+}
+
diff --git a/camel/camel-session.h b/camel/camel-session.h
index 776fd6a..80deb37 100644
--- a/camel/camel-session.h
+++ b/camel/camel-session.h
@@ -132,11 +132,6 @@ struct _CamelSessionClass {
 						 GError **error);
 	gboolean	(*lookup_addressbook)	(CamelSession *session,
 						 const gchar *name);
-	gboolean	(*forward_to)		(CamelSession *session,
-						 CamelFolder *folder,
-						 CamelMimeMessage *message,
-						 const gchar *address,
-						 GError **error);
 	void		(*get_socks_proxy)	(CamelSession *session,
 						 const gchar *for_host,
 						 gchar **host_ret,
@@ -148,6 +143,12 @@ struct _CamelSessionClass {
 						 const gchar *mechanism,
 						 GCancellable *cancellable,
 						 GError **error);
+	gboolean	(*forward_to_sync)	(CamelSession *session,
+						 CamelFolder *folder,
+						 CamelMimeMessage *message,
+						 const gchar *address,
+						 GCancellable *cancellable,
+						 GError **error);
 
 	/* Asynchronous I/O Methods (all have defaults) */
 	void		(*authenticate)		(CamelSession *session,
@@ -160,6 +161,17 @@ struct _CamelSessionClass {
 	gboolean	(*authenticate_finish)	(CamelSession *session,
 						 GAsyncResult *result,
 						 GError **error);
+	void		(*forward_to)		(CamelSession *session,
+						 CamelFolder *folder,
+						 CamelMimeMessage *message,
+						 const gchar *address,
+						 gint io_priority,
+						 GCancellable *cancellable,
+						 GAsyncReadyCallback callback,
+						 gpointer user_data);
+	gboolean	(*forward_to_finish)	(CamelSession *session,
+						 GAsyncResult *result,
+						 GError **error);
 
 	/* Signals */
 	void		(*job_started)		(CamelSession *session,
@@ -247,11 +259,6 @@ void		camel_session_set_junk_headers	(CamelSession *session,
 						 gint len);
 gboolean	camel_session_lookup_addressbook (CamelSession *session,
 						 const gchar *name);
-gboolean	camel_session_forward_to	(CamelSession *session,
-						 CamelFolder *folder,
-						 CamelMimeMessage *message,
-						 const gchar *address,
-						 GError **error);
 void		camel_session_lock		(CamelSession *session,
 						 CamelSessionLock lock);
 void		camel_session_unlock		(CamelSession *session,
@@ -273,6 +280,23 @@ gboolean	camel_session_authenticate_finish
 						(CamelSession *session,
 						 GAsyncResult *result,
 						 GError **error);
+gboolean	camel_session_forward_to_sync	(CamelSession *session,
+						 CamelFolder *folder,
+						 CamelMimeMessage *message,
+						 const gchar *address,
+						 GCancellable *cancellable,
+						 GError **error);
+void		camel_session_forward_to	(CamelSession *session,
+						 CamelFolder *folder,
+						 CamelMimeMessage *message,
+						 const gchar *address,
+						 gint io_priority,
+						 GCancellable *cancellable,
+						 GAsyncReadyCallback callback,
+						 gpointer user_data);
+gboolean	camel_session_forward_to_finish	(CamelSession *session,
+						 GAsyncResult *result,
+						 GError **error);
 
 G_END_DECLS
 
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index f98e997..f4bd7fc 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -2318,13 +2318,15 @@ camel_session_set_network_available
 camel_session_get_junk_headers
 camel_session_set_junk_headers
 camel_session_lookup_addressbook
-camel_session_forward_to
 CamelSessionLock
 camel_session_lock
 camel_session_unlock
 camel_session_authenticate_sync
 camel_session_authenticate
 camel_session_authenticate_finish
+camel_session_forward_to_sync
+camel_session_forward_to
+camel_session_forward_to_finish
 <SUBSECTION Standard>
 CAMEL_SESSION
 CAMEL_IS_SESSION



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]