1933707f3Ssthen /* 2933707f3Ssthen * util/storage/slabhash.h - hashtable consisting of several smaller tables. 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 * Hash table that consists of smaller hash tables. 40933707f3Ssthen * It cannot grow, but that gives it the ability to have multiple 41933707f3Ssthen * locks. Also this means there are multiple LRU lists. 42933707f3Ssthen */ 43933707f3Ssthen 44933707f3Ssthen #ifndef UTIL_STORAGE_SLABHASH_H 45933707f3Ssthen #define UTIL_STORAGE_SLABHASH_H 46933707f3Ssthen #include "util/storage/lruhash.h" 47933707f3Ssthen 48933707f3Ssthen /** default number of slabs */ 49933707f3Ssthen #define HASH_DEFAULT_SLABS 4 50933707f3Ssthen 51933707f3Ssthen /** 52933707f3Ssthen * Hash table formed from several smaller ones. 53933707f3Ssthen * This results in a partitioned lruhash table, a 'slashtable'. 54933707f3Ssthen * None of the data inside the slabhash may be altered. 55933707f3Ssthen * Therefore, no locks are needed to access the structure. 56933707f3Ssthen */ 57933707f3Ssthen struct slabhash { 58933707f3Ssthen /** the size of the array - must be power of 2 */ 59933707f3Ssthen size_t size; 60933707f3Ssthen /** size bitmask - uses high bits. */ 61933707f3Ssthen uint32_t mask; 62933707f3Ssthen /** shift right this many bits to get index into array. */ 63933707f3Ssthen unsigned int shift; 64933707f3Ssthen /** lookup array of hash tables */ 65933707f3Ssthen struct lruhash** array; 66933707f3Ssthen }; 67933707f3Ssthen 68933707f3Ssthen /** 69933707f3Ssthen * Create new slabbed hash table. 70933707f3Ssthen * @param numtables: number of hash tables to use, other parameters used to 71933707f3Ssthen * initialize these smaller hashtables. 72933707f3Ssthen * @param start_size: size of hashtable array at start, must be power of 2. 73933707f3Ssthen * @param maxmem: maximum amount of memory this table is allowed to use. 74933707f3Ssthen * so every table gets maxmem/numtables to use for itself. 75933707f3Ssthen * @param sizefunc: calculates memory usage of entries. 76933707f3Ssthen * @param compfunc: compares entries, 0 on equality. 77933707f3Ssthen * @param delkeyfunc: deletes key. 78933707f3Ssthen * @param deldatafunc: deletes data. 79933707f3Ssthen * @param arg: user argument that is passed to user function calls. 80933707f3Ssthen * @return: new hash table or NULL on malloc failure. 81933707f3Ssthen */ 82933707f3Ssthen struct slabhash* slabhash_create(size_t numtables, size_t start_size, 8377079be7Ssthen size_t maxmem, lruhash_sizefunc_type sizefunc, 8477079be7Ssthen lruhash_compfunc_type compfunc, lruhash_delkeyfunc_type delkeyfunc, 8577079be7Ssthen lruhash_deldatafunc_type deldatafunc, void* arg); 86933707f3Ssthen 87933707f3Ssthen /** 88933707f3Ssthen * Delete hash table. Entries are all deleted. 89933707f3Ssthen * @param table: to delete. 90933707f3Ssthen */ 91933707f3Ssthen void slabhash_delete(struct slabhash* table); 92933707f3Ssthen 93933707f3Ssthen /** 94933707f3Ssthen * Clear hash table. Entries are all deleted. 95933707f3Ssthen * @param table: to make empty. 96933707f3Ssthen */ 97933707f3Ssthen void slabhash_clear(struct slabhash* table); 98933707f3Ssthen 99933707f3Ssthen /** 100933707f3Ssthen * Insert a new element into the hashtable, uses lruhash_insert. 101933707f3Ssthen * If key is already present data pointer in that entry is updated. 102933707f3Ssthen * 103933707f3Ssthen * @param table: hash table. 104933707f3Ssthen * @param hash: hash value. User calculates the hash. 105933707f3Ssthen * @param entry: identifies the entry. 106933707f3Ssthen * If key already present, this entry->key is deleted immediately. 107933707f3Ssthen * But entry->data is set to NULL before deletion, and put into 108933707f3Ssthen * the existing entry. The data is then freed. 109933707f3Ssthen * @param data: the data. 110bdfc4d55Sflorian * @param cb_override: if not NULL overrides the cb_arg for deletefunc. 111933707f3Ssthen */ 11277079be7Ssthen void slabhash_insert(struct slabhash* table, hashvalue_type hash, 113933707f3Ssthen struct lruhash_entry* entry, void* data, void* cb_override); 114933707f3Ssthen 115933707f3Ssthen /** 116933707f3Ssthen * Lookup an entry in the hashtable. Uses lruhash_lookup. 117933707f3Ssthen * At the end of the function you hold a (read/write)lock on the entry. 118933707f3Ssthen * The LRU is updated for the entry (if found). 119933707f3Ssthen * @param table: hash table. 120933707f3Ssthen * @param hash: hash of key. 121933707f3Ssthen * @param key: what to look for, compared against entries in overflow chain. 122933707f3Ssthen * the hash value must be set, and must work with compare function. 123933707f3Ssthen * @param wr: set to true if you desire a writelock on the entry. 124933707f3Ssthen * with a writelock you can update the data part. 125933707f3Ssthen * @return: pointer to the entry or NULL. The entry is locked. 126933707f3Ssthen * The user must unlock the entry when done. 127933707f3Ssthen */ 128933707f3Ssthen struct lruhash_entry* slabhash_lookup(struct slabhash* table, 12977079be7Ssthen hashvalue_type hash, void* key, int wr); 130933707f3Ssthen 131933707f3Ssthen /** 132933707f3Ssthen * Remove entry from hashtable. Does nothing if not found in hashtable. 133933707f3Ssthen * Delfunc is called for the entry. Uses lruhash_remove. 134933707f3Ssthen * @param table: hash table. 135933707f3Ssthen * @param hash: hash of key. 136933707f3Ssthen * @param key: what to look for. 137933707f3Ssthen */ 13877079be7Ssthen void slabhash_remove(struct slabhash* table, hashvalue_type hash, void* key); 139933707f3Ssthen 140933707f3Ssthen /** 141933707f3Ssthen * Output debug info to the log as to state of the hash table. 142933707f3Ssthen * @param table: hash table. 143933707f3Ssthen * @param id: string printed with table to identify the hash table. 144933707f3Ssthen * @param extended: set to true to print statistics on overflow bin lengths. 145933707f3Ssthen */ 146933707f3Ssthen void slabhash_status(struct slabhash* table, const char* id, int extended); 147933707f3Ssthen 148933707f3Ssthen /** 149933707f3Ssthen * Retrieve slab hash total size. 150933707f3Ssthen * @param table: hash table. 151933707f3Ssthen * @return size configured as max. 152933707f3Ssthen */ 153933707f3Ssthen size_t slabhash_get_size(struct slabhash* table); 154933707f3Ssthen 155933707f3Ssthen /** 1562308e98cSsthen * See if slabhash is of given (size, slabs) configuration. 1572308e98cSsthen * @param table: hash table 1582308e98cSsthen * @param size: max size to test for 1592308e98cSsthen * @param slabs: slab count to test for. 1602308e98cSsthen * @return true if equal 1612308e98cSsthen */ 1622308e98cSsthen int slabhash_is_size(struct slabhash* table, size_t size, size_t slabs); 1632308e98cSsthen 1642308e98cSsthen /** 165*2bdc0ed1Ssthen * Update the size of an element in the hashtable, uses 166*2bdc0ed1Ssthen * lruhash_update_space_used. 167*2bdc0ed1Ssthen * 168*2bdc0ed1Ssthen * @param table: hash table. 169*2bdc0ed1Ssthen * @param hash: hash value. User calculates the hash. 170*2bdc0ed1Ssthen * @param cb_override: if not NULL overrides the cb_arg for deletefunc. 171*2bdc0ed1Ssthen * @param diff_size: difference in size to the hash table storage. 172*2bdc0ed1Ssthen */ 173*2bdc0ed1Ssthen void slabhash_update_space_used(struct slabhash* table, hashvalue_type hash, 174*2bdc0ed1Ssthen void* cb_override, int diff_size); 175*2bdc0ed1Ssthen 176*2bdc0ed1Ssthen /** 177933707f3Ssthen * Retrieve slab hash current memory use. 178933707f3Ssthen * @param table: hash table. 179933707f3Ssthen * @return memory in use. 180933707f3Ssthen */ 181933707f3Ssthen size_t slabhash_get_mem(struct slabhash* table); 182933707f3Ssthen 183933707f3Ssthen /** 184933707f3Ssthen * Get lruhash table for a given hash value 185933707f3Ssthen * @param table: slabbed hash table. 186933707f3Ssthen * @param hash: hash value. 187933707f3Ssthen * @return the lru hash table. 188933707f3Ssthen */ 18977079be7Ssthen struct lruhash* slabhash_gettable(struct slabhash* table, hashvalue_type hash); 190933707f3Ssthen 191933707f3Ssthen /** 192933707f3Ssthen * Set markdel function 193933707f3Ssthen * @param table: slabbed hash table. 194933707f3Ssthen * @param md: markdel function ptr. 195933707f3Ssthen */ 19677079be7Ssthen void slabhash_setmarkdel(struct slabhash* table, lruhash_markdelfunc_type md); 197933707f3Ssthen 198933707f3Ssthen /** 199933707f3Ssthen * Traverse a slabhash. 200933707f3Ssthen * @param table: slabbed hash table. 201933707f3Ssthen * @param wr: if true, writelock is obtained, otherwise readlock. 202933707f3Ssthen * @param func: function to call for every element. 203933707f3Ssthen * @param arg: user argument to function. 204933707f3Ssthen */ 205933707f3Ssthen void slabhash_traverse(struct slabhash* table, int wr, 206933707f3Ssthen void (*func)(struct lruhash_entry*, void*), void* arg); 207933707f3Ssthen 20898f3ca02Sbrad /* 20998f3ca02Sbrad * Count entries in slabhash. 21098f3ca02Sbrad * @param table: slabbed hash table; 21198f3ca02Sbrad * @return the number of items 21298f3ca02Sbrad */ 21398f3ca02Sbrad size_t count_slabhash_entries(struct slabhash* table); 21498f3ca02Sbrad 2158b7325afSsthen /** 2168b7325afSsthen * Retrieves number of items in slabhash and the current max collision level 2178b7325afSsthen * @param table: slabbed hash table. 2188b7325afSsthen * @param entries_count: where to save the current number of elements. 2198b7325afSsthen * @param max_collisions: where to save the current max collisions level. 2208b7325afSsthen */ 2218b7325afSsthen void get_slabhash_stats(struct slabhash* table, 2228b7325afSsthen long long* entries_count, long long* max_collisions); 2238b7325afSsthen 224933707f3Ssthen /* --- test representation --- */ 225933707f3Ssthen /** test structure contains test key */ 226933707f3Ssthen struct slabhash_testkey { 227933707f3Ssthen /** the key id */ 228933707f3Ssthen int id; 229933707f3Ssthen /** the entry */ 230933707f3Ssthen struct lruhash_entry entry; 231933707f3Ssthen }; 232933707f3Ssthen /** test structure contains test data */ 233933707f3Ssthen struct slabhash_testdata { 234933707f3Ssthen /** data value */ 235933707f3Ssthen int data; 236933707f3Ssthen }; 237933707f3Ssthen 238933707f3Ssthen /** test sizefunc for lruhash */ 239933707f3Ssthen size_t test_slabhash_sizefunc(void*, void*); 240933707f3Ssthen /** test comparefunc for lruhash */ 241933707f3Ssthen int test_slabhash_compfunc(void*, void*); 242933707f3Ssthen /** test delkey for lruhash */ 243933707f3Ssthen void test_slabhash_delkey(void*, void*); 244933707f3Ssthen /** test deldata for lruhash */ 245933707f3Ssthen void test_slabhash_deldata(void*, void*); 246933707f3Ssthen /* --- end test representation --- */ 247933707f3Ssthen 248933707f3Ssthen #endif /* UTIL_STORAGE_SLABHASH_H */ 249