summaryrefslogtreecommitdiff
path: root/lib/hashtable.c
diff options
context:
space:
mode:
authorroopa <roopa@cumulusnetworks.com>2012-11-09 14:41:32 -0800
committerThomas Graf <tgraf@redhat.com>2012-11-10 00:12:36 +0100
commitc6f89ed02f04ac4984be34418774a7b06ff54f79 (patch)
tree4e8197ac2af4e9199180aa961483e31c5a3885df /lib/hashtable.c
parenta8741fab8e48e55fe10cfb080ba4b28ed4441fb0 (diff)
downloadlibnl-c6f89ed02f04ac4984be34418774a7b06ff54f79.tar.gz
Add nl hashtable structures and access functions
This patch adds the required structures and access functions to create and manage hashtables for netlink cache objects 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>
Diffstat (limited to 'lib/hashtable.c')
-rw-r--r--lib/hashtable.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/lib/hashtable.c b/lib/hashtable.c
new file mode 100644
index 0000000..59cd91e
--- /dev/null
+++ b/lib/hashtable.c
@@ -0,0 +1,141 @@
+/*
+ * netlink/hashtable.c Netlink hashtable Utilities
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2012 Cumulus Networks, Inc
+ */
+#include <string.h>
+#include <netlink-local.h>
+#include <netlink/object.h>
+#include <netlink/hash.h>
+#include <netlink/hashtable.h>
+
+nl_hash_table_t *nl_hash_table_alloc(int size)
+{
+ nl_hash_table_t *ht;
+
+ ht = calloc(1, sizeof (*ht));
+ if (!ht)
+ goto errout;
+
+ ht->nodes = calloc(size, sizeof (*ht->nodes));
+ if (!ht->nodes) {
+ free(ht);
+ goto errout;
+ }
+
+ ht->size = size;
+
+ return ht;
+errout:
+ return NULL;
+}
+
+void nl_hash_table_free(nl_hash_table_t *ht)
+{
+ int i;
+
+ for(i = 0; i < ht->size; i++) {
+ nl_hash_node_t *node = ht->nodes[i];
+ nl_hash_node_t *saved_node;
+
+ while (node) {
+ saved_node = node;
+ node = node->next;
+ free(saved_node);
+ }
+ }
+
+ free(ht->nodes);
+ free(ht);
+}
+
+struct nl_object* nl_hash_table_lookup(nl_hash_table_t *ht,
+ struct nl_object *obj)
+{
+ nl_hash_node_t *node;
+ uint32_t key_hash;
+
+ nl_object_keygen(obj, &key_hash, ht->size);
+ node = ht->nodes[key_hash];
+
+ while (node) {
+ if (nl_object_identical(node->obj, obj))
+ return node->obj;
+ node = node->next;
+ }
+
+ return NULL;
+}
+
+int nl_hash_table_add(nl_hash_table_t *ht, struct nl_object *obj)
+{
+ nl_hash_node_t *node;
+ uint32_t key_hash;
+
+ nl_object_keygen(obj, &key_hash, ht->size);
+ node = ht->nodes[key_hash];
+
+ while (node) {
+ if (nl_object_identical(node->obj, obj)) {
+ NL_DBG(2, "Warning: Add to hashtable found duplicate...\n");
+ return -NLE_EXIST;
+ }
+ node = node->next;
+ }
+
+ NL_DBG (5, "adding cache entry of obj %p in table %p, with hash 0x%x\n",
+ obj, ht, key_hash);
+
+ node = malloc(sizeof(nl_hash_node_t));
+ if (!node)
+ return -NLE_NOMEM;
+ nl_object_get(obj);
+ node->obj = obj;
+ node->key = key_hash;
+ node->key_size = sizeof(uint32_t);
+ node->next = ht->nodes[key_hash];
+ ht->nodes[key_hash] = node;
+
+ return 0;
+}
+
+int nl_hash_table_del(nl_hash_table_t *ht, struct nl_object *obj)
+{
+ nl_hash_node_t *node, *prev;
+ uint32_t key_hash;
+
+ nl_object_keygen(obj, &key_hash, ht->size);
+ prev = node = ht->nodes[key_hash];
+
+ while (node) {
+ if (nl_object_identical(node->obj, obj)) {
+ nl_object_put(obj);
+
+ NL_DBG (5, "deleting cache entry of obj %p in table %p, with"
+ " hash 0x%x\n", obj, ht, key_hash);
+
+ if (node == ht->nodes[key_hash])
+ ht->nodes[key_hash] = node->next;
+ else
+ prev->next = node->next;
+
+ free(node);
+
+ return 0;
+ }
+ prev = node;
+ node = node->next;
+ }
+
+ return -1;
+}
+
+uint32_t nl_hash(void *k, size_t length, uint32_t initval)
+{
+ return(hash(k, length, initval));
+}