[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