[Telepathy-commits] [telepathy-mission-control/master] Rewrite error handling on channel requests

Alberto Mardegan alberto.mardegan at nokia.com
Mon Nov 17 00:05:21 PST 2008


It doesn't seem right that errors occurred while creating accounts are emitted
on the channel dispatcher as dispatch errors. So, this patch moves handling of
these errors to the code in McdAccount which creates the requests, by having
the error stored in the McdChannel and inspected when the channel status
changes to FAILED.
Then the error on the dispatcher is issued from mcd-account.c; it's still
wrong, but we need it if we want to behave as MC4 did.
---
 src/mcd-account.c    |   33 +++++++++++++++++++++++++++++++++
 src/mcd-channel.c    |   32 ++++++++++++++++++++++++++++++++
 src/mcd-channel.h    |    7 +++++--
 src/mcd-connection.c |   17 ++++-------------
 4 files changed, 74 insertions(+), 15 deletions(-)

diff --git a/src/mcd-account.c b/src/mcd-account.c
index 7bbebbe..8748117 100644
--- a/src/mcd-account.c
+++ b/src/mcd-account.c
@@ -2142,6 +2142,37 @@ process_channel_request (McdAccount *account, gpointer userdata,
     mcd_connection_request_channel (priv->connection, channel, &err);
 }
 
+static void
+on_channel_status_changed (McdChannel *channel, McdChannelStatus status,
+                           McdAccount *account)
+{
+    g_debug ("%s (%u)", G_STRFUNC, status);
+    g_return_if_fail (MCD_IS_ACCOUNT (account));
+
+    if (status == MCD_CHANNEL_DISPATCHING)
+    {
+        /* from now on, errors are reported by the dispatcher */
+        g_signal_handlers_disconnect_by_func (channel,
+                                              on_channel_status_changed,
+                                              account);
+    }
+    else if (status == MCD_CHANNEL_FAILED)
+    {
+        const GError *error;
+        McdMaster *master;
+        McdDispatcher *dispatcher = NULL;
+
+        master = mcd_master_get_default ();
+        g_object_get (master, "dispatcher", &dispatcher, NULL);
+        g_return_if_fail (dispatcher != NULL);
+
+        error = _mcd_channel_get_error (channel);
+        g_signal_emit_by_name (G_OBJECT(dispatcher),
+                               "dispatch-failed", channel, error);
+        g_object_unref (dispatcher);
+    }
+}
+
 gboolean
 mcd_account_request_channel_nmc4 (McdAccount *account,
 				  const struct mcd_channel_request *req,
@@ -2159,6 +2190,8 @@ mcd_account_request_channel_nmc4 (McdAccount *account,
 			       req->requestor_client_id);
     _mcd_channel_set_target_id (channel, req->channel_handle_string);
     mcd_channel_set_status (channel, MCD_CHANNEL_NO_PROXY);
+    g_signal_connect (channel, "status-changed",
+                      G_CALLBACK (on_channel_status_changed), account);
 
     return mcd_account_online_request (account,
 				       process_channel_request,
diff --git a/src/mcd-channel.c b/src/mcd-channel.c
index 15d945a..01d9587 100644
--- a/src/mcd-channel.c
+++ b/src/mcd-channel.c
@@ -1171,3 +1171,35 @@ _mcd_channel_get_target_id (McdChannel *channel)
     return g_object_get_data ((GObject *)channel, "TargetID");
 }
 
+/*
+ * _mcd_channel_set_error:
+ * @channel: the #McdChannel.
+ * @error: a #GError.
+ *
+ * Sets @error on channel, and takes ownership of it. As a side effect, if
+ * @error is not %NULL this method causes the channel status be set to
+ * %MCD_CHANNEL_FAILED.
+ */
+void
+_mcd_channel_set_error (McdChannel *channel, GError *error)
+{
+    g_return_if_fail (MCD_IS_CHANNEL (channel));
+    g_object_set_data_full ((GObject *)channel, "Error",
+                            error, (GDestroyNotify)g_error_free);
+    if (error)
+        mcd_channel_set_status (channel, MCD_CHANNEL_FAILED);
+}
+
+/*
+ * _mcd_channel_get_error:
+ * @channel: the #McdChannel.
+ *
+ * Returns: the #GError, or %NULL if no error is set.
+ */
+const GError *
+_mcd_channel_get_error (McdChannel *channel)
+{
+    g_return_val_if_fail (MCD_IS_CHANNEL (channel), NULL);
+    return g_object_get_data ((GObject *)channel, "Error");
+}
+
diff --git a/src/mcd-channel.h b/src/mcd-channel.h
index 4268d2f..aa82650 100644
--- a/src/mcd-channel.h
+++ b/src/mcd-channel.h
@@ -52,8 +52,8 @@ typedef enum
     MCD_CHANNEL_NO_PROXY,     /* Telepathy channel is not yet created */
     MCD_CHANNEL_DISPATCHING, /* Telepathy channel is created and waiting dispatch */
     MCD_CHANNEL_DISPATCHED,  /* Channel has been dispatched to handler */
-    MCD_CHANNEL_FAILED,      /* Channel could not be dispached to handler, dying */
-    
+    MCD_CHANNEL_FAILED,      /* Channel creation failed, or channel could not
+                                be dispached to a handler */
 } McdChannelStatus;
 
 struct _McdChannel
@@ -130,5 +130,8 @@ void _mcd_channel_set_target_id (McdChannel *channel,
                                  const gchar *target_id);
 const gchar *_mcd_channel_get_target_id (McdChannel *channel);
 
+void _mcd_channel_set_error (McdChannel *channel, GError *error);
+const GError *_mcd_channel_get_error (McdChannel *channel);
+
 G_END_DECLS
 #endif /* MCD_CHANNEL_H */
diff --git a/src/mcd-connection.c b/src/mcd-connection.c
index 08aeaa8..3d0bf01 100644
--- a/src/mcd-connection.c
+++ b/src/mcd-connection.c
@@ -663,7 +663,6 @@ static gboolean
 on_channel_capabilities_timeout (McdChannel *channel,
 				 McdConnection *connection)
 {
-    McdConnectionPrivate *priv = MCD_CONNECTION_PRIV (connection);
     struct capabilities_wait_data *cwd;
     GError *mc_error;
 
@@ -675,9 +674,7 @@ on_channel_capabilities_timeout (McdChannel *channel,
     g_debug ("%s: channel %p timed out, returning error!", G_STRFUNC, channel);
 
     mc_error = map_tp_error_to_mc_error (channel, cwd->error);
-    g_signal_emit_by_name (G_OBJECT(priv->dispatcher), "dispatch-failed",
-			   channel, mc_error);
-    g_error_free (mc_error);
+    _mcd_channel_set_error (channel, mc_error);
     g_object_set_data (G_OBJECT (channel), "error_on_creation", NULL);
 
     /* No abort on channel, because we are the only one holding the only
@@ -2047,9 +2044,7 @@ request_channel_cb (TpConnection *proxy, const gchar *channel_path,
 	{
 	    /* Faild dispatch */
 	    GError *mc_error = map_tp_error_to_mc_error (channel, tp_error);
-	    g_signal_emit_by_name (G_OBJECT(priv->dispatcher), "dispatch-failed",
-				   channel, mc_error);
-	    g_error_free (mc_error);
+            _mcd_channel_set_error (channel, mc_error);
             mcd_mission_abort ((McdMission *)channel);
 	}
 	else
@@ -2082,9 +2077,7 @@ request_channel_cb (TpConnection *proxy, const gchar *channel_path,
 	mc_error = g_error_new (MC_ERROR,
 				MC_CHANNEL_REQUEST_GENERIC_ERROR,
 				"Returned channel_path from telepathy is NULL");
-	g_signal_emit_by_name (G_OBJECT(priv->dispatcher),
-			       "dispatch-failed", channel, mc_error);
-	g_error_free (mc_error);
+        _mcd_channel_set_error (channel, mc_error);
         mcd_mission_abort ((McdMission *)channel);
 	return;
     }
@@ -2127,9 +2120,7 @@ request_handles_cb (TpConnection *proxy, const GArray *handles,
 	mc_error = g_error_new (MC_ERROR, MC_INVALID_HANDLE_ERROR,
 		     "Could not map string handle to a valid handle!: %s",
 		     msg);
-	g_signal_emit_by_name (priv->dispatcher, "dispatch-failed",
-			       channel, mc_error);
-	g_error_free (mc_error);
+        _mcd_channel_set_error (channel, mc_error);
 	
 	/* No abort, because we are the only one holding the only reference
 	 * to this temporary channel
-- 
1.5.6.5




More information about the Telepathy-commits mailing list