Re: Patch for the send queue



Sergio Villar Senin wrote:
> Sergio Villar Senin wrote:
>> Hi,
>>
>> this patch does two things:
>>    * makes the queue wait until the user finishes the process of the
>> error_happened notification
>>    * allows the queue to go on even if the sending of one of the
>> messages in the outbox failed
> 
> Second version of the patch, I missed a couple of strdup's.

And third version.

This patch changes the API, it replaces a gboolean by an enum type. Now
Tinymail could do two different things when tny_send_queue_cancel is called:

* using flag tinymail will remove the messages in the outbox
* using flag tinymail will set all the headers as SUSPENDED, this will
prevent the send queue from sending them but it'll keep the messages there

Br
Index: libtinymail-camel/tny-camel-send-queue.c
===================================================================
--- libtinymail-camel/tny-camel-send-queue.c	(revision 3282)
+++ libtinymail-camel/tny-camel-send-queue.c	(working copy)
@@ -57,6 +57,9 @@
 	TnyHeader *header;
 	GError *error;
 	gint i, total;
+	GCond *condition;
+	GMutex *mutex;
+	gboolean had_callback;
 } ErrorInfo;
 
 typedef struct {
@@ -114,8 +117,13 @@
 		g_object_unref (info->self);
 	if (info->error)
 		g_error_free (info->error);
-	g_slice_free (ErrorInfo, info);
 
+
+	g_mutex_lock (info->mutex);
+	g_cond_broadcast (info->condition);
+	info->had_callback = TRUE;
+	g_mutex_unlock (info->mutex);
+
 	return;
 }
 
@@ -134,9 +142,23 @@
 		info->header = TNY_HEADER (g_object_ref (header));
 	info->i = i;
 	info->total = total;
+	info->had_callback = FALSE;
+	info->mutex = g_mutex_new ();
+	info->condition = g_cond_new ();
+
 	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
 		emit_error_on_mainloop, info, destroy_error_info);
 
+	g_mutex_lock (info->mutex);
+	if (!info->had_callback)
+		g_cond_wait (info->condition, info->mutex);
+	g_mutex_unlock (info->mutex);
+
+	g_mutex_free (info->mutex);
+	g_cond_free (info->condition);
+
+	g_slice_free (ErrorInfo, info);
+
 	return;
 }
 
@@ -274,6 +296,7 @@
 	guint i = 0, length = 0;
 	TnyList *list = NULL;
 	TnyDevice *device = info->device;
+	GHashTable *failed_headers;
 
 	priv->is_running = TRUE;
 	list = tny_simple_list_new ();
@@ -316,9 +339,9 @@
 
 	g_object_unref (list);
 
-	priv->do_continue = TRUE;
+	failed_headers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
-	while (length > 0 && priv->do_continue && tny_device_is_online (device))
+	while ((length - g_hash_table_size (failed_headers)) > 0 && tny_device_is_online (device))
 	{
 		TnyHeader *header = NULL;
 		TnyMsg *msg = NULL;
@@ -368,6 +391,21 @@
 			}
 			g_object_unref (giter);
 
+			/* Some code to remove the previously failed items */
+			giter = tny_list_create_iterator (headers);
+			while (!tny_iterator_is_done (giter))
+			{
+				TnyHeader *curhdr = TNY_HEADER (tny_iterator_get_current (giter));
+
+				if (g_hash_table_lookup_extended (failed_headers, tny_header_get_uid (curhdr),
+								  NULL, NULL))
+					to_remove = g_list_prepend (to_remove, curhdr);
+
+				g_object_unref (curhdr);
+				tny_iterator_next (giter);
+			}
+			g_object_unref (giter);
+
 			while (to_remove) {
 				tny_list_remove (headers, G_OBJECT (to_remove->data));
 				to_remove = g_list_next (to_remove);
@@ -412,11 +450,13 @@
 
 				if (err != NULL) {
 					emit_error (self, header, msg, err, i, priv->total);
-					priv->do_continue = FALSE;
+					g_hash_table_insert (failed_headers, 
+							     g_strdup (tny_header_get_uid (header)), NULL);
 				}
 			} else {
 				emit_error (self, header, msg, err, i, priv->total);
-				priv->do_continue = FALSE;
+				g_hash_table_insert (failed_headers, 
+						     g_strdup (tny_header_get_uid (header)), NULL);
 			}
 
 			g_mutex_lock (priv->todo_lock);
@@ -427,10 +467,8 @@
 					priv->cur_i = i;
 					tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
 					tny_folder_transfer_msgs (outbox, hassent, sentbox, TRUE, &newerr);
-					if (newerr != NULL) 
-					{
+					if (newerr != NULL) {
 						emit_error (self, header, msg, newerr, i, priv->total);
-						priv->do_continue = FALSE;
 						g_error_free (newerr);
 					}
 					priv->total--;
@@ -465,12 +503,12 @@
 
 	}
 
-	priv->is_running = FALSE;
-
 errorhandler:
 
 	priv->is_running = FALSE;
 
+	g_hash_table_destroy (failed_headers);
+
 	g_object_unref (sentbox);
 	g_object_unref (outbox);
 
@@ -506,66 +544,65 @@
 
 
 static void
-tny_camel_send_queue_cancel (TnySendQueue *self, gboolean remove, GError **err)
+tny_camel_send_queue_cancel (TnySendQueue *self, TnySendQueueCancelAction cancel_action, GError **err)
 {
-	TNY_CAMEL_SEND_QUEUE_GET_CLASS (self)->cancel_func (self, remove, err);
+	TNY_CAMEL_SEND_QUEUE_GET_CLASS (self)->cancel_func (self, cancel_action, err);
 }
 
 static void
-tny_camel_send_queue_cancel_default (TnySendQueue *self, gboolean remove, GError **err)
+tny_camel_send_queue_cancel_default (TnySendQueue *self, TnySendQueueCancelAction cancel_action, GError **err)
 {
 	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (self);
+	TnyFolder *outbox;
+	TnyList *headers = tny_simple_list_new ();
+	TnyIterator *iter;
 
 	g_mutex_lock (priv->sending_lock);
 
 	priv->is_running = FALSE;
-	priv->do_continue = FALSE;
 
-	if (remove)
+	outbox = tny_send_queue_get_outbox (self);
+
+	tny_folder_get_headers (outbox, headers, TRUE, err);
+	
+	if (err != NULL && *err != NULL)
 	{
-		TnyFolder *outbox;
-		TnyList *headers = tny_simple_list_new ();
-		TnyIterator *iter;
+		g_object_unref (headers);
+		g_object_unref (outbox);
+		g_mutex_unlock (priv->sending_lock);
+		return;
+	}
 
-		outbox = tny_send_queue_get_outbox (self);
+	iter = tny_list_create_iterator (headers);
+	while (!tny_iterator_is_done (iter))
+	{
+		TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
 
-		tny_folder_get_headers (outbox, headers, TRUE, err);
-
+		/* Remove or suspend the message */
+		if (cancel_action == TNY_SEND_QUEUE_CANCEL_ACTION_REMOVE)
+			tny_folder_remove_msg (outbox, header, err);
+		else if (cancel_action == TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND)
+			tny_header_set_flag (header, TNY_HEADER_FLAG_SUSPENDED);
+		
 		if (err != NULL && *err != NULL)
 		{
+			g_object_unref (header);
+			g_object_unref (iter);
 			g_object_unref (headers);
 			g_object_unref (outbox);
 			g_mutex_unlock (priv->sending_lock);
 			return;
 		}
 
-		iter = tny_list_create_iterator (headers);
+		g_object_unref (header);
+		tny_iterator_next (iter);
+	}
+	g_object_unref (iter);
+	g_object_unref (headers);
 
-		while (!tny_iterator_is_done (iter))
-		{
-			TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
-			tny_folder_remove_msg (outbox, header, err);
+	tny_folder_sync (outbox, TRUE, err);
+	g_object_unref (outbox);
 
-			if (err != NULL && *err != NULL)
-			{
-				g_object_unref (header);
-				g_object_unref (iter);
-				g_object_unref (headers);
-				g_object_unref (outbox);
-				g_mutex_unlock (priv->sending_lock);
-				return;
-			}
-
-			g_object_unref (header);
-			tny_iterator_next (iter);
-		}
-		g_object_unref (iter);
-		g_object_unref (headers);
-
-		tny_folder_sync (outbox, TRUE, err);
-		g_object_unref (outbox);
-	}
-
 	g_mutex_unlock (priv->sending_lock);
 
 	return;
@@ -1052,7 +1089,6 @@
 	priv->outbox_cache = NULL;
 	priv->todo_lock = g_mutex_new ();
 	priv->sending_lock = g_mutex_new ();
-	priv->do_continue = FALSE;
 	priv->is_running = FALSE;
 	priv->thread = NULL;
 
Index: libtinymail/tny-send-queue.c
===================================================================
--- libtinymail/tny-send-queue.c	(revision 3282)
+++ libtinymail/tny-send-queue.c	(working copy)
@@ -38,7 +38,7 @@
 /**
  * tny_send_queue_cancel:
  * @self: a #TnySendQueue
- * @remove: also remove queued messages
+ * @cancel_action: a #TnySendQueueCancelAction, it could remove messages or just mark them as suspended
  * @err: (null-ok): a #GError or NULL
  *
  * Cancels the current operation
@@ -47,14 +47,14 @@
  * audience: application-developer
  **/
 void 
-tny_send_queue_cancel (TnySendQueue *self, gboolean remove, GError **err)
+tny_send_queue_cancel (TnySendQueue *self, TnySendQueueCancelAction cancel_action, GError **err)
 {
 #ifdef DBC /* require */
 	g_assert (TNY_IS_SEND_QUEUE (self));
 	g_assert (TNY_SEND_QUEUE_GET_IFACE (self)->cancel_func != NULL);
 #endif
 
-	TNY_SEND_QUEUE_GET_IFACE (self)->cancel_func (self, remove, err);
+	TNY_SEND_QUEUE_GET_IFACE (self)->cancel_func (self, cancel_action, err);
 	return;
 }
 
Index: libtinymail/tny-send-queue.h
===================================================================
--- libtinymail/tny-send-queue.h	(revision 3282)
+++ libtinymail/tny-send-queue.h	(working copy)
@@ -48,6 +48,12 @@
 	TNY_SEND_QUEUE_LAST_SIGNAL
 };
 
+typedef enum
+{
+	TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND,
+	TNY_SEND_QUEUE_CANCEL_ACTION_REMOVE
+} TnySendQueueCancelAction;
+
 extern guint tny_send_queue_signals[TNY_SEND_QUEUE_LAST_SIGNAL];
 
 
@@ -64,7 +70,7 @@
 	void (*add_func) (TnySendQueue *self, TnyMsg *msg, GError **err);
 	TnyFolder* (*get_sentbox_func) (TnySendQueue *self);
 	TnyFolder* (*get_outbox_func) (TnySendQueue *self);
-	void (*cancel_func) (TnySendQueue *self, gboolean remove, GError **err);
+	void (*cancel_func) (TnySendQueue *self, TnySendQueueCancelAction cancel_action, GError **err);
 
 };
 
@@ -73,7 +79,7 @@
 void tny_send_queue_add (TnySendQueue *self, TnyMsg *msg, GError **err);
 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);
+void tny_send_queue_cancel (TnySendQueue *self, TnySendQueueCancelAction cancel_action, GError **err);
 
 G_END_DECLS
 


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