commit 02ea44a1484abb69e2a5e9e50c0e8ca4846c9bf8 Author: Alban Crequy Date: Fri Jan 28 12:00:44 2011 +0000 DBusGProxy: remove duplicate owner match rules. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=33646 diff --git a/dbus/dbus-gproxy.c b/dbus/dbus-gproxy.c index 1e7331f..aa08771 100644 --- a/dbus/dbus-gproxy.c +++ b/dbus/dbus-gproxy.c @@ -147,8 +147,14 @@ struct _DBusGProxyManager GHashTable *proxy_lists; /**< Hash used to route incoming signals * and iterate over proxies + * tristring -> DBusGProxyList + */ + GHashTable *owner_match_rules; /**< Hash to keep track of match rules of + * NameOwnerChanged. + * gchar *name -> guint refcount */ GHashTable *owner_names; /**< Hash to keep track of mapping from + * char * -> GSList of DBusGProxyNameOwnerInfo * base name -> [name,name,...] for proxies which * are for names. */ @@ -260,6 +266,16 @@ dbus_g_proxy_manager_unref (DBusGProxyManager *manager) } + if (manager->owner_match_rules) + { + /* Since we destroyed all proxies, none can be tracking + * name owners + */ + g_assert (g_hash_table_size (manager->owner_match_rules) == 0); + g_hash_table_destroy (manager->owner_match_rules); + manager->owner_match_rules = NULL; + } + if (manager->owner_names) { /* Since we destroyed all proxies, none can be tracking @@ -485,18 +501,13 @@ g_proxy_get_signal_match_rule (DBusGProxy *proxy) } static char * -g_proxy_get_owner_match_rule (DBusGProxy *proxy) +get_owner_match_rule (const gchar *name) { - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - if (priv->name) - { return g_strdup_printf ("type='signal',sender='" DBUS_SERVICE_DBUS "',path='" DBUS_PATH_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged'" - ",arg0='%s'", priv->name); - } - return NULL; + ",arg0='%s'", name); } typedef struct @@ -922,6 +933,7 @@ dbus_g_proxy_manager_register (DBusGProxyManager *manager, if (manager->proxy_lists == NULL) { g_assert (manager->owner_names == NULL); + g_assert (manager->owner_match_rules == NULL); list = NULL; manager->proxy_lists = g_hash_table_new_full (tristring_hash, @@ -932,6 +944,10 @@ dbus_g_proxy_manager_register (DBusGProxyManager *manager, g_str_equal, g_free, NULL); + manager->owner_match_rules = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); } else { @@ -958,21 +974,35 @@ dbus_g_proxy_manager_register (DBusGProxyManager *manager, * but only if the server is a message bus, * not if it's a peer. */ - char *rule; - - rule = g_proxy_get_signal_match_rule (proxy); - /* We don't check for errors; it's not like anyone would handle them, and - * we don't want a round trip here. - */ - dbus_bus_add_match (manager->connection, - rule, NULL); - g_free (rule); + char *rule; + gpointer orig_key, value; + + rule = g_proxy_get_signal_match_rule (proxy); + /* We don't check for errors; it's not like anyone would handle them, and + * we don't want a round trip here. + */ + dbus_bus_add_match (manager->connection, rule, NULL); + g_free (rule); - rule = g_proxy_get_owner_match_rule (proxy); - if (rule) - dbus_bus_add_match (manager->connection, - rule, NULL); - g_free (rule); + if (g_hash_table_lookup_extended (manager->owner_match_rules, + priv->name, &orig_key, &value)) + { + /* The owner match rule is already here. Increment the refcount */ + gint count = GPOINTER_TO_INT (value) + 1; + g_hash_table_steal (manager->owner_match_rules, orig_key); + g_hash_table_insert (manager->owner_match_rules, orig_key, + GINT_TO_POINTER (count)); + } + else + { + char *rule; + rule = get_owner_match_rule (priv->name); + dbus_bus_add_match (manager->connection, + rule, NULL); + g_free (rule); + g_hash_table_insert (manager->owner_match_rules, g_strdup (priv->name), + GINT_TO_POINTER (1)); + } } g_assert (g_slist_find (list->proxies, proxy) == NULL); @@ -1071,19 +1101,35 @@ dbus_g_proxy_manager_unregister (DBusGProxyManager *manager, if (list->proxies == NULL) { char *rule; + gpointer orig_key, value; + g_hash_table_remove (manager->proxy_lists, tri); - list = NULL; rule = g_proxy_get_signal_match_rule (proxy); dbus_bus_remove_match (manager->connection, rule, NULL); g_free (rule); - rule = g_proxy_get_owner_match_rule (proxy); - if (rule) - dbus_bus_remove_match (manager->connection, - rule, NULL); - g_free (rule); + + if (priv->name && g_hash_table_lookup_extended ( + manager->owner_match_rules, priv->name, &orig_key, &value)) + { + gint count = GPOINTER_TO_INT (value) - 1; + if (count == 0) + { + rule = get_owner_match_rule (priv->name); + dbus_bus_remove_match (manager->connection, + rule, NULL); + g_free (rule); + g_hash_table_remove (manager->owner_match_rules, priv->name); + } + else + { + g_hash_table_steal (manager->owner_match_rules, orig_key); + g_hash_table_insert (manager->owner_match_rules, orig_key, + GINT_TO_POINTER (count)); + } + } } if (g_hash_table_size (manager->proxy_lists) == 0) @@ -1092,6 +1138,12 @@ dbus_g_proxy_manager_unregister (DBusGProxyManager *manager, manager->proxy_lists = NULL; } + if (g_hash_table_size (manager->owner_match_rules) == 0) + { + g_hash_table_destroy (manager->owner_match_rules); + manager->owner_match_rules = NULL; + } + g_free (tri); UNLOCK_MANAGER (manager);