From 85b587f07c754bd2399fb227c6ea79509502d38c Mon Sep 17 00:00:00 2001 From: Vijay Bellur Date: Wed, 2 Dec 2009 06:08:56 +0000 Subject: Add support in rbthash to make use of user provided mempool. Signed-off-by: Vijay Bellur Signed-off-by: Anand V. Avati BUG: 221 (stat prefetch implementation) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=221 --- libglusterfs/src/rbthash.c | 52 ++++++++++++--- libglusterfs/src/rbthash.h | 5 +- .../performance/stat-prefetch/src/stat-prefetch.c | 78 ++++++++++++++++++---- .../performance/stat-prefetch/src/stat-prefetch.h | 7 ++ 4 files changed, 118 insertions(+), 24 deletions(-) diff --git a/libglusterfs/src/rbthash.c b/libglusterfs/src/rbthash.c index 3b0f4ed4fcf..1c6294872b5 100644 --- a/libglusterfs/src/rbthash.c +++ b/libglusterfs/src/rbthash.c @@ -78,9 +78,20 @@ err: return ret; } +/* + * rbthash_table_init - Initialize a RBT based hash table + * @buckets - Number of buckets in the hash table + * @hfunc - hashing function + * @dfunc - destroyer for data in the RBT + * @expected_entries - Number of entries expected in RBT. Mutually exclusive + * with entrypool. + * @entrypool - Memory pool in lieu of expected_entries. + */ rbthash_table_t * -rbthash_table_init (int buckets, rbt_hasher_t hfunc, rbt_data_destroyer_t dfunc) +rbthash_table_init (int buckets, rbt_hasher_t hfunc, + rbt_data_destroyer_t dfunc, unsigned long expected_entries, + struct mem_pool *entrypool) { rbthash_table_t *newtab = NULL; int ret = -1; @@ -90,6 +101,19 @@ rbthash_table_init (int buckets, rbt_hasher_t hfunc, rbt_data_destroyer_t dfunc) return NULL; } + if (!entrypool && !expected_entries) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, + "Both mem-pool and expected entries not provided"); + return NULL; + } + + if (entrypool && expected_entries) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, + "Both mem-pool and expected entries are provided"); + return NULL; + } + + newtab = CALLOC (1, sizeof (*newtab)); if (!newtab) return NULL; @@ -100,10 +124,17 @@ rbthash_table_init (int buckets, rbt_hasher_t hfunc, rbt_data_destroyer_t dfunc) goto free_newtab; } - newtab->entrypool = mem_pool_new (rbthash_entry_t, GF_RBTHASH_MEMPOOL); - if (!newtab->entrypool) { - gf_log (GF_RBTHASH, GF_LOG_ERROR,"Failed to allocate mem-pool"); - goto free_buckets; + if (expected_entries) { + newtab->entrypool = + mem_pool_new (rbthash_entry_t, expected_entries); + if (!newtab->entrypool) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, + "Failed to allocate mem-pool"); + goto free_buckets; + } + newtab->pool_alloced = _gf_true; + } else { + newtab->entrypool = entrypool; } LOCK_INIT (&newtab->tablelock); @@ -112,13 +143,16 @@ rbthash_table_init (int buckets, rbt_hasher_t hfunc, rbt_data_destroyer_t dfunc) if (ret == -1) { gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to init buckets"); - mem_pool_destroy (newtab->entrypool); - } else + if (newtab->pool_alloced) + mem_pool_destroy (newtab->entrypool); + } else { gf_log (GF_RBTHASH, GF_LOG_TRACE, "Inited hash table: buckets:" " %d", buckets); + } newtab->hashfunc = hfunc; newtab->dfunc = dfunc; + free_buckets: if (ret == -1) FREE (newtab->buckets); @@ -132,7 +166,6 @@ free_newtab: return newtab; } - rbthash_entry_t * rbthash_init_entry (rbthash_table_t *tbl, void *data, void *key, int keylen) { @@ -379,7 +412,8 @@ rbthash_table_destroy (rbthash_table_t *tbl) return; rbthash_table_destroy_buckets (tbl); - mem_pool_destroy (tbl->entrypool); + if (tbl->pool_alloced) + mem_pool_destroy (tbl->entrypool); FREE (tbl->buckets); FREE (tbl); diff --git a/libglusterfs/src/rbthash.h b/libglusterfs/src/rbthash.h index 5bfa6afd0ef..3f6d788f4cb 100644 --- a/libglusterfs/src/rbthash.h +++ b/libglusterfs/src/rbthash.h @@ -23,6 +23,7 @@ #include "locking.h" #include "mem-pool.h" #include "logging.h" +#include "common-utils.h" #include @@ -52,11 +53,13 @@ typedef struct rbthash_table { struct rbthash_bucket *buckets; rbt_hasher_t hashfunc; rbt_data_destroyer_t dfunc; + gf_boolean_t pool_alloced; } rbthash_table_t; extern rbthash_table_t * rbthash_table_init (int buckets, rbt_hasher_t hfunc, - rbt_data_destroyer_t dfunc); + rbt_data_destroyer_t dfunc, unsigned long expected_entries, + struct mem_pool *entrypool); extern int rbthash_insert (rbthash_table_t *tbl, void *data, void *key, int keylen); diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.c b/xlators/performance/stat-prefetch/src/stat-prefetch.c index 258d92c68ff..a9934bb1544 100644 --- a/xlators/performance/stat-prefetch/src/stat-prefetch.c +++ b/xlators/performance/stat-prefetch/src/stat-prefetch.c @@ -19,8 +19,8 @@ #include "stat-prefetch.h" -#define GF_SP_CACHE_BUCKETS 4096 - +#define GF_SP_CACHE_BUCKETS 1 +#define GF_SP_CACHE_ENTRIES_EXPECTED 1048576 sp_cache_t * sp_cache_ref (sp_cache_t *cache) @@ -164,15 +164,25 @@ sp_hashfn (void *data, int len) } sp_cache_t * -sp_cache_init (void) +sp_cache_init (xlator_t *this) { - sp_cache_t *cache = NULL; + sp_cache_t *cache = NULL; + sp_private_t *priv = NULL; + + priv = this->private; + + if (!priv) + goto out; + + if (!priv->mem_pool) + goto out; + cache = CALLOC (1, sizeof (*cache)); if (cache) { cache->table = rbthash_table_init (GF_SP_CACHE_BUCKETS, - sp_hashfn, - free); + sp_hashfn, free, + 0, priv->mem_pool); if (cache->table == NULL) { FREE (cache); cache = NULL; @@ -180,6 +190,7 @@ sp_cache_init (void) } LOCK_INIT (&cache->lock); + cache->this = this; } out: @@ -202,18 +213,32 @@ sp_cache_remove_entry (sp_cache_t *cache, char *name, char remove_all) { int32_t ret = -1; rbthash_table_t *table = NULL; + xlator_t *this; + sp_private_t *priv = NULL; if ((cache == NULL) || ((name == NULL) && !remove_all)) { goto out; } + this = cache->this; + + if (this == NULL) + goto out; + + if (this->private == NULL) + goto out; + + priv = this->private; + LOCK (&cache->lock); { if (remove_all) { table = cache->table; cache->table = rbthash_table_init (GF_SP_CACHE_BUCKETS, sp_hashfn, - free); + free, + 0, + priv->mem_pool); if (cache->table == NULL) { cache->table = table; } else { @@ -1001,16 +1026,21 @@ int32_t sp_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, gf_dirent_t *entries) { - sp_local_t *local = NULL; - sp_cache_t *cache = NULL; - fd_t *fd = NULL; - int32_t ret = 0; - char was_present = 1; + sp_local_t *local = NULL; + sp_cache_t *cache = NULL; + fd_t *fd = NULL; + int32_t ret = 0; + char was_present = 1; + sp_private_t *priv = NULL; if (op_ret == -1) { goto out; } + if (!this->private) { + goto out; + } + local = frame->local; if (local == NULL) { goto out; @@ -1018,12 +1048,25 @@ sp_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, fd = local->fd; + priv = this->private; + + LOCK (&priv->lock); + { + if (!priv->mem_pool) + priv->mem_pool = mem_pool_new (rbthash_entry_t, + GF_SP_CACHE_ENTRIES_EXPECTED); + } + UNLOCK (&priv->lock); + + if (!priv->mem_pool) + goto out; + LOCK (&fd->lock); { cache = __sp_get_cache_fd (this, fd); if (cache == NULL) { was_present = 0; - cache = sp_cache_init (); + cache = sp_cache_init (this); if (cache == NULL) { goto unlock; } @@ -4029,7 +4072,9 @@ sp_release (xlator_t *this, fd_t *fd) int32_t init (xlator_t *this) { - int32_t ret = -1; + int32_t ret = -1; + sp_private_t *priv = NULL; + if (!this->children || this->children->next) { gf_log ("stat-prefetch", GF_LOG_ERROR, @@ -4038,6 +4083,11 @@ init (xlator_t *this) goto out; } + priv = CALLOC (1, sizeof(sp_private_t)); + LOCK_INIT (&priv->lock); + + this->private = priv; + ret = 0; out: return ret; diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.h b/xlators/performance/stat-prefetch/src/stat-prefetch.h index 0e935330335..2a251e346c2 100644 --- a/xlators/performance/stat-prefetch/src/stat-prefetch.h +++ b/xlators/performance/stat-prefetch/src/stat-prefetch.h @@ -44,6 +44,7 @@ struct sp_cache { unsigned long miss; unsigned long hits; uint32_t ref; + xlator_t *this; }; typedef struct sp_cache sp_cache_t; @@ -77,6 +78,12 @@ struct sp_local { }; typedef struct sp_local sp_local_t; +struct sp_private { + struct mem_pool *mem_pool; + gf_lock_t lock; +}; +typedef struct sp_private sp_private_t; + void sp_local_free (sp_local_t *local); -- cgit