[PATCH v2 3/6] Add hash support in cache mngr

roopa at cumulusnetworks.com roopa at cumulusnetworks.com
Fri Nov 9 17:41:33 EST 2012


From: roopa <roopa at cumulusnetworks.com>

This patch adds support to create, delete modify hash table for a cache

Signed-off-by: Shrijeet Mukherjee <shm at cumulusnetworks.com>
Signed-off-by: Nolan Leake <nolan at cumulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa at cumulusnetworks.com>
Reviewed-by: Wilson Kok <wkok at cumulusnetworks.com>
---
 include/netlink-types.h     |    2 +
 include/netlink/cache-api.h |    3 ++
 include/netlink/cache.h     |    2 +
 lib/cache.c                 |   71 +++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/include/netlink-types.h b/include/netlink-types.h
index 23930b8..0be58d1 100644
--- a/include/netlink-types.h
+++ b/include/netlink-types.h
@@ -30,6 +30,7 @@
 struct nl_cache_ops;
 struct nl_sock;
 struct nl_object;
+struct nl_hash_table;
 
 struct nl_cb
 {
@@ -78,6 +79,7 @@ struct nl_cache
 	int			c_nitems;
 	int                     c_iarg1;
 	int                     c_iarg2;
+	struct nl_hash_table *	hashtable;
 	struct nl_cache_ops *   c_ops;
 };
 
diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h
index 390cbea..aa5eeb6 100644
--- a/include/netlink/cache-api.h
+++ b/include/netlink/cache-api.h
@@ -186,6 +186,9 @@ struct nl_cache_ops
 	/** Netlink protocol */
 	int			co_protocol;
 
+	/** cache object hash size **/
+	int			co_hash_size;
+
 	/** Group definition */
 	struct nl_af_group *	co_groups;
 	
diff --git a/include/netlink/cache.h b/include/netlink/cache.h
index fd137e1..c919e6b 100644
--- a/include/netlink/cache.h
+++ b/include/netlink/cache.h
@@ -71,6 +71,8 @@ extern void			nl_cache_set_arg2(struct nl_cache *, int);
 extern int			nl_cache_is_empty(struct nl_cache *);
 extern struct nl_object *	nl_cache_search(struct nl_cache *,
 						struct nl_object *);
+extern struct nl_object *	nl_cache_lookup(struct nl_cache *,
+						struct nl_object *);
 extern void			nl_cache_mark_all(struct nl_cache *);
 
 /* Dumping */
diff --git a/lib/cache.c b/lib/cache.c
index f73fedf..af4ee95 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -53,6 +53,7 @@
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/object.h>
+#include <netlink/hashtable.h>
 #include <netlink/utils.h>
 
 /**
@@ -190,6 +191,22 @@ struct nl_cache *nl_cache_alloc(struct nl_cache_ops *ops)
 	nl_init_list_head(&cache->c_items);
 	cache->c_ops = ops;
 
+	/*
+	 * If object type provides a hash keygen
+	 * functions, allocate a hash table for the
+	 * cache objects for faster lookups
+	 */
+	if (ops->co_obj_ops->oo_keygen) {
+		int hashtable_size;
+
+		if (ops->co_hash_size)
+			hashtable_size = ops->co_hash_size;
+		else
+			hashtable_size = NL_MAX_HASH_ENTRIES;
+
+		cache->hashtable = nl_hash_table_alloc(hashtable_size);
+	}
+
 	NL_DBG(2, "Allocated cache %p <%s>.\n", cache, nl_cache_name(cache));
 
 	return cache;
@@ -362,6 +379,10 @@ void nl_cache_free(struct nl_cache *cache)
 		return;
 
 	nl_cache_clear(cache);
+
+	if (cache->hashtable)
+		nl_hash_table_free(cache->hashtable);
+
 	NL_DBG(1, "Freeing cache %p <%s>...\n", cache, nl_cache_name(cache));
 	free(cache);
 }
@@ -375,8 +396,18 @@ void nl_cache_free(struct nl_cache *cache)
 
 static int __cache_add(struct nl_cache *cache, struct nl_object *obj)
 {
+	int ret;
+
 	obj->ce_cache = cache;
 
+	if (cache->hashtable) {
+		ret = nl_hash_table_add(cache->hashtable, obj);
+		if (ret < 0) {
+			obj->ce_cache = NULL;
+			return ret;
+		}
+	}
+
 	nl_list_add_tail(&obj->ce_list, &cache->c_items);
 	cache->c_nitems++;
 
@@ -411,6 +442,7 @@ static int __cache_add(struct nl_cache *cache, struct nl_object *obj)
 int nl_cache_add(struct nl_cache *cache, struct nl_object *obj)
 {
 	struct nl_object *new;
+	int ret = 0;
 
 	if (cache->c_ops->co_obj_ops != obj->ce_ops)
 		return -NLE_OBJ_MISMATCH;
@@ -424,7 +456,11 @@ int nl_cache_add(struct nl_cache *cache, struct nl_object *obj)
 		new = obj;
 	}
 
-	return __cache_add(cache, new);
+	ret = __cache_add(cache, new);
+	if (ret < 0)
+		nl_object_put(new);
+
+	return ret;
 }
 
 /**
@@ -474,11 +510,19 @@ int nl_cache_move(struct nl_cache *cache, struct nl_object *obj)
  */
 void nl_cache_remove(struct nl_object *obj)
 {
+	int ret;
 	struct nl_cache *cache = obj->ce_cache;
 
 	if (cache == NULL)
 		return;
 
+	if (cache->hashtable) {
+		ret = nl_hash_table_del(cache->hashtable, obj);
+		if (ret < 0)
+			NL_DBG(3, "Failed to delete %p from cache %p <%s>.\n",
+			       obj, cache, nl_cache_name(cache));
+	}
+
 	nl_list_del(&obj->ce_list);
 	obj->ce_cache = NULL;
 	nl_object_put(obj);
@@ -566,8 +610,13 @@ struct update_xdata {
 static int update_msg_parser(struct nl_msg *msg, void *arg)
 {
 	struct update_xdata *x = arg;
-	
-	return nl_cache_parse(x->ops, &msg->nm_src, msg->nm_nlh, x->params);
+	int ret = 0;
+
+	ret = nl_cache_parse(x->ops, &msg->nm_src, msg->nm_nlh, x->params);
+	if (ret == -NLE_EXIST)
+		return NL_SKIP;
+	else
+		return ret;
 }
 /** @endcond */
 
@@ -842,6 +891,19 @@ restart:
  * @name Utillities
  * @{
  */
+static struct nl_object *__cache_fast_lookup(struct nl_cache *cache,
+					     struct nl_object *needle)
+{
+	struct nl_object *obj;
+
+	obj = nl_hash_table_lookup(cache->hashtable, needle);
+	if (obj) {
+	    nl_object_get(obj);
+	    return obj;
+	}
+
+	return NULL;
+}
 
 /**
  * Search object in cache
@@ -863,6 +925,9 @@ struct nl_object *nl_cache_search(struct nl_cache *cache,
 {
 	struct nl_object *obj;
 
+	if (cache->hashtable)
+		return __cache_fast_lookup(cache, needle);
+
 	nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
 		if (nl_object_identical(obj, needle)) {
 			nl_object_get(obj);
-- 
1.7.2.5




More information about the libnl mailing list