summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroopa <roopa@cumulusnetworks.com>2012-11-09 14:41:33 -0800
committerThomas Graf <tgraf@redhat.com>2012-11-10 00:12:44 +0100
commit55c0e036b04b567a81cca441117b4e2ce5e22ef2 (patch)
treeddfde923c8b6fb5a0492546429f049cf29b5b956
parentc6f89ed02f04ac4984be34418774a7b06ff54f79 (diff)
downloadlibnl-55c0e036b04b567a81cca441117b4e2ce5e22ef2.tar.gz
Add hash support in cache mngr
This patch adds support to create, delete modify hash table for a cache Signed-off-by: Shrijeet Mukherjee <shm@cumulusnetworks.com> Signed-off-by: Nolan Leake <nolan@cumulusnetworks.com> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com> Reviewed-by: Wilson Kok <wkok@cumulusnetworks.com> Signed-off-by: Thomas Graf <tgraf@suug.ch>
-rw-r--r--include/netlink-types.h2
-rw-r--r--include/netlink/cache-api.h3
-rw-r--r--include/netlink/cache.h2
-rw-r--r--lib/cache.c71
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);