1933707f3Ssthen /* 2933707f3Ssthen * util/storage/lruhash.h - hashtable, hash function, LRU keeping. 3933707f3Ssthen * 4933707f3Ssthen * Copyright (c) 2007, NLnet Labs. All rights reserved. 5933707f3Ssthen * 6933707f3Ssthen * This software is open source. 7933707f3Ssthen * 8933707f3Ssthen * Redistribution and use in source and binary forms, with or without 9933707f3Ssthen * modification, are permitted provided that the following conditions 10933707f3Ssthen * are met: 11933707f3Ssthen * 12933707f3Ssthen * Redistributions of source code must retain the above copyright notice, 13933707f3Ssthen * this list of conditions and the following disclaimer. 14933707f3Ssthen * 15933707f3Ssthen * Redistributions in binary form must reproduce the above copyright notice, 16933707f3Ssthen * this list of conditions and the following disclaimer in the documentation 17933707f3Ssthen * and/or other materials provided with the distribution. 18933707f3Ssthen * 19933707f3Ssthen * Neither the name of the NLNET LABS nor the names of its contributors may 20933707f3Ssthen * be used to endorse or promote products derived from this software without 21933707f3Ssthen * specific prior written permission. 22933707f3Ssthen * 23933707f3Ssthen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 245d76a658Ssthen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 255d76a658Ssthen * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 265d76a658Ssthen * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 275d76a658Ssthen * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 285d76a658Ssthen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 295d76a658Ssthen * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 305d76a658Ssthen * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 315d76a658Ssthen * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 325d76a658Ssthen * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 335d76a658Ssthen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34933707f3Ssthen */ 35933707f3Ssthen 36933707f3Ssthen /** 37933707f3Ssthen * \file 38933707f3Ssthen * 39933707f3Ssthen * This file contains a hashtable with LRU keeping of entries. 40933707f3Ssthen * 41933707f3Ssthen * The hash table keeps a maximum memory size. Old entries are removed 42933707f3Ssthen * to make space for new entries. 43933707f3Ssthen * 44933707f3Ssthen * The locking strategy is as follows: 45933707f3Ssthen * o since (almost) every read also implies a LRU update, the 46933707f3Ssthen * hashtable lock is a spinlock, not rwlock. 47933707f3Ssthen * o the idea is to move every thread through the hash lock quickly, 48933707f3Ssthen * so that the next thread can access the lookup table. 49933707f3Ssthen * o User performs hash function. 50933707f3Ssthen * 51933707f3Ssthen * For read: 52933707f3Ssthen * o lock hashtable. 53933707f3Ssthen * o lookup hash bin. 54933707f3Ssthen * o lock hash bin. 55933707f3Ssthen * o find entry (if failed, unlock hash, unl bin, exit). 56933707f3Ssthen * o swizzle pointers for LRU update. 57933707f3Ssthen * o unlock hashtable. 58933707f3Ssthen * o lock entry (rwlock). 59933707f3Ssthen * o unlock hash bin. 60933707f3Ssthen * o work on entry. 61933707f3Ssthen * o unlock entry. 62933707f3Ssthen * 63933707f3Ssthen * To update an entry, gain writelock and change the entry. 64933707f3Ssthen * (the entry must keep the same hashvalue, so a data update.) 65933707f3Ssthen * (you cannot upgrade a readlock to a writelock, because the item may 66933707f3Ssthen * be deleted, it would cause race conditions. So instead, unlock and 67933707f3Ssthen * relookup it in the hashtable.) 68933707f3Ssthen * 69933707f3Ssthen * To delete an entry: 70933707f3Ssthen * o unlock the entry if you hold the lock already. 71933707f3Ssthen * o lock hashtable. 72933707f3Ssthen * o lookup hash bin. 73933707f3Ssthen * o lock hash bin. 74933707f3Ssthen * o find entry (if failed, unlock hash, unl bin, exit). 75933707f3Ssthen * o remove entry from hashtable bin overflow chain. 76933707f3Ssthen * o unlock hashtable. 77933707f3Ssthen * o lock entry (writelock). 78933707f3Ssthen * o unlock hash bin. 79933707f3Ssthen * o unlock entry (nobody else should be waiting for this lock, 80933707f3Ssthen * since you removed it from hashtable, and you got writelock while 81933707f3Ssthen * holding the hashbinlock so you are the only one.) 82933707f3Ssthen * Note you are only allowed to obtain a lock while holding hashbinlock. 83933707f3Ssthen * o delete entry. 84933707f3Ssthen * 85933707f3Ssthen * The above sequence is: 86933707f3Ssthen * o race free, works with read, write and delete. 87933707f3Ssthen * o but has a queue, imagine someone needing a writelock on an item. 88933707f3Ssthen * but there are still readlocks. The writelocker waits, but holds 89933707f3Ssthen * the hashbinlock. The next thread that comes in and needs the same 90933707f3Ssthen * hashbin will wait for the lock while holding the hashtable lock. 91933707f3Ssthen * thus halting the entire system on hashtable. 92933707f3Ssthen * This is because of the delete protection. 93933707f3Ssthen * Readlocks will be easier on the rwlock on entries. 94933707f3Ssthen * While the writer is holding writelock, similar problems happen with 95933707f3Ssthen * a reader or writer needing the same item. 96933707f3Ssthen * the scenario requires more than three threads. 97933707f3Ssthen * o so the queue length is 3 threads in a bad situation. The fourth is 98933707f3Ssthen * unable to use the hashtable. 99933707f3Ssthen * 100933707f3Ssthen * If you need to acquire locks on multiple items from the hashtable. 101933707f3Ssthen * o you MUST release all locks on items from the hashtable before 102933707f3Ssthen * doing the next lookup/insert/delete/whatever. 103933707f3Ssthen * o To acquire multiple items you should use a special routine that 104933707f3Ssthen * obtains the locks on those multiple items in one go. 105933707f3Ssthen */ 106933707f3Ssthen 107933707f3Ssthen #ifndef UTIL_STORAGE_LRUHASH_H 108933707f3Ssthen #define UTIL_STORAGE_LRUHASH_H 109933707f3Ssthen #include "util/locks.h" 110933707f3Ssthen struct lruhash_bin; 111933707f3Ssthen struct lruhash_entry; 112933707f3Ssthen 113933707f3Ssthen /** default start size for hash arrays */ 114933707f3Ssthen #define HASH_DEFAULT_STARTARRAY 1024 /* entries in array */ 115933707f3Ssthen /** default max memory for hash arrays */ 116933707f3Ssthen #define HASH_DEFAULT_MAXMEM 4*1024*1024 /* bytes */ 117933707f3Ssthen 118933707f3Ssthen /** the type of a hash value */ 11977079be7Ssthen typedef uint32_t hashvalue_type; 120933707f3Ssthen 121933707f3Ssthen /** 122933707f3Ssthen * Type of function that calculates the size of an entry. 123933707f3Ssthen * Result must include the size of struct lruhash_entry. 124933707f3Ssthen * Keys that are identical must also calculate to the same size. 125933707f3Ssthen * size = func(key, data). 126933707f3Ssthen */ 12777079be7Ssthen typedef size_t (*lruhash_sizefunc_type)(void*, void*); 128933707f3Ssthen 129933707f3Ssthen /** type of function that compares two keys. return 0 if equal. */ 13077079be7Ssthen typedef int (*lruhash_compfunc_type)(void*, void*); 131933707f3Ssthen 132933707f3Ssthen /** old keys are deleted. 133933707f3Ssthen * The RRset type has to revoke its ID number, markdel() is used first. 134933707f3Ssthen * This function is called: func(key, userarg) */ 13577079be7Ssthen typedef void (*lruhash_delkeyfunc_type)(void*, void*); 136933707f3Ssthen 137933707f3Ssthen /** old data is deleted. This function is called: func(data, userarg). */ 13877079be7Ssthen typedef void (*lruhash_deldatafunc_type)(void*, void*); 139933707f3Ssthen 140933707f3Ssthen /** mark a key as pending to be deleted (and not to be used by anyone). 141933707f3Ssthen * called: func(key) */ 14277079be7Ssthen typedef void (*lruhash_markdelfunc_type)(void*); 143933707f3Ssthen 144933707f3Ssthen /** 145933707f3Ssthen * Hash table that keeps LRU list of entries. 146933707f3Ssthen */ 147933707f3Ssthen struct lruhash { 148933707f3Ssthen /** lock for exclusive access, to the lookup array */ 14977079be7Ssthen lock_quick_type lock; 150933707f3Ssthen /** the size function for entries in this table */ 15177079be7Ssthen lruhash_sizefunc_type sizefunc; 152933707f3Ssthen /** the compare function for entries in this table. */ 15377079be7Ssthen lruhash_compfunc_type compfunc; 154933707f3Ssthen /** how to delete keys. */ 15577079be7Ssthen lruhash_delkeyfunc_type delkeyfunc; 156933707f3Ssthen /** how to delete data. */ 15777079be7Ssthen lruhash_deldatafunc_type deldatafunc; 158933707f3Ssthen /** how to mark a key pending deletion */ 15977079be7Ssthen lruhash_markdelfunc_type markdelfunc; 160933707f3Ssthen /** user argument for user functions */ 161933707f3Ssthen void* cb_arg; 162933707f3Ssthen 163933707f3Ssthen /** the size of the lookup array */ 164933707f3Ssthen size_t size; 165933707f3Ssthen /** size bitmask - since size is a power of 2 */ 166933707f3Ssthen int size_mask; 167933707f3Ssthen /** lookup array of bins */ 168933707f3Ssthen struct lruhash_bin* array; 169933707f3Ssthen 170933707f3Ssthen /** the lru list, start and end, noncyclical double linked list. */ 171933707f3Ssthen struct lruhash_entry* lru_start; 172933707f3Ssthen /** lru list end item (least recently used) */ 173933707f3Ssthen struct lruhash_entry* lru_end; 174933707f3Ssthen 175933707f3Ssthen /** the number of entries in the hash table. */ 176933707f3Ssthen size_t num; 177933707f3Ssthen /** the amount of space used, roughly the number of bytes in use. */ 178933707f3Ssthen size_t space_used; 179933707f3Ssthen /** the amount of space the hash table is maximally allowed to use. */ 180933707f3Ssthen size_t space_max; 1818b7325afSsthen /** the maximum collisions were detected during the lruhash_insert operations. */ 1828b7325afSsthen size_t max_collisions; 183933707f3Ssthen }; 184933707f3Ssthen 185933707f3Ssthen /** 186933707f3Ssthen * A single bin with a linked list of entries in it. 187933707f3Ssthen */ 188933707f3Ssthen struct lruhash_bin { 189933707f3Ssthen /** 190933707f3Ssthen * Lock for exclusive access to the linked list 191933707f3Ssthen * This lock makes deletion of items safe in this overflow list. 192933707f3Ssthen */ 19377079be7Ssthen lock_quick_type lock; 194933707f3Ssthen /** linked list of overflow entries */ 195933707f3Ssthen struct lruhash_entry* overflow_list; 196933707f3Ssthen }; 197933707f3Ssthen 198933707f3Ssthen /** 199933707f3Ssthen * An entry into the hash table. 200933707f3Ssthen * To change overflow_next you need to hold the bin lock. 201933707f3Ssthen * To change the lru items you need to hold the hashtable lock. 202933707f3Ssthen * This structure is designed as part of key struct. And key pointer helps 203933707f3Ssthen * to get the surrounding structure. Data should be allocated on its own. 204933707f3Ssthen */ 205933707f3Ssthen struct lruhash_entry { 206933707f3Ssthen /** 207933707f3Ssthen * rwlock for access to the contents of the entry 208933707f3Ssthen * Note that it does _not_ cover the lru_ and overflow_ ptrs. 209933707f3Ssthen * Even with a writelock, you cannot change hash and key. 210933707f3Ssthen * You need to delete it to change hash or key. 211933707f3Ssthen */ 21277079be7Ssthen lock_rw_type lock; 213933707f3Ssthen /** next entry in overflow chain. Covered by hashlock and binlock. */ 214933707f3Ssthen struct lruhash_entry* overflow_next; 215933707f3Ssthen /** next entry in lru chain. covered by hashlock. */ 216933707f3Ssthen struct lruhash_entry* lru_next; 217933707f3Ssthen /** prev entry in lru chain. covered by hashlock. */ 218933707f3Ssthen struct lruhash_entry* lru_prev; 219933707f3Ssthen /** hash value of the key. It may not change, until entry deleted. */ 22077079be7Ssthen hashvalue_type hash; 221933707f3Ssthen /** key */ 222933707f3Ssthen void* key; 223933707f3Ssthen /** data */ 224933707f3Ssthen void* data; 225933707f3Ssthen }; 226933707f3Ssthen 227933707f3Ssthen /** 228933707f3Ssthen * Create new hash table. 229933707f3Ssthen * @param start_size: size of hashtable array at start, must be power of 2. 230933707f3Ssthen * @param maxmem: maximum amount of memory this table is allowed to use. 231933707f3Ssthen * @param sizefunc: calculates memory usage of entries. 232933707f3Ssthen * @param compfunc: compares entries, 0 on equality. 233933707f3Ssthen * @param delkeyfunc: deletes key. 234933707f3Ssthen * Calling both delkey and deldata will also free the struct lruhash_entry. 235933707f3Ssthen * Make it part of the key structure and delete it in delkeyfunc. 236933707f3Ssthen * @param deldatafunc: deletes data. 237933707f3Ssthen * @param arg: user argument that is passed to user function calls. 238933707f3Ssthen * @return: new hash table or NULL on malloc failure. 239933707f3Ssthen */ 240933707f3Ssthen struct lruhash* lruhash_create(size_t start_size, size_t maxmem, 24177079be7Ssthen lruhash_sizefunc_type sizefunc, lruhash_compfunc_type compfunc, 24277079be7Ssthen lruhash_delkeyfunc_type delkeyfunc, 24377079be7Ssthen lruhash_deldatafunc_type deldatafunc, void* arg); 244933707f3Ssthen 245933707f3Ssthen /** 246933707f3Ssthen * Delete hash table. Entries are all deleted. 247933707f3Ssthen * @param table: to delete. 248933707f3Ssthen */ 249933707f3Ssthen void lruhash_delete(struct lruhash* table); 250933707f3Ssthen 251933707f3Ssthen /** 252933707f3Ssthen * Clear hash table. Entries are all deleted, while locking them before 253933707f3Ssthen * doing so. At end the table is empty. 254933707f3Ssthen * @param table: to make empty. 255933707f3Ssthen */ 256933707f3Ssthen void lruhash_clear(struct lruhash* table); 257933707f3Ssthen 258933707f3Ssthen /** 259933707f3Ssthen * Insert a new element into the hashtable. 260933707f3Ssthen * If key is already present data pointer in that entry is updated. 261933707f3Ssthen * The space calculation function is called with the key, data. 262933707f3Ssthen * If necessary the least recently used entries are deleted to make space. 263933707f3Ssthen * If necessary the hash array is grown up. 264933707f3Ssthen * 265933707f3Ssthen * @param table: hash table. 266933707f3Ssthen * @param hash: hash value. User calculates the hash. 267933707f3Ssthen * @param entry: identifies the entry. 268933707f3Ssthen * If key already present, this entry->key is deleted immediately. 269933707f3Ssthen * But entry->data is set to NULL before deletion, and put into 270933707f3Ssthen * the existing entry. The data is then freed. 271933707f3Ssthen * @param data: the data. 272933707f3Ssthen * @param cb_override: if not null overrides the cb_arg for the deletefunc. 273933707f3Ssthen */ 27477079be7Ssthen void lruhash_insert(struct lruhash* table, hashvalue_type hash, 275933707f3Ssthen struct lruhash_entry* entry, void* data, void* cb_override); 276933707f3Ssthen 277933707f3Ssthen /** 278933707f3Ssthen * Lookup an entry in the hashtable. 279933707f3Ssthen * At the end of the function you hold a (read/write)lock on the entry. 280933707f3Ssthen * The LRU is updated for the entry (if found). 281933707f3Ssthen * @param table: hash table. 282933707f3Ssthen * @param hash: hash of key. 283933707f3Ssthen * @param key: what to look for, compared against entries in overflow chain. 284933707f3Ssthen * the hash value must be set, and must work with compare function. 285933707f3Ssthen * @param wr: set to true if you desire a writelock on the entry. 286933707f3Ssthen * with a writelock you can update the data part. 287933707f3Ssthen * @return: pointer to the entry or NULL. The entry is locked. 288933707f3Ssthen * The user must unlock the entry when done. 289933707f3Ssthen */ 29077079be7Ssthen struct lruhash_entry* lruhash_lookup(struct lruhash* table, 29177079be7Ssthen hashvalue_type hash, void* key, int wr); 292933707f3Ssthen 293933707f3Ssthen /** 294933707f3Ssthen * Touch entry, so it becomes the most recently used in the LRU list. 295933707f3Ssthen * Caller must hold hash table lock. The entry must be inserted already. 296933707f3Ssthen * @param table: hash table. 297933707f3Ssthen * @param entry: entry to make first in LRU. 298933707f3Ssthen */ 299933707f3Ssthen void lru_touch(struct lruhash* table, struct lruhash_entry* entry); 300933707f3Ssthen 301933707f3Ssthen /** 302933707f3Ssthen * Set the markdelfunction (or NULL) 303933707f3Ssthen */ 30477079be7Ssthen void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md); 305933707f3Ssthen 306*2bdc0ed1Ssthen /** 307*2bdc0ed1Ssthen * Update the size of an element in the hashtable. 308*2bdc0ed1Ssthen * 309*2bdc0ed1Ssthen * @param table: hash table. 310*2bdc0ed1Ssthen * @param cb_override: if not NULL overrides the cb_arg for deletefunc. 311*2bdc0ed1Ssthen * @param diff_size: difference in size to the hash table storage. 312*2bdc0ed1Ssthen * This is newsize - oldsize, a positive number uses more space. 313*2bdc0ed1Ssthen */ 314*2bdc0ed1Ssthen void lruhash_update_space_used(struct lruhash* table, void* cb_override, 315*2bdc0ed1Ssthen int diff_size); 316*2bdc0ed1Ssthen 3172be9e038Ssthen /************************* getdns functions ************************/ 3182be9e038Ssthen /*** these are used by getdns only and not by unbound. ***/ 3192be9e038Ssthen 3202be9e038Ssthen /** 3212be9e038Ssthen * Demote entry, so it becomes the least recently used in the LRU list. 3222be9e038Ssthen * Caller must hold hash table lock. The entry must be inserted already. 3232be9e038Ssthen * @param table: hash table. 3242be9e038Ssthen * @param entry: entry to make last in LRU. 3252be9e038Ssthen */ 3262be9e038Ssthen void lru_demote(struct lruhash* table, struct lruhash_entry* entry); 3272be9e038Ssthen 3282be9e038Ssthen /** 3292be9e038Ssthen * Insert a new element into the hashtable, or retrieve the corresponding 3302be9e038Ssthen * element of it exits. 3312be9e038Ssthen * 3322be9e038Ssthen * If key is already present data pointer in that entry is kept. 3332be9e038Ssthen * If it is not present, a new entry is created. In that case, 3342be9e038Ssthen * the space calculation function is called with the key, data. 3352be9e038Ssthen * If necessary the least recently used entries are deleted to make space. 3362be9e038Ssthen * If necessary the hash array is grown up. 3372be9e038Ssthen * 3382be9e038Ssthen * @param table: hash table. 3392be9e038Ssthen * @param hash: hash value. User calculates the hash. 3402be9e038Ssthen * @param entry: identifies the entry. 3412be9e038Ssthen * @param data: the data. 3422be9e038Ssthen * @param cb_arg: if not null overrides the cb_arg for the deletefunc. 3432be9e038Ssthen * @return: pointer to the existing entry if the key was already present, 3442be9e038Ssthen * or to the entry argument if it was not. 3452be9e038Ssthen */ 3462be9e038Ssthen struct lruhash_entry* lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash, 3472be9e038Ssthen struct lruhash_entry* entry, void* data, void* cb_arg); 3482be9e038Ssthen 349933707f3Ssthen /************************* Internal functions ************************/ 350933707f3Ssthen /*** these are only exposed for unit tests. ***/ 351933707f3Ssthen 352933707f3Ssthen /** 353933707f3Ssthen * Remove entry from hashtable. Does nothing if not found in hashtable. 354933707f3Ssthen * Delfunc is called for the entry. 355933707f3Ssthen * @param table: hash table. 356933707f3Ssthen * @param hash: hash of key. 357933707f3Ssthen * @param key: what to look for. 358933707f3Ssthen */ 35977079be7Ssthen void lruhash_remove(struct lruhash* table, hashvalue_type hash, void* key); 360933707f3Ssthen 361933707f3Ssthen /** init the hash bins for the table */ 362933707f3Ssthen void bin_init(struct lruhash_bin* array, size_t size); 363933707f3Ssthen 364933707f3Ssthen /** delete the hash bin and entries inside it */ 365933707f3Ssthen void bin_delete(struct lruhash* table, struct lruhash_bin* bin); 366933707f3Ssthen 367933707f3Ssthen /** 368933707f3Ssthen * Find entry in hash bin. You must have locked the bin. 369933707f3Ssthen * @param table: hash table with function pointers. 370933707f3Ssthen * @param bin: hash bin to look into. 371933707f3Ssthen * @param hash: hash value to look for. 372933707f3Ssthen * @param key: key to look for. 3738b7325afSsthen * @param collisions: how many collisions were found during the search. 374933707f3Ssthen * @return: the entry or NULL if not found. 375933707f3Ssthen */ 376933707f3Ssthen struct lruhash_entry* bin_find_entry(struct lruhash* table, 3778b7325afSsthen struct lruhash_bin* bin, hashvalue_type hash, void* key, size_t* collisions); 378933707f3Ssthen 379933707f3Ssthen /** 380933707f3Ssthen * Remove entry from bin overflow chain. 381933707f3Ssthen * You must have locked the bin. 382933707f3Ssthen * @param bin: hash bin to look into. 383933707f3Ssthen * @param entry: entry ptr that needs removal. 384933707f3Ssthen */ 385933707f3Ssthen void bin_overflow_remove(struct lruhash_bin* bin, 386933707f3Ssthen struct lruhash_entry* entry); 387933707f3Ssthen 388933707f3Ssthen /** 389933707f3Ssthen * Split hash bin into two new ones. Based on increased size_mask. 390933707f3Ssthen * Caller must hold hash table lock. 391933707f3Ssthen * At the end the routine acquires all hashbin locks (in the old array). 392933707f3Ssthen * This makes it wait for other threads to finish with the bins. 393933707f3Ssthen * So the bins are ready to be deleted after this function. 394933707f3Ssthen * @param table: hash table with function pointers. 395933707f3Ssthen * @param newa: new increased array. 396933707f3Ssthen * @param newmask: new lookup mask. 397933707f3Ssthen */ 398933707f3Ssthen void bin_split(struct lruhash* table, struct lruhash_bin* newa, 399933707f3Ssthen int newmask); 400933707f3Ssthen 401933707f3Ssthen /** 402933707f3Ssthen * Try to make space available by deleting old entries. 403933707f3Ssthen * Assumes that the lock on the hashtable is being held by caller. 404933707f3Ssthen * Caller must not hold bin locks. 405933707f3Ssthen * @param table: hash table. 406933707f3Ssthen * @param list: list of entries that are to be deleted later. 407933707f3Ssthen * Entries have been removed from the hash table and writelock is held. 408933707f3Ssthen */ 409933707f3Ssthen void reclaim_space(struct lruhash* table, struct lruhash_entry** list); 410933707f3Ssthen 411933707f3Ssthen /** 412933707f3Ssthen * Grow the table lookup array. Becomes twice as large. 413933707f3Ssthen * Caller must hold the hash table lock. Must not hold any bin locks. 414933707f3Ssthen * Tries to grow, on malloc failure, nothing happened. 415933707f3Ssthen * @param table: hash table. 416933707f3Ssthen */ 417933707f3Ssthen void table_grow(struct lruhash* table); 418933707f3Ssthen 419933707f3Ssthen /** 420933707f3Ssthen * Put entry at front of lru. entry must be unlinked from lru. 421933707f3Ssthen * Caller must hold hash table lock. 422933707f3Ssthen * @param table: hash table with lru head and tail. 423933707f3Ssthen * @param entry: entry to make most recently used. 424933707f3Ssthen */ 425933707f3Ssthen void lru_front(struct lruhash* table, struct lruhash_entry* entry); 426933707f3Ssthen 427933707f3Ssthen /** 428933707f3Ssthen * Remove entry from lru list. 429933707f3Ssthen * Caller must hold hash table lock. 430933707f3Ssthen * @param table: hash table with lru head and tail. 431933707f3Ssthen * @param entry: entry to remove from lru. 432933707f3Ssthen */ 433933707f3Ssthen void lru_remove(struct lruhash* table, struct lruhash_entry* entry); 434933707f3Ssthen 435933707f3Ssthen /** 436933707f3Ssthen * Output debug info to the log as to state of the hash table. 437933707f3Ssthen * @param table: hash table. 438933707f3Ssthen * @param id: string printed with table to identify the hash table. 439933707f3Ssthen * @param extended: set to true to print statistics on overflow bin lengths. 440933707f3Ssthen */ 441933707f3Ssthen void lruhash_status(struct lruhash* table, const char* id, int extended); 442933707f3Ssthen 443933707f3Ssthen /** 444933707f3Ssthen * Get memory in use now by the lruhash table. 445933707f3Ssthen * @param table: hash table. Will be locked before use. And unlocked after. 446933707f3Ssthen * @return size in bytes. 447933707f3Ssthen */ 448933707f3Ssthen size_t lruhash_get_mem(struct lruhash* table); 449933707f3Ssthen 450933707f3Ssthen /** 451933707f3Ssthen * Traverse a lruhash. Call back for every element in the table. 452933707f3Ssthen * @param h: hash table. Locked before use. 453933707f3Ssthen * @param wr: if true writelock is obtained on element, otherwise readlock. 454933707f3Ssthen * @param func: function for every element. Do not lock or unlock elements. 455933707f3Ssthen * @param arg: user argument to func. 456933707f3Ssthen */ 457933707f3Ssthen void lruhash_traverse(struct lruhash* h, int wr, 458933707f3Ssthen void (*func)(struct lruhash_entry*, void*), void* arg); 459933707f3Ssthen 460933707f3Ssthen #endif /* UTIL_STORAGE_LRUHASH_H */ 461