New API function: tny_send_queue_add_async



Hi, 
This patch implements a new API function in TnySendQueue class, with 
its 
camel implementation of course. 

The main purpose of this function is to provide an user callback for 
adding message to OUTBOX. Current sync implementation uses 
tny_folder_add_msg_async function to add message to OUTBOX in order 
to avoid slow UI responses when big mails are sent. The problem is 
that sync version of send_queue_add does not allow user callbacks, so 
applications could not detect when messages is fully moved to OUTBOX.


-- 
Javier Fernández García-Boente
Ingeniero en Informática                 
mailto:jfernandez igalia com                    
Igalia http://www.igalia.com
Telf. +34 981 91 39 91  
Fax.  +34 981 91 39 49
 
Index: libtinymail-camel/tny-camel-send-queue.c
===================================================================
--- libtinymail-camel/tny-camel-send-queue.c	(revision 2656)
+++ libtinymail-camel/tny-camel-send-queue.c	(working copy)
@@ -28,6 +28,7 @@
 #include <tny-folder.h>
 #include <tny-error.h>
 
+#include <tny-camel-queue-priv.h>
 #include <tny-camel-folder.h>
 #include <tny-transport-account.h>
 #include <tny-store-account.h>
@@ -64,6 +65,8 @@
 	guint signal_id;
 } ControlInfo;
 
+
+
 static gboolean 
 emit_error_on_mainloop (gpointer data)
 {
@@ -173,8 +176,8 @@
 	info->total = total;
 
 	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
-			emit_control_signals_on_mainloop, info, destroy_control_info);
-
+			 emit_control_signals_on_mainloop, info, destroy_control_info);
+	
 	return;
 }
 
@@ -298,6 +301,8 @@
 
 			/* Emits msg-sending signal to inform a new msg is being sent */
 			emit_control (self, header, msg, TNY_SEND_QUEUE_MSG_SENDING, i, priv->total);
+			
+			sleep(45);
 
 			if (err == NULL) 
 			{
@@ -480,23 +485,43 @@
 typedef struct {
 	TnyMsg *msg;
 	TnySendQueue *self;
+	TnySendQueueAddCallback callback;
+	TnyStatusCallback status_callback;
+	TnyIdleStopper* stopper;
+	gboolean cancelled;
+	guint depth;
+	TnySessionCamel *session;
+	GCond* condition;
+	gboolean had_callback;
+	GMutex *mutex;
+	gpointer user_data;
 } OnAddedInfo;
 
+
 static void
 on_added (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
 {
 	OnAddedInfo *info = (OnAddedInfo *) user_data;
 	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (info->self);
 
-	if (err)
-		emit_error (info->self, NULL, info->msg, err, priv->total, priv->total+1);
+	/* Call user callback after msg has beed added to OUTBOX, waiting to be sent*/
+	if (info->callback) {
+		info->callback (info->self, info->cancelled, info->msg, info->user_data, err);		
+	}
 
+	if (err) {
+		emit_error (info->self, NULL, info->msg, err, priv->total, priv->total+1); 
+	}
+	
 	priv->total++;
 	if (priv->total >= 1 && !priv->is_running)
 		create_worker (info->self);
 
-	g_object_unref (info->self);
-	g_object_unref (info->msg);
+
+	if (info->self)
+		g_object_unref (info->self);
+	if (info->msg)
+		g_object_unref (info->msg);
 	g_slice_free (OnAddedInfo, info);
 
 	return;
@@ -556,6 +581,70 @@
 }
 
 
+static void
+tny_camel_send_queue_add_async (TnySendQueue *self, TnyMsg *msg, TnySendQueueAddCallback callback, TnyStatusCallback status_callback, gpointer user_data)
+{
+	TNY_CAMEL_SEND_QUEUE_GET_CLASS (self)->add_async_func (self, msg, callback, status_callback, user_data);
+}
+
+
+static void
+tny_camel_send_queue_add_async_default (TnySendQueue *self, TnyMsg *msg, TnySendQueueAddCallback callback, TnyStatusCallback status_callback, gpointer user_data)
+{
+	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (self);
+	GError *err = NULL;
+
+	g_assert (TNY_IS_CAMEL_MSG (msg));
+
+	g_mutex_lock (priv->todo_lock);
+	{
+		TnyFolder *outbox;
+		TnyList *headers = tny_simple_list_new ();
+		OnAddedInfo *info = NULL;
+
+		outbox = tny_send_queue_get_outbox (self);
+
+		if (!outbox || !TNY_IS_FOLDER (outbox))
+		{
+			g_set_error (&err, TNY_SEND_QUEUE_ERROR, 
+				TNY_SEND_QUEUE_ERROR_ADD,
+				"Operating can't continue: send queue not ready "
+				"because it does not have a valid outbox. "
+				"This problem indicates a bug in the software.");
+			g_object_unref (headers);
+			g_mutex_unlock (priv->todo_lock);
+			return;
+		}
+
+		tny_folder_get_headers (outbox, headers, TRUE, &err);
+
+		if (err!= NULL)
+		{
+			g_object_unref (headers);
+			g_object_unref (outbox);
+			g_mutex_unlock (priv->todo_lock);
+			return;
+		}
+
+		priv->total = tny_list_get_length (headers);
+		g_object_unref (headers);
+
+		info = g_slice_new (OnAddedInfo);
+		info->msg = TNY_MSG (g_object_ref (msg));
+		info->self = TNY_SEND_QUEUE (g_object_ref (self));
+		info->callback = callback;
+		info->user_data = user_data;
+
+		tny_folder_add_msg_async (outbox, msg, on_added, NULL, info);
+
+		g_object_unref (outbox);
+	}
+	g_mutex_unlock (priv->todo_lock);
+
+	return;
+}
+
+
 static TnyFolder*
 create_maildir (TnySendQueue *self, const gchar *name)
 {
@@ -823,6 +912,7 @@
 	TnySendQueueIface *klass = (TnySendQueueIface *)g;
 
 	klass->add_func = tny_camel_send_queue_add;
+	klass->add_async_func = tny_camel_send_queue_add_async;
 	klass->get_outbox_func = tny_camel_send_queue_get_outbox;
 	klass->get_sentbox_func = tny_camel_send_queue_get_sentbox;
 	klass->cancel_func = tny_camel_send_queue_cancel;
@@ -839,6 +929,7 @@
 	object_class = (GObjectClass*) class;
 
 	class->add_func = tny_camel_send_queue_add_default;
+	class->add_async_func = tny_camel_send_queue_add_async_default;
 	class->get_outbox_func = tny_camel_send_queue_get_outbox_default;
 	class->get_sentbox_func = tny_camel_send_queue_get_sentbox_default;
 	class->cancel_func = tny_camel_send_queue_cancel_default;
Index: libtinymail-camel/tny-camel-send-queue.h
===================================================================
--- libtinymail-camel/tny-camel-send-queue.h	(revision 2656)
+++ libtinymail-camel/tny-camel-send-queue.h	(working copy)
@@ -50,6 +50,7 @@
 
 	/* virtual methods */
 	void (*add_func) (TnySendQueue *self, TnyMsg *msg, GError **err);
+	void (*add_async_func) (TnySendQueue *self, TnyMsg *msg, TnySendQueueAddCallback callback, TnyStatusCallback status_callback, gpointer user_data);
 	TnyFolder* (*get_sentbox_func) (TnySendQueue *self);
 	TnyFolder* (*get_outbox_func) (TnySendQueue *self);
 	void (*cancel_func) (TnySendQueue *self, gboolean remove, GError **err);
Index: libtinymail/tny-send-queue.c
===================================================================
--- libtinymail/tny-send-queue.c	(revision 2656)
+++ libtinymail/tny-send-queue.c	(working copy)
@@ -133,8 +133,31 @@
 }
 
 
+/**
+ * tny_send_queue_add_async:
+ * @self: A #TnySendQueue instance
+ * @msg: a #TnyMsg instance
+ * @err: a #GError instance or NULL
+ *
+ * Add a message to the send queue.
+ *
+ **/
+void 
+tny_send_queue_add_async (TnySendQueue *self, TnyMsg *msg, TnySendQueueAddCallback callback, TnyStatusCallback status_callback, gpointer user_data)
+{
+#ifdef DBC /* require */
+	g_assert (TNY_IS_SEND_QUEUE (self));
+	g_assert (msg);
+	g_assert (TNY_IS_MSG (msg));
+	g_assert (TNY_SEND_QUEUE_GET_IFACE (self)->add_async_func != NULL);
+#endif
 
+	TNY_SEND_QUEUE_GET_IFACE (self)->add_async_func (self, msg, callback, status_callback, user_data);
+	return;
+}
 
+
+
 static void
 tny_send_queue_base_init (gpointer g_class)
 {
Index: libtinymail/tny-send-queue.h
===================================================================
--- libtinymail/tny-send-queue.h	(revision 2656)
+++ libtinymail/tny-send-queue.h	(working copy)
@@ -62,6 +62,7 @@
 
 	/* methods */
 	void (*add_func) (TnySendQueue *self, TnyMsg *msg, GError **err);
+	void (*add_async_func) (TnySendQueue *self, TnyMsg *msg, TnySendQueueAddCallback callback, TnyStatusCallback status_callback, gpointer user_data);
 	TnyFolder* (*get_sentbox_func) (TnySendQueue *self);
 	TnyFolder* (*get_outbox_func) (TnySendQueue *self);
 	void (*cancel_func) (TnySendQueue *self, gboolean remove, GError **err);
@@ -71,6 +72,7 @@
 GType tny_send_queue_get_type (void);
 
 void tny_send_queue_add (TnySendQueue *self, TnyMsg *msg, GError **err);
+void tny_send_queue_add_async (TnySendQueue *self, TnyMsg *msg, TnySendQueueAddCallback callback, TnyStatusCallback status_callback, gpointer user_data);
 TnyFolder* tny_send_queue_get_sentbox (TnySendQueue *self);
 TnyFolder* tny_send_queue_get_outbox (TnySendQueue *self);
 void tny_send_queue_cancel (TnySendQueue *self, gboolean remove, GError **err);


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