diff options
Diffstat (limited to 'libglusterfs/src/rbthash.c')
| -rw-r--r-- | libglusterfs/src/rbthash.c | 78 |
1 files changed, 55 insertions, 23 deletions
diff --git a/libglusterfs/src/rbthash.c b/libglusterfs/src/rbthash.c index 3a45d9fb6..0d7b9e521 100644 --- a/libglusterfs/src/rbthash.c +++ b/libglusterfs/src/rbthash.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> This file is part of GlusterFS. - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ @@ -124,7 +115,6 @@ rbthash_table_init (int buckets, rbt_hasher_t hfunc, newtab->buckets = GF_CALLOC (buckets, sizeof (struct rbthash_bucket), gf_common_mt_rbthash_bucket); if (!newtab->buckets) { - gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to allocate memory"); goto free_newtab; } @@ -142,6 +132,7 @@ rbthash_table_init (int buckets, rbt_hasher_t hfunc, } LOCK_INIT (&newtab->tablelock); + INIT_LIST_HEAD (&newtab->list); newtab->numbuckets = buckets; ret = __rbthash_init_buckets (newtab, buckets); @@ -189,10 +180,10 @@ rbthash_init_entry (rbthash_table_t *tbl, void *data, void *key, int keylen) entry->data = data; entry->key = GF_CALLOC (keylen, sizeof (char), gf_common_mt_char); if (!entry->key) { - gf_log (GF_RBTHASH, GF_LOG_ERROR, "Memory allocation failed"); goto free_entry; } + INIT_LIST_HEAD (&entry->list); memcpy (entry->key, key, keylen); entry->keylen = keylen; entry->keyhash = tbl->hashfunc (entry->key, entry->keylen); @@ -201,7 +192,7 @@ rbthash_init_entry (rbthash_table_t *tbl, void *data, void *key, int keylen) ret = 0; free_entry: if (ret == -1) { - mem_put (tbl->entrypool, entry); + mem_put (entry); entry = NULL; } @@ -217,20 +208,26 @@ rbthash_deinit_entry (rbthash_table_t *tbl, rbthash_entry_t *entry) if (!entry) return; - if (entry->key) - GF_FREE (entry->key); + GF_FREE (entry->key); if (tbl) { if ((entry->data) && (tbl->dfunc)) tbl->dfunc (entry->data); - mem_put (tbl->entrypool, entry); + + LOCK (&tbl->tablelock); + { + list_del_init (&entry->list); + } + UNLOCK (&tbl->tablelock); + + mem_put (entry); } return; } -inline struct rbthash_bucket * +static inline struct rbthash_bucket * rbthash_entry_bucket (rbthash_table_t *tbl, rbthash_entry_t * entry) { int nbucket = 0; @@ -294,11 +291,17 @@ rbthash_insert (rbthash_table_t *tbl, void *data, void *key, int keylen) rbthash_deinit_entry (tbl, entry); } + LOCK (&tbl->tablelock); + { + list_add_tail (&entry->list, &tbl->list); + } + UNLOCK (&tbl->tablelock); + err: return ret; } -inline struct rbthash_bucket * +static inline struct rbthash_bucket * rbthash_key_bucket (rbthash_table_t *tbl, void *key, int keylen) { uint32_t keyhash = 0; @@ -378,7 +381,14 @@ rbthash_remove (rbthash_table_t *tbl, void *key, int keylen) GF_FREE (entry->key); dataref = entry->data; - mem_put (tbl->entrypool, entry); + + LOCK (&tbl->tablelock); + { + list_del_init (&entry->list); + } + UNLOCK (&tbl->tablelock); + + mem_put (entry); return dataref; } @@ -424,3 +434,25 @@ rbthash_table_destroy (rbthash_table_t *tbl) GF_FREE (tbl); } + +void +rbthash_table_traverse (rbthash_table_t *tbl, rbt_traverse_t traverse, + void *mydata) +{ + rbthash_entry_t *entry = NULL; + + if ((tbl == NULL) || (traverse == NULL)) { + goto out; + } + + LOCK (&tbl->tablelock); + { + list_for_each_entry (entry, &tbl->list, list) { + traverse (entry->data, mydata); + } + } + UNLOCK (&tbl->tablelock); + +out: + return; +} |
