about summary refs log tree commit diff
path: root/shared/nm-glib-aux/nm-dedup-multi.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared/nm-glib-aux/nm-dedup-multi.c')
-rw-r--r--shared/nm-glib-aux/nm-dedup-multi.c1495
1 files changed, 742 insertions, 753 deletions
diff --git a/shared/nm-glib-aux/nm-dedup-multi.c b/shared/nm-glib-aux/nm-dedup-multi.c
index 6e23228e..4a16f850 100644
--- a/shared/nm-glib-aux/nm-dedup-multi.c
+++ b/shared/nm-glib-aux/nm-dedup-multi.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: LGPL-2.1+
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /*
  * Copyright (C) 2017 Red Hat, Inc.
  */
@@ -13,383 +13,379 @@
 /*****************************************************************************/
 
 typedef struct {
-	/* the stack-allocated lookup entry. It has a compatible
-	 * memory layout with NMDedupMultiEntry and NMDedupMultiHeadEntry.
-	 *
-	 * It is recognizable by having lst_entries_sentinel.next set to NULL.
-	 * Contrary to the other entries, which have lst_entries.next
-	 * always non-NULL.
-	 * */
-	CList lst_entries_sentinel;
-	const NMDedupMultiObj *obj;
-	const NMDedupMultiIdxType *idx_type;
-	bool lookup_head;
+    /* the stack-allocated lookup entry. It has a compatible
+     * memory layout with NMDedupMultiEntry and NMDedupMultiHeadEntry.
+     *
+     * It is recognizable by having lst_entries_sentinel.next set to NULL.
+     * Contrary to the other entries, which have lst_entries.next
+     * always non-NULL.
+     * */
+    CList                      lst_entries_sentinel;
+    const NMDedupMultiObj *    obj;
+    const NMDedupMultiIdxType *idx_type;
+    bool                       lookup_head;
 } LookupEntry;
 
 struct _NMDedupMultiIndex {
-	int ref_count;
-	GHashTable *idx_entries;
-	GHashTable *idx_objs;
+    int         ref_count;
+    GHashTable *idx_entries;
+    GHashTable *idx_objs;
 };
 
 /*****************************************************************************/
 
 static void
-ASSERT_idx_type (const NMDedupMultiIdxType *idx_type)
+ASSERT_idx_type(const NMDedupMultiIdxType *idx_type)
 {
-	nm_assert (idx_type);
+    nm_assert(idx_type);
 #if NM_MORE_ASSERTS > 10
-	nm_assert (idx_type->klass);
-	nm_assert (idx_type->klass->idx_obj_id_hash_update);
-	nm_assert (idx_type->klass->idx_obj_id_equal);
-	nm_assert (!!idx_type->klass->idx_obj_partition_hash_update == !!idx_type->klass->idx_obj_partition_equal);
-	nm_assert (idx_type->lst_idx_head.next);
+    nm_assert(idx_type->klass);
+    nm_assert(idx_type->klass->idx_obj_id_hash_update);
+    nm_assert(idx_type->klass->idx_obj_id_equal);
+    nm_assert(!!idx_type->klass->idx_obj_partition_hash_update
+              == !!idx_type->klass->idx_obj_partition_equal);
+    nm_assert(idx_type->lst_idx_head.next);
 #endif
 }
 
 void
-nm_dedup_multi_idx_type_init (NMDedupMultiIdxType *idx_type,
-                              const NMDedupMultiIdxTypeClass *klass)
+nm_dedup_multi_idx_type_init(NMDedupMultiIdxType *idx_type, const NMDedupMultiIdxTypeClass *klass)
 {
-	nm_assert (idx_type);
-	nm_assert (klass);
+    nm_assert(idx_type);
+    nm_assert(klass);
 
-	memset (idx_type, 0, sizeof (*idx_type));
-	idx_type->klass = klass;
-	c_list_init (&idx_type->lst_idx_head);
+    *idx_type = (NMDedupMultiIdxType){
+        .klass        = klass,
+        .lst_idx_head = C_LIST_INIT(idx_type->lst_idx_head),
+    };
 
-	ASSERT_idx_type (idx_type);
+    ASSERT_idx_type(idx_type);
 }
 
 /*****************************************************************************/
 
 static NMDedupMultiEntry *
-_entry_lookup_obj (const NMDedupMultiIndex *self,
-                   const NMDedupMultiIdxType *idx_type,
-                   const NMDedupMultiObj *obj)
+_entry_lookup_obj(const NMDedupMultiIndex *  self,
+                  const NMDedupMultiIdxType *idx_type,
+                  const NMDedupMultiObj *    obj)
 {
-	const LookupEntry stack_entry = {
-		.obj = obj,
-		.idx_type = idx_type,
-		.lookup_head = FALSE,
-	};
-
-	ASSERT_idx_type (idx_type);
-	return g_hash_table_lookup (self->idx_entries, &stack_entry);
+    const LookupEntry stack_entry = {
+        .obj         = obj,
+        .idx_type    = idx_type,
+        .lookup_head = FALSE,
+    };
+
+    ASSERT_idx_type(idx_type);
+    return g_hash_table_lookup(self->idx_entries, &stack_entry);
 }
 
 static NMDedupMultiHeadEntry *
-_entry_lookup_head (const NMDedupMultiIndex *self,
-                    const NMDedupMultiIdxType *idx_type,
-                    const NMDedupMultiObj *obj)
+_entry_lookup_head(const NMDedupMultiIndex *  self,
+                   const NMDedupMultiIdxType *idx_type,
+                   const NMDedupMultiObj *    obj)
 {
-	NMDedupMultiHeadEntry *head_entry;
-	const LookupEntry stack_entry = {
-		.obj = obj,
-		.idx_type = idx_type,
-		.lookup_head = TRUE,
-	};
-
-	ASSERT_idx_type (idx_type);
-
-	if (!idx_type->klass->idx_obj_partition_equal) {
-		if (c_list_is_empty (&idx_type->lst_idx_head))
-			head_entry = NULL;
-		else {
-			nm_assert (c_list_length (&idx_type->lst_idx_head) == 1);
-			head_entry = c_list_entry (idx_type->lst_idx_head.next, NMDedupMultiHeadEntry, lst_idx);
-		}
-		nm_assert (head_entry == g_hash_table_lookup (self->idx_entries, &stack_entry));
-		return head_entry;
-	}
-
-	return g_hash_table_lookup (self->idx_entries, &stack_entry);
+    NMDedupMultiHeadEntry *head_entry;
+    const LookupEntry      stack_entry = {
+        .obj         = obj,
+        .idx_type    = idx_type,
+        .lookup_head = TRUE,
+    };
+
+    ASSERT_idx_type(idx_type);
+
+    if (!idx_type->klass->idx_obj_partition_equal) {
+        if (c_list_is_empty(&idx_type->lst_idx_head))
+            head_entry = NULL;
+        else {
+            nm_assert(c_list_length(&idx_type->lst_idx_head) == 1);
+            head_entry = c_list_entry(idx_type->lst_idx_head.next, NMDedupMultiHeadEntry, lst_idx);
+        }
+        nm_assert(head_entry == g_hash_table_lookup(self->idx_entries, &stack_entry));
+        return head_entry;
+    }
+
+    return g_hash_table_lookup(self->idx_entries, &stack_entry);
 }
 
 static void
-_entry_unpack (const NMDedupMultiEntry *entry,
-               const NMDedupMultiIdxType **out_idx_type,
-               const NMDedupMultiObj **out_obj,
-               gboolean *out_lookup_head)
+_entry_unpack(const NMDedupMultiEntry *   entry,
+              const NMDedupMultiIdxType **out_idx_type,
+              const NMDedupMultiObj **    out_obj,
+              gboolean *                  out_lookup_head)
 {
-	const NMDedupMultiHeadEntry *head_entry;
-	const LookupEntry *lookup_entry;
-
-	nm_assert (entry);
-
-	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (LookupEntry, lst_entries_sentinel) == G_STRUCT_OFFSET (NMDedupMultiEntry, lst_entries));
-	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, lst_entries) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, lst_entries_head));
-	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, obj) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, idx_type));
-	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, is_head) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, is_head));
-
-	if (!entry->lst_entries.next) {
-		/* the entry is stack-allocated by _entry_lookup(). */
-		lookup_entry = (LookupEntry *) entry;
-		*out_obj = lookup_entry->obj;
-		*out_idx_type = lookup_entry->idx_type;
-		*out_lookup_head = lookup_entry->lookup_head;
-	} else if (entry->is_head) {
-		head_entry = (NMDedupMultiHeadEntry *) entry;
-		nm_assert (!c_list_is_empty (&head_entry->lst_entries_head));
-		*out_obj = c_list_entry (head_entry->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->obj;
-		*out_idx_type = head_entry->idx_type;
-		*out_lookup_head = TRUE;
-	} else {
-		*out_obj = entry->obj;
-		*out_idx_type = entry->head->idx_type;
-		*out_lookup_head = FALSE;
-	}
-
-	nm_assert (NM_IN_SET (*out_lookup_head, FALSE, TRUE));
-	ASSERT_idx_type (*out_idx_type);
-
-	/* for lookup of the head, we allow to omit object, but only
-	 * if the idx_type does not partition the objects. Otherwise, we
-	 * require a obj to compare. */
-	nm_assert (   !*out_lookup_head
-	           || (   *out_obj
-	               || !(*out_idx_type)->klass->idx_obj_partition_equal));
-
-	/* lookup of the object requires always an object. */
-	nm_assert (   *out_lookup_head
-	           || *out_obj);
+    const NMDedupMultiHeadEntry *head_entry;
+    const LookupEntry *          lookup_entry;
+
+    nm_assert(entry);
+
+    G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(LookupEntry, lst_entries_sentinel)
+                         == G_STRUCT_OFFSET(NMDedupMultiEntry, lst_entries));
+    G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMDedupMultiEntry, lst_entries)
+                         == G_STRUCT_OFFSET(NMDedupMultiHeadEntry, lst_entries_head));
+    G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMDedupMultiEntry, obj)
+                         == G_STRUCT_OFFSET(NMDedupMultiHeadEntry, idx_type));
+    G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMDedupMultiEntry, is_head)
+                         == G_STRUCT_OFFSET(NMDedupMultiHeadEntry, is_head));
+
+    if (!entry->lst_entries.next) {
+        /* the entry is stack-allocated by _entry_lookup(). */
+        lookup_entry     = (LookupEntry *) entry;
+        *out_obj         = lookup_entry->obj;
+        *out_idx_type    = lookup_entry->idx_type;
+        *out_lookup_head = lookup_entry->lookup_head;
+    } else if (entry->is_head) {
+        head_entry = (NMDedupMultiHeadEntry *) entry;
+        nm_assert(!c_list_is_empty(&head_entry->lst_entries_head));
+        *out_obj =
+            c_list_entry(head_entry->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->obj;
+        *out_idx_type    = head_entry->idx_type;
+        *out_lookup_head = TRUE;
+    } else {
+        *out_obj         = entry->obj;
+        *out_idx_type    = entry->head->idx_type;
+        *out_lookup_head = FALSE;
+    }
+
+    nm_assert(NM_IN_SET(*out_lookup_head, FALSE, TRUE));
+    ASSERT_idx_type(*out_idx_type);
+
+    /* for lookup of the head, we allow to omit object, but only
+     * if the idx_type does not partition the objects. Otherwise, we
+     * require a obj to compare. */
+    nm_assert(!*out_lookup_head || (*out_obj || !(*out_idx_type)->klass->idx_obj_partition_equal));
+
+    /* lookup of the object requires always an object. */
+    nm_assert(*out_lookup_head || *out_obj);
 }
 
 static guint
-_dict_idx_entries_hash (const NMDedupMultiEntry *entry)
+_dict_idx_entries_hash(const NMDedupMultiEntry *entry)
 {
-	const NMDedupMultiIdxType *idx_type;
-	const NMDedupMultiObj *obj;
-	gboolean lookup_head;
-	NMHashState h;
+    const NMDedupMultiIdxType *idx_type;
+    const NMDedupMultiObj *    obj;
+    gboolean                   lookup_head;
+    NMHashState                h;
 
-	_entry_unpack (entry, &idx_type, &obj, &lookup_head);
+    _entry_unpack(entry, &idx_type, &obj, &lookup_head);
 
-	nm_hash_init (&h, 1914869417u);
-	if (idx_type->klass->idx_obj_partition_hash_update) {
-		nm_assert (obj);
-		idx_type->klass->idx_obj_partition_hash_update (idx_type, obj, &h);
-	}
+    nm_hash_init(&h, 1914869417u);
+    if (idx_type->klass->idx_obj_partition_hash_update) {
+        nm_assert(obj);
+        idx_type->klass->idx_obj_partition_hash_update(idx_type, obj, &h);
+    }
 
-	if (!lookup_head)
-		idx_type->klass->idx_obj_id_hash_update (idx_type, obj, &h);
+    if (!lookup_head)
+        idx_type->klass->idx_obj_id_hash_update(idx_type, obj, &h);
 
-	nm_hash_update_val (&h, idx_type);
-	return nm_hash_complete (&h);
+    nm_hash_update_val(&h, idx_type);
+    return nm_hash_complete(&h);
 }
 
 static gboolean
-_dict_idx_entries_equal (const NMDedupMultiEntry *entry_a,
-                         const NMDedupMultiEntry *entry_b)
+_dict_idx_entries_equal(const NMDedupMultiEntry *entry_a, const NMDedupMultiEntry *entry_b)
 {
-	const NMDedupMultiIdxType *idx_type_a, *idx_type_b;
-	const NMDedupMultiObj *obj_a, *obj_b;
-	gboolean lookup_head_a, lookup_head_b;
-
-	_entry_unpack (entry_a, &idx_type_a, &obj_a, &lookup_head_a);
-	_entry_unpack (entry_b, &idx_type_b, &obj_b, &lookup_head_b);
-
-	if (   idx_type_a != idx_type_b
-	    || lookup_head_a != lookup_head_b)
-		return FALSE;
-	if (!nm_dedup_multi_idx_type_partition_equal (idx_type_a, obj_a, obj_b))
-		return FALSE;
-	if (   !lookup_head_a
-	    && !nm_dedup_multi_idx_type_id_equal (idx_type_a, obj_a, obj_b))
-		return FALSE;
-	return TRUE;
+    const NMDedupMultiIdxType *idx_type_a, *idx_type_b;
+    const NMDedupMultiObj *    obj_a, *obj_b;
+    gboolean                   lookup_head_a, lookup_head_b;
+
+    _entry_unpack(entry_a, &idx_type_a, &obj_a, &lookup_head_a);
+    _entry_unpack(entry_b, &idx_type_b, &obj_b, &lookup_head_b);
+
+    if (idx_type_a != idx_type_b || lookup_head_a != lookup_head_b)
+        return FALSE;
+    if (!nm_dedup_multi_idx_type_partition_equal(idx_type_a, obj_a, obj_b))
+        return FALSE;
+    if (!lookup_head_a && !nm_dedup_multi_idx_type_id_equal(idx_type_a, obj_a, obj_b))
+        return FALSE;
+    return TRUE;
 }
 
 /*****************************************************************************/
 
 static gboolean
-_add (NMDedupMultiIndex *self,
-      NMDedupMultiIdxType *idx_type,
-      const NMDedupMultiObj *obj,
-      NMDedupMultiEntry *entry,
-      NMDedupMultiIdxMode mode,
-      const NMDedupMultiEntry *entry_order,
-      NMDedupMultiHeadEntry *head_existing,
-      const NMDedupMultiEntry **out_entry,
-      const NMDedupMultiObj **out_obj_old)
+_add(NMDedupMultiIndex *       self,
+     NMDedupMultiIdxType *     idx_type,
+     const NMDedupMultiObj *   obj,
+     NMDedupMultiEntry *       entry,
+     NMDedupMultiIdxMode       mode,
+     const NMDedupMultiEntry * entry_order,
+     NMDedupMultiHeadEntry *   head_existing,
+     const NMDedupMultiEntry **out_entry,
+     const NMDedupMultiObj **  out_obj_old)
 {
-	NMDedupMultiHeadEntry *head_entry;
-	const NMDedupMultiObj *obj_new, *obj_old;
-	gboolean add_head_entry = FALSE;
-
-	nm_assert (self);
-	ASSERT_idx_type (idx_type);
-	nm_assert (obj);
-	nm_assert (NM_IN_SET (mode,
-	                      NM_DEDUP_MULTI_IDX_MODE_PREPEND,
-	                      NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
-	                      NM_DEDUP_MULTI_IDX_MODE_APPEND,
-	                      NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE));
-	nm_assert (!head_existing || head_existing->idx_type == idx_type);
-	nm_assert (({
-	                const NMDedupMultiHeadEntry *_h;
-	                gboolean _ok = TRUE;
-	                if (head_existing) {
-	                    _h = nm_dedup_multi_index_lookup_head (self, idx_type, obj);
-	                    if (head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING)
-	                        _ok = (_h == NULL);
-	                    else
-	                        _ok = (_h == head_existing);
-	                }
-	                _ok;
-	            }));
-
-	if (entry) {
-		gboolean changed = FALSE;
-
-		nm_dedup_multi_entry_set_dirty (entry, FALSE);
-
-		nm_assert (!head_existing || entry->head == head_existing);
-		nm_assert (!entry_order || entry_order->head == entry->head);
-		nm_assert (!entry_order || c_list_contains (&entry->lst_entries, &entry_order->lst_entries));
-		nm_assert (!entry_order || c_list_contains (&entry_order->lst_entries, &entry->lst_entries));
-
-		switch (mode) {
-		case NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE:
-			if (entry_order) {
-				if (nm_c_list_move_before ((CList *) &entry_order->lst_entries, &entry->lst_entries))
-					changed = TRUE;
-			} else {
-				if (nm_c_list_move_front ((CList *) &entry->head->lst_entries_head, &entry->lst_entries))
-					changed = TRUE;
-			}
-			break;
-		case NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE:
-			if (entry_order) {
-				if (nm_c_list_move_after ((CList *) &entry_order->lst_entries, &entry->lst_entries))
-					changed = TRUE;
-			} else {
-				if (nm_c_list_move_tail ((CList *) &entry->head->lst_entries_head, &entry->lst_entries))
-					changed = TRUE;
-			}
-			break;
-		case NM_DEDUP_MULTI_IDX_MODE_PREPEND:
-		case NM_DEDUP_MULTI_IDX_MODE_APPEND:
-			break;
-		};
-
-		nm_assert (obj->klass == ((const NMDedupMultiObj *) entry->obj)->klass);
-		if (   obj == entry->obj
-		    || obj->klass->obj_full_equal (obj,
-		                                   entry->obj)) {
-			NM_SET_OUT (out_entry, entry);
-			NM_SET_OUT (out_obj_old, nm_dedup_multi_obj_ref (entry->obj));
-			return changed;
-		}
-
-		obj_new = nm_dedup_multi_index_obj_intern (self, obj);
-
-		obj_old = entry->obj;
-		entry->obj = obj_new;
-
-		NM_SET_OUT (out_entry, entry);
-		if (out_obj_old)
-			*out_obj_old = obj_old;
-		else
-			nm_dedup_multi_obj_unref (obj_old);
-		return TRUE;
-	}
-
-	if (    idx_type->klass->idx_obj_partitionable
-	    && !idx_type->klass->idx_obj_partitionable (idx_type, obj)) {
-		/* this object cannot be partitioned by this idx_type. */
-		nm_assert (!head_existing || head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING);
-		NM_SET_OUT (out_entry, NULL);
-		NM_SET_OUT (out_obj_old, NULL);
-		return FALSE;
-	}
-
-	obj_new = nm_dedup_multi_index_obj_intern (self, obj);
-
-	if (!head_existing)
-		head_entry = _entry_lookup_head (self, idx_type, obj_new);
-	else if (head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING)
-		head_entry = NULL;
-	else
-		head_entry = head_existing;
-
-	if (!head_entry) {
-		head_entry = g_slice_new0 (NMDedupMultiHeadEntry);
-		head_entry->is_head = TRUE;
-		head_entry->idx_type = idx_type;
-		c_list_init (&head_entry->lst_entries_head);
-		c_list_link_tail (&idx_type->lst_idx_head, &head_entry->lst_idx);
-		add_head_entry = TRUE;
-	} else
-		nm_assert (c_list_contains (&idx_type->lst_idx_head, &head_entry->lst_idx));
-
-	if (entry_order) {
-		nm_assert (!add_head_entry);
-		nm_assert (entry_order->head == head_entry);
-		nm_assert (c_list_contains (&head_entry->lst_entries_head, &entry_order->lst_entries));
-		nm_assert (c_list_contains (&entry_order->lst_entries, &head_entry->lst_entries_head));
-	}
-
-	entry = g_slice_new0 (NMDedupMultiEntry);
-	entry->obj = obj_new;
-	entry->head = head_entry;
-
-	switch (mode) {
-	case NM_DEDUP_MULTI_IDX_MODE_PREPEND:
-	case NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE:
-		if (entry_order)
-			c_list_link_before ((CList *) &entry_order->lst_entries, &entry->lst_entries);
-		else
-			c_list_link_front (&head_entry->lst_entries_head, &entry->lst_entries);
-		break;
-	default:
-		if (entry_order)
-			c_list_link_after ((CList *) &entry_order->lst_entries, &entry->lst_entries);
-		else
-			c_list_link_tail (&head_entry->lst_entries_head, &entry->lst_entries);
-		break;
-	};
-
-	idx_type->len++;
-	head_entry->len++;
-
-	if (   add_head_entry
-	    && !g_hash_table_add (self->idx_entries, head_entry))
-		nm_assert_not_reached ();
-
-	if (!g_hash_table_add (self->idx_entries, entry))
-		nm_assert_not_reached ();
-
-	NM_SET_OUT (out_entry, entry);
-	NM_SET_OUT (out_obj_old, NULL);
-	return TRUE;
+    NMDedupMultiHeadEntry *head_entry;
+    const NMDedupMultiObj *obj_new, *obj_old;
+    gboolean               add_head_entry = FALSE;
+
+    nm_assert(self);
+    ASSERT_idx_type(idx_type);
+    nm_assert(obj);
+    nm_assert(NM_IN_SET(mode,
+                        NM_DEDUP_MULTI_IDX_MODE_PREPEND,
+                        NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
+                        NM_DEDUP_MULTI_IDX_MODE_APPEND,
+                        NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE));
+    nm_assert(!head_existing || head_existing->idx_type == idx_type);
+    nm_assert(({
+        const NMDedupMultiHeadEntry *_h;
+        gboolean                     _ok = TRUE;
+        if (head_existing) {
+            _h = nm_dedup_multi_index_lookup_head(self, idx_type, obj);
+            if (head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING)
+                _ok = (_h == NULL);
+            else
+                _ok = (_h == head_existing);
+        }
+        _ok;
+    }));
+
+    if (entry) {
+        gboolean changed = FALSE;
+
+        nm_dedup_multi_entry_set_dirty(entry, FALSE);
+
+        nm_assert(!head_existing || entry->head == head_existing);
+        nm_assert(!entry_order || entry_order->head == entry->head);
+        nm_assert(!entry_order || c_list_contains(&entry->lst_entries, &entry_order->lst_entries));
+        nm_assert(!entry_order || c_list_contains(&entry_order->lst_entries, &entry->lst_entries));
+
+        switch (mode) {
+        case NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE:
+            if (entry_order) {
+                if (nm_c_list_move_before((CList *) &entry_order->lst_entries, &entry->lst_entries))
+                    changed = TRUE;
+            } else {
+                if (nm_c_list_move_front((CList *) &entry->head->lst_entries_head,
+                                         &entry->lst_entries))
+                    changed = TRUE;
+            }
+            break;
+        case NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE:
+            if (entry_order) {
+                if (nm_c_list_move_after((CList *) &entry_order->lst_entries, &entry->lst_entries))
+                    changed = TRUE;
+            } else {
+                if (nm_c_list_move_tail((CList *) &entry->head->lst_entries_head,
+                                        &entry->lst_entries))
+                    changed = TRUE;
+            }
+            break;
+        case NM_DEDUP_MULTI_IDX_MODE_PREPEND:
+        case NM_DEDUP_MULTI_IDX_MODE_APPEND:
+            break;
+        };
+
+        nm_assert(obj->klass == ((const NMDedupMultiObj *) entry->obj)->klass);
+        if (obj == entry->obj || obj->klass->obj_full_equal(obj, entry->obj)) {
+            NM_SET_OUT(out_entry, entry);
+            NM_SET_OUT(out_obj_old, nm_dedup_multi_obj_ref(entry->obj));
+            return changed;
+        }
+
+        obj_new = nm_dedup_multi_index_obj_intern(self, obj);
+
+        obj_old    = entry->obj;
+        entry->obj = obj_new;
+
+        NM_SET_OUT(out_entry, entry);
+        if (out_obj_old)
+            *out_obj_old = obj_old;
+        else
+            nm_dedup_multi_obj_unref(obj_old);
+        return TRUE;
+    }
+
+    if (idx_type->klass->idx_obj_partitionable
+        && !idx_type->klass->idx_obj_partitionable(idx_type, obj)) {
+        /* this object cannot be partitioned by this idx_type. */
+        nm_assert(!head_existing || head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING);
+        NM_SET_OUT(out_entry, NULL);
+        NM_SET_OUT(out_obj_old, NULL);
+        return FALSE;
+    }
+
+    obj_new = nm_dedup_multi_index_obj_intern(self, obj);
+
+    if (!head_existing)
+        head_entry = _entry_lookup_head(self, idx_type, obj_new);
+    else if (head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING)
+        head_entry = NULL;
+    else
+        head_entry = head_existing;
+
+    if (!head_entry) {
+        head_entry           = g_slice_new0(NMDedupMultiHeadEntry);
+        head_entry->is_head  = TRUE;
+        head_entry->idx_type = idx_type;
+        c_list_init(&head_entry->lst_entries_head);
+        c_list_link_tail(&idx_type->lst_idx_head, &head_entry->lst_idx);
+        add_head_entry = TRUE;
+    } else
+        nm_assert(c_list_contains(&idx_type->lst_idx_head, &head_entry->lst_idx));
+
+    if (entry_order) {
+        nm_assert(!add_head_entry);
+        nm_assert(entry_order->head == head_entry);
+        nm_assert(c_list_contains(&head_entry->lst_entries_head, &entry_order->lst_entries));
+        nm_assert(c_list_contains(&entry_order->lst_entries, &head_entry->lst_entries_head));
+    }
+
+    entry       = g_slice_new0(NMDedupMultiEntry);
+    entry->obj  = obj_new;
+    entry->head = head_entry;
+
+    switch (mode) {
+    case NM_DEDUP_MULTI_IDX_MODE_PREPEND:
+    case NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE:
+        if (entry_order)
+            c_list_link_before((CList *) &entry_order->lst_entries, &entry->lst_entries);
+        else
+            c_list_link_front(&head_entry->lst_entries_head, &entry->lst_entries);
+        break;
+    default:
+        if (entry_order)
+            c_list_link_after((CList *) &entry_order->lst_entries, &entry->lst_entries);
+        else
+            c_list_link_tail(&head_entry->lst_entries_head, &entry->lst_entries);
+        break;
+    };
+
+    idx_type->len++;
+    head_entry->len++;
+
+    if (add_head_entry && !g_hash_table_add(self->idx_entries, head_entry))
+        nm_assert_not_reached();
+
+    if (!g_hash_table_add(self->idx_entries, entry))
+        nm_assert_not_reached();
+
+    NM_SET_OUT(out_entry, entry);
+    NM_SET_OUT(out_obj_old, NULL);
+    return TRUE;
 }
 
 gboolean
-nm_dedup_multi_index_add (NMDedupMultiIndex *self,
-                          NMDedupMultiIdxType *idx_type,
-                          /*const NMDedupMultiObj * */ gconstpointer obj,
-                          NMDedupMultiIdxMode mode,
-                          const NMDedupMultiEntry **out_entry,
-                          /* const NMDedupMultiObj ** */ gpointer out_obj_old)
+nm_dedup_multi_index_add(NMDedupMultiIndex *                        self,
+                         NMDedupMultiIdxType *                      idx_type,
+                         /*const NMDedupMultiObj * */ gconstpointer obj,
+                         NMDedupMultiIdxMode                        mode,
+                         const NMDedupMultiEntry **                 out_entry,
+                         /* const NMDedupMultiObj ** */ gpointer    out_obj_old)
 {
-	NMDedupMultiEntry *entry;
-
-	g_return_val_if_fail (self, FALSE);
-	g_return_val_if_fail (idx_type, FALSE);
-	g_return_val_if_fail (obj, FALSE);
-	g_return_val_if_fail (NM_IN_SET (mode,
-	                                 NM_DEDUP_MULTI_IDX_MODE_PREPEND,
-	                                 NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
-	                                 NM_DEDUP_MULTI_IDX_MODE_APPEND,
-	                                 NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE),
-	                      FALSE);
-
-	entry = _entry_lookup_obj (self, idx_type, obj);
-	return _add (self, idx_type, obj,
-	             entry, mode,
-	             NULL, NULL,
-	             out_entry, out_obj_old);
+    NMDedupMultiEntry *entry;
+
+    g_return_val_if_fail(self, FALSE);
+    g_return_val_if_fail(idx_type, FALSE);
+    g_return_val_if_fail(obj, FALSE);
+    g_return_val_if_fail(NM_IN_SET(mode,
+                                   NM_DEDUP_MULTI_IDX_MODE_PREPEND,
+                                   NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
+                                   NM_DEDUP_MULTI_IDX_MODE_APPEND,
+                                   NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE),
+                         FALSE);
+
+    entry = _entry_lookup_obj(self, idx_type, obj);
+    return _add(self, idx_type, obj, entry, mode, NULL, NULL, out_entry, out_obj_old);
 }
 
 /* nm_dedup_multi_index_add_full:
@@ -427,216 +423,211 @@ nm_dedup_multi_index_add (NMDedupMultiIndex *self,
  * Return: %TRUE if anything changed, %FALSE if nothing changed.
  */
 gboolean
-nm_dedup_multi_index_add_full (NMDedupMultiIndex *self,
-                               NMDedupMultiIdxType *idx_type,
-                               /*const NMDedupMultiObj * */ gconstpointer obj,
-                               NMDedupMultiIdxMode mode,
-                               const NMDedupMultiEntry *entry_order,
-                               const NMDedupMultiEntry *entry_existing,
-                               const NMDedupMultiHeadEntry *head_existing,
-                               const NMDedupMultiEntry **out_entry,
-                               /* const NMDedupMultiObj ** */ gpointer out_obj_old)
+nm_dedup_multi_index_add_full(NMDedupMultiIndex *                        self,
+                              NMDedupMultiIdxType *                      idx_type,
+                              /*const NMDedupMultiObj * */ gconstpointer obj,
+                              NMDedupMultiIdxMode                        mode,
+                              const NMDedupMultiEntry *                  entry_order,
+                              const NMDedupMultiEntry *                  entry_existing,
+                              const NMDedupMultiHeadEntry *              head_existing,
+                              const NMDedupMultiEntry **                 out_entry,
+                              /* const NMDedupMultiObj ** */ gpointer    out_obj_old)
 {
-	NMDedupMultiEntry *entry;
-
-	g_return_val_if_fail (self, FALSE);
-	g_return_val_if_fail (idx_type, FALSE);
-	g_return_val_if_fail (obj, FALSE);
-	g_return_val_if_fail (NM_IN_SET (mode,
-	                                 NM_DEDUP_MULTI_IDX_MODE_PREPEND,
-	                                 NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
-	                                 NM_DEDUP_MULTI_IDX_MODE_APPEND,
-	                                 NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE),
-	                      FALSE);
-
-	if (entry_existing == NULL)
-		entry = _entry_lookup_obj (self, idx_type, obj);
-	else if (entry_existing == NM_DEDUP_MULTI_ENTRY_MISSING) {
-		nm_assert (!_entry_lookup_obj (self, idx_type, obj));
-		entry = NULL;
-	} else {
-		nm_assert (entry_existing == _entry_lookup_obj (self, idx_type, obj));
-		entry = (NMDedupMultiEntry *) entry_existing;
-	}
-	return _add (self, idx_type, obj,
-	             entry,
-	             mode, entry_order,
-	             (NMDedupMultiHeadEntry *) head_existing,
-	             out_entry, out_obj_old);
+    NMDedupMultiEntry *entry;
+
+    g_return_val_if_fail(self, FALSE);
+    g_return_val_if_fail(idx_type, FALSE);
+    g_return_val_if_fail(obj, FALSE);
+    g_return_val_if_fail(NM_IN_SET(mode,
+                                   NM_DEDUP_MULTI_IDX_MODE_PREPEND,
+                                   NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
+                                   NM_DEDUP_MULTI_IDX_MODE_APPEND,
+                                   NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE),
+                         FALSE);
+
+    if (entry_existing == NULL)
+        entry = _entry_lookup_obj(self, idx_type, obj);
+    else if (entry_existing == NM_DEDUP_MULTI_ENTRY_MISSING) {
+        nm_assert(!_entry_lookup_obj(self, idx_type, obj));
+        entry = NULL;
+    } else {
+        nm_assert(entry_existing == _entry_lookup_obj(self, idx_type, obj));
+        entry = (NMDedupMultiEntry *) entry_existing;
+    }
+    return _add(self,
+                idx_type,
+                obj,
+                entry,
+                mode,
+                entry_order,
+                (NMDedupMultiHeadEntry *) head_existing,
+                out_entry,
+                out_obj_old);
 }
 
 /*****************************************************************************/
 
 static void
-_remove_entry (NMDedupMultiIndex *self,
-               NMDedupMultiEntry *entry,
-               gboolean *out_head_entry_removed)
+_remove_entry(NMDedupMultiIndex *self, NMDedupMultiEntry *entry, gboolean *out_head_entry_removed)
 {
-	const NMDedupMultiObj *obj;
-	NMDedupMultiHeadEntry *head_entry;
-	NMDedupMultiIdxType *idx_type;
+    const NMDedupMultiObj *obj;
+    NMDedupMultiHeadEntry *head_entry;
+    NMDedupMultiIdxType *  idx_type;
 
-	nm_assert (self);
-	nm_assert (entry);
-	nm_assert (entry->obj);
-	nm_assert (entry->head);
-	nm_assert (!c_list_is_empty (&entry->lst_entries));
-	nm_assert (g_hash_table_lookup (self->idx_entries, entry) == entry);
+    nm_assert(self);
+    nm_assert(entry);
+    nm_assert(entry->obj);
+    nm_assert(entry->head);
+    nm_assert(!c_list_is_empty(&entry->lst_entries));
+    nm_assert(g_hash_table_lookup(self->idx_entries, entry) == entry);
 
-	head_entry = (NMDedupMultiHeadEntry *) entry->head;
-	obj = entry->obj;
+    head_entry = (NMDedupMultiHeadEntry *) entry->head;
+    obj        = entry->obj;
 
-	nm_assert (head_entry);
-	nm_assert (head_entry->len > 0);
-	nm_assert (g_hash_table_lookup (self->idx_entries, head_entry) == head_entry);
+    nm_assert(head_entry);
+    nm_assert(head_entry->len > 0);
+    nm_assert(g_hash_table_lookup(self->idx_entries, head_entry) == head_entry);
 
-	idx_type = (NMDedupMultiIdxType *) head_entry->idx_type;
-	ASSERT_idx_type (idx_type);
+    idx_type = (NMDedupMultiIdxType *) head_entry->idx_type;
+    ASSERT_idx_type(idx_type);
 
-	nm_assert (idx_type->len >= head_entry->len);
-	if (--head_entry->len > 0) {
-		nm_assert (idx_type->len > 1);
-		idx_type->len--;
-		head_entry = NULL;
-	}
+    nm_assert(idx_type->len >= head_entry->len);
+    if (--head_entry->len > 0) {
+        nm_assert(idx_type->len > 1);
+        idx_type->len--;
+        head_entry = NULL;
+    }
 
-	NM_SET_OUT (out_head_entry_removed, head_entry != NULL);
+    NM_SET_OUT(out_head_entry_removed, head_entry != NULL);
 
-	if (!g_hash_table_remove (self->idx_entries, entry))
-		nm_assert_not_reached ();
+    if (!g_hash_table_remove(self->idx_entries, entry))
+        nm_assert_not_reached();
 
-	if (   head_entry
-	    && !g_hash_table_remove (self->idx_entries, head_entry))
-		nm_assert_not_reached ();
+    if (head_entry && !g_hash_table_remove(self->idx_entries, head_entry))
+        nm_assert_not_reached();
 
-	c_list_unlink_stale (&entry->lst_entries);
-	g_slice_free (NMDedupMultiEntry, entry);
+    c_list_unlink_stale(&entry->lst_entries);
+    g_slice_free(NMDedupMultiEntry, entry);
 
-	if (head_entry) {
-		nm_assert (c_list_is_empty (&head_entry->lst_entries_head));
-		c_list_unlink_stale (&head_entry->lst_idx);
-		g_slice_free (NMDedupMultiHeadEntry, head_entry);
-	}
+    if (head_entry) {
+        nm_assert(c_list_is_empty(&head_entry->lst_entries_head));
+        c_list_unlink_stale(&head_entry->lst_idx);
+        g_slice_free(NMDedupMultiHeadEntry, head_entry);
+    }
 
-	nm_dedup_multi_obj_unref (obj);
+    nm_dedup_multi_obj_unref(obj);
 }
 
 static guint
-_remove_head (NMDedupMultiIndex *self,
-              NMDedupMultiHeadEntry *head_entry,
-              gboolean remove_all /* otherwise just dirty ones */,
-              gboolean mark_survivors_dirty)
+_remove_head(NMDedupMultiIndex *    self,
+             NMDedupMultiHeadEntry *head_entry,
+             gboolean               remove_all /* otherwise just dirty ones */,
+             gboolean               mark_survivors_dirty)
 {
-	guint n;
-	gboolean head_entry_removed;
-	CList *iter_entry, *iter_entry_safe;
-
-	nm_assert (self);
-	nm_assert (head_entry);
-	nm_assert (head_entry->len > 0);
-	nm_assert (head_entry->len == c_list_length (&head_entry->lst_entries_head));
-	nm_assert (g_hash_table_lookup (self->idx_entries, head_entry) == head_entry);
-
-	n = 0;
-	c_list_for_each_safe (iter_entry, iter_entry_safe, &head_entry->lst_entries_head) {
-		NMDedupMultiEntry *entry;
-
-		entry = c_list_entry (iter_entry, NMDedupMultiEntry, lst_entries);
-		if (   remove_all
-		    || entry->dirty) {
-			_remove_entry (self,
-			               entry,
-			               &head_entry_removed);
-			n++;
-			if (head_entry_removed)
-				break;
-		} else if (mark_survivors_dirty)
-			nm_dedup_multi_entry_set_dirty (entry, TRUE);
-	}
-
-	return n;
+    guint    n;
+    gboolean head_entry_removed;
+    CList *  iter_entry, *iter_entry_safe;
+
+    nm_assert(self);
+    nm_assert(head_entry);
+    nm_assert(head_entry->len > 0);
+    nm_assert(head_entry->len == c_list_length(&head_entry->lst_entries_head));
+    nm_assert(g_hash_table_lookup(self->idx_entries, head_entry) == head_entry);
+
+    n = 0;
+    c_list_for_each_safe (iter_entry, iter_entry_safe, &head_entry->lst_entries_head) {
+        NMDedupMultiEntry *entry;
+
+        entry = c_list_entry(iter_entry, NMDedupMultiEntry, lst_entries);
+        if (remove_all || entry->dirty) {
+            _remove_entry(self, entry, &head_entry_removed);
+            n++;
+            if (head_entry_removed)
+                break;
+        } else if (mark_survivors_dirty)
+            nm_dedup_multi_entry_set_dirty(entry, TRUE);
+    }
+
+    return n;
 }
 
 static guint
-_remove_idx_entry (NMDedupMultiIndex *self,
-                   NMDedupMultiIdxType *idx_type,
-                   gboolean remove_all /* otherwise just dirty ones */,
-                   gboolean mark_survivors_dirty)
+_remove_idx_entry(NMDedupMultiIndex *  self,
+                  NMDedupMultiIdxType *idx_type,
+                  gboolean             remove_all /* otherwise just dirty ones */,
+                  gboolean             mark_survivors_dirty)
 {
-	guint n;
-	CList *iter_idx, *iter_idx_safe;
-
-	nm_assert (self);
-	ASSERT_idx_type (idx_type);
-
-	n = 0;
-	c_list_for_each_safe (iter_idx, iter_idx_safe, &idx_type->lst_idx_head) {
-		n += _remove_head (self,
-		                   c_list_entry (iter_idx, NMDedupMultiHeadEntry, lst_idx),
-		                   remove_all, mark_survivors_dirty);
-	}
-	return n;
+    guint  n;
+    CList *iter_idx, *iter_idx_safe;
+
+    nm_assert(self);
+    ASSERT_idx_type(idx_type);
+
+    n = 0;
+    c_list_for_each_safe (iter_idx, iter_idx_safe, &idx_type->lst_idx_head) {
+        n += _remove_head(self,
+                          c_list_entry(iter_idx, NMDedupMultiHeadEntry, lst_idx),
+                          remove_all,
+                          mark_survivors_dirty);
+    }
+    return n;
 }
 
 guint
-nm_dedup_multi_index_remove_entry (NMDedupMultiIndex *self,
-                                   gconstpointer entry)
+nm_dedup_multi_index_remove_entry(NMDedupMultiIndex *self, gconstpointer entry)
 {
-	g_return_val_if_fail (self, 0);
+    g_return_val_if_fail(self, 0);
 
-	nm_assert (entry);
+    nm_assert(entry);
 
-	if (!((NMDedupMultiEntry *) entry)->is_head) {
-		_remove_entry (self, (NMDedupMultiEntry *) entry, NULL);
-		return 1;
-	}
-	return _remove_head (self, (NMDedupMultiHeadEntry *) entry, TRUE, FALSE);
+    if (!((NMDedupMultiEntry *) entry)->is_head) {
+        _remove_entry(self, (NMDedupMultiEntry *) entry, NULL);
+        return 1;
+    }
+    return _remove_head(self, (NMDedupMultiHeadEntry *) entry, TRUE, FALSE);
 }
 
 guint
-nm_dedup_multi_index_remove_obj (NMDedupMultiIndex *self,
-                                 NMDedupMultiIdxType *idx_type,
-                                 /*const NMDedupMultiObj * */ gconstpointer obj,
-                                 /*const NMDedupMultiObj ** */ gconstpointer *out_obj)
+nm_dedup_multi_index_remove_obj(NMDedupMultiIndex *                          self,
+                                NMDedupMultiIdxType *                        idx_type,
+                                /*const NMDedupMultiObj * */ gconstpointer   obj,
+                                /*const NMDedupMultiObj ** */ gconstpointer *out_obj)
 {
-	const NMDedupMultiEntry *entry;
+    const NMDedupMultiEntry *entry;
 
-	entry = nm_dedup_multi_index_lookup_obj (self, idx_type, obj);
-	if (!entry) {
-		NM_SET_OUT (out_obj, NULL);
-		return 0;
-	}
+    entry = nm_dedup_multi_index_lookup_obj(self, idx_type, obj);
+    if (!entry) {
+        NM_SET_OUT(out_obj, NULL);
+        return 0;
+    }
 
-	/* since we are about to remove the object, we obviously pass
-	 * a reference to @out_obj, the caller MUST unref the object,
-	 * if he chooses to provide @out_obj. */
-	NM_SET_OUT (out_obj, nm_dedup_multi_obj_ref (entry->obj));
+    /* since we are about to remove the object, we obviously pass
+     * a reference to @out_obj, the caller MUST unref the object,
+     * if he chooses to provide @out_obj. */
+    NM_SET_OUT(out_obj, nm_dedup_multi_obj_ref(entry->obj));
 
-	_remove_entry (self, (NMDedupMultiEntry *) entry, NULL);
-	return 1;
+    _remove_entry(self, (NMDedupMultiEntry *) entry, NULL);
+    return 1;
 }
 
 guint
-nm_dedup_multi_index_remove_head (NMDedupMultiIndex *self,
-                                  NMDedupMultiIdxType *idx_type,
-                                  /*const NMDedupMultiObj * */ gconstpointer obj)
+nm_dedup_multi_index_remove_head(NMDedupMultiIndex *                        self,
+                                 NMDedupMultiIdxType *                      idx_type,
+                                 /*const NMDedupMultiObj * */ gconstpointer obj)
 {
-	const NMDedupMultiHeadEntry *entry;
+    const NMDedupMultiHeadEntry *entry;
 
-	entry = nm_dedup_multi_index_lookup_head (self, idx_type, obj);
-	return entry
-	       ? _remove_head (self, (NMDedupMultiHeadEntry *) entry, TRUE, FALSE)
-	       : 0;
+    entry = nm_dedup_multi_index_lookup_head(self, idx_type, obj);
+    return entry ? _remove_head(self, (NMDedupMultiHeadEntry *) entry, TRUE, FALSE) : 0;
 }
 
 guint
-nm_dedup_multi_index_remove_idx (NMDedupMultiIndex *self,
-                                 NMDedupMultiIdxType *idx_type)
+nm_dedup_multi_index_remove_idx(NMDedupMultiIndex *self, NMDedupMultiIdxType *idx_type)
 {
-	g_return_val_if_fail (self, 0);
-	g_return_val_if_fail (idx_type, 0);
+    g_return_val_if_fail(self, 0);
+    g_return_val_if_fail(idx_type, 0);
 
-	return _remove_idx_entry (self, idx_type, TRUE, FALSE);
+    return _remove_idx_entry(self, idx_type, TRUE, FALSE);
 }
 
 /*****************************************************************************/
@@ -652,16 +643,16 @@ nm_dedup_multi_index_remove_idx (NMDedupMultiIndex *self,
  * Returns: the cache entry or %NULL if the entry wasn't found.
  */
 const NMDedupMultiEntry *
-nm_dedup_multi_index_lookup_obj (const NMDedupMultiIndex *self,
-                                 const NMDedupMultiIdxType *idx_type,
-                                 /*const NMDedupMultiObj * */ gconstpointer obj)
+nm_dedup_multi_index_lookup_obj(const NMDedupMultiIndex *                  self,
+                                const NMDedupMultiIdxType *                idx_type,
+                                /*const NMDedupMultiObj * */ gconstpointer obj)
 {
-	g_return_val_if_fail (self, FALSE);
-	g_return_val_if_fail (idx_type, FALSE);
-	g_return_val_if_fail (obj, FALSE);
+    g_return_val_if_fail(self, FALSE);
+    g_return_val_if_fail(idx_type, FALSE);
+    g_return_val_if_fail(obj, FALSE);
 
-	nm_assert (idx_type && idx_type->klass);
-	return _entry_lookup_obj (self, idx_type, obj);
+    nm_assert(idx_type && idx_type->klass);
+    return _entry_lookup_obj(self, idx_type, obj);
 }
 
 /**
@@ -678,61 +669,60 @@ nm_dedup_multi_index_lookup_obj (const NMDedupMultiIndex *self,
  * Returns: the cache entry or %NULL if the entry wasn't found.
  */
 const NMDedupMultiHeadEntry *
-nm_dedup_multi_index_lookup_head (const NMDedupMultiIndex *self,
-                                  const NMDedupMultiIdxType *idx_type,
-                                  /*const NMDedupMultiObj * */ gconstpointer obj)
+nm_dedup_multi_index_lookup_head(const NMDedupMultiIndex *                  self,
+                                 const NMDedupMultiIdxType *                idx_type,
+                                 /*const NMDedupMultiObj * */ gconstpointer obj)
 {
-	g_return_val_if_fail (self, FALSE);
-	g_return_val_if_fail (idx_type, FALSE);
+    g_return_val_if_fail(self, FALSE);
+    g_return_val_if_fail(idx_type, FALSE);
 
-	return _entry_lookup_head (self, idx_type, obj);
+    return _entry_lookup_head(self, idx_type, obj);
 }
 
 /*****************************************************************************/
 
 void
-nm_dedup_multi_index_dirty_set_head (NMDedupMultiIndex *self,
-                                     const NMDedupMultiIdxType *idx_type,
-                                     /*const NMDedupMultiObj * */ gconstpointer obj)
+nm_dedup_multi_index_dirty_set_head(NMDedupMultiIndex *                        self,
+                                    const NMDedupMultiIdxType *                idx_type,
+                                    /*const NMDedupMultiObj * */ gconstpointer obj)
 {
-	NMDedupMultiHeadEntry *head_entry;
-	CList *iter_entry;
+    NMDedupMultiHeadEntry *head_entry;
+    CList *                iter_entry;
 
-	g_return_if_fail (self);
-	g_return_if_fail (idx_type);
+    g_return_if_fail(self);
+    g_return_if_fail(idx_type);
 
-	head_entry = _entry_lookup_head (self, idx_type, obj);
-	if (!head_entry)
-		return;
+    head_entry = _entry_lookup_head(self, idx_type, obj);
+    if (!head_entry)
+        return;
 
-	c_list_for_each (iter_entry, &head_entry->lst_entries_head) {
-		NMDedupMultiEntry *entry;
+    c_list_for_each (iter_entry, &head_entry->lst_entries_head) {
+        NMDedupMultiEntry *entry;
 
-		entry = c_list_entry (iter_entry, NMDedupMultiEntry, lst_entries);
-		nm_dedup_multi_entry_set_dirty (entry, TRUE);
-	}
+        entry = c_list_entry(iter_entry, NMDedupMultiEntry, lst_entries);
+        nm_dedup_multi_entry_set_dirty(entry, TRUE);
+    }
 }
 
 void
-nm_dedup_multi_index_dirty_set_idx (NMDedupMultiIndex *self,
-                                    const NMDedupMultiIdxType *idx_type)
+nm_dedup_multi_index_dirty_set_idx(NMDedupMultiIndex *self, const NMDedupMultiIdxType *idx_type)
 {
-	CList *iter_idx, *iter_entry;
+    CList *iter_idx, *iter_entry;
 
-	g_return_if_fail (self);
-	g_return_if_fail (idx_type);
+    g_return_if_fail(self);
+    g_return_if_fail(idx_type);
 
-	c_list_for_each (iter_idx, &idx_type->lst_idx_head) {
-		NMDedupMultiHeadEntry *head_entry;
+    c_list_for_each (iter_idx, &idx_type->lst_idx_head) {
+        NMDedupMultiHeadEntry *head_entry;
 
-		head_entry = c_list_entry (iter_idx, NMDedupMultiHeadEntry, lst_idx);
-		c_list_for_each (iter_entry, &head_entry->lst_entries_head) {
-			NMDedupMultiEntry *entry;
+        head_entry = c_list_entry(iter_idx, NMDedupMultiHeadEntry, lst_idx);
+        c_list_for_each (iter_entry, &head_entry->lst_entries_head) {
+            NMDedupMultiEntry *entry;
 
-			entry = c_list_entry (iter_entry, NMDedupMultiEntry, lst_entries);
-			nm_dedup_multi_entry_set_dirty (entry, TRUE);
-		}
-	}
+            entry = c_list_entry(iter_entry, NMDedupMultiEntry, lst_entries);
+            nm_dedup_multi_entry_set_dirty(entry, TRUE);
+        }
+    }
 }
 
 /**
@@ -750,219 +740,212 @@ nm_dedup_multi_index_dirty_set_idx (NMDedupMultiIndex *self,
  * Returns: number of deleted entries.
  */
 guint
-nm_dedup_multi_index_dirty_remove_idx (NMDedupMultiIndex *self,
-                                       NMDedupMultiIdxType *idx_type,
-                                       gboolean mark_survivors_dirty)
+nm_dedup_multi_index_dirty_remove_idx(NMDedupMultiIndex *  self,
+                                      NMDedupMultiIdxType *idx_type,
+                                      gboolean             mark_survivors_dirty)
 {
-	g_return_val_if_fail (self, 0);
-	g_return_val_if_fail (idx_type, 0);
+    g_return_val_if_fail(self, 0);
+    g_return_val_if_fail(idx_type, 0);
 
-	return _remove_idx_entry (self, idx_type, FALSE, mark_survivors_dirty);
+    return _remove_idx_entry(self, idx_type, FALSE, mark_survivors_dirty);
 }
 
 /*****************************************************************************/
 
 static guint
-_dict_idx_objs_hash (const NMDedupMultiObj *obj)
+_dict_idx_objs_hash(const NMDedupMultiObj *obj)
 {
-	NMHashState h;
+    NMHashState h;
 
-	nm_hash_init (&h, 1748638583u);
-	obj->klass->obj_full_hash_update (obj, &h);
-	return nm_hash_complete (&h);
+    nm_hash_init(&h, 1748638583u);
+    obj->klass->obj_full_hash_update(obj, &h);
+    return nm_hash_complete(&h);
 }
 
 static gboolean
-_dict_idx_objs_equal (const NMDedupMultiObj *obj_a,
-                      const NMDedupMultiObj *obj_b)
+_dict_idx_objs_equal(const NMDedupMultiObj *obj_a, const NMDedupMultiObj *obj_b)
 {
-	return    obj_a == obj_b
-	       || (   obj_a->klass == obj_b->klass
-	           && obj_a->klass->obj_full_equal (obj_a, obj_b));
+    return obj_a == obj_b
+           || (obj_a->klass == obj_b->klass && obj_a->klass->obj_full_equal(obj_a, obj_b));
 }
 
 void
-nm_dedup_multi_index_obj_release (NMDedupMultiIndex *self,
-                                  /* const NMDedupMultiObj * */ gconstpointer obj)
+nm_dedup_multi_index_obj_release(NMDedupMultiIndex *                         self,
+                                 /* const NMDedupMultiObj * */ gconstpointer obj)
 {
-	nm_assert (self);
-	nm_assert (obj);
-	nm_assert (g_hash_table_lookup (self->idx_objs, obj) == obj);
-	nm_assert (((const NMDedupMultiObj *) obj)->_multi_idx == self);
-
-	((NMDedupMultiObj *) obj)->_multi_idx = NULL;
-	if (!g_hash_table_remove (self->idx_objs, obj))
-		nm_assert_not_reached ();
+    nm_assert(self);
+    nm_assert(obj);
+    nm_assert(g_hash_table_lookup(self->idx_objs, obj) == obj);
+    nm_assert(((const NMDedupMultiObj *) obj)->_multi_idx == self);
+
+    ((NMDedupMultiObj *) obj)->_multi_idx = NULL;
+    if (!g_hash_table_remove(self->idx_objs, obj))
+        nm_assert_not_reached();
 }
 
 gconstpointer
-nm_dedup_multi_index_obj_find (NMDedupMultiIndex *self,
-                               /* const NMDedupMultiObj * */ gconstpointer obj)
+nm_dedup_multi_index_obj_find(NMDedupMultiIndex *                         self,
+                              /* const NMDedupMultiObj * */ gconstpointer obj)
 {
-	g_return_val_if_fail (self, NULL);
-	g_return_val_if_fail (obj, NULL);
+    g_return_val_if_fail(self, NULL);
+    g_return_val_if_fail(obj, NULL);
 
-	return g_hash_table_lookup (self->idx_objs, obj);
+    return g_hash_table_lookup(self->idx_objs, obj);
 }
 
 gconstpointer
-nm_dedup_multi_index_obj_intern (NMDedupMultiIndex *self,
-                                 /* const NMDedupMultiObj * */ gconstpointer obj)
+nm_dedup_multi_index_obj_intern(NMDedupMultiIndex *                         self,
+                                /* const NMDedupMultiObj * */ gconstpointer obj)
 {
-	const NMDedupMultiObj *obj_new = obj;
-	const NMDedupMultiObj *obj_old;
+    const NMDedupMultiObj *obj_new = obj;
+    const NMDedupMultiObj *obj_old;
 
-	nm_assert (self);
-	nm_assert (obj_new);
+    nm_assert(self);
+    nm_assert(obj_new);
 
-	if (obj_new->_multi_idx == self) {
-		nm_assert (g_hash_table_lookup (self->idx_objs, obj_new) == obj_new);
-		nm_dedup_multi_obj_ref (obj_new);
-		return obj_new;
-	}
+    if (obj_new->_multi_idx == self) {
+        nm_assert(g_hash_table_lookup(self->idx_objs, obj_new) == obj_new);
+        nm_dedup_multi_obj_ref(obj_new);
+        return obj_new;
+    }
 
-	obj_old = g_hash_table_lookup (self->idx_objs, obj_new);
-	nm_assert (obj_old != obj_new);
+    obj_old = g_hash_table_lookup(self->idx_objs, obj_new);
+    nm_assert(obj_old != obj_new);
 
-	if (obj_old) {
-		nm_assert (obj_old->_multi_idx == self);
-		nm_dedup_multi_obj_ref (obj_old);
-		return obj_old;
-	}
+    if (obj_old) {
+        nm_assert(obj_old->_multi_idx == self);
+        nm_dedup_multi_obj_ref(obj_old);
+        return obj_old;
+    }
 
-	if (nm_dedup_multi_obj_needs_clone (obj_new))
-		obj_new = nm_dedup_multi_obj_clone (obj_new);
-	else
-		obj_new = nm_dedup_multi_obj_ref (obj_new);
+    if (nm_dedup_multi_obj_needs_clone(obj_new))
+        obj_new = nm_dedup_multi_obj_clone(obj_new);
+    else
+        obj_new = nm_dedup_multi_obj_ref(obj_new);
 
-	nm_assert (obj_new);
-	nm_assert (!obj_new->_multi_idx);
+    nm_assert(obj_new);
+    nm_assert(!obj_new->_multi_idx);
 
-	if (!g_hash_table_add (self->idx_objs, (gpointer) obj_new))
-		nm_assert_not_reached ();
+    if (!g_hash_table_add(self->idx_objs, (gpointer) obj_new))
+        nm_assert_not_reached();
 
-	((NMDedupMultiObj *) obj_new)->_multi_idx = self;
-	return obj_new;
+    ((NMDedupMultiObj *) obj_new)->_multi_idx = self;
+    return obj_new;
 }
 
 void
-nm_dedup_multi_obj_unref (const NMDedupMultiObj *obj)
+nm_dedup_multi_obj_unref(const NMDedupMultiObj *obj)
 {
-	if (obj) {
-		nm_assert (obj->_ref_count > 0);
-		nm_assert (obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
+    if (obj) {
+        nm_assert(obj->_ref_count > 0);
+        nm_assert(obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
 
 again:
-		if (--(((NMDedupMultiObj *) obj)->_ref_count) <= 0) {
-			if (obj->_multi_idx) {
-				/* restore the ref-count to 1 and release the object first
-				 * from the index. Then, retry again to unref. */
-				((NMDedupMultiObj *) obj)->_ref_count++;
-				nm_dedup_multi_index_obj_release (obj->_multi_idx, obj);
-				nm_assert (obj->_ref_count == 1);
-				nm_assert (!obj->_multi_idx);
-				goto again;
-			}
-
-			obj->klass->obj_destroy ((NMDedupMultiObj *) obj);
-		}
-	}
+        if (--(((NMDedupMultiObj *) obj)->_ref_count) <= 0) {
+            if (obj->_multi_idx) {
+                /* restore the ref-count to 1 and release the object first
+                 * from the index. Then, retry again to unref. */
+                ((NMDedupMultiObj *) obj)->_ref_count++;
+                nm_dedup_multi_index_obj_release(obj->_multi_idx, obj);
+                nm_assert(obj->_ref_count == 1);
+                nm_assert(!obj->_multi_idx);
+                goto again;
+            }
+
+            obj->klass->obj_destroy((NMDedupMultiObj *) obj);
+        }
+    }
 }
 
 gboolean
-nm_dedup_multi_obj_needs_clone (const NMDedupMultiObj *obj)
+nm_dedup_multi_obj_needs_clone(const NMDedupMultiObj *obj)
 {
-	nm_assert (obj);
+    nm_assert(obj);
 
-	if (   obj->_multi_idx
-	    || obj->_ref_count == NM_OBJ_REF_COUNT_STACKINIT)
-		return TRUE;
+    if (obj->_multi_idx || obj->_ref_count == NM_OBJ_REF_COUNT_STACKINIT)
+        return TRUE;
 
-	if (   obj->klass->obj_needs_clone
-	    && obj->klass->obj_needs_clone (obj))
-		return TRUE;
+    if (obj->klass->obj_needs_clone && obj->klass->obj_needs_clone(obj))
+        return TRUE;
 
-	return FALSE;
+    return FALSE;
 }
 
 const NMDedupMultiObj *
-nm_dedup_multi_obj_clone (const NMDedupMultiObj *obj)
+nm_dedup_multi_obj_clone(const NMDedupMultiObj *obj)
 {
-	const NMDedupMultiObj *o;
+    const NMDedupMultiObj *o;
 
-	nm_assert (obj);
+    nm_assert(obj);
 
-	o = obj->klass->obj_clone (obj);
-	nm_assert (o);
-	nm_assert (o->_ref_count == 1);
-	return o;
+    o = obj->klass->obj_clone(obj);
+    nm_assert(o);
+    nm_assert(o->_ref_count == 1);
+    return o;
 }
 
 gconstpointer *
-nm_dedup_multi_objs_to_array_head (const NMDedupMultiHeadEntry *head_entry,
-                                   NMDedupMultiFcnSelectPredicate predicate,
-                                   gpointer user_data,
-                                   guint *out_len)
+nm_dedup_multi_objs_to_array_head(const NMDedupMultiHeadEntry *  head_entry,
+                                  NMDedupMultiFcnSelectPredicate predicate,
+                                  gpointer                       user_data,
+                                  guint *                        out_len)
 {
-	gconstpointer *result;
-	CList *iter;
-	guint i;
-
-	if (!head_entry) {
-		NM_SET_OUT (out_len, 0);
-		return NULL;
-	}
-
-	result = g_new (gconstpointer, head_entry->len + 1);
-	i = 0;
-	c_list_for_each (iter, &head_entry->lst_entries_head) {
-		const NMDedupMultiObj *obj = c_list_entry (iter, NMDedupMultiEntry, lst_entries)->obj;
-
-		if (   !predicate
-		    || predicate (obj, user_data)) {
-			nm_assert (i < head_entry->len);
-			result[i++] = obj;
-		}
-	}
-
-	if (i == 0) {
-		g_free (result);
-		NM_SET_OUT (out_len, 0);
-		return NULL;
-	}
-
-	nm_assert (i <= head_entry->len);
-	NM_SET_OUT (out_len, i);
-	result[i++] = NULL;
-	return result;
+    gconstpointer *result;
+    CList *        iter;
+    guint          i;
+
+    if (!head_entry) {
+        NM_SET_OUT(out_len, 0);
+        return NULL;
+    }
+
+    result = g_new(gconstpointer, head_entry->len + 1);
+    i      = 0;
+    c_list_for_each (iter, &head_entry->lst_entries_head) {
+        const NMDedupMultiObj *obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj;
+
+        if (!predicate || predicate(obj, user_data)) {
+            nm_assert(i < head_entry->len);
+            result[i++] = obj;
+        }
+    }
+
+    if (i == 0) {
+        g_free(result);
+        NM_SET_OUT(out_len, 0);
+        return NULL;
+    }
+
+    nm_assert(i <= head_entry->len);
+    NM_SET_OUT(out_len, i);
+    result[i++] = NULL;
+    return result;
 }
 
 GPtrArray *
-nm_dedup_multi_objs_to_ptr_array_head (const NMDedupMultiHeadEntry *head_entry,
-                                       NMDedupMultiFcnSelectPredicate predicate,
-                                       gpointer user_data)
+nm_dedup_multi_objs_to_ptr_array_head(const NMDedupMultiHeadEntry *  head_entry,
+                                      NMDedupMultiFcnSelectPredicate predicate,
+                                      gpointer                       user_data)
 {
-	GPtrArray *result;
-	CList *iter;
-
-	if (!head_entry)
-		return NULL;
-
-	result = g_ptr_array_new_full (head_entry->len,
-	                               (GDestroyNotify) nm_dedup_multi_obj_unref);
-	c_list_for_each (iter, &head_entry->lst_entries_head) {
-		const NMDedupMultiObj *obj = c_list_entry (iter, NMDedupMultiEntry, lst_entries)->obj;
-
-		if (   !predicate
-		    || predicate (obj, user_data))
-			g_ptr_array_add (result, (gpointer) nm_dedup_multi_obj_ref (obj));
-	}
-
-	if (result->len == 0) {
-		g_ptr_array_unref (result);
-		return NULL;
-	}
-	return result;
+    GPtrArray *result;
+    CList *    iter;
+
+    if (!head_entry)
+        return NULL;
+
+    result = g_ptr_array_new_full(head_entry->len, (GDestroyNotify) nm_dedup_multi_obj_unref);
+    c_list_for_each (iter, &head_entry->lst_entries_head) {
+        const NMDedupMultiObj *obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj;
+
+        if (!predicate || predicate(obj, user_data))
+            g_ptr_array_add(result, (gpointer) nm_dedup_multi_obj_ref(obj));
+    }
+
+    if (result->len == 0) {
+        g_ptr_array_unref(result);
+        return NULL;
+    }
+    return result;
 }
 
 /**
@@ -981,96 +964,102 @@ nm_dedup_multi_objs_to_ptr_array_head (const NMDedupMultiHeadEntry *head_entry,
  * right place and nothing was done.
  */
 gboolean
-nm_dedup_multi_entry_reorder (const NMDedupMultiEntry *entry,
-                              const NMDedupMultiEntry *entry_order,
-                              gboolean order_after)
+nm_dedup_multi_entry_reorder(const NMDedupMultiEntry *entry,
+                             const NMDedupMultiEntry *entry_order,
+                             gboolean                 order_after)
 {
-	nm_assert (entry);
-
-	if (!entry_order) {
-		const NMDedupMultiHeadEntry *head_entry = entry->head;
-
-		if (order_after) {
-			if (nm_c_list_move_tail ((CList *) &head_entry->lst_entries_head, (CList *) &entry->lst_entries))
-				return TRUE;
-		} else {
-			if (nm_c_list_move_front ((CList *) &head_entry->lst_entries_head, (CList *) &entry->lst_entries))
-				return TRUE;
-		}
-	} else {
-		if (order_after) {
-			if (nm_c_list_move_after ((CList *) &entry_order->lst_entries, (CList *) &entry->lst_entries))
-				return TRUE;
-		} else {
-			if (nm_c_list_move_before ((CList *) &entry_order->lst_entries, (CList *) &entry->lst_entries))
-				return TRUE;
-		}
-	}
-
-	return FALSE;
+    nm_assert(entry);
+
+    if (!entry_order) {
+        const NMDedupMultiHeadEntry *head_entry = entry->head;
+
+        if (order_after) {
+            if (nm_c_list_move_tail((CList *) &head_entry->lst_entries_head,
+                                    (CList *) &entry->lst_entries))
+                return TRUE;
+        } else {
+            if (nm_c_list_move_front((CList *) &head_entry->lst_entries_head,
+                                     (CList *) &entry->lst_entries))
+                return TRUE;
+        }
+    } else {
+        if (order_after) {
+            if (nm_c_list_move_after((CList *) &entry_order->lst_entries,
+                                     (CList *) &entry->lst_entries))
+                return TRUE;
+        } else {
+            if (nm_c_list_move_before((CList *) &entry_order->lst_entries,
+                                      (CList *) &entry->lst_entries))
+                return TRUE;
+        }
+    }
+
+    return FALSE;
 }
 
 /*****************************************************************************/
 
 NMDedupMultiIndex *
-nm_dedup_multi_index_new (void)
+nm_dedup_multi_index_new(void)
 {
-	NMDedupMultiIndex *self;
-
-	self = g_slice_new0 (NMDedupMultiIndex);
-	self->ref_count = 1;
-	self->idx_entries = g_hash_table_new ((GHashFunc) _dict_idx_entries_hash, (GEqualFunc) _dict_idx_entries_equal);
-	self->idx_objs    = g_hash_table_new ((GHashFunc) _dict_idx_objs_hash,    (GEqualFunc) _dict_idx_objs_equal);
-	return self;
+    NMDedupMultiIndex *self;
+
+    self            = g_slice_new0(NMDedupMultiIndex);
+    self->ref_count = 1;
+    self->idx_entries =
+        g_hash_table_new((GHashFunc) _dict_idx_entries_hash, (GEqualFunc) _dict_idx_entries_equal);
+    self->idx_objs =
+        g_hash_table_new((GHashFunc) _dict_idx_objs_hash, (GEqualFunc) _dict_idx_objs_equal);
+    return self;
 }
 
 NMDedupMultiIndex *
-nm_dedup_multi_index_ref (NMDedupMultiIndex *self)
+nm_dedup_multi_index_ref(NMDedupMultiIndex *self)
 {
-	g_return_val_if_fail (self, NULL);
-	g_return_val_if_fail (self->ref_count > 0, NULL);
+    g_return_val_if_fail(self, NULL);
+    g_return_val_if_fail(self->ref_count > 0, NULL);
 
-	self->ref_count++;
-	return self;
+    self->ref_count++;
+    return self;
 }
 
 NMDedupMultiIndex *
-nm_dedup_multi_index_unref (NMDedupMultiIndex *self)
+nm_dedup_multi_index_unref(NMDedupMultiIndex *self)
 {
-	GHashTableIter iter;
-	const NMDedupMultiIdxType *idx_type;
-	NMDedupMultiEntry *entry;
-	const NMDedupMultiObj *obj;
+    GHashTableIter             iter;
+    const NMDedupMultiIdxType *idx_type;
+    NMDedupMultiEntry *        entry;
+    const NMDedupMultiObj *    obj;
 
-	g_return_val_if_fail (self, NULL);
-	g_return_val_if_fail (self->ref_count > 0, NULL);
+    g_return_val_if_fail(self, NULL);
+    g_return_val_if_fail(self->ref_count > 0, NULL);
 
-	if (--self->ref_count > 0)
-		return NULL;
+    if (--self->ref_count > 0)
+        return NULL;
 
 more:
-	g_hash_table_iter_init (&iter, self->idx_entries);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &entry, NULL)) {
-		if (entry->is_head)
-			idx_type = ((NMDedupMultiHeadEntry *) entry)->idx_type;
-		else
-			idx_type = entry->head->idx_type;
-		_remove_idx_entry (self, (NMDedupMultiIdxType *) idx_type, TRUE, FALSE);
-		goto more;
-	}
-
-	nm_assert (g_hash_table_size (self->idx_entries) == 0);
-
-	g_hash_table_iter_init (&iter, self->idx_objs);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &obj, NULL)) {
-		nm_assert (obj->_multi_idx == self);
-		((NMDedupMultiObj * )obj)->_multi_idx = NULL;
-	}
-	g_hash_table_remove_all (self->idx_objs);
-
-	g_hash_table_unref (self->idx_entries);
-	g_hash_table_unref (self->idx_objs);
-
-	g_slice_free (NMDedupMultiIndex, self);
-	return NULL;
+    g_hash_table_iter_init(&iter, self->idx_entries);
+    while (g_hash_table_iter_next(&iter, (gpointer *) &entry, NULL)) {
+        if (entry->is_head)
+            idx_type = ((NMDedupMultiHeadEntry *) entry)->idx_type;
+        else
+            idx_type = entry->head->idx_type;
+        _remove_idx_entry(self, (NMDedupMultiIdxType *) idx_type, TRUE, FALSE);
+        goto more;
+    }
+
+    nm_assert(g_hash_table_size(self->idx_entries) == 0);
+
+    g_hash_table_iter_init(&iter, self->idx_objs);
+    while (g_hash_table_iter_next(&iter, (gpointer *) &obj, NULL)) {
+        nm_assert(obj->_multi_idx == self);
+        ((NMDedupMultiObj *) obj)->_multi_idx = NULL;
+    }
+    g_hash_table_remove_all(self->idx_objs);
+
+    g_hash_table_unref(self->idx_entries);
+    g_hash_table_unref(self->idx_objs);
+
+    g_slice_free(NMDedupMultiIndex, self);
+    return NULL;
 }