xref: /openbsd-src/usr.sbin/unbound/util/storage/lruhash.h (revision 2bdc0ed15d5bcb82703283d48e5e85ed47cc34d3)
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