libnl 3.7.0
hashtable.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2012 Cumulus Networks, Inc
4 */
5
6#include <string.h>
7#include <netlink-private/netlink.h>
8#include <netlink/object.h>
9#include <netlink/hash.h>
10#include <netlink/hashtable.h>
11
12/**
13 * @ingroup core_types
14 * @defgroup hashtable Hashtable
15 * @{
16 */
17
18/**
19 * Allocate hashtable
20 * @arg size Size of hashtable in number of elements
21 *
22 * @return Allocated hashtable or NULL.
23 */
25{
27
28 ht = calloc(1, sizeof (*ht));
29 if (!ht)
30 goto errout;
31
32 ht->nodes = calloc(size, sizeof (*ht->nodes));
33 if (!ht->nodes) {
34 free(ht);
35 goto errout;
36 }
37
38 ht->size = size;
39
40 return ht;
41errout:
42 return NULL;
43}
44
45/**
46 * Free hashtable including all nodes
47 * @arg ht Hashtable
48 *
49 * @note Reference counter of all objects in the hashtable will be decremented.
50 */
52{
53 int i;
54
55 for(i = 0; i < ht->size; i++) {
56 nl_hash_node_t *node = ht->nodes[i];
57 nl_hash_node_t *saved_node;
58
59 while (node) {
60 saved_node = node;
61 node = node->next;
62 nl_object_put(saved_node->obj);
63 free(saved_node);
64 }
65 }
66
67 free(ht->nodes);
68 free(ht);
69}
70
71/**
72 * Lookup identical object in hashtable
73 * @arg ht Hashtable
74 * @arg obj Object to lookup
75 *
76 * Generates hashkey for `obj` and traverses the corresponding chain calling
77 * `nl_object_identical()` on each trying to find a match.
78 *
79 * @return Pointer to object if match was found or NULL.
80 */
82 struct nl_object *obj)
83{
84 nl_hash_node_t *node;
85 uint32_t key_hash;
86
87 nl_object_keygen(obj, &key_hash, ht->size);
88 node = ht->nodes[key_hash];
89
90 while (node) {
91 if (nl_object_identical(node->obj, obj))
92 return node->obj;
93 node = node->next;
94 }
95
96 return NULL;
97}
98
99/**
100 * Add object to hashtable
101 * @arg ht Hashtable
102 * @arg obj Object to add
103 *
104 * Adds `obj` to the hashtable. Object type must support hashing, otherwise all
105 * objects will be added to the chain `0`.
106 *
107 * @note The reference counter of the object is incremented.
108 *
109 * @return 0 on success or a negative error code
110 * @retval -NLE_EXIST Identical object already present in hashtable
111 */
112int nl_hash_table_add(nl_hash_table_t *ht, struct nl_object *obj)
113{
114 nl_hash_node_t *node;
115 uint32_t key_hash;
116
117 nl_object_keygen(obj, &key_hash, ht->size);
118 node = ht->nodes[key_hash];
119
120 while (node) {
121 if (nl_object_identical(node->obj, obj)) {
122 NL_DBG(2, "Warning: Add to hashtable found duplicate...\n");
123 return -NLE_EXIST;
124 }
125 node = node->next;
126 }
127
128 NL_DBG (5, "adding cache entry of obj %p in table %p, with hash 0x%x\n",
129 obj, ht, key_hash);
130
131 node = malloc(sizeof(nl_hash_node_t));
132 if (!node)
133 return -NLE_NOMEM;
134 nl_object_get(obj);
135 node->obj = obj;
136 node->key = key_hash;
137 node->key_size = sizeof(uint32_t);
138 node->next = ht->nodes[key_hash];
139 ht->nodes[key_hash] = node;
140
141 return 0;
142}
143
144/**
145 * Remove object from hashtable
146 * @arg ht Hashtable
147 * @arg obj Object to remove
148 *
149 * Remove `obj` from hashtable if it exists.
150 *
151 * @note Reference counter of object will be decremented.
152 *
153 * @return 0 on success or a negative error code.
154 * @retval -NLE_OBJ_NOTFOUND Object not present in hashtable.
155 */
156int nl_hash_table_del(nl_hash_table_t *ht, struct nl_object *obj)
157{
158 nl_hash_node_t *node, *prev;
159 uint32_t key_hash;
160
161 nl_object_keygen(obj, &key_hash, ht->size);
162 prev = node = ht->nodes[key_hash];
163
164 while (node) {
165 if (nl_object_identical(node->obj, obj)) {
166 nl_object_put(obj);
167
168 NL_DBG (5, "deleting cache entry of obj %p in table %p, with"
169 " hash 0x%x\n", obj, ht, key_hash);
170
171 if (node == ht->nodes[key_hash])
172 ht->nodes[key_hash] = node->next;
173 else
174 prev->next = node->next;
175
176 free(node);
177
178 return 0;
179 }
180 prev = node;
181 node = node->next;
182 }
183
184 return -NLE_OBJ_NOTFOUND;
185}
186
187uint32_t nl_hash(void *k, size_t length, uint32_t initval)
188{
189 return(__nl_hash((char *) k, length, initval));
190}
191
192/** @} */
int nl_hash_table_del(nl_hash_table_t *ht, struct nl_object *obj)
Remove object from hashtable.
Definition: hashtable.c:156
nl_hash_table_t * nl_hash_table_alloc(int size)
Allocate hashtable.
Definition: hashtable.c:24
void nl_hash_table_free(nl_hash_table_t *ht)
Free hashtable including all nodes.
Definition: hashtable.c:51
int nl_hash_table_add(nl_hash_table_t *ht, struct nl_object *obj)
Add object to hashtable.
Definition: hashtable.c:112
struct nl_object * nl_hash_table_lookup(nl_hash_table_t *ht, struct nl_object *obj)
Lookup identical object in hashtable.
Definition: hashtable.c:81
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition: object.c:214
int nl_object_identical(struct nl_object *a, struct nl_object *b)
Check if the identifiers of two objects are identical.
Definition: object.c:312
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition: object.c:203
void nl_object_keygen(struct nl_object *obj, uint32_t *hashkey, uint32_t hashtbl_sz)
Generate object hash key.
Definition: object.c:465