|
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 |
#ifndef __NM_DEDUP_MULTI_H__
|
|
Packit Service |
b23acc |
#define __NM_DEDUP_MULTI_H__
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
#include "nm-obj.h"
|
|
Packit Service |
b23acc |
#include "nm-std-aux/c-list-util.h"
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
struct _NMHashState;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
typedef struct _NMDedupMultiObj NMDedupMultiObj;
|
|
Packit Service |
b23acc |
typedef struct _NMDedupMultiObjClass NMDedupMultiObjClass;
|
|
Packit Service |
b23acc |
typedef struct _NMDedupMultiIdxType NMDedupMultiIdxType;
|
|
Packit Service |
b23acc |
typedef struct _NMDedupMultiIdxTypeClass NMDedupMultiIdxTypeClass;
|
|
Packit Service |
b23acc |
typedef struct _NMDedupMultiEntry NMDedupMultiEntry;
|
|
Packit Service |
b23acc |
typedef struct _NMDedupMultiHeadEntry NMDedupMultiHeadEntry;
|
|
Packit Service |
b23acc |
typedef struct _NMDedupMultiIndex NMDedupMultiIndex;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
typedef enum _NMDedupMultiIdxMode {
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_PREPEND,
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* append new objects to the end of the list.
|
|
Packit Service |
b23acc |
* If the object is already in the cache, don't move it. */
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_APPEND,
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* like NM_DEDUP_MULTI_IDX_MODE_APPEND, but if the object
|
|
Packit Service |
b23acc |
* is already in the cache, move it to the end. */
|
|
Packit Service |
b23acc |
NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE,
|
|
Packit Service |
b23acc |
} NMDedupMultiIdxMode;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
struct _NMDedupMultiObj {
|
|
Packit Service |
b23acc |
union {
|
|
Packit Service |
b23acc |
NMObjBaseInst parent;
|
|
Packit Service |
b23acc |
const NMDedupMultiObjClass *klass;
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
NMDedupMultiIndex *_multi_idx;
|
|
Packit Service |
b23acc |
guint _ref_count;
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
struct _NMDedupMultiObjClass {
|
|
Packit Service |
b23acc |
NMObjBaseClass parent;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *(*obj_clone) (const NMDedupMultiObj *obj);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
gboolean (*obj_needs_clone) (const NMDedupMultiObj *obj);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
void (*obj_destroy) (NMDedupMultiObj *obj);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* the NMDedupMultiObj can be deduplicated. For that the obj_full_hash_update()
|
|
Packit Service |
b23acc |
* and obj_full_equal() compare *all* fields of the object, even minor ones. */
|
|
Packit Service |
b23acc |
void (*obj_full_hash_update) (const NMDedupMultiObj *obj,
|
|
Packit Service |
b23acc |
struct _NMHashState *h);
|
|
Packit Service |
b23acc |
gboolean (*obj_full_equal) (const NMDedupMultiObj *obj_a,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj_b);
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static inline const NMDedupMultiObj *
|
|
Packit Service |
b23acc |
nm_dedup_multi_obj_ref (const NMDedupMultiObj *obj)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
/* ref and unref accept const pointers. Objects is supposed to be shared
|
|
Packit Service |
b23acc |
* and kept immutable. Disallowing to take/return a reference to a const
|
|
Packit Service |
b23acc |
* NMPObject is cumbersome, because callers are precisely expected to
|
|
Packit Service |
b23acc |
* keep a ref on the otherwise immutable object. */
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
nm_assert (obj);
|
|
Packit Service |
b23acc |
nm_assert (obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
|
|
Packit Service |
b23acc |
nm_assert (obj->_ref_count > 0);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
((NMDedupMultiObj *) obj)->_ref_count++;
|
|
Packit Service |
b23acc |
return obj;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
void nm_dedup_multi_obj_unref (const NMDedupMultiObj *obj);
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *nm_dedup_multi_obj_clone (const NMDedupMultiObj *obj);
|
|
Packit Service |
b23acc |
gboolean nm_dedup_multi_obj_needs_clone (const NMDedupMultiObj *obj);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
gconstpointer nm_dedup_multi_index_obj_intern (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer obj);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
void nm_dedup_multi_index_obj_release (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer obj);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer nm_dedup_multi_index_obj_find (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer obj);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* the NMDedupMultiIdxType is an access handle under which you can store and
|
|
Packit Service |
b23acc |
* retrieve NMDedupMultiObj instances in NMDedupMultiIndex.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* The NMDedupMultiIdxTypeClass determines its behavior, but you can have
|
|
Packit Service |
b23acc |
* multiple instances (of the same class).
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* For example, NMIP4Config can have idx-type to put there all IPv4 Routes.
|
|
Packit Service |
b23acc |
* This idx-type instance is private to the NMIP4Config instance. Basically,
|
|
Packit Service |
b23acc |
* the NMIP4Config instance uses the idx-type to maintain an ordered list
|
|
Packit Service |
b23acc |
* of routes in NMDedupMultiIndex.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* However, a NMDedupMultiIdxType may also partition the set of objects
|
|
Packit Service |
b23acc |
* in multiple distinct lists. NMIP4Config doesn't do that (because instead
|
|
Packit Service |
b23acc |
* of creating one idx-type for IPv4 and IPv6 routes, it just cretaes
|
|
Packit Service |
b23acc |
* to distinct idx-types, one for each address family.
|
|
Packit Service |
b23acc |
* This partitioning is used by NMPlatform to maintain a lookup index for
|
|
Packit Service |
b23acc |
* routes by ifindex. As the ifindex is dynamic, it does not create an
|
|
Packit Service |
b23acc |
* idx-type instance for each ifindex. Instead, it has one idx-type for
|
|
Packit Service |
b23acc |
* all routes. But whenever accessing NMDedupMultiIndex with an NMDedupMultiObj,
|
|
Packit Service |
b23acc |
* the partitioning NMDedupMultiIdxType takes into account the NMDedupMultiObj
|
|
Packit Service |
b23acc |
* instance to associate it with the right list.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* Hence, a NMDedupMultiIdxEntry has a list of possibly multiple NMDedupMultiHeadEntry
|
|
Packit Service |
b23acc |
* instances, which each is the head for a list of NMDedupMultiEntry instances.
|
|
Packit Service |
b23acc |
* In the platform example, the NMDedupMultiHeadEntry partition the indexed objects
|
|
Packit Service |
b23acc |
* by their ifindex. */
|
|
Packit Service |
b23acc |
struct _NMDedupMultiIdxType {
|
|
Packit Service |
b23acc |
union {
|
|
Packit Service |
b23acc |
NMObjBaseInst parent;
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxTypeClass *klass;
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
CList lst_idx_head;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
guint len;
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
void nm_dedup_multi_idx_type_init (NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxTypeClass *klass);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
struct _NMDedupMultiIdxTypeClass {
|
|
Packit Service |
b23acc |
NMObjBaseClass parent;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
void (*idx_obj_id_hash_update) (const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj,
|
|
Packit Service |
b23acc |
struct _NMHashState *h);
|
|
Packit Service |
b23acc |
gboolean (*idx_obj_id_equal) (const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj_a,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj_b);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* an NMDedupMultiIdxTypeClass which implements partitioning of the
|
|
Packit Service |
b23acc |
* tracked objects, must implement the idx_obj_partition*() functions.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* idx_obj_partitionable() may return NULL if the object cannot be tracked.
|
|
Packit Service |
b23acc |
* For example, a index for routes by ifindex, may not want to track any
|
|
Packit Service |
b23acc |
* routes that don't have a valid ifindex. If the idx-type says that the
|
|
Packit Service |
b23acc |
* object is not partitionable, it is never added to the NMDedupMultiIndex. */
|
|
Packit Service |
b23acc |
gboolean (*idx_obj_partitionable) (const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj);
|
|
Packit Service |
b23acc |
void (*idx_obj_partition_hash_update) (const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj,
|
|
Packit Service |
b23acc |
struct _NMHashState *h);
|
|
Packit Service |
b23acc |
gboolean (*idx_obj_partition_equal) (const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj_a,
|
|
Packit Service |
b23acc |
const NMDedupMultiObj *obj_b);
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static inline gboolean
|
|
Packit Service |
b23acc |
nm_dedup_multi_idx_type_id_equal (const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer obj_a,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer obj_b)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
nm_assert (idx_type);
|
|
Packit Service |
b23acc |
return obj_a == obj_b
|
|
Packit Service |
b23acc |
|| idx_type->klass->idx_obj_id_equal (idx_type,
|
|
Packit Service |
b23acc |
obj_a,
|
|
Packit Service |
b23acc |
obj_b);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static inline gboolean
|
|
Packit Service |
b23acc |
nm_dedup_multi_idx_type_partition_equal (const NMDedupMultiIdxType *idx_type,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer obj_a,
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer obj_b)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
nm_assert (idx_type);
|
|
Packit Service |
b23acc |
if (idx_type->klass->idx_obj_partition_equal) {
|
|
Packit Service |
b23acc |
nm_assert (obj_a);
|
|
Packit Service |
b23acc |
nm_assert (obj_b);
|
|
Packit Service |
b23acc |
return obj_a == obj_b
|
|
Packit Service |
b23acc |
|| idx_type->klass->idx_obj_partition_equal (idx_type,
|
|
Packit Service |
b23acc |
obj_a,
|
|
Packit Service |
b23acc |
obj_b);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
struct _NMDedupMultiEntry {
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* this is the list of all entries that share the same head entry.
|
|
Packit Service |
b23acc |
* All entries compare equal according to idx_obj_partition_equal(). */
|
|
Packit Service |
b23acc |
CList lst_entries;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* const NMDedupMultiObj * */ gconstpointer obj;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
bool is_head;
|
|
Packit Service |
b23acc |
bool dirty;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
const NMDedupMultiHeadEntry *head;
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
struct _NMDedupMultiHeadEntry {
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* this is the list of all entries that share the same head entry.
|
|
Packit Service |
b23acc |
* All entries compare equal according to idx_obj_partition_equal(). */
|
|
Packit Service |
b23acc |
CList lst_entries_head;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
bool is_head;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
guint len;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
CList lst_idx;
|
|
Packit Service |
b23acc |
};
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static inline gconstpointer
|
|
Packit Service |
b23acc |
nm_dedup_multi_entry_get_obj (const NMDedupMultiEntry *entry)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
/* convenience method that allows to skip the %NULL check on
|
|
Packit Service |
b23acc |
* @entry. Think of the NULL-conditional operator ?. of C# */
|
|
Packit Service |
b23acc |
return entry ? entry->obj : NULL;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static inline void
|
|
Packit Service |
b23acc |
nm_dedup_multi_entry_set_dirty (const NMDedupMultiEntry *entry,
|
|
Packit Service |
b23acc |
gboolean dirty)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
/* NMDedupMultiEntry is always exposed as a const object, because it is not
|
|
Packit Service |
b23acc |
* supposed to be modified outside NMDedupMultiIndex API. Except the "dirty"
|
|
Packit Service |
b23acc |
* flag. In C++ speak, it is a mutable field.
|
|
Packit Service |
b23acc |
*
|
|
Packit Service |
b23acc |
* Add this inline function, to cast-away constness and set the dirty flag. */
|
|
Packit Service |
b23acc |
nm_assert (entry);
|
|
Packit Service |
b23acc |
((NMDedupMultiEntry *) entry)->dirty = dirty;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
NMDedupMultiIndex *nm_dedup_multi_index_new (void);
|
|
Packit Service |
b23acc |
NMDedupMultiIndex *nm_dedup_multi_index_ref (NMDedupMultiIndex *self);
|
|
Packit Service |
b23acc |
NMDedupMultiIndex *nm_dedup_multi_index_unref (NMDedupMultiIndex *self);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static inline void
|
|
Packit Service |
b23acc |
_nm_auto_unref_dedup_multi_index (NMDedupMultiIndex **v)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
if (*v)
|
|
Packit Service |
b23acc |
nm_dedup_multi_index_unref (*v);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
#define nm_auto_unref_dedup_multi_index nm_auto(_nm_auto_unref_dedup_multi_index)
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
#define NM_DEDUP_MULTI_ENTRY_MISSING ((const NMDedupMultiEntry *) GUINT_TO_POINTER (1))
|
|
Packit Service |
b23acc |
#define NM_DEDUP_MULTI_HEAD_ENTRY_MISSING ((const NMDedupMultiHeadEntry *) GUINT_TO_POINTER (1))
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
gboolean 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 |
gboolean 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 |
const NMDedupMultiEntry *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 |
const NMDedupMultiHeadEntry *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 |
guint nm_dedup_multi_index_remove_entry (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
gconstpointer entry);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
guint 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 |
guint 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 |
guint nm_dedup_multi_index_remove_idx (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
NMDedupMultiIdxType *idx_type);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
void 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 |
void nm_dedup_multi_index_dirty_set_idx (NMDedupMultiIndex *self,
|
|
Packit Service |
b23acc |
const NMDedupMultiIdxType *idx_type);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
guint 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 |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
typedef struct _NMDedupMultiIter {
|
|
Packit Service |
b23acc |
const CList *_head;
|
|
Packit Service |
b23acc |
const CList *_next;
|
|
Packit Service |
b23acc |
const NMDedupMultiEntry *current;
|
|
Packit Service |
b23acc |
} NMDedupMultiIter;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static inline void
|
|
Packit Service |
b23acc |
nm_dedup_multi_iter_init (NMDedupMultiIter *iter, const NMDedupMultiHeadEntry *head)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
g_return_if_fail (iter);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (head && !c_list_is_empty (&head->lst_entries_head)) {
|
|
Packit Service |
b23acc |
iter->_head = &head->lst_entries_head;
|
|
Packit Service |
b23acc |
iter->_next = head->lst_entries_head.next;
|
|
Packit Service |
b23acc |
} else {
|
|
Packit Service |
b23acc |
iter->_head = NULL;
|
|
Packit Service |
b23acc |
iter->_next = NULL;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
iter->current = NULL;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static inline gboolean
|
|
Packit Service |
b23acc |
nm_dedup_multi_iter_next (NMDedupMultiIter *iter)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
g_return_val_if_fail (iter, FALSE);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (!iter->_next)
|
|
Packit Service |
b23acc |
return FALSE;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/* we always look ahead for the next. This way, the user
|
|
Packit Service |
b23acc |
* may delete the current entry (but no other entries). */
|
|
Packit Service |
b23acc |
iter->current = c_list_entry (iter->_next, NMDedupMultiEntry, lst_entries);
|
|
Packit Service |
b23acc |
if (iter->_next->next == iter->_head)
|
|
Packit Service |
b23acc |
iter->_next = NULL;
|
|
Packit Service |
b23acc |
else
|
|
Packit Service |
b23acc |
iter->_next = iter->_next->next;
|
|
Packit Service |
b23acc |
return TRUE;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
#define nm_dedup_multi_iter_for_each(iter, head_entry) \
|
|
Packit Service |
b23acc |
for (nm_dedup_multi_iter_init ((iter), (head_entry)); \
|
|
Packit Service |
b23acc |
nm_dedup_multi_iter_next ((iter)); \
|
|
Packit Service |
b23acc |
)
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
typedef gboolean (*NMDedupMultiFcnSelectPredicate) (/* const NMDedupMultiObj * */ gconstpointer obj,
|
|
Packit Service |
b23acc |
gpointer user_data);
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
gconstpointer *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 |
GPtrArray *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 |
static inline const NMDedupMultiEntry *
|
|
Packit Service |
b23acc |
nm_dedup_multi_head_entry_get_idx (const NMDedupMultiHeadEntry *head_entry,
|
|
Packit Service |
b23acc |
int idx)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
CList *iter;
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
if (head_entry) {
|
|
Packit Service |
b23acc |
if (idx >= 0) {
|
|
Packit Service |
b23acc |
c_list_for_each (iter, &head_entry->lst_entries_head) {
|
|
Packit Service |
b23acc |
if (idx-- == 0)
|
|
Packit Service |
b23acc |
return c_list_entry (iter, NMDedupMultiEntry, lst_entries);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
} else {
|
|
Packit Service |
b23acc |
for (iter = head_entry->lst_entries_head.prev;
|
|
Packit Service |
b23acc |
iter != &head_entry->lst_entries_head;
|
|
Packit Service |
b23acc |
iter = iter->prev) {
|
|
Packit Service |
b23acc |
if (++idx == 0)
|
|
Packit Service |
b23acc |
return c_list_entry (iter, NMDedupMultiEntry, lst_entries);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
return NULL;
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
static inline void
|
|
Packit Service |
b23acc |
nm_dedup_multi_head_entry_sort (const NMDedupMultiHeadEntry *head_entry,
|
|
Packit Service |
b23acc |
CListSortCmp cmp,
|
|
Packit Service |
b23acc |
gconstpointer user_data)
|
|
Packit Service |
b23acc |
{
|
|
Packit Service |
b23acc |
if (head_entry) {
|
|
Packit Service |
b23acc |
/* the head entry can be sorted directly without messing up the
|
|
Packit Service |
b23acc |
* index to which it belongs. Of course, this does mess up any
|
|
Packit Service |
b23acc |
* NMDedupMultiIter instances. */
|
|
Packit Service |
b23acc |
c_list_sort ((CList *) &head_entry->lst_entries_head, cmp, user_data);
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
}
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
gboolean 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 |
/*****************************************************************************/
|
|
Packit Service |
b23acc |
|
|
Packit Service |
b23acc |
#endif /* __NM_DEDUP_MULTI_H__ */
|