From 02ec76df5aaa3a3ad197cb1d53c0388029775b07 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 20 Jan 2016 17:44:50 +0100 Subject: [PATCH] device: cleanup handling available-connections For update, don't delete first and add it again. Just do it in one step. For recheck, don't delete all connections first to add them all anew. Instead, check what changes and only emit the changed signal if there are any actual changes. --- src/devices/nm-device.c | 120 +++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 51 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 010c7fe99c..84b50451e7 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -9285,32 +9285,28 @@ nm_device_check_connection_available (NMDevice *self, static void available_connections_notify (NMDevice *self) { - g_object_notify (G_OBJECT (self), NM_DEVICE_AVAILABLE_CONNECTIONS); -} - -static void -available_connections_del_all (NMDevice *self, gboolean do_signal) -{ - g_hash_table_remove_all (NM_DEVICE_GET_PRIVATE (self)->available_connections); - if (do_signal == TRUE) - available_connections_notify (self); + g_object_notify ((GObject *) self, NM_DEVICE_AVAILABLE_CONNECTIONS); } static gboolean -available_connections_update (NMDevice *self, NMConnection *connection) +available_connections_del_all (NMDevice *self) { - if (nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL)) { - g_hash_table_add (NM_DEVICE_GET_PRIVATE (self)->available_connections, - g_object_ref (connection)); - return TRUE; - } - return FALSE; + if (g_hash_table_size (self->priv->available_connections) == 0) + return FALSE; + g_hash_table_remove_all (self->priv->available_connections); + return TRUE; } static gboolean -_del_available_connection (NMDevice *self, NMConnection *connection) +available_connections_add (NMDevice *self, NMConnection *connection) { - return g_hash_table_remove (NM_DEVICE_GET_PRIVATE (self)->available_connections, connection); + return nm_g_hash_table_add (self->priv->available_connections, g_object_ref (connection)); +} + +static gboolean +available_connections_del (NMDevice *self, NMConnection *connection) +{ + return g_hash_table_remove (self->priv->available_connections, connection); } static gboolean @@ -9345,22 +9341,51 @@ nm_device_recheck_available_connections (NMDevice *self) { NMDevicePrivate *priv; const GSList *connections, *iter; + gboolean changed = FALSE; + GHashTableIter h_iter; + NMConnection *connection; g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE(self); if (priv->con_provider) { - available_connections_del_all (self, FALSE); + gs_unref_hashtable GHashTable *prune_list = NULL; + + if (g_hash_table_size (priv->available_connections) > 0) { + prune_list = g_hash_table_new (g_direct_hash, g_direct_equal); + g_hash_table_iter_init (&h_iter, priv->available_connections); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) + g_hash_table_add (prune_list, connection); + } connections = nm_connection_provider_get_connections (priv->con_provider); - for (iter = connections; iter; iter = g_slist_next (iter)) - available_connections_update (self, NM_CONNECTION (iter->data)); + for (iter = connections; iter; iter = g_slist_next (iter)) { + connection = NM_CONNECTION (iter->data); - available_connections_notify (self); + if (available_connections_add (self, connection)) { + if (prune_list) + g_hash_table_remove (prune_list, connection); + changed = TRUE; + } + } + + if (prune_list) { + g_hash_table_iter_init (&h_iter, prune_list); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) { + if (available_connections_del (self, connection)) + changed = TRUE; + } + } + } else { + if (available_connections_del_all (self)) + changed = TRUE; } - available_connections_check_delete_unrealized (self); + if (changed) { + available_connections_notify (self); + available_connections_check_delete_unrealized (self); + } } /** @@ -9400,14 +9425,26 @@ nm_device_get_available_connections (NMDevice *self, const char *specific_object } static void -cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) +cp_connection_added_or_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) { + gboolean changed; NMDevice *self = user_data; g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection)); - if (available_connections_update (self, connection)) + if (nm_device_check_connection_available (self, + connection, + NM_DEVICE_CHECK_CON_AVAILABLE_NONE, + NULL)) + changed = available_connections_add (self, connection); + else + changed = available_connections_del (self, connection); + + if (changed) { available_connections_notify (self); + available_connections_check_delete_unrealized (self); + } } static void @@ -9417,26 +9454,7 @@ cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpoin g_return_if_fail (NM_IS_DEVICE (self)); - if (_del_available_connection (self, connection)) { - available_connections_notify (self); - available_connections_check_delete_unrealized (self); - } -} - -static void -cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) -{ - NMDevice *self = user_data; - gboolean added, deleted; - - g_return_if_fail (NM_IS_DEVICE (self)); - - /* FIXME: don't remove it from the hash if it's just going to get re-added */ - deleted = _del_available_connection (self, connection); - added = available_connections_update (self, connection); - - /* Only signal if the connection was removed OR added, but not both */ - if (added != deleted) { + if (available_connections_del (self, connection)) { available_connections_notify (self); available_connections_check_delete_unrealized (self); } @@ -10058,7 +10076,8 @@ _set_state_full (NMDevice *self, req = priv->act_request ? g_object_ref (priv->act_request) : NULL; if (state <= NM_DEVICE_STATE_UNAVAILABLE) { - available_connections_del_all (self, TRUE); + if (available_connections_del_all (self)) + available_connections_notify (self); _clear_queued_act_request (priv); } @@ -10746,7 +10765,7 @@ constructed (GObject *object) g_assert (priv->con_provider); g_signal_connect (priv->con_provider, NM_CP_SIGNAL_CONNECTION_ADDED, - G_CALLBACK (cp_connection_added), + G_CALLBACK (cp_connection_added_or_updated), self); g_signal_connect (priv->con_provider, @@ -10756,7 +10775,7 @@ constructed (GObject *object) g_signal_connect (priv->con_provider, NM_CP_SIGNAL_CONNECTION_UPDATED, - G_CALLBACK (cp_connection_updated), + G_CALLBACK (cp_connection_added_or_updated), self); /* Update default-unmanaged device available connections immediately, @@ -10811,13 +10830,12 @@ dispose (GObject *object) link_disconnect_action_cancel (self); if (priv->con_provider) { - g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_added_or_updated, self); g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_removed, self); - g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_updated, self); priv->con_provider = NULL; } - g_hash_table_remove_all (priv->available_connections); + available_connections_del_all (self); nm_clear_g_source (&priv->carrier_wait_id);