|
Packit Service |
b23acc |
// SPDX-License-Identifier: LGPL-2.1+
|
|
Packit Service |
b23acc |
/*
|
|
Packit Service |
b23acc |
* Copyright (C) 2017 Red Hat, Inc.
|
|
Packit Service |
b23acc |
*/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
#include "nm-default.h"
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
#include "nm-dedup-multi.h"
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
#include "nm-hash-utils.h"
|
|
Packit Service |
b23acc |
#include "nm-c-list.h"
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
typedef struct {
|
|
Packit Service |
b23acc |
/* the stack-allocated lookup entry. It has a compatible
|
|
Packit Service |
b23acc |
* memory layout with NMDedupMultiEntry and NMDedupMultiHeadEntry.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* It is recognizable by having lst_entries_sentinel.next set to NULL.
|
|
Packit Service |
b23acc |
* Contrary to the other entries, which have lst_entries.next
|
|
Packit Service |
b23acc |
* always non-NULL.
|
|
Packit Service |
b23acc |
* */
|
|
Packit Service |
b23acc |
CList lst_entries_sentinel;
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj;
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type;
|
|
Packit Service |
b23acc |
bool lookup_head;
|
|
Packit Service |
b23acc |
} LookupEntry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
struct _NMDedupMultiIndex {
|
|
Packit Service |
b23acc |
int ref_count;
|
|
Packit Service |
b23acc |
GHashTable *idx_entries;
|
|
Packit Service |
b23acc |
GHashTable *idx_objs;
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static void
|
|
Packit Service |
b23acc |
ASSERT_idx_type (const NMDedupMultiIdxType *idx_type)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
nm_assert (idx_type);
|
|
Packit Service |
b23acc |
#if NM_MORE_ASSERTS > 10
|
|
Packit Service |
b23acc |
nm_assert (idx_type->klass);
|
|
Packit Service |
b23acc |
nm_assert (idx_type->klass->idx_obj_id_hash_update);
|
|
Packit Service |
b23acc |
nm_assert (idx_type->klass->idx_obj_id_equal);
|
|
Packit Service |
b23acc |
nm_assert (!!idx_type->klass->idx_obj_partition_hash_update == !!idx_type->klass->idx_obj_partition_equal);
|
|
Packit Service |
b23acc |
nm_assert (idx_type->lst_idx_head.next);
|
|
Packit Service |
b23acc |
#endif
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
void
|
|
Packit Service |
b23acc |
nm_dedup_multi_idx_type_init (NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxTypeClass *klass)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
nm_assert (idx_type);
|
|
Packit Service |
b23acc |
nm_assert (klass);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
memset (idx_type, 0, sizeof (*idx_type));
|
|
Packit Service |
b23acc |
idx_type->klass = klass;
|
|
Packit Service |
b23acc |
c_list_init (&idx_type->lst_idx_head);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
ASSERT_idx_type (idx_type);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static NMDedupMultiEntry *
|
|
Packit Service |
b23acc |
_entry_lookup_obj (const NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
const LookupEntry stack_entry = {
|
|
Packit Service |
b23acc |
.obj = obj,
|
|
Packit Service |
b23acc |
.idx_type = idx_type,
|
|
Packit Service |
b23acc |
.lookup_head = FALSE,
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
ASSERT_idx_type (idx_type);
|
|
Packit Service |
b23acc |
return g_hash_table_lookup (self->idx_entries, &stack_entry);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static NMDedupMultiHeadEntry *
|
|
Packit Service |
b23acc |
_entry_lookup_head (const NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
NMDedupMultiHeadEntry *head_entry;
|
|
Packit Service |
b23acc |
const LookupEntry stack_entry = {
|
|
Packit Service |
b23acc |
.obj = obj,
|
|
Packit Service |
b23acc |
.idx_type = idx_type,
|
|
Packit Service |
b23acc |
.lookup_head = TRUE,
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
ASSERT_idx_type (idx_type);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!idx_type->klass->idx_obj_partition_equal) {
|
|
Packit Service |
b23acc |
if (c_list_is_empty (&idx_type->lst_idx_head))
|
|
Packit Service |
b23acc |
head_entry = NULL;
|
|
Packit Service |
b23acc |
else {
|
|
Packit Service |
b23acc |
nm_assert (c_list_length (&idx_type->lst_idx_head) == 1);
|
|
Packit Service |
b23acc |
head_entry = c_list_entry (idx_type->lst_idx_head.next, NMDedupMultiHeadEntry, lst_idx);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
nm_assert (head_entry == g_hash_table_lookup (self->idx_entries, &stack_entry));
|
|
Packit Service |
b23acc |
return head_entry;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return g_hash_table_lookup (self->idx_entries, &stack_entry);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static void
|
|
Packit Service |
b23acc |
_entry_unpack (const NMDedupMultiEntry *entry,
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType **out_idx_type,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj **out_obj,
|
|
Packit Service |
b23acc |
gboolean *out_lookup_head)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
const NMDedupMultiHeadEntry *head_entry;
|
|
Packit Service |
b23acc |
const LookupEntry *lookup_entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (entry);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (LookupEntry, lst_entries_sentinel) == G_STRUCT_OFFSET (NMDedupMultiEntry, lst_entries));
|
|
Packit Service |
b23acc |
G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, lst_entries) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, lst_entries_head));
|
|
Packit Service |
b23acc |
G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, obj) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, idx_type));
|
|
Packit Service |
b23acc |
G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, is_head) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, is_head));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!entry->lst_entries.next) {
|
|
Packit Service |
b23acc |
/* the entry is stack-allocated by _entry_lookup(). */
|
|
Packit Service |
b23acc |
lookup_entry = (LookupEntry *) entry;
|
|
Packit Service |
b23acc |
*out_obj = lookup_entry->obj;
|
|
Packit Service |
b23acc |
*out_idx_type = lookup_entry->idx_type;
|
|
Packit Service |
b23acc |
*out_lookup_head = lookup_entry->lookup_head;
|
|
Packit Service |
b23acc |
} else if (entry->is_head) {
|
|
Packit Service |
b23acc |
head_entry = (NMDedupMultiHeadEntry *) entry;
|
|
Packit Service |
b23acc |
nm_assert (!c_list_is_empty (&head_entry->lst_entries_head));
|
|
Packit Service |
b23acc |
*out_obj = c_list_entry (head_entry->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->obj;
|
|
Packit Service |
b23acc |
*out_idx_type = head_entry->idx_type;
|
|
Packit Service |
b23acc |
*out_lookup_head = TRUE;
|
|
Packit Service |
b23acc |
} else {
|
|
Packit Service |
b23acc |
*out_obj = entry->obj;
|
|
Packit Service |
b23acc |
*out_idx_type = entry->head->idx_type;
|
|
Packit Service |
b23acc |
*out_lookup_head = FALSE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (NM_IN_SET (*out_lookup_head, FALSE, TRUE));
|
|
Packit Service |
b23acc |
ASSERT_idx_type (*out_idx_type);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* for lookup of the head, we allow to omit object, but only
|
|
Packit Service |
b23acc |
* if the idx_type does not partition the objects. Otherwise, we
|
|
Packit Service |
b23acc |
* require a obj to compare. */
|
|
Packit Service |
b23acc |
nm_assert ( !*out_lookup_head
|
|
Packit Service |
b23acc |
|| ( *out_obj
|
|
Packit Service |
b23acc |
|| !(*out_idx_type)->klass->idx_obj_partition_equal));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* lookup of the object requires always an object. */
|
|
Packit Service |
b23acc |
nm_assert ( *out_lookup_head
|
|
Packit Service |
b23acc |
|| *out_obj);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static guint
|
|
Packit Service |
b23acc |
_dict_idx_entries_hash (const NMDedupMultiEntry *entry)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type;
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj;
|
|
Packit Service |
b23acc |
gboolean lookup_head;
|
|
Packit Service |
b23acc |
NMHashState h;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_entry_unpack (entry, &idx_type, &obj, &lookup_head);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_hash_init (&h, 1914869417u);
|
|
Packit Service |
b23acc |
if (idx_type->klass->idx_obj_partition_hash_update) {
|
|
Packit Service |
b23acc |
nm_assert (obj);
|
|
Packit Service |
b23acc |
idx_type->klass->idx_obj_partition_hash_update (idx_type, obj, &h);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!lookup_head)
|
|
Packit Service |
b23acc |
idx_type->klass->idx_obj_id_hash_update (idx_type, obj, &h);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_hash_update_val (&h, idx_type);
|
|
Packit Service |
b23acc |
return nm_hash_complete (&h);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static gboolean
|
|
Packit Service |
b23acc |
_dict_idx_entries_equal (const NMDedupMultiEntry *entry_a,
|
|
Packit Service |
b23acc |
const NMDedupMultiEntry *entry_b)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type_a, *idx_type_b;
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj_a, *obj_b;
|
|
Packit Service |
b23acc |
gboolean lookup_head_a, lookup_head_b;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_entry_unpack (entry_a, &idx_type_a, &obj_a, &lookup_head_a);
|
|
Packit Service |
b23acc |
_entry_unpack (entry_b, &idx_type_b, &obj_b, &lookup_head_b);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if ( idx_type_a != idx_type_b
|
|
Packit Service |
b23acc |
|| lookup_head_a != lookup_head_b)
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
if (!nm_dedup_multi_idx_type_partition_equal (idx_type_a, obj_a, obj_b))
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
if ( !lookup_head_a
|
|
Packit Service |
b23acc |
&& !nm_dedup_multi_idx_type_id_equal (idx_type_a, obj_a, obj_b))
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static gboolean
|
|
Packit Service |
b23acc |
_add (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj,
|
|
Packit Service |
b23acc |
NMDedupMultiEntry *entry,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxMode mode,
|
|
Packit Service |
b23acc |
const NMDedupMultiEntry *entry_order,
|
|
Packit Service |
b23acc |
NMDedupMultiHeadEntry *head_existing,
|
|
Packit Service |
b23acc |
const NMDedupMultiEntry **out_entry,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj **out_obj_old)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
NMDedupMultiHeadEntry *head_entry;
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj_new, *obj_old;
|
|
Packit Service |
b23acc |
gboolean add_head_entry = FALSE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (self);
|
|
Packit Service |
b23acc |
ASSERT_idx_type (idx_type);
|
|
Packit Service |
b23acc |
nm_assert (obj);
|
|
Packit Service |
b23acc |
nm_assert (NM_IN_SET (mode,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_PREPEND,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_APPEND,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE));
|
|
Packit Service |
b23acc |
nm_assert (!head_existing || head_existing->idx_type == idx_type);
|
|
Packit Service |
b23acc |
nm_assert (({
|
|
Packit Service |
b23acc |
const NMDedupMultiHeadEntry *_h;
|
|
Packit Service |
b23acc |
gboolean _ok = TRUE;
|
|
Packit Service |
b23acc |
if (head_existing) {
|
|
Packit Service |
b23acc |
_h = nm_dedup_multi_index_lookup_head (self, idx_type, obj);
|
|
Packit Service |
b23acc |
if (head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING)
|
|
Packit Service |
b23acc |
_ok = (_h == NULL);
|
|
Packit Service |
b23acc |
else
|
|
Packit Service |
b23acc |
_ok = (_h == head_existing);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
_ok;
|
|
Packit Service |
b23acc |
}));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (entry) {
|
|
Packit Service |
b23acc |
gboolean changed = FALSE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_dedup_multi_entry_set_dirty (entry, FALSE);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (!head_existing || entry->head == head_existing);
|
|
Packit Service |
b23acc |
nm_assert (!entry_order || entry_order->head == entry->head);
|
|
Packit Service |
b23acc |
nm_assert (!entry_order || c_list_contains (&entry->lst_entries, &entry_order->lst_entries));
|
|
Packit Service |
b23acc |
nm_assert (!entry_order || c_list_contains (&entry_order->lst_entries, &entry->lst_entries));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
switch (mode) {
|
|
Packit Service |
b23acc |
case NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE:
|
|
Packit Service |
b23acc |
if (entry_order) {
|
|
Packit Service |
b23acc |
if (nm_c_list_move_before ((CList *) &entry_order->lst_entries, &entry->lst_entries))
|
|
Packit Service |
b23acc |
changed = TRUE;
|
|
Packit Service |
b23acc |
} else {
|
|
Packit Service |
b23acc |
if (nm_c_list_move_front ((CList *) &entry->head->lst_entries_head, &entry->lst_entries))
|
|
Packit Service |
b23acc |
changed = TRUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
break;
|
|
Packit Service |
b23acc |
case NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE:
|
|
Packit Service |
b23acc |
if (entry_order) {
|
|
Packit Service |
b23acc |
if (nm_c_list_move_after ((CList *) &entry_order->lst_entries, &entry->lst_entries))
|
|
Packit Service |
b23acc |
changed = TRUE;
|
|
Packit Service |
b23acc |
} else {
|
|
Packit Service |
b23acc |
if (nm_c_list_move_tail ((CList *) &entry->head->lst_entries_head, &entry->lst_entries))
|
|
Packit Service |
b23acc |
changed = TRUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
break;
|
|
Packit Service |
b23acc |
case NM_DEDUP_MULTI_IDX_MODE_PREPEND:
|
|
Packit Service |
b23acc |
case NM_DEDUP_MULTI_IDX_MODE_APPEND:
|
|
Packit Service |
b23acc |
break;
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (obj->klass == ((const NMDedupMultiObj *) entry->obj)->klass);
|
|
Packit Service |
b23acc |
if ( obj == entry->obj
|
|
Packit Service |
b23acc |
|| obj->klass->obj_full_equal (obj,
|
|
Packit Service |
b23acc |
entry->obj)) {
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_entry, entry);
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_obj_old, nm_dedup_multi_obj_ref (entry->obj));
|
|
Packit Service |
b23acc |
return changed;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
obj_new = nm_dedup_multi_index_obj_intern (self, obj);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
obj_old = entry->obj;
|
|
Packit Service |
b23acc |
entry->obj = obj_new;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_entry, entry);
|
|
Packit Service |
b23acc |
if (out_obj_old)
|
|
Packit Service |
b23acc |
*out_obj_old = obj_old;
|
|
Packit Service |
b23acc |
else
|
|
Packit Service |
b23acc |
nm_dedup_multi_obj_unref (obj_old);
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if ( idx_type->klass->idx_obj_partitionable
|
|
Packit Service |
b23acc |
&& !idx_type->klass->idx_obj_partitionable (idx_type, obj)) {
|
|
Packit Service |
b23acc |
/* this object cannot be partitioned by this idx_type. */
|
|
Packit Service |
b23acc |
nm_assert (!head_existing || head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING);
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_entry, NULL);
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_obj_old, NULL);
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
obj_new = nm_dedup_multi_index_obj_intern (self, obj);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!head_existing)
|
|
Packit Service |
b23acc |
head_entry = _entry_lookup_head (self, idx_type, obj_new);
|
|
Packit Service |
b23acc |
else if (head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING)
|
|
Packit Service |
b23acc |
head_entry = NULL;
|
|
Packit Service |
b23acc |
else
|
|
Packit Service |
b23acc |
head_entry = head_existing;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!head_entry) {
|
|
Packit Service |
b23acc |
head_entry = g_slice_new0 (NMDedupMultiHeadEntry);
|
|
Packit Service |
b23acc |
head_entry->is_head = TRUE;
|
|
Packit Service |
b23acc |
head_entry->idx_type = idx_type;
|
|
Packit Service |
b23acc |
c_list_init (&head_entry->lst_entries_head);
|
|
Packit Service |
b23acc |
c_list_link_tail (&idx_type->lst_idx_head, &head_entry->lst_idx);
|
|
Packit Service |
b23acc |
add_head_entry = TRUE;
|
|
Packit Service |
b23acc |
} else
|
|
Packit Service |
b23acc |
nm_assert (c_list_contains (&idx_type->lst_idx_head, &head_entry->lst_idx));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (entry_order) {
|
|
Packit Service |
b23acc |
nm_assert (!add_head_entry);
|
|
Packit Service |
b23acc |
nm_assert (entry_order->head == head_entry);
|
|
Packit Service |
b23acc |
nm_assert (c_list_contains (&head_entry->lst_entries_head, &entry_order->lst_entries));
|
|
Packit Service |
b23acc |
nm_assert (c_list_contains (&entry_order->lst_entries, &head_entry->lst_entries_head));
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
entry = g_slice_new0 (NMDedupMultiEntry);
|
|
Packit Service |
b23acc |
entry->obj = obj_new;
|
|
Packit Service |
b23acc |
entry->head = head_entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
switch (mode) {
|
|
Packit Service |
b23acc |
case NM_DEDUP_MULTI_IDX_MODE_PREPEND:
|
|
Packit Service |
b23acc |
case NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE:
|
|
Packit Service |
b23acc |
if (entry_order)
|
|
Packit Service |
b23acc |
c_list_link_before ((CList *) &entry_order->lst_entries, &entry->lst_entries);
|
|
Packit Service |
b23acc |
else
|
|
Packit Service |
b23acc |
c_list_link_front (&head_entry->lst_entries_head, &entry->lst_entries);
|
|
Packit Service |
b23acc |
break;
|
|
Packit Service |
b23acc |
default:
|
|
Packit Service |
b23acc |
if (entry_order)
|
|
Packit Service |
b23acc |
c_list_link_after ((CList *) &entry_order->lst_entries, &entry->lst_entries);
|
|
Packit Service |
b23acc |
else
|
|
Packit Service |
b23acc |
c_list_link_tail (&head_entry->lst_entries_head, &entry->lst_entries);
|
|
Packit Service |
b23acc |
break;
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
idx_type->len++;
|
|
Packit Service |
b23acc |
head_entry->len++;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if ( add_head_entry
|
|
Packit Service |
b23acc |
&& !g_hash_table_add (self->idx_entries, head_entry))
|
|
Packit Service |
b23acc |
nm_assert_not_reached ();
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!g_hash_table_add (self->idx_entries, entry))
|
|
Packit Service |
b23acc |
nm_assert_not_reached ();
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_entry, entry);
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_obj_old, NULL);
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
gboolean
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_add (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
/*const NMDedupMultiObj * */ gconstpointer obj,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxMode mode,
|
|
Packit Service |
b23acc |
const NMDedupMultiEntry **out_entry,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj ** */ gpointer out_obj_old)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
NMDedupMultiEntry *entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self, FALSE);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (idx_type, FALSE);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (obj, FALSE);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (NM_IN_SET (mode,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_PREPEND,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_APPEND,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE),
|
|
Packit Service |
b23acc |
FALSE);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
entry = _entry_lookup_obj (self, idx_type, obj);
|
|
Packit Service |
b23acc |
return _add (self, idx_type, obj,
|
|
Packit Service |
b23acc |
entry, mode,
|
|
Packit Service |
b23acc |
NULL, NULL,
|
|
Packit Service |
b23acc |
out_entry, out_obj_old);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* nm_dedup_multi_index_add_full:
|
|
Packit Service |
b23acc |
* @self: the index instance.
|
|
Packit Service |
b23acc |
* @idx_type: the index handle for storing @obj.
|
|
Packit Service |
b23acc |
* @obj: the NMDedupMultiObj instance to add.
|
|
Packit Service |
b23acc |
* @mode: whether to append or prepend the new item. If @entry_order is given,
|
|
Packit Service |
b23acc |
* the entry will be sorted after/before, instead of appending/prepending to
|
|
Packit Service |
b23acc |
* the entire list. If a comparable object is already tracked, then it may
|
|
Packit Service |
b23acc |
* still be resorted by specifying one of the "FORCE" modes.
|
|
Packit Service |
b23acc |
* @entry_order: if not NULL, the new entry will be sorted before or after @entry_order.
|
|
Packit Service |
b23acc |
* If given, @entry_order MUST be tracked by @self, and the object it points to MUST
|
|
Packit Service |
b23acc |
* be in the same partition tracked by @idx_type. That is, they must have the same
|
|
Packit Service |
b23acc |
* head_entry and it means, you must ensure that @entry_order and the created/modified
|
|
Packit Service |
b23acc |
* entry will share the same head.
|
|
Packit Service |
b23acc |
* @entry_existing: if not NULL, it safes a hash lookup of the entry where the
|
|
Packit Service |
b23acc |
* object will be placed in. You can omit this, and it will be automatically
|
|
Packit Service |
b23acc |
* detected (at the expense of an additional hash lookup).
|
|
Packit Service |
b23acc |
* Basically, this is the result of nm_dedup_multi_index_lookup_obj(),
|
|
Packit Service |
b23acc |
* with the peculiarity that if you know that @obj is not yet tracked,
|
|
Packit Service |
b23acc |
* you may specify %NM_DEDUP_MULTI_ENTRY_MISSING.
|
|
Packit Service |
b23acc |
* @head_existing: an optional argument to safe a lookup for the head. If specified,
|
|
Packit Service |
b23acc |
* it must be identical to nm_dedup_multi_index_lookup_head(), with the peculiarity
|
|
Packit Service |
b23acc |
* that if the head is not yet tracked, you may specify %NM_DEDUP_MULTI_HEAD_ENTRY_MISSING
|
|
Packit Service |
b23acc |
* @out_entry: if give, return the added entry. This entry may have already exists (update)
|
|
Packit Service |
b23acc |
* or be newly created. If @obj is not partitionable according to @idx_type, @obj
|
|
Packit Service |
b23acc |
* is not to be added and it returns %NULL.
|
|
Packit Service |
b23acc |
* @out_obj_old: if given, return the previously contained object. It only
|
|
Packit Service |
b23acc |
* returns a object, if a matching entry was tracked previously, not if a
|
|
Packit Service |
b23acc |
* new entry was created. Note that when passing @out_obj_old you obtain a reference
|
|
Packit Service |
b23acc |
* to the boxed object and MUST return it with nm_dedup_multi_obj_unref().
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* Adds and object to the index.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* Return: %TRUE if anything changed, %FALSE if nothing changed.
|
|
Packit Service |
b23acc |
*/
|
|
Packit Service |
b23acc |
gboolean
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_add_full (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
/*const NMDedupMultiObj * */ gconstpointer obj,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxMode mode,
|
|
Packit Service |
b23acc |
const NMDedupMultiEntry *entry_order,
|
|
Packit Service |
b23acc |
const NMDedupMultiEntry *entry_existing,
|
|
Packit Service |
b23acc |
const NMDedupMultiHeadEntry *head_existing,
|
|
Packit Service |
b23acc |
const NMDedupMultiEntry **out_entry,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj ** */ gpointer out_obj_old)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
NMDedupMultiEntry *entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self, FALSE);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (idx_type, FALSE);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (obj, FALSE);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (NM_IN_SET (mode,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_PREPEND,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_APPEND,
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE),
|
|
Packit Service |
b23acc |
FALSE);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (entry_existing == NULL)
|
|
Packit Service |
b23acc |
entry = _entry_lookup_obj (self, idx_type, obj);
|
|
Packit Service |
b23acc |
else if (entry_existing == NM_DEDUP_MULTI_ENTRY_MISSING) {
|
|
Packit Service |
b23acc |
nm_assert (!_entry_lookup_obj (self, idx_type, obj));
|
|
Packit Service |
b23acc |
entry = NULL;
|
|
Packit Service |
b23acc |
} else {
|
|
Packit Service |
b23acc |
nm_assert (entry_existing == _entry_lookup_obj (self, idx_type, obj));
|
|
Packit Service |
b23acc |
entry = (NMDedupMultiEntry *) entry_existing;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
return _add (self, idx_type, obj,
|
|
Packit Service |
b23acc |
entry,
|
|
Packit Service |
b23acc |
mode, entry_order,
|
|
Packit Service |
b23acc |
(NMDedupMultiHeadEntry *) head_existing,
|
|
Packit Service |
b23acc |
out_entry, out_obj_old);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static void
|
|
Packit Service |
b23acc |
_remove_entry (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
NMDedupMultiEntry *entry,
|
|
Packit Service |
b23acc |
gboolean *out_head_entry_removed)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj;
|
|
Packit Service |
b23acc |
NMDedupMultiHeadEntry *head_entry;
|
|
Packit Service |
b23acc |
NMDedupMultiIdxType *idx_type;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (self);
|
|
Packit Service |
b23acc |
nm_assert (entry);
|
|
Packit Service |
b23acc |
nm_assert (entry->obj);
|
|
Packit Service |
b23acc |
nm_assert (entry->head);
|
|
Packit Service |
b23acc |
nm_assert (!c_list_is_empty (&entry->lst_entries));
|
|
Packit Service |
b23acc |
nm_assert (g_hash_table_lookup (self->idx_entries, entry) == entry);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
head_entry = (NMDedupMultiHeadEntry *) entry->head;
|
|
Packit Service |
b23acc |
obj = entry->obj;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (head_entry);
|
|
Packit Service |
b23acc |
nm_assert (head_entry->len > 0);
|
|
Packit Service |
b23acc |
nm_assert (g_hash_table_lookup (self->idx_entries, head_entry) == head_entry);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
idx_type = (NMDedupMultiIdxType *) head_entry->idx_type;
|
|
Packit Service |
b23acc |
ASSERT_idx_type (idx_type);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (idx_type->len >= head_entry->len);
|
|
Packit Service |
b23acc |
if (--head_entry->len > 0) {
|
|
Packit Service |
b23acc |
nm_assert (idx_type->len > 1);
|
|
Packit Service |
b23acc |
idx_type->len--;
|
|
Packit Service |
b23acc |
head_entry = NULL;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_head_entry_removed, head_entry != NULL);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!g_hash_table_remove (self->idx_entries, entry))
|
|
Packit Service |
b23acc |
nm_assert_not_reached ();
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if ( head_entry
|
|
Packit Service |
b23acc |
&& !g_hash_table_remove (self->idx_entries, head_entry))
|
|
Packit Service |
b23acc |
nm_assert_not_reached ();
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
c_list_unlink_stale (&entry->lst_entries);
|
|
Packit Service |
b23acc |
g_slice_free (NMDedupMultiEntry, entry);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (head_entry) {
|
|
Packit Service |
b23acc |
nm_assert (c_list_is_empty (&head_entry->lst_entries_head));
|
|
Packit Service |
b23acc |
c_list_unlink_stale (&head_entry->lst_idx);
|
|
Packit Service |
b23acc |
g_slice_free (NMDedupMultiHeadEntry, head_entry);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_dedup_multi_obj_unref (obj);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static guint
|
|
Packit Service |
b23acc |
_remove_head (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
NMDedupMultiHeadEntry *head_entry,
|
|
Packit Service |
b23acc |
gboolean remove_all /* otherwise just dirty ones */,
|
|
Packit Service |
b23acc |
gboolean mark_survivors_dirty)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
guint n;
|
|
Packit Service |
b23acc |
gboolean head_entry_removed;
|
|
Packit Service |
b23acc |
CList *iter_entry, *iter_entry_safe;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (self);
|
|
Packit Service |
b23acc |
nm_assert (head_entry);
|
|
Packit Service |
b23acc |
nm_assert (head_entry->len > 0);
|
|
Packit Service |
b23acc |
nm_assert (head_entry->len == c_list_length (&head_entry->lst_entries_head));
|
|
Packit Service |
b23acc |
nm_assert (g_hash_table_lookup (self->idx_entries, head_entry) == head_entry);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
n = 0;
|
|
Packit Service |
b23acc |
c_list_for_each_safe (iter_entry, iter_entry_safe, &head_entry->lst_entries_head) {
|
|
Packit Service |
b23acc |
NMDedupMultiEntry *entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
entry = c_list_entry (iter_entry, NMDedupMultiEntry, lst_entries);
|
|
Packit Service |
b23acc |
if ( remove_all
|
|
Packit Service |
b23acc |
|| entry->dirty) {
|
|
Packit Service |
b23acc |
_remove_entry (self,
|
|
Packit Service |
b23acc |
entry,
|
|
Packit Service |
b23acc |
&head_entry_removed);
|
|
Packit Service |
b23acc |
n++;
|
|
Packit Service |
b23acc |
if (head_entry_removed)
|
|
Packit Service |
b23acc |
break;
|
|
Packit Service |
b23acc |
} else if (mark_survivors_dirty)
|
|
Packit Service |
b23acc |
nm_dedup_multi_entry_set_dirty (entry, TRUE);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return n;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static guint
|
|
Packit Service |
b23acc |
_remove_idx_entry (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
gboolean remove_all /* otherwise just dirty ones */,
|
|
Packit Service |
b23acc |
gboolean mark_survivors_dirty)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
guint n;
|
|
Packit Service |
b23acc |
CList *iter_idx, *iter_idx_safe;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (self);
|
|
Packit Service |
b23acc |
ASSERT_idx_type (idx_type);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
n = 0;
|
|
Packit Service |
b23acc |
c_list_for_each_safe (iter_idx, iter_idx_safe, &idx_type->lst_idx_head) {
|
|
Packit Service |
b23acc |
n += _remove_head (self,
|
|
Packit Service |
b23acc |
c_list_entry (iter_idx, NMDedupMultiHeadEntry, lst_idx),
|
|
Packit Service |
b23acc |
remove_all, mark_survivors_dirty);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
return n;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
guint
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_remove_entry (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
gconstpointer entry)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self, 0);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (entry);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!((NMDedupMultiEntry *) entry)->is_head) {
|
|
Packit Service |
b23acc |
_remove_entry (self, (NMDedupMultiEntry *) entry, NULL);
|
|
Packit Service |
b23acc |
return 1;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
return _remove_head (self, (NMDedupMultiHeadEntry *) entry, TRUE, FALSE);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
guint
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_remove_obj (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
/*const NMDedupMultiObj * */ gconstpointer obj,
|
|
Packit Service |
b23acc |
/*const NMDedupMultiObj ** */ gconstpointer *out_obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
const NMDedupMultiEntry *entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
entry = nm_dedup_multi_index_lookup_obj (self, idx_type, obj);
|
|
Packit Service |
b23acc |
if (!entry) {
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_obj, NULL);
|
|
Packit Service |
b23acc |
return 0;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* since we are about to remove the object, we obviously pass
|
|
Packit Service |
b23acc |
* a reference to @out_obj, the caller MUST unref the object,
|
|
Packit Service |
b23acc |
* if he chooses to provide @out_obj. */
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_obj, nm_dedup_multi_obj_ref (entry->obj));
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
_remove_entry (self, (NMDedupMultiEntry *) entry, NULL);
|
|
Packit Service |
b23acc |
return 1;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
guint
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_remove_head (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
/*const NMDedupMultiObj * */ gconstpointer obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
const NMDedupMultiHeadEntry *entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
entry = nm_dedup_multi_index_lookup_head (self, idx_type, obj);
|
|
Packit Service |
b23acc |
return entry
|
|
Packit Service |
b23acc |
? _remove_head (self, (NMDedupMultiHeadEntry *) entry, TRUE, FALSE)
|
|
Packit Service |
b23acc |
: 0;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
guint
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_remove_idx (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxType *idx_type)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self, 0);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (idx_type, 0);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return _remove_idx_entry (self, idx_type, TRUE, FALSE);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/**
|
|
Packit Service |
b23acc |
* nm_dedup_multi_index_lookup_obj:
|
|
Packit Service |
b23acc |
* @self: the index cache
|
|
Packit Service |
b23acc |
* @idx_type: the lookup index type
|
|
Packit Service |
b23acc |
* @obj: the object to lookup. This means the match is performed
|
|
Packit Service |
b23acc |
* according to NMDedupMultiIdxTypeClass's idx_obj_id_equal()
|
|
Packit Service |
b23acc |
* of @idx_type.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* Returns: the cache entry or %NULL if the entry wasn't found.
|
|
Packit Service |
b23acc |
*/
|
|
Packit Service |
b23acc |
const NMDedupMultiEntry *
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_lookup_obj (const NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
/*const NMDedupMultiObj * */ gconstpointer obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self, FALSE);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (idx_type, FALSE);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (obj, FALSE);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (idx_type && idx_type->klass);
|
|
Packit Service |
b23acc |
return _entry_lookup_obj (self, idx_type, obj);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/**
|
|
Packit Service |
b23acc |
* nm_dedup_multi_index_lookup_head:
|
|
Packit Service |
b23acc |
* @self: the index cache
|
|
Packit Service |
b23acc |
* @idx_type: the lookup index type
|
|
Packit Service |
b23acc |
* @obj: the object to lookup, of type "const NMDedupMultiObj *".
|
|
Packit Service |
b23acc |
* Depending on the idx_type, you *must* also provide a selector
|
|
Packit Service |
b23acc |
* object, even when looking up the list head. That is, because
|
|
Packit Service |
b23acc |
* the idx_type implementation may choose to partition the objects
|
|
Packit Service |
b23acc |
* in distinct list, so you need a selector object to know which
|
|
Packit Service |
b23acc |
* list head to lookup.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* Returns: the cache entry or %NULL if the entry wasn't found.
|
|
Packit Service |
b23acc |
*/
|
|
Packit Service |
b23acc |
const NMDedupMultiHeadEntry *
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_lookup_head (const NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
/*const NMDedupMultiObj * */ gconstpointer obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self, FALSE);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (idx_type, FALSE);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return _entry_lookup_head (self, idx_type, obj);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
void
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_dirty_set_head (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
/*const NMDedupMultiObj * */ gconstpointer obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
NMDedupMultiHeadEntry *head_entry;
|
|
Packit Service |
b23acc |
CList *iter_entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_return_if_fail (self);
|
|
Packit Service |
b23acc |
g_return_if_fail (idx_type);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
head_entry = _entry_lookup_head (self, idx_type, obj);
|
|
Packit Service |
b23acc |
if (!head_entry)
|
|
Packit Service |
b23acc |
return;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
c_list_for_each (iter_entry, &head_entry->lst_entries_head) {
|
|
Packit Service |
b23acc |
NMDedupMultiEntry *entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
entry = c_list_entry (iter_entry, NMDedupMultiEntry, lst_entries);
|
|
Packit Service |
b23acc |
nm_dedup_multi_entry_set_dirty (entry, TRUE);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
void
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_dirty_set_idx (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
CList *iter_idx, *iter_entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_return_if_fail (self);
|
|
Packit Service |
b23acc |
g_return_if_fail (idx_type);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
c_list_for_each (iter_idx, &idx_type->lst_idx_head) {
|
|
Packit Service |
b23acc |
NMDedupMultiHeadEntry *head_entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
head_entry = c_list_entry (iter_idx, NMDedupMultiHeadEntry, lst_idx);
|
|
Packit Service |
b23acc |
c_list_for_each (iter_entry, &head_entry->lst_entries_head) {
|
|
Packit Service |
b23acc |
NMDedupMultiEntry *entry;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
entry = c_list_entry (iter_entry, NMDedupMultiEntry, lst_entries);
|
|
Packit Service |
b23acc |
nm_dedup_multi_entry_set_dirty (entry, TRUE);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/**
|
|
Packit Service |
b23acc |
* nm_dedup_multi_index_dirty_remove_idx:
|
|
Packit Service |
b23acc |
* @self: the index instance
|
|
Packit Service |
b23acc |
* @idx_type: the index-type to select the objects.
|
|
Packit Service |
b23acc |
* @mark_survivors_dirty: while the function removes all entries that are
|
|
Packit Service |
b23acc |
* marked as dirty, if @set_dirty is true, the surviving objects
|
|
Packit Service |
b23acc |
* will be marked dirty right away.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* Deletes all entries for @idx_type that are marked dirty. Only
|
|
Packit Service |
b23acc |
* non-dirty objects survive. If @mark_survivors_dirty is set to TRUE, the survivors
|
|
Packit Service |
b23acc |
* are marked as dirty right away.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* Returns: number of deleted entries.
|
|
Packit Service |
b23acc |
*/
|
|
Packit Service |
b23acc |
guint
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_dirty_remove_idx (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
gboolean mark_survivors_dirty)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self, 0);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (idx_type, 0);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return _remove_idx_entry (self, idx_type, FALSE, mark_survivors_dirty);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static guint
|
|
Packit Service |
b23acc |
_dict_idx_objs_hash (const NMDedupMultiObj *obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
NMHashState h;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_hash_init (&h, 1748638583u);
|
|
Packit Service |
b23acc |
obj->klass->obj_full_hash_update (obj, &h);
|
|
Packit Service |
b23acc |
return nm_hash_complete (&h);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static gboolean
|
|
Packit Service |
b23acc |
_dict_idx_objs_equal (const NMDedupMultiObj *obj_a,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj_b)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
return obj_a == obj_b
|
|
Packit Service |
b23acc |
|| ( obj_a->klass == obj_b->klass
|
|
Packit Service |
b23acc |
&& obj_a->klass->obj_full_equal (obj_a, obj_b));
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
void
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_obj_release (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
nm_assert (self);
|
|
Packit Service |
b23acc |
nm_assert (obj);
|
|
Packit Service |
b23acc |
nm_assert (g_hash_table_lookup (self->idx_objs, obj) == obj);
|
|
Packit Service |
b23acc |
nm_assert (((const NMDedupMultiObj *) obj)->_multi_idx == self);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
((NMDedupMultiObj *) obj)->_multi_idx = NULL;
|
|
Packit Service |
b23acc |
if (!g_hash_table_remove (self->idx_objs, obj))
|
|
Packit Service |
b23acc |
nm_assert_not_reached ();
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
gconstpointer
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_obj_find (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self, NULL);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (obj, NULL);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return g_hash_table_lookup (self->idx_objs, obj);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
gconstpointer
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_obj_intern (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj_new = obj;
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj_old;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (self);
|
|
Packit Service |
b23acc |
nm_assert (obj_new);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (obj_new->_multi_idx == self) {
|
|
Packit Service |
b23acc |
nm_assert (g_hash_table_lookup (self->idx_objs, obj_new) == obj_new);
|
|
Packit Service |
b23acc |
nm_dedup_multi_obj_ref (obj_new);
|
|
Packit Service |
b23acc |
return obj_new;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
obj_old = g_hash_table_lookup (self->idx_objs, obj_new);
|
|
Packit Service |
b23acc |
nm_assert (obj_old != obj_new);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (obj_old) {
|
|
Packit Service |
b23acc |
nm_assert (obj_old->_multi_idx == self);
|
|
Packit Service |
b23acc |
nm_dedup_multi_obj_ref (obj_old);
|
|
Packit Service |
b23acc |
return obj_old;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (nm_dedup_multi_obj_needs_clone (obj_new))
|
|
Packit Service |
b23acc |
obj_new = nm_dedup_multi_obj_clone (obj_new);
|
|
Packit Service |
b23acc |
else
|
|
Packit Service |
b23acc |
obj_new = nm_dedup_multi_obj_ref (obj_new);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (obj_new);
|
|
Packit Service |
b23acc |
nm_assert (!obj_new->_multi_idx);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!g_hash_table_add (self->idx_objs, (gpointer) obj_new))
|
|
Packit Service |
b23acc |
nm_assert_not_reached ();
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
((NMDedupMultiObj *) obj_new)->_multi_idx = self;
|
|
Packit Service |
b23acc |
return obj_new;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
void
|
|
Packit Service |
b23acc |
nm_dedup_multi_obj_unref (const NMDedupMultiObj *obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
if (obj) {
|
|
Packit Service |
b23acc |
nm_assert (obj->_ref_count > 0);
|
|
Packit Service |
b23acc |
nm_assert (obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
again:
|
|
Packit Service |
b23acc |
if (--(((NMDedupMultiObj *) obj)->_ref_count) <= 0) {
|
|
Packit Service |
b23acc |
if (obj->_multi_idx) {
|
|
Packit Service |
b23acc |
/* restore the ref-count to 1 and release the object first
|
|
Packit Service |
b23acc |
* from the index. Then, retry again to unref. */
|
|
Packit Service |
b23acc |
((NMDedupMultiObj *) obj)->_ref_count++;
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_obj_release (obj->_multi_idx, obj);
|
|
Packit Service |
b23acc |
nm_assert (obj->_ref_count == 1);
|
|
Packit Service |
b23acc |
nm_assert (!obj->_multi_idx);
|
|
Packit Service |
b23acc |
goto again;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
obj->klass->obj_destroy ((NMDedupMultiObj *) obj);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
gboolean
|
|
Packit Service |
b23acc |
nm_dedup_multi_obj_needs_clone (const NMDedupMultiObj *obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
nm_assert (obj);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if ( obj->_multi_idx
|
|
Packit Service |
b23acc |
|| obj->_ref_count == NM_OBJ_REF_COUNT_STACKINIT)
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if ( obj->klass->obj_needs_clone
|
|
Packit Service |
b23acc |
&& obj->klass->obj_needs_clone (obj))
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *
|
|
Packit Service |
b23acc |
nm_dedup_multi_obj_clone (const NMDedupMultiObj *obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *o;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (obj);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
o = obj->klass->obj_clone (obj);
|
|
Packit Service |
b23acc |
nm_assert (o);
|
|
Packit Service |
b23acc |
nm_assert (o->_ref_count == 1);
|
|
Packit Service |
b23acc |
return o;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
gconstpointer *
|
|
Packit Service |
b23acc |
nm_dedup_multi_objs_to_array_head (const NMDedupMultiHeadEntry *head_entry,
|
|
Packit Service |
b23acc |
NMDedupMultiFcnSelectPredicate predicate,
|
|
Packit Service |
b23acc |
gpointer user_data,
|
|
Packit Service |
b23acc |
guint *out_len)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
gconstpointer *result;
|
|
Packit Service |
b23acc |
CList *iter;
|
|
Packit Service |
b23acc |
guint i;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!head_entry) {
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_len, 0);
|
|
Packit Service |
b23acc |
return NULL;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
result = g_new (gconstpointer, head_entry->len + 1);
|
|
Packit Service |
b23acc |
i = 0;
|
|
Packit Service |
b23acc |
c_list_for_each (iter, &head_entry->lst_entries_head) {
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj = c_list_entry (iter, NMDedupMultiEntry, lst_entries)->obj;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if ( !predicate
|
|
Packit Service |
b23acc |
|| predicate (obj, user_data)) {
|
|
Packit Service |
b23acc |
nm_assert (i < head_entry->len);
|
|
Packit Service |
b23acc |
result[i++] = obj;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (i == 0) {
|
|
Packit Service |
b23acc |
g_free (result);
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_len, 0);
|
|
Packit Service |
b23acc |
return NULL;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (i <= head_entry->len);
|
|
Packit Service |
b23acc |
NM_SET_OUT (out_len, i);
|
|
Packit Service |
b23acc |
result[i++] = NULL;
|
|
Packit Service |
b23acc |
return result;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
GPtrArray *
|
|
Packit Service |
b23acc |
nm_dedup_multi_objs_to_ptr_array_head (const NMDedupMultiHeadEntry *head_entry,
|
|
Packit Service |
b23acc |
NMDedupMultiFcnSelectPredicate predicate,
|
|
Packit Service |
b23acc |
gpointer user_data)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
GPtrArray *result;
|
|
Packit Service |
b23acc |
CList *iter;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!head_entry)
|
|
Packit Service |
b23acc |
return NULL;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
result = g_ptr_array_new_full (head_entry->len,
|
|
Packit Service |
b23acc |
(GDestroyNotify) nm_dedup_multi_obj_unref);
|
|
Packit Service |
b23acc |
c_list_for_each (iter, &head_entry->lst_entries_head) {
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj = c_list_entry (iter, NMDedupMultiEntry, lst_entries)->obj;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if ( !predicate
|
|
Packit Service |
b23acc |
|| predicate (obj, user_data))
|
|
Packit Service |
b23acc |
g_ptr_array_add (result, (gpointer) nm_dedup_multi_obj_ref (obj));
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (result->len == 0) {
|
|
Packit Service |
b23acc |
g_ptr_array_unref (result);
|
|
Packit Service |
b23acc |
return NULL;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
return result;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/**
|
|
Packit Service |
b23acc |
* nm_dedup_multi_entry_reorder:
|
|
Packit Service |
b23acc |
* @entry: the entry to reorder. It must not be NULL (and tracked in an index).
|
|
Packit Service |
b23acc |
* @entry_order: (allow-none): an optional other entry. It MUST be in the same
|
|
Packit Service |
b23acc |
* list as entry. If given, @entry will be ordered after/before @entry_order.
|
|
Packit Service |
b23acc |
* If left at %NULL, @entry will be moved to the front/end of the list.
|
|
Packit Service |
b23acc |
* @order_after: if @entry_order is given, %TRUE means to move @entry after
|
|
Packit Service |
b23acc |
* @entry_order (otherwise before).
|
|
Packit Service |
b23acc |
* If @entry_order is %NULL, %TRUE means to move @entry to the tail of the list
|
|
Packit Service |
b23acc |
* (otherwise the beginning). Note that "tail of the list" here means that @entry
|
|
Packit Service |
b23acc |
* will be linked before the head of the circular list.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* Returns: %TRUE, if anything was changed. Otherwise, @entry was already at the
|
|
Packit Service |
b23acc |
* right place and nothing was done.
|
|
Packit Service |
b23acc |
*/
|
|
Packit Service |
b23acc |
gboolean
|
|
Packit Service |
b23acc |
nm_dedup_multi_entry_reorder (const NMDedupMultiEntry *entry,
|
|
Packit Service |
b23acc |
const NMDedupMultiEntry *entry_order,
|
|
Packit Service |
b23acc |
gboolean order_after)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
nm_assert (entry);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!entry_order) {
|
|
Packit Service |
b23acc |
const NMDedupMultiHeadEntry *head_entry = entry->head;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (order_after) {
|
|
Packit Service |
b23acc |
if (nm_c_list_move_tail ((CList *) &head_entry->lst_entries_head, (CList *) &entry->lst_entries))
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
} else {
|
|
Packit Service |
b23acc |
if (nm_c_list_move_front ((CList *) &head_entry->lst_entries_head, (CList *) &entry->lst_entries))
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
} else {
|
|
Packit Service |
b23acc |
if (order_after) {
|
|
Packit Service |
b23acc |
if (nm_c_list_move_after ((CList *) &entry_order->lst_entries, (CList *) &entry->lst_entries))
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
} else {
|
|
Packit Service |
b23acc |
if (nm_c_list_move_before ((CList *) &entry_order->lst_entries, (CList *) &entry->lst_entries))
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
NMDedupMultiIndex *
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_new (void)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
NMDedupMultiIndex *self;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
self = g_slice_new0 (NMDedupMultiIndex);
|
|
Packit Service |
b23acc |
self->ref_count = 1;
|
|
Packit Service |
b23acc |
self->idx_entries = g_hash_table_new ((GHashFunc) _dict_idx_entries_hash, (GEqualFunc) _dict_idx_entries_equal);
|
|
Packit Service |
b23acc |
self->idx_objs = g_hash_table_new ((GHashFunc) _dict_idx_objs_hash, (GEqualFunc) _dict_idx_objs_equal);
|
|
Packit Service |
b23acc |
return self;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
NMDedupMultiIndex *
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_ref (NMDedupMultiIndex *self)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self, NULL);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self->ref_count > 0, NULL);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
self->ref_count++;
|
|
Packit Service |
b23acc |
return self;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
NMDedupMultiIndex *
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_unref (NMDedupMultiIndex *self)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
GHashTableIter iter;
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type;
|
|
Packit Service |
b23acc |
NMDedupMultiEntry *entry;
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self, NULL);
|
|
Packit Service |
b23acc |
g_return_val_if_fail (self->ref_count > 0, NULL);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (--self->ref_count > 0)
|
|
Packit Service |
b23acc |
return NULL;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
more:
|
|
Packit Service |
b23acc |
g_hash_table_iter_init (&iter, self->idx_entries);
|
|
Packit Service |
b23acc |
while (g_hash_table_iter_next (&iter, (gpointer *) &entry, NULL)) {
|
|
Packit Service |
b23acc |
if (entry->is_head)
|
|
Packit Service |
b23acc |
idx_type = ((NMDedupMultiHeadEntry *) entry)->idx_type;
|
|
Packit Service |
b23acc |
else
|
|
Packit Service |
b23acc |
idx_type = entry->head->idx_type;
|
|
Packit Service |
b23acc |
_remove_idx_entry (self, (NMDedupMultiIdxType *) idx_type, TRUE, FALSE);
|
|
Packit Service |
b23acc |
goto more;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (g_hash_table_size (self->idx_entries) == 0);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_hash_table_iter_init (&iter, self->idx_objs);
|
|
Packit Service |
b23acc |
while (g_hash_table_iter_next (&iter, (gpointer *) &obj, NULL)) {
|
|
Packit Service |
b23acc |
nm_assert (obj->_multi_idx == self);
|
|
Packit Service |
b23acc |
((NMDedupMultiObj * )obj)->_multi_idx = NULL;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
g_hash_table_remove_all (self->idx_objs);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_hash_table_unref (self->idx_entries);
|
|
Packit Service |
b23acc |
g_hash_table_unref (self->idx_objs);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
g_slice_free (NMDedupMultiIndex, self);
|
|
Packit Service |
b23acc |
return NULL;
|
|
Packit Service |
b23acc |
}
|