Re: Patch for the send queue



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.
Index: tny-camel-send-queue.c
===================================================================
--- tny-camel-send-queue.c	(revision 3278)
+++ 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);
 
@@ -519,7 +557,6 @@
 	g_mutex_lock (priv->sending_lock);
 
 	priv->is_running = FALSE;
-	priv->do_continue = FALSE;
 
 	if (remove)
 	{
@@ -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 3278)
+++ ../libtinymail/tny-send-queue.c	(working copy)
@@ -202,7 +202,8 @@
  * @arg3: a GError containing the error that happened
  * @arg4: (null-ok): user data
  *
- * Emitted when a message didn't get sent because of an error
+ * Emitted when a message didn't get sent because of an error. Note
+ * that the send queue will stop until the callback is finished
  **/
 		tny_send_queue_signals[TNY_SEND_QUEUE_ERROR_HAPPENED] =
 			g_signal_new ("error_happened",


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