Electroneum
lruhash.h File Reference
#include "util/locks.h"
Include dependency graph for lruhash.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  lruhash
 
struct  lruhash_bin
 
struct  lruhash_entry
 

Macros

#define HASH_DEFAULT_STARTARRAY   1024 /* entries in array */
 
#define HASH_DEFAULT_MAXMEM   4*1024*1024 /* bytes */
 

Typedefs

typedef uint32_t hashvalue_type
 
typedef size_t(* lruhash_sizefunc_type) (void *, void *)
 
typedef int(* lruhash_compfunc_type) (void *, void *)
 
typedef void(* lruhash_delkeyfunc_type) (void *, void *)
 
typedef void(* lruhash_deldatafunc_type) (void *, void *)
 
typedef void(* lruhash_markdelfunc_type) (void *)
 

Functions

struct lruhashlruhash_create (size_t start_size, size_t maxmem, lruhash_sizefunc_type sizefunc, lruhash_compfunc_type compfunc, lruhash_delkeyfunc_type delkeyfunc, lruhash_deldatafunc_type deldatafunc, void *arg)
 
void lruhash_delete (struct lruhash *table)
 
void lruhash_clear (struct lruhash *table)
 
void lruhash_insert (struct lruhash *table, hashvalue_type hash, struct lruhash_entry *entry, void *data, void *cb_override)
 
struct lruhash_entrylruhash_lookup (struct lruhash *table, hashvalue_type hash, void *key, int wr)
 
void lru_touch (struct lruhash *table, struct lruhash_entry *entry)
 
void lruhash_setmarkdel (struct lruhash *table, lruhash_markdelfunc_type md)
 
void lru_demote (struct lruhash *table, struct lruhash_entry *entry)
 
struct lruhash_entrylruhash_insert_or_retrieve (struct lruhash *table, hashvalue_type hash, struct lruhash_entry *entry, void *data, void *cb_arg)
 
void lruhash_remove (struct lruhash *table, hashvalue_type hash, void *key)
 
void bin_init (struct lruhash_bin *array, size_t size)
 
void bin_delete (struct lruhash *table, struct lruhash_bin *bin)
 
struct lruhash_entrybin_find_entry (struct lruhash *table, struct lruhash_bin *bin, hashvalue_type hash, void *key)
 
void bin_overflow_remove (struct lruhash_bin *bin, struct lruhash_entry *entry)
 
void bin_split (struct lruhash *table, struct lruhash_bin *newa, int newmask)
 
void reclaim_space (struct lruhash *table, struct lruhash_entry **list)
 
void table_grow (struct lruhash *table)
 
void lru_front (struct lruhash *table, struct lruhash_entry *entry)
 
void lru_remove (struct lruhash *table, struct lruhash_entry *entry)
 
void lruhash_status (struct lruhash *table, const char *id, int extended)
 
size_t lruhash_get_mem (struct lruhash *table)
 
void lruhash_traverse (struct lruhash *h, int wr, void(*func)(struct lruhash_entry *, void *), void *arg)
 

Detailed Description

This file contains a hashtable with LRU keeping of entries.

The hash table keeps a maximum memory size. Old entries are removed to make space for new entries.

The locking strategy is as follows: o since (almost) every read also implies a LRU update, the hashtable lock is a spinlock, not rwlock. o the idea is to move every thread through the hash lock quickly, so that the next thread can access the lookup table. o User performs hash function.

For read: o lock hashtable. o lookup hash bin. o lock hash bin. o find entry (if failed, unlock hash, unl bin, exit). o swizzle pointers for LRU update. o unlock hashtable. o lock entry (rwlock). o unlock hash bin. o work on entry. o unlock entry.

To update an entry, gain writelock and change the entry. (the entry must keep the same hashvalue, so a data update.) (you cannot upgrade a readlock to a writelock, because the item may be deleted, it would cause race conditions. So instead, unlock and relookup it in the hashtable.)

To delete an entry: o unlock the entry if you hold the lock already. o lock hashtable. o lookup hash bin. o lock hash bin. o find entry (if failed, unlock hash, unl bin, exit). o remove entry from hashtable bin overflow chain. o unlock hashtable. o lock entry (writelock). o unlock hash bin. o unlock entry (nobody else should be waiting for this lock, since you removed it from hashtable, and you got writelock while holding the hashbinlock so you are the only one.) Note you are only allowed to obtain a lock while holding hashbinlock. o delete entry.

The above sequence is: o race free, works with read, write and delete. o but has a queue, imagine someone needing a writelock on an item. but there are still readlocks. The writelocker waits, but holds the hashbinlock. The next thread that comes in and needs the same hashbin will wait for the lock while holding the hashtable lock. thus halting the entire system on hashtable. This is because of the delete protection. Readlocks will be easier on the rwlock on entries. While the writer is holding writelock, similar problems happen with a reader or writer needing the same item. the scenario requires more than three threads. o so the queue length is 3 threads in a bad situation. The fourth is unable to use the hashtable.

If you need to acquire locks on multiple items from the hashtable. o you MUST release all locks on items from the hashtable before doing the next lookup/insert/delete/whatever. o To acquire multiple items you should use a special routine that obtains the locks on those multiple items in one go.

Definition in file lruhash.h.

Macro Definition Documentation

◆ HASH_DEFAULT_MAXMEM

#define HASH_DEFAULT_MAXMEM   4*1024*1024 /* bytes */

default max memory for hash arrays

Definition at line 116 of file lruhash.h.

◆ HASH_DEFAULT_STARTARRAY

#define HASH_DEFAULT_STARTARRAY   1024 /* entries in array */

default start size for hash arrays

Definition at line 114 of file lruhash.h.

Typedef Documentation

◆ hashvalue_type

the type of a hash value

Definition at line 119 of file lruhash.h.

◆ lruhash_compfunc_type

typedef int(* lruhash_compfunc_type) (void *, void *)

type of function that compares two keys. return 0 if equal.

Definition at line 130 of file lruhash.h.

◆ lruhash_deldatafunc_type

typedef void(* lruhash_deldatafunc_type) (void *, void *)

old data is deleted. This function is called: func(data, userarg).

Definition at line 138 of file lruhash.h.

◆ lruhash_delkeyfunc_type

typedef void(* lruhash_delkeyfunc_type) (void *, void *)

old keys are deleted. The RRset type has to revoke its ID number, markdel() is used first. This function is called: func(key, userarg)

Definition at line 135 of file lruhash.h.

◆ lruhash_markdelfunc_type

typedef void(* lruhash_markdelfunc_type) (void *)

mark a key as pending to be deleted (and not to be used by anyone). called: func(key)

Definition at line 142 of file lruhash.h.

◆ lruhash_sizefunc_type

typedef size_t(* lruhash_sizefunc_type) (void *, void *)

Type of function that calculates the size of an entry. Result must include the size of struct lruhash_entry. Keys that are identical must also calculate to the same size. size = func(key, data).

Definition at line 127 of file lruhash.h.

Function Documentation

◆ bin_delete()

void bin_delete ( struct lruhash table,
struct lruhash_bin bin 
)

delete the hash bin and entries inside it

◆ bin_find_entry()

struct lruhash_entry* bin_find_entry ( struct lruhash table,
struct lruhash_bin bin,
hashvalue_type  hash,
void *  key 
)

Find entry in hash bin. You must have locked the bin.

Parameters
tablehash table with function pointers.
binhash bin to look into.
hashhash value to look for.
keykey to look for.
Returns
: the entry or NULL if not found.

◆ bin_init()

void bin_init ( struct lruhash_bin array,
size_t  size 
)

init the hash bins for the table

◆ bin_overflow_remove()

void bin_overflow_remove ( struct lruhash_bin bin,
struct lruhash_entry entry 
)

Remove entry from bin overflow chain. You must have locked the bin.

Parameters
binhash bin to look into.
entryentry ptr that needs removal.

◆ bin_split()

void bin_split ( struct lruhash table,
struct lruhash_bin newa,
int  newmask 
)

Split hash bin into two new ones. Based on increased size_mask. Caller must hold hash table lock. At the end the routine acquires all hashbin locks (in the old array). This makes it wait for other threads to finish with the bins. So the bins are ready to be deleted after this function.

Parameters
tablehash table with function pointers.
newanew increased array.
newmasknew lookup mask.

◆ lru_demote()

void lru_demote ( struct lruhash table,
struct lruhash_entry entry 
)

Demote entry, so it becomes the least recently used in the LRU list. Caller must hold hash table lock. The entry must be inserted already.

Parameters
tablehash table.
entryentry to make last in LRU.

◆ lru_front()

void lru_front ( struct lruhash table,
struct lruhash_entry entry 
)

Put entry at front of lru. entry must be unlinked from lru. Caller must hold hash table lock.

Parameters
tablehash table with lru head and tail.
entryentry to make most recently used.

◆ lru_remove()

void lru_remove ( struct lruhash table,
struct lruhash_entry entry 
)

Remove entry from lru list. Caller must hold hash table lock.

Parameters
tablehash table with lru head and tail.
entryentry to remove from lru.

◆ lru_touch()

void lru_touch ( struct lruhash table,
struct lruhash_entry entry 
)

Touch entry, so it becomes the most recently used in the LRU list. Caller must hold hash table lock. The entry must be inserted already.

Parameters
tablehash table.
entryentry to make first in LRU.

◆ lruhash_clear()

void lruhash_clear ( struct lruhash table)

Clear hash table. Entries are all deleted, while locking them before doing so. At end the table is empty.

Parameters
tableto make empty.

◆ lruhash_create()

struct lruhash* lruhash_create ( size_t  start_size,
size_t  maxmem,
lruhash_sizefunc_type  sizefunc,
lruhash_compfunc_type  compfunc,
lruhash_delkeyfunc_type  delkeyfunc,
lruhash_deldatafunc_type  deldatafunc,
void *  arg 
)

Create new hash table.

Parameters
start_sizesize of hashtable array at start, must be power of 2.
maxmemmaximum amount of memory this table is allowed to use.
sizefunccalculates memory usage of entries.
compfunccompares entries, 0 on equality.
delkeyfuncdeletes key. Calling both delkey and deldata will also free the struct lruhash_entry. Make it part of the key structure and delete it in delkeyfunc.
deldatafuncdeletes data.
arguser argument that is passed to user function calls.
Returns
: new hash table or NULL on malloc failure.

◆ lruhash_delete()

void lruhash_delete ( struct lruhash table)

Delete hash table. Entries are all deleted.

Parameters
tableto delete.

◆ lruhash_get_mem()

size_t lruhash_get_mem ( struct lruhash table)

Get memory in use now by the lruhash table.

Parameters
tablehash table. Will be locked before use. And unlocked after.
Returns
size in bytes.

◆ lruhash_insert()

void lruhash_insert ( struct lruhash table,
hashvalue_type  hash,
struct lruhash_entry entry,
void *  data,
void *  cb_override 
)

Insert a new element into the hashtable. If key is already present data pointer in that entry is updated. The space calculation function is called with the key, data. If necessary the least recently used entries are deleted to make space. If necessary the hash array is grown up.

Parameters
tablehash table.
hashhash value. User calculates the hash.
entryidentifies the entry. If key already present, this entry->key is deleted immediately. But entry->data is set to NULL before deletion, and put into the existing entry. The data is then freed.
datathe data.
cb_overrideif not null overrides the cb_arg for the deletefunc.

◆ lruhash_insert_or_retrieve()

struct lruhash_entry* lruhash_insert_or_retrieve ( struct lruhash table,
hashvalue_type  hash,
struct lruhash_entry entry,
void *  data,
void *  cb_arg 
)

Insert a new element into the hashtable, or retrieve the corresponding element of it exits.

If key is already present data pointer in that entry is kept. If it is not present, a new entry is created. In that case, the space calculation function is called with the key, data. If necessary the least recently used entries are deleted to make space. If necessary the hash array is grown up.

Parameters
tablehash table.
hashhash value. User calculates the hash.
entryidentifies the entry.
datathe data.
cb_argif not null overrides the cb_arg for the deletefunc.
Returns
: pointer to the existing entry if the key was already present, or to the entry argument if it was not.

◆ lruhash_lookup()

struct lruhash_entry* lruhash_lookup ( struct lruhash table,
hashvalue_type  hash,
void *  key,
int  wr 
)

Lookup an entry in the hashtable. At the end of the function you hold a (read/write)lock on the entry. The LRU is updated for the entry (if found).

Parameters
tablehash table.
hashhash of key.
keywhat to look for, compared against entries in overflow chain. the hash value must be set, and must work with compare function.
wrset to true if you desire a writelock on the entry. with a writelock you can update the data part.
Returns
: pointer to the entry or NULL. The entry is locked. The user must unlock the entry when done.

◆ lruhash_remove()

void lruhash_remove ( struct lruhash table,
hashvalue_type  hash,
void *  key 
)

Remove entry from hashtable. Does nothing if not found in hashtable. Delfunc is called for the entry.

Parameters
tablehash table.
hashhash of key.
keywhat to look for.

◆ lruhash_setmarkdel()

void lruhash_setmarkdel ( struct lruhash table,
lruhash_markdelfunc_type  md 
)

Set the markdelfunction (or NULL)

◆ lruhash_status()

void lruhash_status ( struct lruhash table,
const char *  id,
int  extended 
)

Output debug info to the log as to state of the hash table.

Parameters
tablehash table.
idstring printed with table to identify the hash table.
extendedset to true to print statistics on overflow bin lengths.

◆ lruhash_traverse()

void lruhash_traverse ( struct lruhash h,
int  wr,
void(*)(struct lruhash_entry *, void *)  func,
void *  arg 
)

Traverse a lruhash. Call back for every element in the table.

Parameters
hhash table. Locked before use.
wrif true writelock is obtained on element, otherwise readlock.
funcfunction for every element. Do not lock or unlock elements.
arguser argument to func.

◆ reclaim_space()

void reclaim_space ( struct lruhash table,
struct lruhash_entry **  list 
)

Try to make space available by deleting old entries. Assumes that the lock on the hashtable is being held by caller. Caller must not hold bin locks.

Parameters
tablehash table.
listlist of entries that are to be deleted later. Entries have been removed from the hash table and writelock is held.

◆ table_grow()

void table_grow ( struct lruhash table)

Grow the table lookup array. Becomes twice as large. Caller must hold the hash table lock. Must not hold any bin locks. Tries to grow, on malloc failure, nothing happened.

Parameters
tablehash table.