summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2011-03-08 11:39:06 -0500
committerDavid Zeuthen <davidz@redhat.com>2011-03-08 11:39:06 -0500
commit7dc0d1001df48dfa458834a80400ed2c38a4f0d8 (patch)
treee8ecec9b4a9dbff72f1bf62b0352e34f8e3c6452
parentb88ccc1ee609ef3384418d8763ab1a707b1426be (diff)
Use path_prefix match rule for efficiency
... but still handle the case where this match key is not available. For the record, this match key will will be available in future bus daemons. See https://bugs.freedesktop.org/show_bug.cgi?id=34869 https://bugs.freedesktop.org/show_bug.cgi?id=34870 for more details. Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r--src/gdbusproxymanager.c121
1 files changed, 96 insertions, 25 deletions
diff --git a/src/gdbusproxymanager.c b/src/gdbusproxymanager.c
index 106179b..5b0d8f0 100644
--- a/src/gdbusproxymanager.c
+++ b/src/gdbusproxymanager.c
@@ -126,6 +126,7 @@ struct _GDBusProxyManagerPrivate
GHashTable *map_object_path_to_object_proxy;
guint signal_subscription_id;
+ gchar *match_rule;
GDBusProxyTypeFunc get_proxy_type_func;
gpointer get_proxy_type_user_data;
@@ -1095,37 +1096,84 @@ static void
subscribe_signals (GDBusProxyManager *manager,
const gchar *name_owner)
{
+ GError *error;
+ GVariant *ret;
+
g_return_if_fail (G_IS_DBUS_PROXY_MANAGER (manager));
g_return_if_fail (manager->priv->signal_subscription_id == 0);
g_return_if_fail (g_dbus_is_unique_name (name_owner));
- /* Right now we just subscribe to *all* signals from the name owner which
- * is rather wasteful. It's probably not a big practical problem because
- * users typically want all objects that the name owner supplies.
- *
- * Anyway, it would be better to be able to say "match messages
- * where path is /foo/bar or below, e.g.
- *
- * type='signal',path='/foo/bar*'
- *
- * which would match all messages with a PATH header file that matches "/foo/bar*", e.g.
- *
- * "/foo/bar", "/foo/bar/object0", ... (but also /foo/barbar - big deal..)
- *
- * TODO: file a bug with dbus-1 and ask for this feature in the bus daemon.
+ /* the bus daemon may not implement path_prefix so gracefully
+ * handle this by using a fallback
*/
+ manager->priv->match_rule = g_strdup_printf ("type='signal',sender='%s',path_prefix='%s'",
+ name_owner,
+ manager->priv->object_path);
+
+ error = NULL;
+ ret = g_dbus_connection_call_sync (manager->priv->connection,
+ "org.freedesktop.DBus",
+ "/org/freedeskop/DBus",
+ "org.freedesktop.DBus",
+ "AddMatch",
+ g_variant_new ("(s)",
+ manager->priv->match_rule),
+ NULL, /* reply_type */
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, /* default timeout */
+ NULL, /* TODO: Cancellable */
+ &error);
+ if (ret != NULL)
+ {
+ /* yay, bus daemon supports path_prefix */
+ g_variant_unref (ret);
+
+ /* still need to ask GDBusConnection for the callbacks */
+ manager->priv->signal_subscription_id =
+ g_dbus_connection_signal_subscribe (manager->priv->connection,
+ name_owner,
+ NULL, /* interface */
+ NULL, /* member */
+ NULL, /* path - TODO: really want wilcard support here */
+ NULL, /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE |
+ G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
+ signal_cb,
+ manager,
+ NULL); /* user_data_free_func */
- manager->priv->signal_subscription_id =
- g_dbus_connection_signal_subscribe (manager->priv->connection,
- name_owner,
- NULL, /* interface */
- NULL, /* member */
- NULL, /* path - TODO: really want wilcard support here */
- NULL, /* arg0 */
- G_DBUS_SIGNAL_FLAGS_NONE,
- signal_cb,
- manager,
- NULL); /* user_data_free_func */
+ }
+ else
+ {
+ /* TODO: we could report this to the user
+ g_warning ("Message bus daemon does not support path_prefix: %s (%s %d)",
+ error->message,
+ g_quark_to_string (error->domain),
+ error->code);
+ */
+
+ g_error_free (error);
+
+ /* no need to call RemoveMatch when done since it didn't work */
+ g_free (manager->priv->match_rule);
+ manager->priv->match_rule = NULL;
+
+ /* Fallback is to subscribe to *all* signals from the name owner which
+ * is rather wasteful. It's probably not a big practical problem because
+ * users typically want all objects that the name owner supplies.
+ */
+ manager->priv->signal_subscription_id =
+ g_dbus_connection_signal_subscribe (manager->priv->connection,
+ name_owner,
+ NULL, /* interface */
+ NULL, /* member */
+ NULL, /* path - TODO: really want wilcard support here */
+ NULL, /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ signal_cb,
+ manager,
+ NULL); /* user_data_free_func */
+ }
}
static void
@@ -1139,6 +1187,29 @@ maybe_unsubscribe_signals (GDBusProxyManager *manager)
manager->priv->signal_subscription_id);
manager->priv->signal_subscription_id = 0;
}
+
+ if (manager->priv->match_rule != NULL)
+ {
+ /* Since the AddMatch call succeeded this is guaranteed to not
+ * fail - therefore, don't bother checking the return value
+ */
+ g_dbus_connection_call (manager->priv->connection,
+ "org.freedesktop.DBus",
+ "/org/freedeskop/DBus",
+ "org.freedesktop.DBus",
+ "RemoveMatch",
+ g_variant_new ("(s)",
+ manager->priv->match_rule),
+ NULL, /* reply_type */
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, /* default timeout */
+ NULL, /* GCancellable */
+ NULL, /* GAsyncReadyCallback */
+ NULL); /* user data */
+ g_free (manager->priv->match_rule);
+ manager->priv->match_rule = NULL;
+ }
+
}
/* ---------------------------------------------------------------------------------------------------- */