[telepathy-mission-control/master] McdDispatcher, McdConnection: wait for dispatcher to be ready before starting dispatcher processing on connections

Simon McVittie simon.mcvittie at collabora.co.uk
Mon May 18 03:51:01 PDT 2009


Also add some debug regarding the dispatcher's startup process.
---
 src/mcd-connection-priv.h |    2 +
 src/mcd-connection.c      |   23 ++++++++++++--
 src/mcd-dispatcher-priv.h |    4 ++
 src/mcd-dispatcher.c      |   72 +++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 94 insertions(+), 7 deletions(-)

diff --git a/src/mcd-connection-priv.h b/src/mcd-connection-priv.h
index 0890d8a..db5e6bb 100644
--- a/src/mcd-connection-priv.h
+++ b/src/mcd-connection-priv.h
@@ -44,6 +44,8 @@ void _mcd_connection_set_tp_connection (McdConnection *connection,
                                         const gchar *bus_name,
                                         const gchar *obj_path, GError **error);
 
+G_GNUC_INTERNAL void _mcd_connection_start_dispatching (McdConnection *self);
+
 G_END_DECLS
 
 #endif
diff --git a/src/mcd-connection.c b/src/mcd-connection.c
index 17f592a..cbaad2d 100644
--- a/src/mcd-connection.c
+++ b/src/mcd-connection.c
@@ -114,6 +114,8 @@ struct _McdConnectionPrivate
     guint has_contact_capabilities_if : 1;
     guint has_requests_if : 1;
 
+    /* FALSE until the dispatcher has said it's ready for us */
+    guint dispatching_started : 1;
     /* FALSE until channels announced by NewChannel/NewChannels need to be
      * dispatched */
     guint dispatched_initial_channels : 1;
@@ -1415,13 +1417,26 @@ on_connection_ready (TpConnection *tp_conn, const GError *error,
     if (priv->has_alias_if)
 	_mcd_connection_setup_alias (connection);
 
-    if (priv->has_requests_if)
-        mcd_connection_setup_requests (connection);
+    _mcd_dispatcher_add_connection (priv->dispatcher, connection);
+}
+
+void
+_mcd_connection_start_dispatching (McdConnection *self)
+{
+    g_return_if_fail (MCD_IS_CONNECTION (self));
+    g_return_if_fail (!self->priv->dispatching_started);
+
+    DEBUG ("%p", self);
+
+    self->priv->dispatching_started = TRUE;
+
+    if (self->priv->has_requests_if)
+        mcd_connection_setup_requests (self);
     else
-        mcd_connection_setup_pre_requests (connection);
+        mcd_connection_setup_pre_requests (self);
 
     /* and request all channels */
-    request_unrequested_channels (connection);
+    request_unrequested_channels (self);
 }
 
 static void
diff --git a/src/mcd-dispatcher-priv.h b/src/mcd-dispatcher-priv.h
index 5000f9b..9b1fc7d 100644
--- a/src/mcd-dispatcher-priv.h
+++ b/src/mcd-dispatcher-priv.h
@@ -28,6 +28,7 @@
 #define MCD_DISPATCHER_PRIV_H
 
 #include "mcd-dispatcher.h"
+#include "mcd-connection.h"
 
 G_BEGIN_DECLS
 
@@ -54,6 +55,9 @@ G_GNUC_INTERNAL
 void _mcd_dispatcher_recover_channel (McdDispatcher *dispatcher,
                                       McdChannel *channel);
 
+G_GNUC_INTERNAL void _mcd_dispatcher_add_connection (McdDispatcher *self,
+    McdConnection *connection);
+
 G_END_DECLS
 
 #endif /* MCD_DISPATCHER_H */
diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c
index 2186cb0..05dce93 100644
--- a/src/mcd-dispatcher.c
+++ b/src/mcd-dispatcher.c
@@ -46,6 +46,7 @@
 #include "mcd-signals-marshal.h"
 #include "mcd-account-priv.h"
 #include "mcd-connection.h"
+#include "mcd-connection-priv.h"
 #include "mcd-channel.h"
 #include "mcd-master.h"
 #include "mcd-channel-priv.h"
@@ -215,6 +216,9 @@ struct _McdDispatcherPrivate
     gsize startup_lock;
     gboolean startup_completed;
 
+    /* connection => itself, borrowed */
+    GHashTable *connections;
+
     /* Initially FALSE, meaning we suppress OperationList.DispatchOperations
      * change notification signals because nobody has retrieved that property
      * yet. Set to TRUE the first time someone reads the DispatchOperations
@@ -1856,14 +1860,27 @@ mcd_dispatcher_release_startup_lock (McdDispatcher *self)
     if (self->priv->startup_completed)
         return;
 
+    DEBUG ("%p (decrementing from %" G_GSIZE_FORMAT ")",
+           self, self->priv->startup_lock);
+
     g_assert (self->priv->startup_lock >= 1);
 
     self->priv->startup_lock--;
 
     if (self->priv->startup_lock == 0)
     {
+        GHashTableIter iter;
+        gpointer k;
+
         DEBUG ("All initial clients have been inspected");
         self->priv->startup_completed = TRUE;
+
+        g_hash_table_iter_init (&iter, self->priv->connections);
+
+        while (g_hash_table_iter_next (&iter, &k, NULL))
+        {
+            _mcd_connection_start_dispatching (k);
+        }
     }
 }
 
@@ -2031,12 +2048,16 @@ get_interfaces_cb (TpProxy *proxy,
         arr++;
     }
 
+    DEBUG ("Client %s", client->name);
+
     client_add_interface_by_id (client);
     if (client->interfaces & MCD_CLIENT_APPROVER)
     {
         if (!self->priv->startup_completed)
             self->priv->startup_lock++;
 
+        DEBUG ("%s is an Approver", client->name);
+
         tp_cli_dbus_properties_call_get
             (client->proxy, -1, MC_IFACE_CLIENT_APPROVER,
              "ApproverChannelFilter", get_channel_filter_cb,
@@ -2047,6 +2068,8 @@ get_interfaces_cb (TpProxy *proxy,
         if (!self->priv->startup_completed)
             self->priv->startup_lock++;
 
+        DEBUG ("%s is a Handler", client->name);
+
         tp_cli_dbus_properties_call_get_all
             (client->proxy, -1, MC_IFACE_CLIENT_HANDLER,
              handler_get_all_cb, NULL, NULL, G_OBJECT (self));
@@ -2056,6 +2079,8 @@ get_interfaces_cb (TpProxy *proxy,
         if (!self->priv->startup_completed)
             self->priv->startup_lock++;
 
+        DEBUG ("%s is an Observer", client->name);
+
         tp_cli_dbus_properties_call_get
             (client->proxy, -1, MC_IFACE_CLIENT_OBSERVER,
              "ObserverChannelFilter", get_channel_filter_cb,
@@ -2313,6 +2338,8 @@ list_names_cb (TpDBusDaemon *proxy,
 {
     McdDispatcher *self = MCD_DISPATCHER (weak_object);
 
+    DEBUG ("ListNames returned");
+
     new_names_cb (self, out0, FALSE);
 
     /* paired with one of the two locks in _constructed */
@@ -2328,6 +2355,8 @@ list_activatable_names_cb (TpDBusDaemon *proxy,
 {
     McdDispatcher *self = MCD_DISPATCHER (weak_object);
 
+    DEBUG ("ListActivatableNames returned");
+
     new_names_cb (self, out0, TRUE);
 
     /* paired with one of the two locks in _constructed */
@@ -2396,6 +2425,10 @@ mcd_dispatcher_constructed (GObject *object)
     McdDispatcherPrivate *priv = MCD_DISPATCHER_PRIV (object);
     GError *error = NULL;
 
+    DEBUG ("Starting to look for clients");
+    priv->startup_completed = FALSE;
+    priv->startup_lock = 2;   /* ListNames + ListActivatableNames */
+
     tp_cli_dbus_daemon_connect_to_name_owner_changed (priv->dbus_daemon,
         name_owner_changed_cb, NULL, NULL, object, NULL);
 
@@ -2405,9 +2438,6 @@ mcd_dispatcher_constructed (GObject *object)
     tp_cli_dbus_daemon_call_list_names (priv->dbus_daemon,
         -1, list_names_cb, NULL, NULL, object);
 
-    priv->startup_completed = FALSE;
-    priv->startup_lock = 2;   /* ListNames + ListActivatableNames */
-
     dgc = TP_PROXY (priv->dbus_daemon)->dbus_connection;
 
     if (!_mcd_dbus_daemon_request_name (priv->dbus_daemon,
@@ -2582,6 +2612,8 @@ mcd_dispatcher_init (McdDispatcher * dispatcher)
 
     priv->clients = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
         (GDestroyNotify) mcd_client_free);
+
+    priv->connections = g_hash_table_new (NULL, NULL);
 }
 
 McdDispatcher *
@@ -3506,3 +3538,37 @@ dispatcher_iface_init (gpointer g_iface,
     IMPLEMENT (ensure_channel);
 #undef IMPLEMENT
 }
+
+static void
+mcd_dispatcher_lost_connection (gpointer data,
+                                GObject *corpse)
+{
+    McdDispatcher *self = MCD_DISPATCHER (data);
+
+    /* not safe to dereference corpse any more, so just print its address -
+     * that's enough to pair up with add_connection calls */
+    DEBUG ("%p: %p", self, corpse);
+
+    g_hash_table_remove (self->priv->connections, corpse);
+}
+
+void
+_mcd_dispatcher_add_connection (McdDispatcher *self,
+                                McdConnection *connection)
+{
+    g_return_if_fail (MCD_IS_DISPATCHER (self));
+
+    DEBUG ("%p: %p (%s)", self, connection,
+           mcd_connection_get_object_path (connection));
+
+    g_hash_table_insert (self->priv->connections, connection, connection);
+    g_object_weak_ref ((GObject *) connection, mcd_dispatcher_lost_connection,
+                       g_object_ref (self));
+
+    if (self->priv->startup_completed)
+    {
+        _mcd_connection_start_dispatching (connection);
+    }
+    /* else _mcd_connection_start_dispatching will be called when we're ready
+     * for it */
+}
-- 
1.5.6.5




More information about the telepathy-commits mailing list