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);