diff --git a/src/nm-device.c b/src/nm-device.c index f20b5a323a..72b6890796 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -4639,6 +4639,18 @@ nm_device_state_changed (NMDevice *device, "Activation (%s) failed for connection '%s'", nm_device_get_iface (device), nm_connection_get_id (connection)); + + /* If the connection doesn't yet have a timestamp, set it to zero so that + * we can distinguish between connections we've tried to activate and have + * failed (zero timestamp), connections that succeeded (non-zero timestamp), + * and those we haven't tried yet (no timestamp). + */ + if (!nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), NULL)) { + nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (connection), + (guint64) 0, + TRUE); + } + /* Schedule the transition to DISCONNECTED. The device can't transition * immediately because we can't change states again from the state * handler for a variety of reasons. diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index ddc758c710..c1c55b058c 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -16,7 +16,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * (C) Copyright 2008 Novell, Inc. - * (C) Copyright 2008 - 2011 Red Hat, Inc. + * (C) Copyright 2008 - 2012 Red Hat, Inc. */ #include "config.h" @@ -107,6 +107,7 @@ typedef struct { NMConnection *agent_secrets; guint64 timestamp; /* Up-to-date timestamp of connection use */ + gboolean timestamp_set; GHashTable *seen_bssids; /* Up-to-date BSSIDs that's been seen for the connection */ } NMSettingsConnectionPrivate; @@ -1061,7 +1062,7 @@ get_settings_auth_cb (NMSettingsConnection *self, GHashTable *settings; NMConnection *dupl_con; NMSettingConnection *s_con; - guint64 timestamp; + guint64 timestamp = 0; dupl_con = nm_connection_duplicate (NM_CONNECTION (self)); g_assert (dupl_con); @@ -1072,7 +1073,7 @@ get_settings_auth_cb (NMSettingsConnection *self, * timestamps are kept track of in a private variable. So, substitute * timestamp property with the real one here before returning the settings. */ - timestamp = nm_settings_connection_get_timestamp (self); + nm_settings_connection_get_timestamp (self, ×tamp); if (timestamp) { s_con = nm_connection_get_setting_connection (NM_CONNECTION (dupl_con)); g_assert (s_con); @@ -1403,18 +1404,23 @@ nm_settings_connection_signal_remove (NMSettingsConnection *self) /** * nm_settings_connection_get_timestamp: * @connection: the #NMSettingsConnection + * @out_timestamp: the connection's timestamp * - * Returns current connection's timestamp. + * Returns the time (in seconds since the Unix epoch) when the connection + * was last successfully activated. * - * Returns: timestamp of the last connection use (0 when it's not used) + * Returns: %TRUE if the timestamp has ever been set, otherwise %FALSE. **/ -guint64 -nm_settings_connection_get_timestamp (NMSettingsConnection *connection) +gboolean +nm_settings_connection_get_timestamp (NMSettingsConnection *connection, + guint64 *out_timestamp) { g_return_val_if_fail (connection != NULL, 0); g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (connection), 0); - return NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->timestamp; + if (out_timestamp) + *out_timestamp = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->timestamp; + return NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->timestamp_set; } /** @@ -1440,6 +1446,7 @@ nm_settings_connection_update_timestamp (NMSettingsConnection *connection, /* Update timestamp in private storage */ priv->timestamp = timestamp; + priv->timestamp_set = TRUE; if (flush_to_disk == FALSE) return; @@ -1497,9 +1504,10 @@ nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *connection } /* Update connection's timestamp */ - if (!err) + if (!err) { priv->timestamp = timestamp; - else { + priv->timestamp_set = TRUE; + } else { nm_log_dbg (LOGD_SETTINGS, "failed to read connection timestamp for '%s': (%d) %s", connection_uuid, err->code, err->message); g_clear_error (&err); diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h index 9a0e866c49..73ca8192ad 100644 --- a/src/settings/nm-settings-connection.h +++ b/src/settings/nm-settings-connection.h @@ -122,7 +122,8 @@ gboolean nm_settings_connection_check_permission (NMSettingsConnection *self, void nm_settings_connection_signal_remove (NMSettingsConnection *self); -guint64 nm_settings_connection_get_timestamp (NMSettingsConnection *connection); +gboolean nm_settings_connection_get_timestamp (NMSettingsConnection *connection, + guint64 *out_timestamp); void nm_settings_connection_update_timestamp (NMSettingsConnection *connection, guint64 timestamp, diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index ea0ff31a5d..1d3c74f6e9 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -287,7 +287,7 @@ connection_sort (gconstpointer pa, gconstpointer pb) NMSettingConnection *con_a; NMConnection *b = NM_CONNECTION (pb); NMSettingConnection *con_b; - guint64 ts_a, ts_b; + guint64 ts_a = 0, ts_b = 0; con_a = nm_connection_get_setting_connection (a); g_assert (con_a); @@ -300,8 +300,8 @@ connection_sort (gconstpointer pa, gconstpointer pb) return 1; } - ts_a = nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (pa)); - ts_b = nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (pb)); + nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (pa), &ts_a); + nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (pb), &ts_b); if (ts_a > ts_b) return -1; else if (ts_a == ts_b) @@ -1657,7 +1657,7 @@ best_connection_sort (gconstpointer a, gconstpointer b, gpointer user_data) { NMSettingsConnection *ac = (NMSettingsConnection *) a; NMSettingsConnection *bc = (NMSettingsConnection *) b; - guint64 ats, bts; + guint64 ats = 0, bts = 0; if (!ac && bc) return -1; @@ -1669,8 +1669,8 @@ best_connection_sort (gconstpointer a, gconstpointer b, gpointer user_data) g_assert (ac && bc); /* In the future we may use connection priorities in addition to timestamps */ - ats = nm_settings_connection_get_timestamp (ac); - bts = nm_settings_connection_get_timestamp (bc); + nm_settings_connection_get_timestamp (ac, &ats); + nm_settings_connection_get_timestamp (bc, &bts); if (ats < bts) return -1; @@ -1697,6 +1697,8 @@ get_best_connections (NMConnectionProvider *provider, g_hash_table_iter_init (&iter, priv->connections); while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) { + guint64 cur_ts = 0; + if (ctype1 && !nm_connection_is_type (NM_CONNECTION (connection), ctype1)) continue; if (ctype2 && !nm_connection_is_type (NM_CONNECTION (connection), ctype2)) @@ -1705,10 +1707,11 @@ get_best_connections (NMConnectionProvider *provider, continue; /* Don't bother with a connection that's older than the oldest one in the list */ - if ( max_requested - && added >= max_requested - && nm_settings_connection_get_timestamp (connection) <= oldest) - continue; + if (max_requested && added >= max_requested) { + nm_settings_connection_get_timestamp (connection, &cur_ts); + if (cur_ts <= oldest) + continue; + } /* List is sorted with oldest first */ sorted = g_slist_insert_sorted_with_data (sorted, connection, best_connection_sort, NULL); @@ -1720,7 +1723,7 @@ get_best_connections (NMConnectionProvider *provider, added--; } - oldest = nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (sorted->data)); + nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (sorted->data), &oldest); } return g_slist_reverse (sorted);