Run clang-format on the whole tree
[lttng-tools.git] / src / common / hashtable / hashtable.cpp
CommitLineData
bec39940 1/*
21cf9b6b 2 * Copyright (C) 2011 EfficiOS Inc.
bec39940 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
bec39940 5 *
bec39940
DG
6 */
7
6c1c0768 8#define _LGPL_SOURCE
28ab034a
JG
9#include "hashtable.hpp"
10#include "utils.hpp"
bec39940 11
c9e313bc
SM
12#include <common/common.hpp>
13#include <common/defaults.hpp>
bec39940 14
28ab034a
JG
15#include <string.h>
16#include <urcu.h>
17#include <urcu/compiler.h>
bec39940 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;
bec39940
DG
22
23static unsigned long min_hash_alloc_size = 1;
13fe1164 24static unsigned long max_hash_buckets_size = 0;
bec39940 25
42ce408e
MD
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
bec39940
DG
33/*
34 * Match function for string node.
35 */
36static int match_str(struct cds_lfht_node *node, const void *key)
37{
38 struct lttng_ht_node_str *match_node =
0114db0e 39 lttng::utils::container_of(node, &lttng_ht_node_str::node);
bec39940
DG
40
41 return hash_match_key_str(match_node->key, (void *) key);
42}
43
44/*
45 * Match function for ulong node.
46 */
47static int match_ulong(struct cds_lfht_node *node, const void *key)
48{
49 struct lttng_ht_node_ulong *match_node =
0114db0e 50 lttng::utils::container_of(node, &lttng_ht_node_ulong::node);
bec39940
DG
51
52 return hash_match_key_ulong((void *) match_node->key, (void *) key);
53}
54
d88aee68
DG
55/*
56 * Match function for u64 node.
57 */
58static int match_u64(struct cds_lfht_node *node, const void *key)
59{
60 struct lttng_ht_node_u64 *match_node =
0114db0e 61 lttng::utils::container_of(node, &lttng_ht_node_u64::node);
d88aee68
DG
62
63 return hash_match_key_u64(&match_node->key, (void *) key);
64}
65
3c4599b9
JD
66/*
67 * Match function for two uint64_t node.
68 */
69static int match_two_u64(struct cds_lfht_node *node, const void *key)
70{
71 struct lttng_ht_node_two_u64 *match_node =
0114db0e 72 lttng::utils::container_of(node, &lttng_ht_node_two_u64::node);
3c4599b9
JD
73
74 return hash_match_key_two_u64((void *) &match_node->key, (void *) key);
75}
76
28ab034a 77static inline const char *lttng_ht_type_str(enum lttng_ht_type type)
e2530e2b
FD
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
bec39940
DG
94/*
95 * Return an allocated lttng hashtable.
96 */
6dca8ba7 97struct lttng_ht *lttng_ht_new(unsigned long size, lttng_ht_type type)
bec39940
DG
98{
99 struct lttng_ht *ht;
100
101 /* Test size */
dc78d159
MD
102 if (!size)
103 size = DEFAULT_HT_SIZE;
bec39940 104
6dcd74cf
JG
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
64803277 112 ht = zmalloc<lttng_ht>();
bec39940
DG
113 if (ht == NULL) {
114 PERROR("zmalloc lttng_ht");
115 goto error;
116 }
117
28ab034a
JG
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);
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
28ab034a 152 DBG3("Created hashtable size %lu at %p of type %s", size, ht->ht, lttng_ht_type_str(type));
bec39940
DG
153
154 return ht;
155
156error:
157 return NULL;
158}
159
160/*
161 * Free a lttng hashtable.
162 */
163void lttng_ht_destroy(struct lttng_ht *ht)
164{
165 int ret;
166
167 ret = cds_lfht_destroy(ht->ht, NULL);
a0377dfe 168 LTTNG_ASSERT(!ret);
cf5280ea 169 free(ht);
bec39940
DG
170}
171
172/*
173 * Init lttng ht node string.
174 */
175void lttng_ht_node_init_str(struct lttng_ht_node_str *node, char *key)
176{
a0377dfe 177 LTTNG_ASSERT(node);
bec39940
DG
178
179 node->key = key;
180 cds_lfht_node_init(&node->node);
181}
182
183/*
184 * Init lttng ht node unsigned long.
185 */
28ab034a 186void lttng_ht_node_init_ulong(struct lttng_ht_node_ulong *node, unsigned long key)
bec39940 187{
a0377dfe 188 LTTNG_ASSERT(node);
bec39940
DG
189
190 node->key = key;
191 cds_lfht_node_init(&node->node);
192}
193
d88aee68
DG
194/*
195 * Init lttng ht node uint64_t.
196 */
28ab034a 197void lttng_ht_node_init_u64(struct lttng_ht_node_u64 *node, uint64_t key)
d88aee68 198{
a0377dfe 199 LTTNG_ASSERT(node);
d88aee68
DG
200
201 node->key = key;
202 cds_lfht_node_init(&node->node);
203}
204
3c4599b9
JD
205/*
206 * Init lttng ht node with two uint64_t.
207 */
28ab034a 208void lttng_ht_node_init_two_u64(struct lttng_ht_node_two_u64 *node, uint64_t key1, uint64_t key2)
3c4599b9 209{
a0377dfe 210 LTTNG_ASSERT(node);
3c4599b9
JD
211
212 node->key.key1 = key1;
213 node->key.key2 = key2;
214 cds_lfht_node_init(&node->node);
215}
216
bec39940
DG
217/*
218 * Free lttng ht node string.
219 */
220void lttng_ht_node_free_str(struct lttng_ht_node_str *node)
221{
a0377dfe 222 LTTNG_ASSERT(node);
bec39940
DG
223 free(node);
224}
225
226/*
227 * Free lttng ht node unsigned long.
228 */
229void lttng_ht_node_free_ulong(struct lttng_ht_node_ulong *node)
230{
a0377dfe 231 LTTNG_ASSERT(node);
bec39940
DG
232 free(node);
233}
234
d88aee68
DG
235/*
236 * Free lttng ht node uint64_t.
237 */
7972aab2 238void lttng_ht_node_free_u64(struct lttng_ht_node_u64 *node)
d88aee68 239{
a0377dfe 240 LTTNG_ASSERT(node);
d88aee68
DG
241 free(node);
242}
243
3c4599b9
JD
244/*
245 * Free lttng ht node two uint64_t.
246 */
247void lttng_ht_node_free_two_u64(struct lttng_ht_node_two_u64 *node)
248{
a0377dfe 249 LTTNG_ASSERT(node);
3c4599b9
JD
250 free(node);
251}
252
bec39940
DG
253/*
254 * Lookup function in hashtable.
255 */
28ab034a 256void lttng_ht_lookup(struct lttng_ht *ht, const void *key, struct lttng_ht_iter *iter)
bec39940 257{
a0377dfe
FD
258 LTTNG_ASSERT(ht);
259 LTTNG_ASSERT(ht->ht);
bec39940 260
28ab034a 261 cds_lfht_lookup(ht->ht, ht->hash_fct(key, lttng_ht_seed), ht->match_fct, key, &iter->iter);
bec39940
DG
262}
263
264/*
265 * Add unique string node to hashtable.
266 */
28ab034a 267void lttng_ht_add_unique_str(struct lttng_ht *ht, struct lttng_ht_node_str *node)
bec39940
DG
268{
269 struct cds_lfht_node *node_ptr;
a0377dfe
FD
270 LTTNG_ASSERT(ht);
271 LTTNG_ASSERT(ht->ht);
272 LTTNG_ASSERT(node);
bec39940 273
42ce408e
MD
274 /* RCU read lock protects from ABA. */
275 rcu_read_lock();
28ab034a
JG
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);
42ce408e 281 rcu_read_unlock();
a0377dfe 282 LTTNG_ASSERT(node_ptr == &node->node);
bec39940
DG
283}
284
efa116c6
JD
285/*
286 * Add string node to hashtable.
287 */
28ab034a 288void lttng_ht_add_str(struct lttng_ht *ht, struct lttng_ht_node_str *node)
efa116c6 289{
a0377dfe
FD
290 LTTNG_ASSERT(ht);
291 LTTNG_ASSERT(ht->ht);
292 LTTNG_ASSERT(node);
efa116c6 293
42ce408e
MD
294 /* RCU read lock protects from ABA. */
295 rcu_read_lock();
28ab034a 296 cds_lfht_add(ht->ht, ht->hash_fct(node->key, lttng_ht_seed), &node->node);
42ce408e 297 rcu_read_unlock();
efa116c6
JD
298}
299
aefea3b7
DG
300/*
301 * Add unsigned long node to hashtable.
302 */
303void lttng_ht_add_ulong(struct lttng_ht *ht, struct lttng_ht_node_ulong *node)
304{
a0377dfe
FD
305 LTTNG_ASSERT(ht);
306 LTTNG_ASSERT(ht->ht);
307 LTTNG_ASSERT(node);
aefea3b7 308
42ce408e
MD
309 /* RCU read lock protects from ABA. */
310 rcu_read_lock();
28ab034a 311 cds_lfht_add(ht->ht, ht->hash_fct((void *) node->key, lttng_ht_seed), &node->node);
42ce408e 312 rcu_read_unlock();
aefea3b7
DG
313}
314
d88aee68
DG
315/*
316 * Add uint64_t node to hashtable.
d88aee68
DG
317 */
318void lttng_ht_add_u64(struct lttng_ht *ht, struct lttng_ht_node_u64 *node)
319{
a0377dfe
FD
320 LTTNG_ASSERT(ht);
321 LTTNG_ASSERT(ht->ht);
322 LTTNG_ASSERT(node);
d88aee68 323
42ce408e
MD
324 /* RCU read lock protects from ABA. */
325 rcu_read_lock();
28ab034a 326 cds_lfht_add(ht->ht, ht->hash_fct(&node->key, lttng_ht_seed), &node->node);
42ce408e 327 rcu_read_unlock();
d88aee68
DG
328}
329
bec39940
DG
330/*
331 * Add unique unsigned long node to hashtable.
332 */
28ab034a 333void lttng_ht_add_unique_ulong(struct lttng_ht *ht, struct lttng_ht_node_ulong *node)
bec39940
DG
334{
335 struct cds_lfht_node *node_ptr;
a0377dfe
FD
336 LTTNG_ASSERT(ht);
337 LTTNG_ASSERT(ht->ht);
338 LTTNG_ASSERT(node);
bec39940 339
42ce408e
MD
340 /* RCU read lock protects from ABA. */
341 rcu_read_lock();
bec39940 342 node_ptr = cds_lfht_add_unique(ht->ht,
28ab034a
JG
343 ht->hash_fct((void *) node->key, lttng_ht_seed),
344 ht->match_fct,
345 (void *) node->key,
346 &node->node);
42ce408e 347 rcu_read_unlock();
a0377dfe 348 LTTNG_ASSERT(node_ptr == &node->node);
bec39940
DG
349}
350
d88aee68
DG
351/*
352 * Add unique uint64_t node to hashtable.
353 */
28ab034a 354void lttng_ht_add_unique_u64(struct lttng_ht *ht, struct lttng_ht_node_u64 *node)
d88aee68
DG
355{
356 struct cds_lfht_node *node_ptr;
a0377dfe
FD
357 LTTNG_ASSERT(ht);
358 LTTNG_ASSERT(ht->ht);
359 LTTNG_ASSERT(node);
d88aee68 360
42ce408e
MD
361 /* RCU read lock protects from ABA. */
362 rcu_read_lock();
d88aee68 363 node_ptr = cds_lfht_add_unique(ht->ht,
28ab034a
JG
364 ht->hash_fct(&node->key, lttng_ht_seed),
365 ht->match_fct,
366 &node->key,
367 &node->node);
42ce408e 368 rcu_read_unlock();
a0377dfe 369 LTTNG_ASSERT(node_ptr == &node->node);
d88aee68
DG
370}
371
3c4599b9
JD
372/*
373 * Add unique two uint64_t node to hashtable.
374 */
28ab034a 375void lttng_ht_add_unique_two_u64(struct lttng_ht *ht, struct lttng_ht_node_two_u64 *node)
3c4599b9
JD
376{
377 struct cds_lfht_node *node_ptr;
a0377dfe
FD
378 LTTNG_ASSERT(ht);
379 LTTNG_ASSERT(ht->ht);
380 LTTNG_ASSERT(node);
3c4599b9 381
42ce408e
MD
382 /* RCU read lock protects from ABA. */
383 rcu_read_lock();
3c4599b9 384 node_ptr = cds_lfht_add_unique(ht->ht,
28ab034a
JG
385 ht->hash_fct((void *) &node->key, lttng_ht_seed),
386 ht->match_fct,
387 (void *) &node->key,
388 &node->node);
42ce408e 389 rcu_read_unlock();
a0377dfe 390 LTTNG_ASSERT(node_ptr == &node->node);
3c4599b9
JD
391}
392
702b1ea4
MD
393/*
394 * Add replace unsigned long node to hashtable.
395 */
396struct lttng_ht_node_ulong *lttng_ht_add_replace_ulong(struct lttng_ht *ht,
28ab034a 397 struct lttng_ht_node_ulong *node)
702b1ea4
MD
398{
399 struct cds_lfht_node *node_ptr;
a0377dfe
FD
400 LTTNG_ASSERT(ht);
401 LTTNG_ASSERT(ht->ht);
402 LTTNG_ASSERT(node);
702b1ea4 403
42ce408e
MD
404 /* RCU read lock protects from ABA. */
405 rcu_read_lock();
702b1ea4 406 node_ptr = cds_lfht_add_replace(ht->ht,
28ab034a
JG
407 ht->hash_fct((void *) node->key, lttng_ht_seed),
408 ht->match_fct,
409 (void *) node->key,
410 &node->node);
42ce408e 411 rcu_read_unlock();
702b1ea4
MD
412 if (!node_ptr) {
413 return NULL;
414 } else {
0114db0e 415 return lttng::utils::container_of(node_ptr, &lttng_ht_node_ulong::node);
702b1ea4 416 }
a0377dfe 417 LTTNG_ASSERT(node_ptr == &node->node);
702b1ea4
MD
418}
419
d88aee68
DG
420/*
421 * Add replace unsigned long node to hashtable.
422 */
423struct lttng_ht_node_u64 *lttng_ht_add_replace_u64(struct lttng_ht *ht,
28ab034a 424 struct lttng_ht_node_u64 *node)
d88aee68
DG
425{
426 struct cds_lfht_node *node_ptr;
a0377dfe
FD
427 LTTNG_ASSERT(ht);
428 LTTNG_ASSERT(ht->ht);
429 LTTNG_ASSERT(node);
d88aee68 430
42ce408e
MD
431 /* RCU read lock protects from ABA. */
432 rcu_read_lock();
d88aee68 433 node_ptr = cds_lfht_add_replace(ht->ht,
28ab034a
JG
434 ht->hash_fct(&node->key, lttng_ht_seed),
435 ht->match_fct,
436 &node->key,
437 &node->node);
42ce408e 438 rcu_read_unlock();
d88aee68
DG
439 if (!node_ptr) {
440 return NULL;
441 } else {
0114db0e 442 return lttng::utils::container_of(node_ptr, &lttng_ht_node_u64::node);
d88aee68 443 }
a0377dfe 444 LTTNG_ASSERT(node_ptr == &node->node);
d88aee68
DG
445}
446
bec39940
DG
447/*
448 * Delete node from hashtable.
449 */
450int lttng_ht_del(struct lttng_ht *ht, struct lttng_ht_iter *iter)
451{
42ce408e
MD
452 int ret;
453
a0377dfe
FD
454 LTTNG_ASSERT(ht);
455 LTTNG_ASSERT(ht->ht);
456 LTTNG_ASSERT(iter);
bec39940 457
42ce408e
MD
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;
bec39940
DG
463}
464
465/*
466 * Get first node in the hashtable.
467 */
468void lttng_ht_get_first(struct lttng_ht *ht, struct lttng_ht_iter *iter)
469{
a0377dfe
FD
470 LTTNG_ASSERT(ht);
471 LTTNG_ASSERT(ht->ht);
472 LTTNG_ASSERT(iter);
bec39940
DG
473
474 cds_lfht_first(ht->ht, &iter->iter);
475}
476
477/*
478 * Get next node in the hashtable.
479 */
480void lttng_ht_get_next(struct lttng_ht *ht, struct lttng_ht_iter *iter)
481{
a0377dfe
FD
482 LTTNG_ASSERT(ht);
483 LTTNG_ASSERT(ht->ht);
484 LTTNG_ASSERT(iter);
bec39940
DG
485
486 cds_lfht_next(ht->ht, &iter->iter);
487}
488
489/*
490 * Return the number of nodes in the hashtable.
491 */
492unsigned long lttng_ht_get_count(struct lttng_ht *ht)
493{
494 long scb, sca;
495 unsigned long count;
496
a0377dfe
FD
497 LTTNG_ASSERT(ht);
498 LTTNG_ASSERT(ht->ht);
bec39940 499
42ce408e
MD
500 /* RCU read lock protects from ABA and allows RCU traversal. */
501 rcu_read_lock();
bec39940 502 cds_lfht_count_nodes(ht->ht, &scb, &count, &sca);
42ce408e 503 rcu_read_unlock();
bec39940
DG
504
505 return count;
506}
507
508/*
509 * Return lttng ht string node from iterator.
510 */
28ab034a 511struct lttng_ht_node_str *lttng_ht_iter_get_node_str(struct lttng_ht_iter *iter)
bec39940
DG
512{
513 struct cds_lfht_node *node;
514
a0377dfe 515 LTTNG_ASSERT(iter);
bec39940
DG
516 node = cds_lfht_iter_get_node(&iter->iter);
517 if (!node) {
518 return NULL;
519 }
0114db0e 520 return lttng::utils::container_of(node, &lttng_ht_node_str::node);
bec39940
DG
521}
522
523/*
524 * Return lttng ht unsigned long node from iterator.
525 */
28ab034a 526struct lttng_ht_node_ulong *lttng_ht_iter_get_node_ulong(struct lttng_ht_iter *iter)
bec39940
DG
527{
528 struct cds_lfht_node *node;
529
a0377dfe 530 LTTNG_ASSERT(iter);
bec39940
DG
531 node = cds_lfht_iter_get_node(&iter->iter);
532 if (!node) {
533 return NULL;
534 }
0114db0e 535 return lttng::utils::container_of(node, &lttng_ht_node_ulong::node);
bec39940 536}
b6314938 537
d88aee68
DG
538/*
539 * Return lttng ht unsigned long node from iterator.
540 */
28ab034a 541struct lttng_ht_node_u64 *lttng_ht_iter_get_node_u64(struct lttng_ht_iter *iter)
d88aee68
DG
542{
543 struct cds_lfht_node *node;
544
a0377dfe 545 LTTNG_ASSERT(iter);
d88aee68
DG
546 node = cds_lfht_iter_get_node(&iter->iter);
547 if (!node) {
548 return NULL;
549 }
0114db0e 550 return lttng::utils::container_of(node, &lttng_ht_node_u64::node);
d88aee68
DG
551}
552
3c4599b9
JD
553/*
554 * Return lttng ht stream and index id node from iterator.
555 */
28ab034a 556struct lttng_ht_node_two_u64 *lttng_ht_iter_get_node_two_u64(struct lttng_ht_iter *iter)
3c4599b9
JD
557{
558 struct cds_lfht_node *node;
559
a0377dfe 560 LTTNG_ASSERT(iter);
3c4599b9
JD
561 node = cds_lfht_iter_get_node(&iter->iter);
562 if (!node) {
563 return NULL;
564 }
0114db0e 565 return lttng::utils::container_of(node, &lttng_ht_node_two_u64::node);
3c4599b9 566}
This page took 0.100408 seconds and 4 git commands to generate.