2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
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.
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
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
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.
22 #include <urcu/compiler.h>
24 #include <common/common.h>
25 #include <common/defaults.h>
27 #include "hashtable.h"
30 /* seed_lock protects both seed_init and lttng_ht_seed. */
31 static pthread_mutex_t seed_lock
= PTHREAD_MUTEX_INITIALIZER
;
32 static bool seed_init
;
33 unsigned long lttng_ht_seed
;
35 static unsigned long min_hash_alloc_size
= 1;
36 static unsigned long max_hash_buckets_size
= 0;
39 * Getter/lookup functions need to be called with RCU read-side lock
40 * held. However, modification functions (add, add_unique, replace, del)
41 * take the RCU lock internally, so it does not matter whether the
42 * caller hold the RCU lock or not.
46 * Match function for string node.
48 static int match_str(struct cds_lfht_node
*node
, const void *key
)
50 struct lttng_ht_node_str
*match_node
=
51 caa_container_of(node
, struct lttng_ht_node_str
, node
);
53 return hash_match_key_str(match_node
->key
, (void *) key
);
57 * Match function for ulong node.
59 static int match_ulong(struct cds_lfht_node
*node
, const void *key
)
61 struct lttng_ht_node_ulong
*match_node
=
62 caa_container_of(node
, struct lttng_ht_node_ulong
, node
);
64 return hash_match_key_ulong((void *) match_node
->key
, (void *) key
);
68 * Match function for u64 node.
70 static int match_u64(struct cds_lfht_node
*node
, const void *key
)
72 struct lttng_ht_node_u64
*match_node
=
73 caa_container_of(node
, struct lttng_ht_node_u64
, node
);
75 return hash_match_key_u64(&match_node
->key
, (void *) key
);
79 * Match function for two uint64_t node.
81 static int match_two_u64(struct cds_lfht_node
*node
, const void *key
)
83 struct lttng_ht_node_two_u64
*match_node
=
84 caa_container_of(node
, struct lttng_ht_node_two_u64
, node
);
86 return hash_match_key_two_u64((void *) &match_node
->key
, (void *) key
);
90 * Return an allocated lttng hashtable.
93 struct lttng_ht
*lttng_ht_new(unsigned long size
, int type
)
99 size
= DEFAULT_HT_SIZE
;
101 pthread_mutex_lock(&seed_lock
);
103 lttng_ht_seed
= (unsigned long) time(NULL
);
106 pthread_mutex_unlock(&seed_lock
);
108 ht
= zmalloc(sizeof(*ht
));
110 PERROR("zmalloc lttng_ht");
114 ht
->ht
= cds_lfht_new(size
, min_hash_alloc_size
, max_hash_buckets_size
,
115 CDS_LFHT_AUTO_RESIZE
| CDS_LFHT_ACCOUNTING
, NULL
);
117 * There is already an assert in the RCU hashtable code so if the ht is
118 * NULL here there is a *huge* problem.
123 case LTTNG_HT_TYPE_STRING
:
124 ht
->match_fct
= match_str
;
125 ht
->hash_fct
= hash_key_str
;
127 case LTTNG_HT_TYPE_ULONG
:
128 ht
->match_fct
= match_ulong
;
129 ht
->hash_fct
= hash_key_ulong
;
131 case LTTNG_HT_TYPE_U64
:
132 ht
->match_fct
= match_u64
;
133 ht
->hash_fct
= hash_key_u64
;
135 case LTTNG_HT_TYPE_TWO_U64
:
136 ht
->match_fct
= match_two_u64
;
137 ht
->hash_fct
= hash_key_two_u64
;
140 ERR("Unknown lttng hashtable type %d", type
);
141 lttng_ht_destroy(ht
);
145 DBG3("Created hashtable size %lu at %p of type %d", size
, ht
->ht
, type
);
154 * Free a lttng hashtable.
157 void lttng_ht_destroy(struct lttng_ht
*ht
)
161 ret
= cds_lfht_destroy(ht
->ht
, NULL
);
167 * Init lttng ht node string.
170 void lttng_ht_node_init_str(struct lttng_ht_node_str
*node
, char *key
)
175 cds_lfht_node_init(&node
->node
);
179 * Init lttng ht node unsigned long.
182 void lttng_ht_node_init_ulong(struct lttng_ht_node_ulong
*node
,
188 cds_lfht_node_init(&node
->node
);
192 * Init lttng ht node uint64_t.
195 void lttng_ht_node_init_u64(struct lttng_ht_node_u64
*node
,
201 cds_lfht_node_init(&node
->node
);
205 * Init lttng ht node with two uint64_t.
208 void lttng_ht_node_init_two_u64(struct lttng_ht_node_two_u64
*node
,
209 uint64_t key1
, uint64_t key2
)
213 node
->key
.key1
= key1
;
214 node
->key
.key2
= key2
;
215 cds_lfht_node_init(&node
->node
);
219 * Free lttng ht node string.
222 void lttng_ht_node_free_str(struct lttng_ht_node_str
*node
)
229 * Free lttng ht node unsigned long.
232 void lttng_ht_node_free_ulong(struct lttng_ht_node_ulong
*node
)
239 * Free lttng ht node uint64_t.
242 void lttng_ht_node_free_u64(struct lttng_ht_node_u64
*node
)
249 * Free lttng ht node two uint64_t.
252 void lttng_ht_node_free_two_u64(struct lttng_ht_node_two_u64
*node
)
259 * Lookup function in hashtable.
262 void lttng_ht_lookup(struct lttng_ht
*ht
, const void *key
,
263 struct lttng_ht_iter
*iter
)
268 cds_lfht_lookup(ht
->ht
, ht
->hash_fct(key
, lttng_ht_seed
),
269 ht
->match_fct
, key
, &iter
->iter
);
273 * Add unique string node to hashtable.
276 void lttng_ht_add_unique_str(struct lttng_ht
*ht
,
277 struct lttng_ht_node_str
*node
)
279 struct cds_lfht_node
*node_ptr
;
284 /* RCU read lock protects from ABA. */
286 node_ptr
= cds_lfht_add_unique(ht
->ht
, ht
->hash_fct(node
->key
, lttng_ht_seed
),
287 ht
->match_fct
, node
->key
, &node
->node
);
289 assert(node_ptr
== &node
->node
);
293 * Add string node to hashtable.
296 void lttng_ht_add_str(struct lttng_ht
*ht
,
297 struct lttng_ht_node_str
*node
)
303 /* RCU read lock protects from ABA. */
305 cds_lfht_add(ht
->ht
, ht
->hash_fct(node
->key
, lttng_ht_seed
),
311 * Add unsigned long node to hashtable.
314 void lttng_ht_add_ulong(struct lttng_ht
*ht
, struct lttng_ht_node_ulong
*node
)
320 /* RCU read lock protects from ABA. */
322 cds_lfht_add(ht
->ht
, ht
->hash_fct((void *) node
->key
, lttng_ht_seed
),
328 * Add uint64_t node to hashtable.
331 void lttng_ht_add_u64(struct lttng_ht
*ht
, struct lttng_ht_node_u64
*node
)
337 /* RCU read lock protects from ABA. */
339 cds_lfht_add(ht
->ht
, ht
->hash_fct(&node
->key
, lttng_ht_seed
),
345 * Add unique unsigned long node to hashtable.
348 void lttng_ht_add_unique_ulong(struct lttng_ht
*ht
,
349 struct lttng_ht_node_ulong
*node
)
351 struct cds_lfht_node
*node_ptr
;
356 /* RCU read lock protects from ABA. */
358 node_ptr
= cds_lfht_add_unique(ht
->ht
,
359 ht
->hash_fct((void *) node
->key
, lttng_ht_seed
), ht
->match_fct
,
360 (void *) node
->key
, &node
->node
);
362 assert(node_ptr
== &node
->node
);
366 * Add unique uint64_t node to hashtable.
369 void lttng_ht_add_unique_u64(struct lttng_ht
*ht
,
370 struct lttng_ht_node_u64
*node
)
372 struct cds_lfht_node
*node_ptr
;
377 /* RCU read lock protects from ABA. */
379 node_ptr
= cds_lfht_add_unique(ht
->ht
,
380 ht
->hash_fct(&node
->key
, lttng_ht_seed
), ht
->match_fct
,
381 &node
->key
, &node
->node
);
383 assert(node_ptr
== &node
->node
);
387 * Add unique two uint64_t node to hashtable.
390 void lttng_ht_add_unique_two_u64(struct lttng_ht
*ht
,
391 struct lttng_ht_node_two_u64
*node
)
393 struct cds_lfht_node
*node_ptr
;
398 /* RCU read lock protects from ABA. */
400 node_ptr
= cds_lfht_add_unique(ht
->ht
,
401 ht
->hash_fct((void *) &node
->key
, lttng_ht_seed
), ht
->match_fct
,
402 (void *) &node
->key
, &node
->node
);
404 assert(node_ptr
== &node
->node
);
408 * Add replace unsigned long node to hashtable.
411 struct lttng_ht_node_ulong
*lttng_ht_add_replace_ulong(struct lttng_ht
*ht
,
412 struct lttng_ht_node_ulong
*node
)
414 struct cds_lfht_node
*node_ptr
;
419 /* RCU read lock protects from ABA. */
421 node_ptr
= cds_lfht_add_replace(ht
->ht
,
422 ht
->hash_fct((void *) node
->key
, lttng_ht_seed
), ht
->match_fct
,
423 (void *) node
->key
, &node
->node
);
428 return caa_container_of(node_ptr
, struct lttng_ht_node_ulong
, node
);
430 assert(node_ptr
== &node
->node
);
434 * Add replace unsigned long node to hashtable.
437 struct lttng_ht_node_u64
*lttng_ht_add_replace_u64(struct lttng_ht
*ht
,
438 struct lttng_ht_node_u64
*node
)
440 struct cds_lfht_node
*node_ptr
;
445 /* RCU read lock protects from ABA. */
447 node_ptr
= cds_lfht_add_replace(ht
->ht
,
448 ht
->hash_fct(&node
->key
, lttng_ht_seed
), ht
->match_fct
,
449 &node
->key
, &node
->node
);
454 return caa_container_of(node_ptr
, struct lttng_ht_node_u64
, node
);
456 assert(node_ptr
== &node
->node
);
460 * Delete node from hashtable.
463 int lttng_ht_del(struct lttng_ht
*ht
, struct lttng_ht_iter
*iter
)
471 /* RCU read lock protects from ABA. */
473 ret
= cds_lfht_del(ht
->ht
, iter
->iter
.node
);
479 * Get first node in the hashtable.
482 void lttng_ht_get_first(struct lttng_ht
*ht
, struct lttng_ht_iter
*iter
)
488 cds_lfht_first(ht
->ht
, &iter
->iter
);
492 * Get next node in the hashtable.
495 void lttng_ht_get_next(struct lttng_ht
*ht
, struct lttng_ht_iter
*iter
)
501 cds_lfht_next(ht
->ht
, &iter
->iter
);
505 * Return the number of nodes in the hashtable.
508 unsigned long lttng_ht_get_count(struct lttng_ht
*ht
)
516 /* RCU read lock protects from ABA and allows RCU traversal. */
518 cds_lfht_count_nodes(ht
->ht
, &scb
, &count
, &sca
);
525 * Return lttng ht string node from iterator.
528 struct lttng_ht_node_str
*lttng_ht_iter_get_node_str(
529 struct lttng_ht_iter
*iter
)
531 struct cds_lfht_node
*node
;
534 node
= cds_lfht_iter_get_node(&iter
->iter
);
538 return caa_container_of(node
, struct lttng_ht_node_str
, node
);
542 * Return lttng ht unsigned long node from iterator.
545 struct lttng_ht_node_ulong
*lttng_ht_iter_get_node_ulong(
546 struct lttng_ht_iter
*iter
)
548 struct cds_lfht_node
*node
;
551 node
= cds_lfht_iter_get_node(&iter
->iter
);
555 return caa_container_of(node
, struct lttng_ht_node_ulong
, node
);
559 * Return lttng ht unsigned long node from iterator.
562 struct lttng_ht_node_u64
*lttng_ht_iter_get_node_u64(
563 struct lttng_ht_iter
*iter
)
565 struct cds_lfht_node
*node
;
568 node
= cds_lfht_iter_get_node(&iter
->iter
);
572 return caa_container_of(node
, struct lttng_ht_node_u64
, node
);
576 * Return lttng ht stream and index id node from iterator.
579 struct lttng_ht_node_two_u64
*lttng_ht_iter_get_node_two_u64(
580 struct lttng_ht_iter
*iter
)
582 struct cds_lfht_node
*node
;
585 node
= cds_lfht_iter_get_node(&iter
->iter
);
589 return caa_container_of(node
, struct lttng_ht_node_two_u64
, node
);