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