X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=liblttng-ht%2Flttng-ht.c;fp=liblttng-ht%2Flttng-ht.c;h=608b3af10bdbd48180bc7f06fee98fa9e47553c4;hp=0000000000000000000000000000000000000000;hb=bec399405a4667411ae06bbbcbed678e42e93a30;hpb=67cea2c94b841ee9b38ba80ab8a9eafff5f76408 diff --git a/liblttng-ht/lttng-ht.c b/liblttng-ht/lttng-ht.c new file mode 100644 index 000000000..608b3af10 --- /dev/null +++ b/liblttng-ht/lttng-ht.c @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2011 - David Goulet + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; only version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include + +#include +#include +#include + +#include "utils.h" + +#define HASH_SEED 0x42UL /* The answer to life */ + +static unsigned long min_hash_alloc_size = 1; +static unsigned long max_hash_buckets_size = (1UL << 20); + +/* + * Match function for string node. + */ +static int match_str(struct cds_lfht_node *node, const void *key) +{ + struct lttng_ht_node_str *match_node = + caa_container_of(node, struct lttng_ht_node_str, node); + + return hash_match_key_str(match_node->key, (void *) key); +} + +/* + * Match function for ulong node. + */ +static int match_ulong(struct cds_lfht_node *node, const void *key) +{ + struct lttng_ht_node_ulong *match_node = + caa_container_of(node, struct lttng_ht_node_ulong, node); + + return hash_match_key_ulong((void *) match_node->key, (void *) key); +} + +/* + * Return an allocated lttng hashtable. + */ +struct lttng_ht *lttng_ht_new(unsigned long size, int type) +{ + struct lttng_ht *ht; + + /* Test size */ + size != 0 ? : (size = DEFAULT_HT_SIZE); + + ht = zmalloc(sizeof(*ht)); + if (ht == NULL) { + PERROR("zmalloc lttng_ht"); + goto error; + } + + ht->ht = cds_lfht_new(size, min_hash_alloc_size, max_hash_buckets_size, + CDS_LFHT_AUTO_RESIZE, NULL); + /* + * There is already an assert in the RCU hashtable code so if the ht is + * NULL here there is a *huge* problem. + */ + assert(ht->ht); + + switch (type) { + case LTTNG_HT_TYPE_STRING: + ht->match_fct = match_str; + ht->hash_fct = hash_key_str; + break; + case LTTNG_HT_TYPE_ULONG: + ht->match_fct = match_ulong; + ht->hash_fct = hash_key_ulong; + break; + default: + ERR("Unknown lttng hashtable type %d", type); + goto error; + } + + DBG3("Created hashtable size %lu at %p of type %d", size, ht->ht, type); + + return ht; + +error: + return NULL; +} + +/* + * Free a lttng hashtable. + */ +void lttng_ht_destroy(struct lttng_ht *ht) +{ + int ret; + + ret = cds_lfht_destroy(ht->ht, NULL); + assert(!ret); +} + +/* + * Init lttng ht node string. + */ +void lttng_ht_node_init_str(struct lttng_ht_node_str *node, char *key) +{ + assert(node); + + node->key = key; + cds_lfht_node_init(&node->node); +} + +/* + * Init lttng ht node unsigned long. + */ +void lttng_ht_node_init_ulong(struct lttng_ht_node_ulong *node, + unsigned long key) +{ + assert(node); + + node->key = key; + cds_lfht_node_init(&node->node); +} + +/* + * Free lttng ht node string. + */ +void lttng_ht_node_free_str(struct lttng_ht_node_str *node) +{ + assert(node); + free(node); +} + +/* + * Free lttng ht node unsigned long. + */ +void lttng_ht_node_free_ulong(struct lttng_ht_node_ulong *node) +{ + assert(node); + free(node); +} + +/* + * Lookup function in hashtable. + */ +void lttng_ht_lookup(struct lttng_ht *ht, void *key, + struct lttng_ht_iter *iter) +{ + assert(ht); + assert(ht->ht); + assert(key); + + cds_lfht_lookup(ht->ht, ht->hash_fct(key, HASH_SEED), + ht->match_fct, key, &iter->iter); +} + +/* + * Add unique string node to hashtable. + */ +void lttng_ht_add_unique_str(struct lttng_ht *ht, + struct lttng_ht_node_str *node) +{ + struct cds_lfht_node *node_ptr; + assert(ht); + assert(ht->ht); + assert(node); + + node_ptr = cds_lfht_add_unique(ht->ht, ht->hash_fct(node->key, HASH_SEED), + ht->match_fct, node->key, &node->node); + assert(node_ptr == &node->node); +} + +/* + * Add unique unsigned long node to hashtable. + */ +void lttng_ht_add_unique_ulong(struct lttng_ht *ht, + struct lttng_ht_node_ulong *node) +{ + struct cds_lfht_node *node_ptr; + assert(ht); + assert(ht->ht); + assert(node); + + node_ptr = cds_lfht_add_unique(ht->ht, + ht->hash_fct((void *) node->key, HASH_SEED), ht->match_fct, + (void *) node->key, &node->node); + assert(node_ptr == &node->node); +} + +/* + * Delete node from hashtable. + */ +int lttng_ht_del(struct lttng_ht *ht, struct lttng_ht_iter *iter) +{ + assert(ht); + assert(ht->ht); + assert(iter); + + return cds_lfht_del(ht->ht, iter->iter.node); +} + +/* + * Get first node in the hashtable. + */ +void lttng_ht_get_first(struct lttng_ht *ht, struct lttng_ht_iter *iter) +{ + assert(ht); + assert(ht->ht); + assert(iter); + + cds_lfht_first(ht->ht, &iter->iter); +} + +/* + * Get next node in the hashtable. + */ +void lttng_ht_get_next(struct lttng_ht *ht, struct lttng_ht_iter *iter) +{ + assert(ht); + assert(ht->ht); + assert(iter); + + cds_lfht_next(ht->ht, &iter->iter); +} + +/* + * Return the number of nodes in the hashtable. + */ +unsigned long lttng_ht_get_count(struct lttng_ht *ht) +{ + long scb, sca; + unsigned long count; + + assert(ht); + assert(ht->ht); + + cds_lfht_count_nodes(ht->ht, &scb, &count, &sca); + + return count; +} + +/* + * Return lttng ht string node from iterator. + */ +struct lttng_ht_node_str *lttng_ht_iter_get_node_str( + struct lttng_ht_iter *iter) +{ + struct cds_lfht_node *node; + + assert(iter); + node = cds_lfht_iter_get_node(&iter->iter); + if (!node) { + return NULL; + } + return caa_container_of(node, struct lttng_ht_node_str, node); +} + +/* + * Return lttng ht unsigned long node from iterator. + */ +struct lttng_ht_node_ulong *lttng_ht_iter_get_node_ulong( + struct lttng_ht_iter *iter) +{ + struct cds_lfht_node *node; + + assert(iter); + node = cds_lfht_iter_get_node(&iter->iter); + if (!node) { + return NULL; + } + return caa_container_of(node, struct lttng_ht_node_ulong, node); +}