libnm: add internal cmp() function for NMTeamLinkWatcher types
Add internal nm_team_link_watcher_cmp() function. We can implement nm_team_link_watcher_equal() based on that. This was we can sort link watchers so that nm_team_link_watchers_equal() with ignore_order is O(n*log(n)) instead of O(n^2). In general, as basic API cmp() functions are as much effort to implement as equal(), but they can also be used for sorting. In nm_team_link_watcher_cmp(), only compare the fields that are set according to the link watcher type.
This commit is contained in:
@@ -534,7 +534,16 @@ gboolean _nm_utils_inet6_is_token (const struct in6_addr *in6addr);
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
gboolean _nm_team_link_watchers_equal (GPtrArray *a, GPtrArray *b, gboolean ignore_order);
|
int nm_team_link_watcher_cmp (const NMTeamLinkWatcher *watcher, const NMTeamLinkWatcher *other);
|
||||||
|
|
||||||
|
int nm_team_link_watchers_cmp (const NMTeamLinkWatcher *const*a,
|
||||||
|
const NMTeamLinkWatcher *const*b,
|
||||||
|
gsize len,
|
||||||
|
gboolean ignore_order);
|
||||||
|
|
||||||
|
gboolean nm_team_link_watchers_equal (const GPtrArray *a,
|
||||||
|
const GPtrArray *b,
|
||||||
|
gboolean ignore_order);
|
||||||
|
|
||||||
gboolean _nm_utils_team_config_equal (const char *conf1, const char *conf2, gboolean port);
|
gboolean _nm_utils_team_config_equal (const char *conf1, const char *conf2, gboolean port);
|
||||||
GValue *_nm_utils_team_config_get (const char *conf,
|
GValue *_nm_utils_team_config_get (const char *conf,
|
||||||
|
@@ -407,9 +407,9 @@ compare_property (const NMSettInfoSetting *sett_info,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (set_a);
|
a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (set_a);
|
||||||
b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (set_b);
|
b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (set_b);
|
||||||
return _nm_team_link_watchers_equal (a_priv->link_watchers,
|
return nm_team_link_watchers_equal (a_priv->link_watchers,
|
||||||
b_priv->link_watchers,
|
b_priv->link_watchers,
|
||||||
TRUE);
|
TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_PORT_CONFIG)) {
|
if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_PORT_CONFIG)) {
|
||||||
|
@@ -365,6 +365,38 @@ nm_team_link_watcher_unref (NMTeamLinkWatcher *watcher)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nm_team_link_watcher_cmp (const NMTeamLinkWatcher *watcher,
|
||||||
|
const NMTeamLinkWatcher *other)
|
||||||
|
{
|
||||||
|
NM_CMP_SELF (watcher, other);
|
||||||
|
|
||||||
|
NM_CMP_FIELD (watcher, other, type);
|
||||||
|
|
||||||
|
switch (watcher->type) {
|
||||||
|
case LINK_WATCHER_ETHTOOL:
|
||||||
|
NM_CMP_FIELD (watcher, other, ethtool.delay_up);
|
||||||
|
NM_CMP_FIELD (watcher, other, ethtool.delay_down);
|
||||||
|
break;
|
||||||
|
case LINK_WATCHER_NSNA_PING:
|
||||||
|
NM_CMP_FIELD_STR0 (watcher, other, nsna_ping.target_host);
|
||||||
|
NM_CMP_FIELD (watcher, other, nsna_ping.init_wait);
|
||||||
|
NM_CMP_FIELD (watcher, other, nsna_ping.interval);
|
||||||
|
NM_CMP_FIELD (watcher, other, nsna_ping.missed_max);
|
||||||
|
break;
|
||||||
|
case LINK_WATCHER_ARP_PING:
|
||||||
|
NM_CMP_FIELD_STR0 (watcher, other, arp_ping.target_host);
|
||||||
|
NM_CMP_FIELD_STR0 (watcher, other, arp_ping.source_host);
|
||||||
|
NM_CMP_FIELD (watcher, other, arp_ping.init_wait);
|
||||||
|
NM_CMP_FIELD (watcher, other, arp_ping.interval);
|
||||||
|
NM_CMP_FIELD (watcher, other, arp_ping.missed_max);
|
||||||
|
NM_CMP_FIELD (watcher, other, arp_ping.vlanid);
|
||||||
|
NM_CMP_FIELD (watcher, other, arp_ping.flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_team_link_watcher_equal:
|
* nm_team_link_watcher_equal:
|
||||||
* @watcher: the #NMTeamLinkWatcher
|
* @watcher: the #NMTeamLinkWatcher
|
||||||
@@ -381,48 +413,55 @@ gboolean
|
|||||||
nm_team_link_watcher_equal (const NMTeamLinkWatcher *watcher,
|
nm_team_link_watcher_equal (const NMTeamLinkWatcher *watcher,
|
||||||
const NMTeamLinkWatcher *other)
|
const NMTeamLinkWatcher *other)
|
||||||
{
|
{
|
||||||
_CHECK_WATCHER (watcher, FALSE);
|
return nm_team_link_watcher_cmp (watcher, other) == 0;
|
||||||
_CHECK_WATCHER (other, FALSE);
|
}
|
||||||
|
|
||||||
if ( watcher->type != other->type
|
static int
|
||||||
|| !nm_streq0 (watcher->arp_ping.target_host, other->arp_ping.target_host)
|
_team_link_watchers_cmp_p_with_data (gconstpointer data_a,
|
||||||
|| !nm_streq0 (watcher->arp_ping.source_host, other->arp_ping.source_host)
|
gconstpointer data_b,
|
||||||
|| watcher->arp_ping.init_wait != other->arp_ping.init_wait
|
gpointer user_data)
|
||||||
|| watcher->arp_ping.interval != other->arp_ping.interval
|
{
|
||||||
|| watcher->arp_ping.missed_max != other->arp_ping.missed_max
|
return nm_team_link_watcher_cmp (*((const NMTeamLinkWatcher *const*) data_a),
|
||||||
|| watcher->arp_ping.vlanid != other->arp_ping.vlanid
|
*((const NMTeamLinkWatcher *const*) data_b));
|
||||||
|| watcher->arp_ping.flags != other->arp_ping.flags)
|
}
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
int
|
||||||
|
nm_team_link_watchers_cmp (const NMTeamLinkWatcher *const*a,
|
||||||
|
const NMTeamLinkWatcher *const*b,
|
||||||
|
gsize len,
|
||||||
|
gboolean ignore_order)
|
||||||
|
{
|
||||||
|
gs_free const NMTeamLinkWatcher **a_free = NULL;
|
||||||
|
gs_free const NMTeamLinkWatcher **b_free = NULL;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if ( ignore_order
|
||||||
|
&& len > 1) {
|
||||||
|
a = nm_memdup_maybe_a (200, a, len * sizeof (*a), &a_free);
|
||||||
|
b = nm_memdup_maybe_a (200, b, len * sizeof (*b), &b_free);
|
||||||
|
g_qsort_with_data ((gpointer) a, len, sizeof (*a), _team_link_watchers_cmp_p_with_data, NULL);
|
||||||
|
g_qsort_with_data ((gpointer) b, len, sizeof (*b), _team_link_watchers_cmp_p_with_data, NULL);
|
||||||
|
}
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
NM_CMP_RETURN (nm_team_link_watcher_cmp (a[i],
|
||||||
|
b[i]));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_nm_team_link_watchers_equal (GPtrArray *a, GPtrArray *b, gboolean ignore_order)
|
nm_team_link_watchers_equal (const GPtrArray *a,
|
||||||
|
const GPtrArray *b,
|
||||||
|
gboolean ignore_order)
|
||||||
{
|
{
|
||||||
guint i, j;
|
return a == b
|
||||||
|
|| ( a
|
||||||
if (a->len != b->len)
|
&& b
|
||||||
return FALSE;
|
&& a->len == b->len
|
||||||
if (ignore_order) {
|
&& (nm_team_link_watchers_cmp ((const NMTeamLinkWatcher *const*) a->pdata,
|
||||||
/* FIXME: comparing this way is O(n^2). Don't do that, instead
|
(const NMTeamLinkWatcher *const*) b->pdata,
|
||||||
* add nm_team_link_watcher_cmp(), sort both lists, and
|
a->len,
|
||||||
* compare step by step. */
|
ignore_order) == 0));
|
||||||
for (i = 0; i < a->len; i++) {
|
|
||||||
for (j = 0; j < b->len; j++) {
|
|
||||||
if (nm_team_link_watcher_equal (a->pdata[i], b->pdata[j]))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (j == b->len)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (i = 0; i < a->len; i++) {
|
|
||||||
if (!nm_team_link_watcher_equal (a->pdata[i], b->pdata[i]))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1330,9 +1369,9 @@ compare_property (const NMSettInfoSetting *sett_info,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
a_priv = NM_SETTING_TEAM_GET_PRIVATE (set_a);
|
a_priv = NM_SETTING_TEAM_GET_PRIVATE (set_a);
|
||||||
b_priv = NM_SETTING_TEAM_GET_PRIVATE (set_b);
|
b_priv = NM_SETTING_TEAM_GET_PRIVATE (set_b);
|
||||||
return _nm_team_link_watchers_equal (a_priv->link_watchers,
|
return nm_team_link_watchers_equal (a_priv->link_watchers,
|
||||||
b_priv->link_watchers,
|
b_priv->link_watchers,
|
||||||
TRUE);
|
TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_CONFIG)) {
|
if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_CONFIG)) {
|
||||||
|
Reference in New Issue
Block a user