1ae8c6e27Sflorian /* 2ae8c6e27Sflorian * util/storage/lruhash.h - hashtable, hash function, LRU keeping. 3ae8c6e27Sflorian * 4ae8c6e27Sflorian * Copyright (c) 2007, NLnet Labs. All rights reserved. 5ae8c6e27Sflorian * 6ae8c6e27Sflorian * This software is open source. 7ae8c6e27Sflorian * 8ae8c6e27Sflorian * Redistribution and use in source and binary forms, with or without 9ae8c6e27Sflorian * modification, are permitted provided that the following conditions 10ae8c6e27Sflorian * are met: 11ae8c6e27Sflorian * 12ae8c6e27Sflorian * Redistributions of source code must retain the above copyright notice, 13ae8c6e27Sflorian * this list of conditions and the following disclaimer. 14ae8c6e27Sflorian * 15ae8c6e27Sflorian * Redistributions in binary form must reproduce the above copyright notice, 16ae8c6e27Sflorian * this list of conditions and the following disclaimer in the documentation 17ae8c6e27Sflorian * and/or other materials provided with the distribution. 18ae8c6e27Sflorian * 19ae8c6e27Sflorian * Neither the name of the NLNET LABS nor the names of its contributors may 20ae8c6e27Sflorian * be used to endorse or promote products derived from this software without 21ae8c6e27Sflorian * specific prior written permission. 22ae8c6e27Sflorian * 23ae8c6e27Sflorian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24ae8c6e27Sflorian * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25ae8c6e27Sflorian * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26ae8c6e27Sflorian * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27ae8c6e27Sflorian * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28ae8c6e27Sflorian * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29ae8c6e27Sflorian * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30ae8c6e27Sflorian * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31ae8c6e27Sflorian * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32ae8c6e27Sflorian * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33ae8c6e27Sflorian * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34ae8c6e27Sflorian */ 35ae8c6e27Sflorian 36ae8c6e27Sflorian /** 37ae8c6e27Sflorian * \file 38ae8c6e27Sflorian * 39ae8c6e27Sflorian * This file contains a hashtable with LRU keeping of entries. 40ae8c6e27Sflorian * 41ae8c6e27Sflorian * The hash table keeps a maximum memory size. Old entries are removed 42ae8c6e27Sflorian * to make space for new entries. 43ae8c6e27Sflorian * 44ae8c6e27Sflorian * The locking strategy is as follows: 45ae8c6e27Sflorian * o since (almost) every read also implies a LRU update, the 46ae8c6e27Sflorian * hashtable lock is a spinlock, not rwlock. 47ae8c6e27Sflorian * o the idea is to move every thread through the hash lock quickly, 48ae8c6e27Sflorian * so that the next thread can access the lookup table. 49ae8c6e27Sflorian * o User performs hash function. 50ae8c6e27Sflorian * 51ae8c6e27Sflorian * For read: 52ae8c6e27Sflorian * o lock hashtable. 53ae8c6e27Sflorian * o lookup hash bin. 54ae8c6e27Sflorian * o lock hash bin. 55ae8c6e27Sflorian * o find entry (if failed, unlock hash, unl bin, exit). 56ae8c6e27Sflorian * o swizzle pointers for LRU update. 57ae8c6e27Sflorian * o unlock hashtable. 58ae8c6e27Sflorian * o lock entry (rwlock). 59ae8c6e27Sflorian * o unlock hash bin. 60ae8c6e27Sflorian * o work on entry. 61ae8c6e27Sflorian * o unlock entry. 62ae8c6e27Sflorian * 63ae8c6e27Sflorian * To update an entry, gain writelock and change the entry. 64ae8c6e27Sflorian * (the entry must keep the same hashvalue, so a data update.) 65ae8c6e27Sflorian * (you cannot upgrade a readlock to a writelock, because the item may 66ae8c6e27Sflorian * be deleted, it would cause race conditions. So instead, unlock and 67ae8c6e27Sflorian * relookup it in the hashtable.) 68ae8c6e27Sflorian * 69ae8c6e27Sflorian * To delete an entry: 70ae8c6e27Sflorian * o unlock the entry if you hold the lock already. 71ae8c6e27Sflorian * o lock hashtable. 72ae8c6e27Sflorian * o lookup hash bin. 73ae8c6e27Sflorian * o lock hash bin. 74ae8c6e27Sflorian * o find entry (if failed, unlock hash, unl bin, exit). 75ae8c6e27Sflorian * o remove entry from hashtable bin overflow chain. 76ae8c6e27Sflorian * o unlock hashtable. 77ae8c6e27Sflorian * o lock entry (writelock). 78ae8c6e27Sflorian * o unlock hash bin. 79ae8c6e27Sflorian * o unlock entry (nobody else should be waiting for this lock, 80ae8c6e27Sflorian * since you removed it from hashtable, and you got writelock while 81ae8c6e27Sflorian * holding the hashbinlock so you are the only one.) 82ae8c6e27Sflorian * Note you are only allowed to obtain a lock while holding hashbinlock. 83ae8c6e27Sflorian * o delete entry. 84ae8c6e27Sflorian * 85ae8c6e27Sflorian * The above sequence is: 86ae8c6e27Sflorian * o race free, works with read, write and delete. 87ae8c6e27Sflorian * o but has a queue, imagine someone needing a writelock on an item. 88ae8c6e27Sflorian * but there are still readlocks. The writelocker waits, but holds 89ae8c6e27Sflorian * the hashbinlock. The next thread that comes in and needs the same 90ae8c6e27Sflorian * hashbin will wait for the lock while holding the hashtable lock. 91ae8c6e27Sflorian * thus halting the entire system on hashtable. 92ae8c6e27Sflorian * This is because of the delete protection. 93ae8c6e27Sflorian * Readlocks will be easier on the rwlock on entries. 94ae8c6e27Sflorian * While the writer is holding writelock, similar problems happen with 95ae8c6e27Sflorian * a reader or writer needing the same item. 96ae8c6e27Sflorian * the scenario requires more than three threads. 97ae8c6e27Sflorian * o so the queue length is 3 threads in a bad situation. The fourth is 98ae8c6e27Sflorian * unable to use the hashtable. 99ae8c6e27Sflorian * 100ae8c6e27Sflorian * If you need to acquire locks on multiple items from the hashtable. 101ae8c6e27Sflorian * o you MUST release all locks on items from the hashtable before 102ae8c6e27Sflorian * doing the next lookup/insert/delete/whatever. 103ae8c6e27Sflorian * o To acquire multiple items you should use a special routine that 104ae8c6e27Sflorian * obtains the locks on those multiple items in one go. 105ae8c6e27Sflorian */ 106ae8c6e27Sflorian 107ae8c6e27Sflorian #ifndef UTIL_STORAGE_LRUHASH_H 108ae8c6e27Sflorian #define UTIL_STORAGE_LRUHASH_H 109ae8c6e27Sflorian #include "util/locks.h" 110ae8c6e27Sflorian struct lruhash_bin; 111ae8c6e27Sflorian struct lruhash_entry; 112ae8c6e27Sflorian 113ae8c6e27Sflorian /** default start size for hash arrays */ 114ae8c6e27Sflorian #define HASH_DEFAULT_STARTARRAY 1024 /* entries in array */ 115ae8c6e27Sflorian /** default max memory for hash arrays */ 116ae8c6e27Sflorian #define HASH_DEFAULT_MAXMEM 4*1024*1024 /* bytes */ 117ae8c6e27Sflorian 118ae8c6e27Sflorian /** the type of a hash value */ 119ae8c6e27Sflorian typedef uint32_t hashvalue_type; 120ae8c6e27Sflorian 121ae8c6e27Sflorian /** 122ae8c6e27Sflorian * Type of function that calculates the size of an entry. 123ae8c6e27Sflorian * Result must include the size of struct lruhash_entry. 124ae8c6e27Sflorian * Keys that are identical must also calculate to the same size. 125ae8c6e27Sflorian * size = func(key, data). 126ae8c6e27Sflorian */ 127ae8c6e27Sflorian typedef size_t (*lruhash_sizefunc_type)(void*, void*); 128ae8c6e27Sflorian 129ae8c6e27Sflorian /** type of function that compares two keys. return 0 if equal. */ 130ae8c6e27Sflorian typedef int (*lruhash_compfunc_type)(void*, void*); 131ae8c6e27Sflorian 132ae8c6e27Sflorian /** old keys are deleted. 133ae8c6e27Sflorian * The RRset type has to revoke its ID number, markdel() is used first. 134ae8c6e27Sflorian * This function is called: func(key, userarg) */ 135ae8c6e27Sflorian typedef void (*lruhash_delkeyfunc_type)(void*, void*); 136ae8c6e27Sflorian 137ae8c6e27Sflorian /** old data is deleted. This function is called: func(data, userarg). */ 138ae8c6e27Sflorian typedef void (*lruhash_deldatafunc_type)(void*, void*); 139ae8c6e27Sflorian 140ae8c6e27Sflorian /** mark a key as pending to be deleted (and not to be used by anyone). 141ae8c6e27Sflorian * called: func(key) */ 142ae8c6e27Sflorian typedef void (*lruhash_markdelfunc_type)(void*); 143ae8c6e27Sflorian 144ae8c6e27Sflorian /** 145ae8c6e27Sflorian * Hash table that keeps LRU list of entries. 146ae8c6e27Sflorian */ 147ae8c6e27Sflorian struct lruhash { 148ae8c6e27Sflorian /** lock for exclusive access, to the lookup array */ 149ae8c6e27Sflorian lock_quick_type lock; 150ae8c6e27Sflorian /** the size function for entries in this table */ 151ae8c6e27Sflorian lruhash_sizefunc_type sizefunc; 152ae8c6e27Sflorian /** the compare function for entries in this table. */ 153ae8c6e27Sflorian lruhash_compfunc_type compfunc; 154ae8c6e27Sflorian /** how to delete keys. */ 155ae8c6e27Sflorian lruhash_delkeyfunc_type delkeyfunc; 156ae8c6e27Sflorian /** how to delete data. */ 157ae8c6e27Sflorian lruhash_deldatafunc_type deldatafunc; 158ae8c6e27Sflorian /** how to mark a key pending deletion */ 159ae8c6e27Sflorian lruhash_markdelfunc_type markdelfunc; 160ae8c6e27Sflorian /** user argument for user functions */ 161ae8c6e27Sflorian void* cb_arg; 162ae8c6e27Sflorian 163ae8c6e27Sflorian /** the size of the lookup array */ 164ae8c6e27Sflorian size_t size; 165ae8c6e27Sflorian /** size bitmask - since size is a power of 2 */ 166ae8c6e27Sflorian int size_mask; 167ae8c6e27Sflorian /** lookup array of bins */ 168ae8c6e27Sflorian struct lruhash_bin* array; 169ae8c6e27Sflorian 170ae8c6e27Sflorian /** the lru list, start and end, noncyclical double linked list. */ 171ae8c6e27Sflorian struct lruhash_entry* lru_start; 172ae8c6e27Sflorian /** lru list end item (least recently used) */ 173ae8c6e27Sflorian struct lruhash_entry* lru_end; 174ae8c6e27Sflorian 175ae8c6e27Sflorian /** the number of entries in the hash table. */ 176ae8c6e27Sflorian size_t num; 177ae8c6e27Sflorian /** the amount of space used, roughly the number of bytes in use. */ 178ae8c6e27Sflorian size_t space_used; 179ae8c6e27Sflorian /** the amount of space the hash table is maximally allowed to use. */ 180ae8c6e27Sflorian size_t space_max; 181d500c338Sflorian /** the maximum collisions were detected during the lruhash_insert operations. */ 182d500c338Sflorian size_t max_collisions; 183ae8c6e27Sflorian }; 184ae8c6e27Sflorian 185ae8c6e27Sflorian /** 186ae8c6e27Sflorian * A single bin with a linked list of entries in it. 187ae8c6e27Sflorian */ 188ae8c6e27Sflorian struct lruhash_bin { 189ae8c6e27Sflorian /** 190ae8c6e27Sflorian * Lock for exclusive access to the linked list 191ae8c6e27Sflorian * This lock makes deletion of items safe in this overflow list. 192ae8c6e27Sflorian */ 193ae8c6e27Sflorian lock_quick_type lock; 194ae8c6e27Sflorian /** linked list of overflow entries */ 195ae8c6e27Sflorian struct lruhash_entry* overflow_list; 196ae8c6e27Sflorian }; 197ae8c6e27Sflorian 198ae8c6e27Sflorian /** 199ae8c6e27Sflorian * An entry into the hash table. 200ae8c6e27Sflorian * To change overflow_next you need to hold the bin lock. 201ae8c6e27Sflorian * To change the lru items you need to hold the hashtable lock. 202ae8c6e27Sflorian * This structure is designed as part of key struct. And key pointer helps 203ae8c6e27Sflorian * to get the surrounding structure. Data should be allocated on its own. 204ae8c6e27Sflorian */ 205ae8c6e27Sflorian struct lruhash_entry { 206ae8c6e27Sflorian /** 207ae8c6e27Sflorian * rwlock for access to the contents of the entry 208ae8c6e27Sflorian * Note that it does _not_ cover the lru_ and overflow_ ptrs. 209ae8c6e27Sflorian * Even with a writelock, you cannot change hash and key. 210ae8c6e27Sflorian * You need to delete it to change hash or key. 211ae8c6e27Sflorian */ 212ae8c6e27Sflorian lock_rw_type lock; 213ae8c6e27Sflorian /** next entry in overflow chain. Covered by hashlock and binlock. */ 214ae8c6e27Sflorian struct lruhash_entry* overflow_next; 215ae8c6e27Sflorian /** next entry in lru chain. covered by hashlock. */ 216ae8c6e27Sflorian struct lruhash_entry* lru_next; 217ae8c6e27Sflorian /** prev entry in lru chain. covered by hashlock. */ 218ae8c6e27Sflorian struct lruhash_entry* lru_prev; 219ae8c6e27Sflorian /** hash value of the key. It may not change, until entry deleted. */ 220ae8c6e27Sflorian hashvalue_type hash; 221ae8c6e27Sflorian /** key */ 222ae8c6e27Sflorian void* key; 223ae8c6e27Sflorian /** data */ 224ae8c6e27Sflorian void* data; 225ae8c6e27Sflorian }; 226ae8c6e27Sflorian 227ae8c6e27Sflorian /** 228ae8c6e27Sflorian * Create new hash table. 229ae8c6e27Sflorian * @param start_size: size of hashtable array at start, must be power of 2. 230ae8c6e27Sflorian * @param maxmem: maximum amount of memory this table is allowed to use. 231ae8c6e27Sflorian * @param sizefunc: calculates memory usage of entries. 232ae8c6e27Sflorian * @param compfunc: compares entries, 0 on equality. 233ae8c6e27Sflorian * @param delkeyfunc: deletes key. 234ae8c6e27Sflorian * Calling both delkey and deldata will also free the struct lruhash_entry. 235ae8c6e27Sflorian * Make it part of the key structure and delete it in delkeyfunc. 236ae8c6e27Sflorian * @param deldatafunc: deletes data. 237ae8c6e27Sflorian * @param arg: user argument that is passed to user function calls. 238ae8c6e27Sflorian * @return: new hash table or NULL on malloc failure. 239ae8c6e27Sflorian */ 240ae8c6e27Sflorian struct lruhash* lruhash_create(size_t start_size, size_t maxmem, 241ae8c6e27Sflorian lruhash_sizefunc_type sizefunc, lruhash_compfunc_type compfunc, 242ae8c6e27Sflorian lruhash_delkeyfunc_type delkeyfunc, 243ae8c6e27Sflorian lruhash_deldatafunc_type deldatafunc, void* arg); 244ae8c6e27Sflorian 245ae8c6e27Sflorian /** 246ae8c6e27Sflorian * Delete hash table. Entries are all deleted. 247ae8c6e27Sflorian * @param table: to delete. 248ae8c6e27Sflorian */ 249ae8c6e27Sflorian void lruhash_delete(struct lruhash* table); 250ae8c6e27Sflorian 251ae8c6e27Sflorian /** 252ae8c6e27Sflorian * Clear hash table. Entries are all deleted, while locking them before 253ae8c6e27Sflorian * doing so. At end the table is empty. 254ae8c6e27Sflorian * @param table: to make empty. 255ae8c6e27Sflorian */ 256ae8c6e27Sflorian void lruhash_clear(struct lruhash* table); 257ae8c6e27Sflorian 258ae8c6e27Sflorian /** 259ae8c6e27Sflorian * Insert a new element into the hashtable. 260ae8c6e27Sflorian * If key is already present data pointer in that entry is updated. 261ae8c6e27Sflorian * The space calculation function is called with the key, data. 262ae8c6e27Sflorian * If necessary the least recently used entries are deleted to make space. 263ae8c6e27Sflorian * If necessary the hash array is grown up. 264ae8c6e27Sflorian * 265ae8c6e27Sflorian * @param table: hash table. 266ae8c6e27Sflorian * @param hash: hash value. User calculates the hash. 267ae8c6e27Sflorian * @param entry: identifies the entry. 268ae8c6e27Sflorian * If key already present, this entry->key is deleted immediately. 269ae8c6e27Sflorian * But entry->data is set to NULL before deletion, and put into 270ae8c6e27Sflorian * the existing entry. The data is then freed. 271ae8c6e27Sflorian * @param data: the data. 272ae8c6e27Sflorian * @param cb_override: if not null overrides the cb_arg for the deletefunc. 273ae8c6e27Sflorian */ 274ae8c6e27Sflorian void lruhash_insert(struct lruhash* table, hashvalue_type hash, 275ae8c6e27Sflorian struct lruhash_entry* entry, void* data, void* cb_override); 276ae8c6e27Sflorian 277ae8c6e27Sflorian /** 278ae8c6e27Sflorian * Lookup an entry in the hashtable. 279ae8c6e27Sflorian * At the end of the function you hold a (read/write)lock on the entry. 280ae8c6e27Sflorian * The LRU is updated for the entry (if found). 281ae8c6e27Sflorian * @param table: hash table. 282ae8c6e27Sflorian * @param hash: hash of key. 283ae8c6e27Sflorian * @param key: what to look for, compared against entries in overflow chain. 284ae8c6e27Sflorian * the hash value must be set, and must work with compare function. 285ae8c6e27Sflorian * @param wr: set to true if you desire a writelock on the entry. 286ae8c6e27Sflorian * with a writelock you can update the data part. 287ae8c6e27Sflorian * @return: pointer to the entry or NULL. The entry is locked. 288ae8c6e27Sflorian * The user must unlock the entry when done. 289ae8c6e27Sflorian */ 290ae8c6e27Sflorian struct lruhash_entry* lruhash_lookup(struct lruhash* table, 291ae8c6e27Sflorian hashvalue_type hash, void* key, int wr); 292ae8c6e27Sflorian 293ae8c6e27Sflorian /** 294ae8c6e27Sflorian * Touch entry, so it becomes the most recently used in the LRU list. 295ae8c6e27Sflorian * Caller must hold hash table lock. The entry must be inserted already. 296ae8c6e27Sflorian * @param table: hash table. 297ae8c6e27Sflorian * @param entry: entry to make first in LRU. 298ae8c6e27Sflorian */ 299ae8c6e27Sflorian void lru_touch(struct lruhash* table, struct lruhash_entry* entry); 300ae8c6e27Sflorian 301ae8c6e27Sflorian /** 302ae8c6e27Sflorian * Set the markdelfunction (or NULL) 303ae8c6e27Sflorian */ 304ae8c6e27Sflorian void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md); 305ae8c6e27Sflorian 306*096314feSflorian /** 307*096314feSflorian * Update the size of an element in the hashtable. 308*096314feSflorian * 309*096314feSflorian * @param table: hash table. 310*096314feSflorian * @param cb_override: if not NULL overrides the cb_arg for deletefunc. 311*096314feSflorian * @param diff_size: difference in size to the hash table storage. 312*096314feSflorian * This is newsize - oldsize, a positive number uses more space. 313*096314feSflorian */ 314*096314feSflorian void lruhash_update_space_used(struct lruhash* table, void* cb_override, 315*096314feSflorian int diff_size); 316*096314feSflorian 317ae8c6e27Sflorian /************************* getdns functions ************************/ 318ae8c6e27Sflorian /*** these are used by getdns only and not by unbound. ***/ 319ae8c6e27Sflorian 320ae8c6e27Sflorian /** 321ae8c6e27Sflorian * Demote entry, so it becomes the least recently used in the LRU list. 322ae8c6e27Sflorian * Caller must hold hash table lock. The entry must be inserted already. 323ae8c6e27Sflorian * @param table: hash table. 324ae8c6e27Sflorian * @param entry: entry to make last in LRU. 325ae8c6e27Sflorian */ 326ae8c6e27Sflorian void lru_demote(struct lruhash* table, struct lruhash_entry* entry); 327ae8c6e27Sflorian 328ae8c6e27Sflorian /** 329ae8c6e27Sflorian * Insert a new element into the hashtable, or retrieve the corresponding 330ae8c6e27Sflorian * element of it exits. 331ae8c6e27Sflorian * 332ae8c6e27Sflorian * If key is already present data pointer in that entry is kept. 333ae8c6e27Sflorian * If it is not present, a new entry is created. In that case, 334ae8c6e27Sflorian * the space calculation function is called with the key, data. 335ae8c6e27Sflorian * If necessary the least recently used entries are deleted to make space. 336ae8c6e27Sflorian * If necessary the hash array is grown up. 337ae8c6e27Sflorian * 338ae8c6e27Sflorian * @param table: hash table. 339ae8c6e27Sflorian * @param hash: hash value. User calculates the hash. 340ae8c6e27Sflorian * @param entry: identifies the entry. 341ae8c6e27Sflorian * @param data: the data. 342ae8c6e27Sflorian * @param cb_arg: if not null overrides the cb_arg for the deletefunc. 343ae8c6e27Sflorian * @return: pointer to the existing entry if the key was already present, 344ae8c6e27Sflorian * or to the entry argument if it was not. 345ae8c6e27Sflorian */ 346ae8c6e27Sflorian struct lruhash_entry* lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash, 347ae8c6e27Sflorian struct lruhash_entry* entry, void* data, void* cb_arg); 348ae8c6e27Sflorian 349ae8c6e27Sflorian /************************* Internal functions ************************/ 350ae8c6e27Sflorian /*** these are only exposed for unit tests. ***/ 351ae8c6e27Sflorian 352ae8c6e27Sflorian /** 353ae8c6e27Sflorian * Remove entry from hashtable. Does nothing if not found in hashtable. 354ae8c6e27Sflorian * Delfunc is called for the entry. 355ae8c6e27Sflorian * @param table: hash table. 356ae8c6e27Sflorian * @param hash: hash of key. 357ae8c6e27Sflorian * @param key: what to look for. 358ae8c6e27Sflorian */ 359ae8c6e27Sflorian void lruhash_remove(struct lruhash* table, hashvalue_type hash, void* key); 360ae8c6e27Sflorian 361ae8c6e27Sflorian /** init the hash bins for the table */ 362ae8c6e27Sflorian void bin_init(struct lruhash_bin* array, size_t size); 363ae8c6e27Sflorian 364ae8c6e27Sflorian /** delete the hash bin and entries inside it */ 365ae8c6e27Sflorian void bin_delete(struct lruhash* table, struct lruhash_bin* bin); 366ae8c6e27Sflorian 367ae8c6e27Sflorian /** 368ae8c6e27Sflorian * Find entry in hash bin. You must have locked the bin. 369ae8c6e27Sflorian * @param table: hash table with function pointers. 370ae8c6e27Sflorian * @param bin: hash bin to look into. 371ae8c6e27Sflorian * @param hash: hash value to look for. 372ae8c6e27Sflorian * @param key: key to look for. 373d500c338Sflorian * @param collisions: how many collisions were found during the search. 374ae8c6e27Sflorian * @return: the entry or NULL if not found. 375ae8c6e27Sflorian */ 376ae8c6e27Sflorian struct lruhash_entry* bin_find_entry(struct lruhash* table, 377d500c338Sflorian struct lruhash_bin* bin, hashvalue_type hash, void* key, size_t* collisions); 378ae8c6e27Sflorian 379ae8c6e27Sflorian /** 380ae8c6e27Sflorian * Remove entry from bin overflow chain. 381ae8c6e27Sflorian * You must have locked the bin. 382ae8c6e27Sflorian * @param bin: hash bin to look into. 383ae8c6e27Sflorian * @param entry: entry ptr that needs removal. 384ae8c6e27Sflorian */ 385ae8c6e27Sflorian void bin_overflow_remove(struct lruhash_bin* bin, 386ae8c6e27Sflorian struct lruhash_entry* entry); 387ae8c6e27Sflorian 388ae8c6e27Sflorian /** 389ae8c6e27Sflorian * Split hash bin into two new ones. Based on increased size_mask. 390ae8c6e27Sflorian * Caller must hold hash table lock. 391ae8c6e27Sflorian * At the end the routine acquires all hashbin locks (in the old array). 392ae8c6e27Sflorian * This makes it wait for other threads to finish with the bins. 393ae8c6e27Sflorian * So the bins are ready to be deleted after this function. 394ae8c6e27Sflorian * @param table: hash table with function pointers. 395ae8c6e27Sflorian * @param newa: new increased array. 396ae8c6e27Sflorian * @param newmask: new lookup mask. 397ae8c6e27Sflorian */ 398ae8c6e27Sflorian void bin_split(struct lruhash* table, struct lruhash_bin* newa, 399ae8c6e27Sflorian int newmask); 400ae8c6e27Sflorian 401ae8c6e27Sflorian /** 402ae8c6e27Sflorian * Try to make space available by deleting old entries. 403ae8c6e27Sflorian * Assumes that the lock on the hashtable is being held by caller. 404ae8c6e27Sflorian * Caller must not hold bin locks. 405ae8c6e27Sflorian * @param table: hash table. 406ae8c6e27Sflorian * @param list: list of entries that are to be deleted later. 407ae8c6e27Sflorian * Entries have been removed from the hash table and writelock is held. 408ae8c6e27Sflorian */ 409ae8c6e27Sflorian void reclaim_space(struct lruhash* table, struct lruhash_entry** list); 410ae8c6e27Sflorian 411ae8c6e27Sflorian /** 412ae8c6e27Sflorian * Grow the table lookup array. Becomes twice as large. 413ae8c6e27Sflorian * Caller must hold the hash table lock. Must not hold any bin locks. 414ae8c6e27Sflorian * Tries to grow, on malloc failure, nothing happened. 415ae8c6e27Sflorian * @param table: hash table. 416ae8c6e27Sflorian */ 417ae8c6e27Sflorian void table_grow(struct lruhash* table); 418ae8c6e27Sflorian 419ae8c6e27Sflorian /** 420ae8c6e27Sflorian * Put entry at front of lru. entry must be unlinked from lru. 421ae8c6e27Sflorian * Caller must hold hash table lock. 422ae8c6e27Sflorian * @param table: hash table with lru head and tail. 423ae8c6e27Sflorian * @param entry: entry to make most recently used. 424ae8c6e27Sflorian */ 425ae8c6e27Sflorian void lru_front(struct lruhash* table, struct lruhash_entry* entry); 426ae8c6e27Sflorian 427ae8c6e27Sflorian /** 428ae8c6e27Sflorian * Remove entry from lru list. 429ae8c6e27Sflorian * Caller must hold hash table lock. 430ae8c6e27Sflorian * @param table: hash table with lru head and tail. 431ae8c6e27Sflorian * @param entry: entry to remove from lru. 432ae8c6e27Sflorian */ 433ae8c6e27Sflorian void lru_remove(struct lruhash* table, struct lruhash_entry* entry); 434ae8c6e27Sflorian 435ae8c6e27Sflorian /** 436ae8c6e27Sflorian * Output debug info to the log as to state of the hash table. 437ae8c6e27Sflorian * @param table: hash table. 438ae8c6e27Sflorian * @param id: string printed with table to identify the hash table. 439ae8c6e27Sflorian * @param extended: set to true to print statistics on overflow bin lengths. 440ae8c6e27Sflorian */ 441ae8c6e27Sflorian void lruhash_status(struct lruhash* table, const char* id, int extended); 442ae8c6e27Sflorian 443ae8c6e27Sflorian /** 444ae8c6e27Sflorian * Get memory in use now by the lruhash table. 445ae8c6e27Sflorian * @param table: hash table. Will be locked before use. And unlocked after. 446ae8c6e27Sflorian * @return size in bytes. 447ae8c6e27Sflorian */ 448ae8c6e27Sflorian size_t lruhash_get_mem(struct lruhash* table); 449ae8c6e27Sflorian 450ae8c6e27Sflorian /** 451ae8c6e27Sflorian * Traverse a lruhash. Call back for every element in the table. 452ae8c6e27Sflorian * @param h: hash table. Locked before use. 453ae8c6e27Sflorian * @param wr: if true writelock is obtained on element, otherwise readlock. 454ae8c6e27Sflorian * @param func: function for every element. Do not lock or unlock elements. 455ae8c6e27Sflorian * @param arg: user argument to func. 456ae8c6e27Sflorian */ 457ae8c6e27Sflorian void lruhash_traverse(struct lruhash* h, int wr, 458ae8c6e27Sflorian void (*func)(struct lruhash_entry*, void*), void* arg); 459ae8c6e27Sflorian 460ae8c6e27Sflorian #endif /* UTIL_STORAGE_LRUHASH_H */ 461