hce-node application  1.4.3
HCE Hierarchical Cluster Engine node application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cf_shash.h
Go to the documentation of this file.
1 /*
2  * A general purpose hashtable implementation
3  * Uses locks, so only moderately fast
4  * Just, hopefully, the last hash table you'll ever need
5  * And you can keep adding cool things to it
6  * Copywrite 2008 Brian Bulkowski
7  * All rights reserved
8  */
9 
10 #pragma once
11 
12 #include <pthread.h>
13 #include <stddef.h>
14 #include <stdint.h>
15 
17 
18 // #define CITRUSLEAF 1
19 
20 #define SHASH_ERR_FOUND -4
21 #define SHASH_ERR_NOTFOUND -3
22 #define SHASH_ERR_BUFSZ -2
23 #define SHASH_ERR -1
24 #define SHASH_OK 0
25 
26 #ifdef CITRUSLEAF
27 #include "cf.h"
28 #else
29 typedef uint8_t byte;
30 #endif
31 
32 /* cf_hash_fnv
33  * The 64-bit Fowler-Noll-Voll hash function (FNV-1a) */
34 //
35 // This algorithm is PUBLIC DOMAIN:
36 //
37 // FNV hash algorithms and source code have been released into the public domain. The authors of the
38 // FNV algorithmm look deliberate steps to disclose the algorhtm in a public forum soon after it was
39 // invented. More than a year passed after this public disclosure and the authors deliberatly took no
40 // steps to patent the FNV algorithm. Therefore it is safe to say that the FNV authors have no patent
41 // claims on the FNV algorithm as published.
42 // Source: http://www.isthe.com/chongo/tech/comp/fnv/index.html
43 //
44 // FNV on Wikipedia: http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
45 //
46 static inline uint64_t
47 cf_hash_fnv(void *buf, size_t bufsz)
48 {
49  uint64_t hash = 0xcbf29ce484222325ULL;
50  uint8_t *bufp = (uint8_t *)buf;
51  uint8_t *bufe = bufp + bufsz;
52 
53  while (bufp < bufe) {
54  /* XOR the current byte into the bottom of the hash */
55  hash ^= (uint64_t)*bufp++;
56 
57  /* Multiply by the 64-bit FNV magic prime */
58  hash *= 0x100000001b3ULL;
59  }
60 
61  return(hash);
62 }
63 
64 /*
65  * A generic call for hash functions the user can create
66  */
67 typedef uint32_t (*shash_hash_fn) (void *key);
68 
69 /*
70 ** Typedef for a "reduce" fuction that is called on every node
71 ** (Note about return value: some kinds of reduces can manipulate the hash table,
72 ** allowing deletion. See the particulars of the reduce call.)
73 */
74 typedef int (*shash_reduce_fn) (void *key, void *data, void *udata);
75 
76 // Simple (and slow) element is when
77 // everything is variable (although a very nicely packed structure for 32 or 64
78 typedef struct shash_elem_s {
79  struct shash_elem_s *next;
80  bool in_use;
81  uint8_t data[]; // key_len bytes of key, value_len bytes of value
82 } shash_elem;
83 
84 
85 #define SHASH_ELEM_KEY_PTR(_h, _e) ( (void *) _e->data )
86 
87 #define SHASH_ELEM_VALUE_PTR(_h, _e) ( (void *) (_e->data + _h->key_len) )
88 
89 typedef struct shash_s {
90  unsigned int elements; // INVALID in manylocks case - see notes under get_size
91  uint32_t key_len;
92  uint32_t value_len;
93  unsigned int flags;
95 
96  unsigned int table_len; // number of elements currently in the table
97  void *table;
98  pthread_mutex_t biglock;
99  pthread_mutex_t *lock_table;
100 } shash;
101 
102 #define SHASH_ELEM_SZ(_h) ( sizeof(shash_elem) + (_h->key_len) + (_h->value_len) )
103 
104 #define SHASH_CR_RESIZE 0x01 // support resizes (will sometimes hang for long periods)
105 #define SHASH_CR_GRAB 0x02 // support 'grab' call (requires more memory)
106 #define SHASH_CR_MT_BIGLOCK 0x04 // support multithreaded access with a single big lock
107 #define SHASH_CR_MT_MANYLOCK 0x08 // support multithreaded access with a pool of object loccks
108 
109 #define SHASH_REDUCE_DELETE (1) // indicate that a delete should be done during the reduction
110 
111 /*
112  * Create a hash table
113  * Pass in the hash function (required)
114  * the key length if static (if not static pass 0
115  * the value length if static (if not static pass 0
116  * The initial table size
117  * a set of flags
118  */
119 
120 int
121 shash_create(shash **h, shash_hash_fn h_fn, uint32_t key_len, uint32_t value_len, uint32_t sz, unsigned int flags);
122 
123 /* Place a value into the hash
124  * Value will be copied into the hash
125  */
126 int
127 shash_put(shash *h, void *key, void *value);
128 int
129 shash_put_unique(shash *h, void *key, void *value);
130 
131 /* call with the buffer you want filled; if you just want to check for
132  * existence, call with value set to NULL
133  */
134 int
135 shash_get(shash *h, void *key, void *value);
136 
137 /* Returns the pointer to the internal item, and a locked-lock
138  * which allows the touching of internal state. If non-lock hash table,
139  * vlock param will be ignored
140  *
141  * Note that the vlock is passed back only when the return code is BB_OK.
142  * In the case where nothing is found, no lock is held.
143  * It might be better to do it the other way, but you can change it later if you want
144  */
145 int
146 shash_get_vlock(shash *h, void *key, void **value,pthread_mutex_t **vlock);
147 
148 /* Does a get and delete at the same time so you can make sure only one person
149  * gets what was inserted
150  */
151 int
152 shash_get_and_delete(shash *h, void *key, void *value);
153 
154 
155 /*
156 ** Got a key you want removed - this is the function to call
157 */
158 int
159 shash_delete(shash *h, void *key);
160 
161 /*
162 ** Special function you can call when you already have the lock - such as
163 ** a vlock get
164 */
165 int
166 shash_delete_lockfree(shash *h, void *key);
167 
168 
169 /*
170 ** Get the number of elements currently in the hash
171 */
172 uint32_t
174 
175 /*
176  * An interesting idea: readv / writev for these functions?
177  */
178 
179 /* Find / get a value from the hash
180  * But take the reference count on the object; must be returned with the
181  * return call
182  */
183 int
184 shash_grab(shash *h, void *key, uint32_t key_len, void **value, uint32_t *value_len);
185 
186 /* Return a value that has been gotten
187  */
188 int
189 shash_return(shash *h, void *value);
190 
191 /*
192 ** Map/Reduce pattern - call the callback on every element in the hash
193 ** Warning: the entire traversal can hold the lock in the 'biglock' case,
194 ** so make the reduce_fn lightweight! Consider queuing or soemthing if you
195 ** want to do something fancy
196 */
197 int
198 shash_reduce(shash *h, shash_reduce_fn reduce_fn, void *udata);
199 
200 /*
201 ** Map/Reduce pattern - call the callback on every element in the hash
202 ** This instance allows deletion of hash elements during the reduce:
203 ** return -1 to cause the deletion of the element visisted
204 */
205 
206 int
207 shash_reduce_delete(shash *h, shash_reduce_fn reduce_fn, void *udata);
208 
209 
210 /*
211  * Destroy the entire hash - all memory will be freed
212  */
213 void
214 shash_destroy(shash *h);
215