core: define a full sort order for nm_settings_connection_cmp_timestamp()

We want to have some guaranteed order when comparing different connections.
So, in case of equal timestamps, proceed with comparing more properties.

It makes sense to consider the autoconnect-priority next.
This is what get_existing_connection() needs, thus we no longer
need to pre-sort the list.
This commit is contained in:
Thomas Haller 2017-02-05 20:05:57 +01:00
parent 93f7ab2c54
commit ef6c393889
2 changed files with 50 additions and 32 deletions

View file

@ -1749,7 +1749,7 @@ get_existing_connection (NMManager *self, NMDevice *device, gboolean *out_genera
/* XXX: this code will go away soon. Copy the array over to a GSList /* XXX: this code will go away soon. Copy the array over to a GSList
* and don't bother for now. */ * and don't bother for now. */
cons = nm_manager_get_activatable_connections (self, &len, TRUE); cons = nm_manager_get_activatable_connections (self, &len, FALSE);
for (i = len; i > 0; ) for (i = len; i > 0; )
connections = g_slist_prepend (connections, cons[--i]); connections = g_slist_prepend (connections, cons[--i]);
connections = g_slist_sort (connections, (GCompareFunc) nm_settings_connection_cmp_timestamp); connections = g_slist_sort (connections, (GCompareFunc) nm_settings_connection_cmp_timestamp);

View file

@ -2162,29 +2162,64 @@ nm_settings_connection_set_flags_all (NMSettingsConnection *self, NMSettingsConn
/*****************************************************************************/ /*****************************************************************************/
static int
_cmp_timestamp (NMSettingsConnection *a, NMSettingsConnection *b)
{
gboolean a_has_ts, b_has_ts;
guint64 ats = 0, bts = 0;
nm_assert (NM_IS_SETTINGS_CONNECTION (a));
nm_assert (NM_IS_SETTINGS_CONNECTION (b));
a_has_ts = !!nm_settings_connection_get_timestamp (a, &ats);
b_has_ts = !!nm_settings_connection_get_timestamp (b, &bts);
if (a_has_ts != b_has_ts)
return a_has_ts ? -1 : 1;
if (a_has_ts && ats != bts)
return (ats > bts) ? -1 : 1;
return 0;
}
static int
_cmp_last_resort (NMSettingsConnection *a, NMSettingsConnection *b)
{
int c;
nm_assert (NM_IS_SETTINGS_CONNECTION (a));
nm_assert (NM_IS_SETTINGS_CONNECTION (b));
c = g_strcmp0 (nm_connection_get_uuid (NM_CONNECTION (a)),
nm_connection_get_uuid (NM_CONNECTION (b)));
if (c)
return c;
/* hm, same UUID. Use their pointer value to give them a stable
* order. */
return (a > b) ? -1 : 1;
}
/* sorting for "best" connections. /* sorting for "best" connections.
* The function sorts connections in descending timestamp order. * The function sorts connections in descending timestamp order.
* That means an older connection (lower timestamp) goes after * That means an older connection (lower timestamp) goes after
* a newer one. * a newer one.
*/ */
int int
nm_settings_connection_cmp_timestamp (NMSettingsConnection *ac, NMSettingsConnection *bc) nm_settings_connection_cmp_timestamp (NMSettingsConnection *a, NMSettingsConnection *b)
{ {
guint64 ats = 0, bts = 0; int c;
if (ac == bc) if (a == b)
return 0; return 0;
if (!ac) if (!a)
return 1; return 1;
if (!bc) if (!b)
return -1; return -1;
nm_settings_connection_get_timestamp (ac, &ats); if ((c = _cmp_timestamp (a, b)))
nm_settings_connection_get_timestamp (bc, &bts); return c;
if (ats != bts) if ((c = nm_utils_cmp_connection_by_autoconnect_priority (NM_CONNECTION (a), NM_CONNECTION (b))))
return (ats > bts) ? -1 : 1; return c;
return _cmp_last_resort (a, b);
return 0;
} }
int int
@ -2197,32 +2232,15 @@ nm_settings_connection_cmp_timestamp_p_with_data (gconstpointer pa, gconstpointe
int int
nm_settings_connection_cmp_autoconnect_priority (NMSettingsConnection *a, NMSettingsConnection *b) nm_settings_connection_cmp_autoconnect_priority (NMSettingsConnection *a, NMSettingsConnection *b)
{ {
guint64 ats = 0, bts = 0;
int c; int c;
if (a == b) if (a == b)
return 0; return 0;
if ((c = nm_utils_cmp_connection_by_autoconnect_priority (NM_CONNECTION (a), NM_CONNECTION (b))))
/* first we compare them by their autoconnect priority. */
c = nm_utils_cmp_connection_by_autoconnect_priority (NM_CONNECTION (a), NM_CONNECTION (b));
if (c)
return c; return c;
if ((c = _cmp_timestamp (a, b)))
/* then by their last activation timestamp (with the more recently connected one first) */
nm_settings_connection_get_timestamp (a, &ats);
nm_settings_connection_get_timestamp (b, &bts);
if (ats != bts)
return (ats > bts) ? -1 : 1;
/* if they are still equal, sort them by their UUID to give them an arbitrary, but stable
* order. */
c = g_strcmp0 (nm_connection_get_uuid (NM_CONNECTION (a)),
nm_connection_get_uuid (NM_CONNECTION (b)));
if (c)
return c; return c;
return _cmp_last_resort (a, b);
/* hm, still the same. Use their pointer value. */
return (a > b) ? -1 : 1;
} }
int int