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