diff options
author | David Zeuthen <davidz@redhat.com> | 2011-03-08 11:39:06 -0500 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2011-03-08 11:39:06 -0500 |
commit | 7dc0d1001df48dfa458834a80400ed2c38a4f0d8 (patch) | |
tree | e8ecec9b4a9dbff72f1bf62b0352e34f8e3c6452 | |
parent | b88ccc1ee609ef3384418d8763ab1a707b1426be (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.c | 121 |
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; + } + } /* ---------------------------------------------------------------------------------------------------- */ |