]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/hash.h
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / lib / hash.h
index 6ce29f0426dc6ff70afad24d8c0699b8b4988074..45ae6ce60a104ec82ed178e5be08152a59f17686 100644 (file)
@@ -28,16 +28,18 @@ DECLARE_MTYPE(HASH)
 DECLARE_MTYPE(HASH_BACKET)
 
 /* Default hash table size.  */
-#define HASH_INITIAL_SIZE     256      /* initial number of backets. */
-#define HASH_THRESHOLD       10        /* expand when backet. */
+#define HASH_INITIAL_SIZE 256
+/* Expansion threshold */
+#define HASH_THRESHOLD(used, size) ((used) > (size))
 
 #define HASHWALK_CONTINUE 0
 #define HASHWALK_ABORT -1
 
 struct hash_backet {
-       /* if this backet is the head of the linked listed, len denotes the
-        * number of
-        * elements in the list */
+       /*
+        * if this backet is the head of the linked listed, len denotes the
+        * number of elements in the list
+        */
        int len;
 
        /* Linked list.  */
@@ -64,11 +66,14 @@ struct hash {
        /* Hash table size. Must be power of 2 */
        unsigned int size;
 
+       /* If max_size is 0 there is no limit */
+       unsigned int max_size;
+
        /* Key make function. */
        unsigned int (*hash_key)(void *);
 
        /* Data compare function. */
-       int (*hash_cmp)(const void *, const void *);
+       bool (*hash_cmp)(const void *, const void *);
 
        /* Backet alloc. */
        unsigned long count;
@@ -81,29 +86,243 @@ struct hash {
 
 #define hashcount(X) ((X)->count)
 
-extern struct hash *hash_create(unsigned int (*)(void *),
-                               int (*)(const void *, const void *),
-                               const char *);
-extern struct hash *hash_create_size(unsigned int, unsigned int (*)(void *),
-                                    int (*)(const void *, const void *),
-                                    const char *);
+/*
+ * Create a hash table.
+ *
+ * The created hash table uses chaining and a user-provided comparator function
+ * to resolve collisions. For best performance use a perfect hash function.
+ * Worst case lookup time is O(N) when using a constant hash function. Best
+ * case lookup time is O(1) when using a perfect hash function.
+ *
+ * The initial size of the created hash table is HASH_INITIAL_SIZE.
+ *
+ * hash_key
+ *    hash function to use; should return a unique unsigned integer when called
+ *    with a data item. Collisions are acceptable.
+ *
+ * hash_cmp
+ *    comparison function used for resolving collisions; when called with two
+ *    data items, should return nonzero if the two items are equal and 0
+ *    otherwise
+ *
+ * name
+ *    optional name for the hashtable; this is used when displaying global
+ *    hashtable statistics. If this parameter is NULL the hash's name will be
+ *    set to NULL and the default name will be displayed when showing
+ *    statistics.
+ *
+ * Returns:
+ *    a new hash table
+ */
+extern struct hash *hash_create(unsigned int (*hash_key)(void *),
+                               bool (*hash_cmp)(const void *, const void *),
+                               const char *name);
 
-extern void *hash_get(struct hash *, void *, void *(*)(void *));
-extern void *hash_alloc_intern(void *);
-extern void *hash_lookup(struct hash *, void *);
-extern void *hash_release(struct hash *, void *);
+/*
+ * Create a hash table.
+ *
+ * The created hash table uses chaining and a user-provided comparator function
+ * to resolve collisions. For best performance use a perfect hash function.
+ * Worst case lookup time is O(N) when using a constant hash function. Best
+ * case lookup time is O(1) when using a perfect hash function.
+ *
+ * size
+ *    initial number of hash buckets to allocate; must be a power of 2 or the
+ *    program will assert
+ *
+ * hash_key
+ *    hash function to use; should return a unique unsigned integer when called
+ *    with a data item. Collisions are acceptable.
+ *
+ * hash_cmp
+ *    comparison function used for resolving collisions; when called with two
+ *    data items, should return nonzero if the two items are equal and 0
+ *    otherwise
+ *
+ * name
+ *    optional name for the hashtable; this is used when displaying global
+ *    hashtable statistics. If this parameter is NULL the hash's name will be
+ *    set to NULL and the default name will be displayed when showing
+ *    statistics.
+ *
+ * Returns:
+ *    a new hash table
+ */
+extern struct hash *
+hash_create_size(unsigned int size, unsigned int (*hash_key)(void *),
+                bool (*hash_cmp)(const void *, const void *),
+                const char *name);
 
-extern void hash_iterate(struct hash *, void (*)(struct hash_backet *, void *),
-                        void *);
+/*
+ * Retrieve or insert data from / into a hash table.
+ *
+ * This function is somewhat counterintuitive in its usage. In order to look up
+ * an element from its key, you must provide the data item itself, with the
+ * portions used in the hash function set to the same values as the data item
+ * to retrieve. To insert a data element, either provide the key as just
+ * described and provide alloc_func as descrbied below to allocate the full
+ * data element, or provide the full data element and pass 'hash_alloc_intern'
+ * to alloc_func.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * data
+ *    data to insert or retrieve - A hash backet will not be created if
+ *    the alloc_func returns a NULL pointer and nothing will be added to
+ *    the hash.  As such backet->data will always be non-NULL.
+ *
+ * alloc_func
+ *    function to call if the item is not found in the hash table. This
+ *    function is called with the value of 'data' and should create the data
+ *    item to insert and return a pointer to it. If the data has already been
+ *    completely created and provided in the 'data' parameter, passing
+ *    'hash_alloc_intern' to this parameter will cause 'data' to be inserted.
+ *    If this parameter is NULL, then this call to hash_get is equivalent to
+ *    hash_lookup.
+ *
+ * Returns:
+ *    the data item found or inserted, or NULL if alloc_func is NULL and the
+ *    data is not found
+ */
+extern void *hash_get(struct hash *hash, void *data,
+                     void *(*alloc_func)(void *));
 
-extern void hash_walk(struct hash *, int (*)(struct hash_backet *, void *),
-                     void *);
+/*
+ * Dummy element allocation function.
+ *
+ * See hash_get for details.
+ *
+ * data
+ *    data to insert into the hash table
+ *
+ * Returns:
+ *    data
+ */
+extern void *hash_alloc_intern(void *data);
 
-extern void hash_clean(struct hash *, void (*)(void *));
-extern void hash_free(struct hash *);
+/*
+ * Retrieve an item from a hash table.
+ *
+ * This function is equivalent to calling hash_get with alloc_func set to NULL.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * data
+ *    data element with values used for key computation set
+ *
+ * Returns:
+ *    the data element if found, or NULL if not found
+ */
+extern void *hash_lookup(struct hash *hash, void *data);
 
+/*
+ * Remove an element from a hash table.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * data
+ *    data element to remove with values used for key computation set
+ *
+ * Returns:
+ *    the removed element if found, or NULL if not found
+ */
+extern void *hash_release(struct hash *hash, void *data);
+
+/*
+ * Iterate over the elements in a hash table.
+ *
+ * It is safe to delete items passed to the iteration function from the hash
+ * table during iteration.  Please note that adding entries to the hash
+ * during the walk will cause undefined behavior in that some new entries
+ * will be walked and some will not.  So do not do this.
+ *
+ * The backet passed to func will have a non-NULL data pointer.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * func
+ *    function to call with each data item
+ *
+ * arg
+ *    arbitrary argument passed as the second parameter in each call to 'func'
+ */
+extern void hash_iterate(struct hash *hash,
+                        void (*func)(struct hash_backet *, void *), void *arg);
+
+/*
+ * Iterate over the elements in a hash table, stopping on condition.
+ *
+ * It is safe to delete items passed to the iteration function from the hash
+ * table during iteration.  Please note that adding entries to the hash
+ * during the walk will cause undefined behavior in that some new entries
+ * will be walked and some will not.  So do not do this.
+ *
+ * The backet passed to func will have a non-NULL data pointer.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * func
+ *    function to call with each data item. If this function returns
+ *    HASHWALK_ABORT then the iteration stops.
+ *
+ * arg
+ *    arbitrary argument passed as the second parameter in each call to 'func'
+ */
+extern void hash_walk(struct hash *hash,
+                     int (*func)(struct hash_backet *, void *), void *arg);
+
+/*
+ * Remove all elements from a hash table.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * free_func
+ *    function to call with each removed item; intended to free the data
+ */
+extern void hash_clean(struct hash *hash, void (*free_func)(void *));
+
+/*
+ * Delete a hash table.
+ *
+ * This function assumes the table is empty. Call hash_clean to delete the
+ * hashtable contents if necessary.
+ *
+ * hash
+ *    hash table to delete
+ */
+extern void hash_free(struct hash *hash);
+
+/*
+ * Converts a hash table to an unsorted linked list.
+ * Does not modify the hash table in any way.
+ *
+ * hash
+ *    hash table to convert
+ */
+extern struct list *hash_to_list(struct hash *hash);
+
+/*
+ * Hash a string using the modified Bernstein hash.
+ *
+ * This is not a perfect hash function.
+ *
+ * str
+ *    string to hash
+ *
+ * Returns:
+ *    modified Bernstein hash of the string
+ */
 extern unsigned int string_hash_make(const char *);
 
+/*
+ * Install CLI commands for viewing global hash table statistics.
+ */
 extern void hash_cmd_init(void);
 
 #endif /* _ZEBRA_HASH_H */