Run clang-format on the whole tree
[lttng-tools.git] / src / common / hashtable / hashtable.cpp
1 /*
2 * Copyright (C) 2011 EfficiOS Inc.
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #define _LGPL_SOURCE
9 #include "hashtable.hpp"
10 #include "utils.hpp"
11
12 #include <common/common.hpp>
13 #include <common/defaults.hpp>
14
15 #include <string.h>
16 #include <urcu.h>
17 #include <urcu/compiler.h>
18
19 /* seed_lock protects both seed_init and lttng_ht_seed. */
20 static pthread_mutex_t seed_lock = PTHREAD_MUTEX_INITIALIZER;
21 static bool seed_init;
22
23 static unsigned long min_hash_alloc_size = 1;
24 static unsigned long max_hash_buckets_size = 0;
25
26 /*
27 * Getter/lookup functions need to be called with RCU read-side lock
28 * held. However, modification functions (add, add_unique, replace, del)
29 * take the RCU lock internally, so it does not matter whether the
30 * caller hold the RCU lock or not.
31 */
32
33 /*
34 * Match function for string node.
35 */
36 static int match_str(struct cds_lfht_node *node, const void *key)
37 {
38 struct lttng_ht_node_str *match_node =
39 lttng::utils::container_of(node, &lttng_ht_node_str::node);
40
41 return hash_match_key_str(match_node->key, (void *) key);
42 }
43
44 /*
45 * Match function for ulong node.
46 */
47 static int match_ulong(struct cds_lfht_node *node, const void *key)
48 {
49 struct lttng_ht_node_ulong *match_node =
50 lttng::utils::container_of(node, &lttng_ht_node_ulong::node);
51
52 return hash_match_key_ulong((void *) match_node->key, (void *) key);
53 }
54
55 /*
56 * Match function for u64 node.
57 */
58 static int match_u64(struct cds_lfht_node *node, const void *key)
59 {
60 struct lttng_ht_node_u64 *match_node =
61 lttng::utils::container_of(node, &lttng_ht_node_u64::node);
62
63 return hash_match_key_u64(&match_node->key, (void *) key);
64 }
65
66 /*
67 * Match function for two uint64_t node.
68 */
69 static int match_two_u64(struct cds_lfht_node *node, const void *key)
70 {
71 struct lttng_ht_node_two_u64 *match_node =
72 lttng::utils::container_of(node, &lttng_ht_node_two_u64::node);
73
74 return hash_match_key_two_u64((void *) &match_node->key, (void *) key);
75 }
76
77 static inline const char *lttng_ht_type_str(enum lttng_ht_type type)
78 {
79 switch (type) {
80 case LTTNG_HT_TYPE_STRING:
81 return "STRING";
82 case LTTNG_HT_TYPE_ULONG:
83 return "ULONG";
84 case LTTNG_HT_TYPE_U64:
85 return "U64";
86 case LTTNG_HT_TYPE_TWO_U64:
87 return "TWO_U64";
88 default:
89 ERR("Unknown lttng hashtable type %d", type);
90 abort();
91 }
92 }
93
94 /*
95 * Return an allocated lttng hashtable.
96 */
97 struct lttng_ht *lttng_ht_new(unsigned long size, lttng_ht_type type)
98 {
99 struct lttng_ht *ht;
100
101 /* Test size */
102 if (!size)
103 size = DEFAULT_HT_SIZE;
104
105 pthread_mutex_lock(&seed_lock);
106 if (!seed_init) {
107 lttng_ht_seed = (unsigned long) time(NULL);
108 seed_init = true;
109 }
110 pthread_mutex_unlock(&seed_lock);
111
112 ht = zmalloc<lttng_ht>();
113 if (ht == NULL) {
114 PERROR("zmalloc lttng_ht");
115 goto error;
116 }
117
118 ht->ht = cds_lfht_new(size,
119 min_hash_alloc_size,
120 max_hash_buckets_size,
121 CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING,
122 NULL);
123 /*
124 * There is already an assert in the RCU hashtable code so if the ht is
125 * NULL here there is a *huge* problem.
126 */
127 LTTNG_ASSERT(ht->ht);
128
129 switch (type) {
130 case LTTNG_HT_TYPE_STRING:
131 ht->match_fct = match_str;
132 ht->hash_fct = hash_key_str;
133 break;
134 case LTTNG_HT_TYPE_ULONG:
135 ht->match_fct = match_ulong;
136 ht->hash_fct = hash_key_ulong;
137 break;
138 case LTTNG_HT_TYPE_U64:
139 ht->match_fct = match_u64;
140 ht->hash_fct = hash_key_u64;
141 break;
142 case LTTNG_HT_TYPE_TWO_U64:
143 ht->match_fct = match_two_u64;
144 ht->hash_fct = hash_key_two_u64;
145 break;
146 default:
147 ERR("Unknown lttng hashtable type %d", type);
148 lttng_ht_destroy(ht);
149 goto error;
150 }
151
152 DBG3("Created hashtable size %lu at %p of type %s", size, ht->ht, lttng_ht_type_str(type));
153
154 return ht;
155
156 error:
157 return NULL;
158 }
159
160 /*
161 * Free a lttng hashtable.
162 */
163 void lttng_ht_destroy(struct lttng_ht *ht)
164 {
165 int ret;
166
167 ret = cds_lfht_destroy(ht->ht, NULL);
168 LTTNG_ASSERT(!ret);
169 free(ht);
170 }
171
172 /*
173 * Init lttng ht node string.
174 */
175 void lttng_ht_node_init_str(struct lttng_ht_node_str *node, char *key)
176 {
177 LTTNG_ASSERT(node);
178
179 node->key = key;
180 cds_lfht_node_init(&node->node);
181 }
182
183 /*
184 * Init lttng ht node unsigned long.
185 */
186 void lttng_ht_node_init_ulong(struct lttng_ht_node_ulong *node, unsigned long key)
187 {
188 LTTNG_ASSERT(node);
189
190 node->key = key;
191 cds_lfht_node_init(&node->node);
192 }
193
194 /*
195 * Init lttng ht node uint64_t.
196 */
197 void lttng_ht_node_init_u64(struct lttng_ht_node_u64 *node, uint64_t key)
198 {
199 LTTNG_ASSERT(node);
200
201 node->key = key;
202 cds_lfht_node_init(&node->node);
203 }
204
205 /*
206 * Init lttng ht node with two uint64_t.
207 */
208 void lttng_ht_node_init_two_u64(struct lttng_ht_node_two_u64 *node, uint64_t key1, uint64_t key2)
209 {
210 LTTNG_ASSERT(node);
211
212 node->key.key1 = key1;
213 node->key.key2 = key2;
214 cds_lfht_node_init(&node->node);
215 }
216
217 /*
218 * Free lttng ht node string.
219 */
220 void lttng_ht_node_free_str(struct lttng_ht_node_str *node)
221 {
222 LTTNG_ASSERT(node);
223 free(node);
224 }
225
226 /*
227 * Free lttng ht node unsigned long.
228 */
229 void lttng_ht_node_free_ulong(struct lttng_ht_node_ulong *node)
230 {
231 LTTNG_ASSERT(node);
232 free(node);
233 }
234
235 /*
236 * Free lttng ht node uint64_t.
237 */
238 void lttng_ht_node_free_u64(struct lttng_ht_node_u64 *node)
239 {
240 LTTNG_ASSERT(node);
241 free(node);
242 }
243
244 /*
245 * Free lttng ht node two uint64_t.
246 */
247 void lttng_ht_node_free_two_u64(struct lttng_ht_node_two_u64 *node)
248 {
249 LTTNG_ASSERT(node);
250 free(node);
251 }
252
253 /*
254 * Lookup function in hashtable.
255 */
256 void lttng_ht_lookup(struct lttng_ht *ht, const void *key, struct lttng_ht_iter *iter)
257 {
258 LTTNG_ASSERT(ht);
259 LTTNG_ASSERT(ht->ht);
260
261 cds_lfht_lookup(ht->ht, ht->hash_fct(key, lttng_ht_seed), ht->match_fct, key, &iter->iter);
262 }
263
264 /*
265 * Add unique string node to hashtable.
266 */
267 void lttng_ht_add_unique_str(struct lttng_ht *ht, struct lttng_ht_node_str *node)
268 {
269 struct cds_lfht_node *node_ptr;
270 LTTNG_ASSERT(ht);
271 LTTNG_ASSERT(ht->ht);
272 LTTNG_ASSERT(node);
273
274 /* RCU read lock protects from ABA. */
275 rcu_read_lock();
276 node_ptr = cds_lfht_add_unique(ht->ht,
277 ht->hash_fct(node->key, lttng_ht_seed),
278 ht->match_fct,
279 node->key,
280 &node->node);
281 rcu_read_unlock();
282 LTTNG_ASSERT(node_ptr == &node->node);
283 }
284
285 /*
286 * Add string node to hashtable.
287 */
288 void lttng_ht_add_str(struct lttng_ht *ht, struct lttng_ht_node_str *node)
289 {
290 LTTNG_ASSERT(ht);
291 LTTNG_ASSERT(ht->ht);
292 LTTNG_ASSERT(node);
293
294 /* RCU read lock protects from ABA. */
295 rcu_read_lock();
296 cds_lfht_add(ht->ht, ht->hash_fct(node->key, lttng_ht_seed), &node->node);
297 rcu_read_unlock();
298 }
299
300 /*
301 * Add unsigned long node to hashtable.
302 */
303 void lttng_ht_add_ulong(struct lttng_ht *ht, struct lttng_ht_node_ulong *node)
304 {
305 LTTNG_ASSERT(ht);
306 LTTNG_ASSERT(ht->ht);
307 LTTNG_ASSERT(node);
308
309 /* RCU read lock protects from ABA. */
310 rcu_read_lock();
311 cds_lfht_add(ht->ht, ht->hash_fct((void *) node->key, lttng_ht_seed), &node->node);
312 rcu_read_unlock();
313 }
314
315 /*
316 * Add uint64_t node to hashtable.
317 */
318 void lttng_ht_add_u64(struct lttng_ht *ht, struct lttng_ht_node_u64 *node)
319 {
320 LTTNG_ASSERT(ht);
321 LTTNG_ASSERT(ht->ht);
322 LTTNG_ASSERT(node);
323
324 /* RCU read lock protects from ABA. */
325 rcu_read_lock();
326 cds_lfht_add(ht->ht, ht->hash_fct(&node->key, lttng_ht_seed), &node->node);
327 rcu_read_unlock();
328 }
329
330 /*
331 * Add unique unsigned long node to hashtable.
332 */
333 void lttng_ht_add_unique_ulong(struct lttng_ht *ht, struct lttng_ht_node_ulong *node)
334 {
335 struct cds_lfht_node *node_ptr;
336 LTTNG_ASSERT(ht);
337 LTTNG_ASSERT(ht->ht);
338 LTTNG_ASSERT(node);
339
340 /* RCU read lock protects from ABA. */
341 rcu_read_lock();
342 node_ptr = cds_lfht_add_unique(ht->ht,
343 ht->hash_fct((void *) node->key, lttng_ht_seed),
344 ht->match_fct,
345 (void *) node->key,
346 &node->node);
347 rcu_read_unlock();
348 LTTNG_ASSERT(node_ptr == &node->node);
349 }
350
351 /*
352 * Add unique uint64_t node to hashtable.
353 */
354 void lttng_ht_add_unique_u64(struct lttng_ht *ht, struct lttng_ht_node_u64 *node)
355 {
356 struct cds_lfht_node *node_ptr;
357 LTTNG_ASSERT(ht);
358 LTTNG_ASSERT(ht->ht);
359 LTTNG_ASSERT(node);
360
361 /* RCU read lock protects from ABA. */
362 rcu_read_lock();
363 node_ptr = cds_lfht_add_unique(ht->ht,
364 ht->hash_fct(&node->key, lttng_ht_seed),
365 ht->match_fct,
366 &node->key,
367 &node->node);
368 rcu_read_unlock();
369 LTTNG_ASSERT(node_ptr == &node->node);
370 }
371
372 /*
373 * Add unique two uint64_t node to hashtable.
374 */
375 void lttng_ht_add_unique_two_u64(struct lttng_ht *ht, struct lttng_ht_node_two_u64 *node)
376 {
377 struct cds_lfht_node *node_ptr;
378 LTTNG_ASSERT(ht);
379 LTTNG_ASSERT(ht->ht);
380 LTTNG_ASSERT(node);
381
382 /* RCU read lock protects from ABA. */
383 rcu_read_lock();
384 node_ptr = cds_lfht_add_unique(ht->ht,
385 ht->hash_fct((void *) &node->key, lttng_ht_seed),
386 ht->match_fct,
387 (void *) &node->key,
388 &node->node);
389 rcu_read_unlock();
390 LTTNG_ASSERT(node_ptr == &node->node);
391 }
392
393 /*
394 * Add replace unsigned long node to hashtable.
395 */
396 struct lttng_ht_node_ulong *lttng_ht_add_replace_ulong(struct lttng_ht *ht,
397 struct lttng_ht_node_ulong *node)
398 {
399 struct cds_lfht_node *node_ptr;
400 LTTNG_ASSERT(ht);
401 LTTNG_ASSERT(ht->ht);
402 LTTNG_ASSERT(node);
403
404 /* RCU read lock protects from ABA. */
405 rcu_read_lock();
406 node_ptr = cds_lfht_add_replace(ht->ht,
407 ht->hash_fct((void *) node->key, lttng_ht_seed),
408 ht->match_fct,
409 (void *) node->key,
410 &node->node);
411 rcu_read_unlock();
412 if (!node_ptr) {
413 return NULL;
414 } else {
415 return lttng::utils::container_of(node_ptr, &lttng_ht_node_ulong::node);
416 }
417 LTTNG_ASSERT(node_ptr == &node->node);
418 }
419
420 /*
421 * Add replace unsigned long node to hashtable.
422 */
423 struct lttng_ht_node_u64 *lttng_ht_add_replace_u64(struct lttng_ht *ht,
424 struct lttng_ht_node_u64 *node)
425 {
426 struct cds_lfht_node *node_ptr;
427 LTTNG_ASSERT(ht);
428 LTTNG_ASSERT(ht->ht);
429 LTTNG_ASSERT(node);
430
431 /* RCU read lock protects from ABA. */
432 rcu_read_lock();
433 node_ptr = cds_lfht_add_replace(ht->ht,
434 ht->hash_fct(&node->key, lttng_ht_seed),
435 ht->match_fct,
436 &node->key,
437 &node->node);
438 rcu_read_unlock();
439 if (!node_ptr) {
440 return NULL;
441 } else {
442 return lttng::utils::container_of(node_ptr, &lttng_ht_node_u64::node);
443 }
444 LTTNG_ASSERT(node_ptr == &node->node);
445 }
446
447 /*
448 * Delete node from hashtable.
449 */
450 int lttng_ht_del(struct lttng_ht *ht, struct lttng_ht_iter *iter)
451 {
452 int ret;
453
454 LTTNG_ASSERT(ht);
455 LTTNG_ASSERT(ht->ht);
456 LTTNG_ASSERT(iter);
457
458 /* RCU read lock protects from ABA. */
459 rcu_read_lock();
460 ret = cds_lfht_del(ht->ht, iter->iter.node);
461 rcu_read_unlock();
462 return ret;
463 }
464
465 /*
466 * Get first node in the hashtable.
467 */
468 void lttng_ht_get_first(struct lttng_ht *ht, struct lttng_ht_iter *iter)
469 {
470 LTTNG_ASSERT(ht);
471 LTTNG_ASSERT(ht->ht);
472 LTTNG_ASSERT(iter);
473
474 cds_lfht_first(ht->ht, &iter->iter);
475 }
476
477 /*
478 * Get next node in the hashtable.
479 */
480 void lttng_ht_get_next(struct lttng_ht *ht, struct lttng_ht_iter *iter)
481 {
482 LTTNG_ASSERT(ht);
483 LTTNG_ASSERT(ht->ht);
484 LTTNG_ASSERT(iter);
485
486 cds_lfht_next(ht->ht, &iter->iter);
487 }
488
489 /*
490 * Return the number of nodes in the hashtable.
491 */
492 unsigned long lttng_ht_get_count(struct lttng_ht *ht)
493 {
494 long scb, sca;
495 unsigned long count;
496
497 LTTNG_ASSERT(ht);
498 LTTNG_ASSERT(ht->ht);
499
500 /* RCU read lock protects from ABA and allows RCU traversal. */
501 rcu_read_lock();
502 cds_lfht_count_nodes(ht->ht, &scb, &count, &sca);
503 rcu_read_unlock();
504
505 return count;
506 }
507
508 /*
509 * Return lttng ht string node from iterator.
510 */
511 struct lttng_ht_node_str *lttng_ht_iter_get_node_str(struct lttng_ht_iter *iter)
512 {
513 struct cds_lfht_node *node;
514
515 LTTNG_ASSERT(iter);
516 node = cds_lfht_iter_get_node(&iter->iter);
517 if (!node) {
518 return NULL;
519 }
520 return lttng::utils::container_of(node, &lttng_ht_node_str::node);
521 }
522
523 /*
524 * Return lttng ht unsigned long node from iterator.
525 */
526 struct lttng_ht_node_ulong *lttng_ht_iter_get_node_ulong(struct lttng_ht_iter *iter)
527 {
528 struct cds_lfht_node *node;
529
530 LTTNG_ASSERT(iter);
531 node = cds_lfht_iter_get_node(&iter->iter);
532 if (!node) {
533 return NULL;
534 }
535 return lttng::utils::container_of(node, &lttng_ht_node_ulong::node);
536 }
537
538 /*
539 * Return lttng ht unsigned long node from iterator.
540 */
541 struct lttng_ht_node_u64 *lttng_ht_iter_get_node_u64(struct lttng_ht_iter *iter)
542 {
543 struct cds_lfht_node *node;
544
545 LTTNG_ASSERT(iter);
546 node = cds_lfht_iter_get_node(&iter->iter);
547 if (!node) {
548 return NULL;
549 }
550 return lttng::utils::container_of(node, &lttng_ht_node_u64::node);
551 }
552
553 /*
554 * Return lttng ht stream and index id node from iterator.
555 */
556 struct lttng_ht_node_two_u64 *lttng_ht_iter_get_node_two_u64(struct lttng_ht_iter *iter)
557 {
558 struct cds_lfht_node *node;
559
560 LTTNG_ASSERT(iter);
561 node = cds_lfht_iter_get_node(&iter->iter);
562 if (!node) {
563 return NULL;
564 }
565 return lttng::utils::container_of(node, &lttng_ht_node_two_u64::node);
566 }
This page took 0.04168 seconds and 4 git commands to generate.