All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
src/include/citrusleaf/cf_shash.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2008-2013 by Aerospike.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  *****************************************************************************/
22 #pragma once
23 
24  /*
25  * A general purpose hashtable implementation
26  * Uses locks, so only moderately fast
27  * Just, hopefully, the last hash table you'll ever need
28  * And you can keep adding cool things to it
29  */
30 
31 #include <pthread.h>
32 #include <stdbool.h>
33 #include <stddef.h>
34 #include <stdint.h>
35 
36 #include <citrusleaf/cf_types.h>
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 /******************************************************************************
43  * CONSTANTS
44  ******************************************************************************/
45 
46 #define SHASH_ERR_FOUND -4
47 #define SHASH_ERR_NOTFOUND -3
48 #define SHASH_ERR_BUFSZ -2
49 #define SHASH_ERR -1
50 #define SHASH_OK 0
51 
52 /**
53  * support resizes (will sometimes hang for long periods)
54  */
55 #define SHASH_CR_RESIZE 0x01
56 
57 /**
58  * support 'grab' call (requires more memory)
59  */
60 #define SHASH_CR_GRAB 0x02
61 
62 /**
63  * support multithreaded access with a single big lock
64  */
65 #define SHASH_CR_MT_BIGLOCK 0x04
66 
67 /**
68  * support multithreaded access with a pool of object loccks
69  */
70 #define SHASH_CR_MT_MANYLOCK 0x08
71 
72 /**
73  * Do not track memory allocations in this hash table.
74  * (Used only when creating the hash table tracking memory allocations....)
75  */
76 #define SHASH_CR_UNTRACKED 0x10
77 
78 /**
79  * indicate that a delete should be done during the reduction
80  */
81 #define SHASH_REDUCE_DELETE (1)
82 
83 /******************************************************************************
84  * TYPES
85  ******************************************************************************/
86 
87 /**
88  * A generic call for hash functions the user can create
89  */
90 typedef uint32_t (*shash_hash_fn) (void *key);
91 
92 /**
93  * Type for a function to be called under the hash table locks to atomically update a hash table entry.
94  * The old value is the current value of the key, or NULL if non-existent.
95  * The new value is allocated by the caller.
96  * User data can be anything.
97  */
98 typedef void (*shash_update_fn) (void *key, void *value_old, void *value_new, void *udata);
99 
100 /**
101  * Typedef for a "reduce" fuction that is called on every node
102  * (Note about return value: some kinds of reduces can manipulate the hash table,
103  * allowing deletion. See the particulars of the reduce call.)
104  */
105 typedef int (*shash_reduce_fn) (void *key, void *data, void *udata);
106 
107 /**
108  * Simple (and slow) element is when
109  * everything is variable (although a very nicely packed structure for 32 or 64
110  */
111 struct shash_elem_s {
113  bool in_use;
114  uint8_t data[]; // key_len bytes of key, value_len bytes of value
115 };
116 
117 typedef struct shash_elem_s shash_elem;
118 
119 struct shash_s {
120  uint elements; // INVALID in manylocks case - see notes under get_size
121  uint32_t key_len;
122  uint32_t value_len;
125  uint table_len; // number of elements currently in the table
126  void * table;
127  pthread_mutex_t biglock;
128  pthread_mutex_t * lock_table;
129 };
130 
131 typedef struct shash_s shash;
132 
133 /******************************************************************************
134  * FUNCTIONS
135  ******************************************************************************/
136 
137 /**
138  * Create a hash table
139  * Pass in the hash function (required)
140  * the key length if static (if not static pass 0
141  * the value length if static (if not static pass 0
142  * The initial table size
143  * a set of flags
144  */
145 int shash_create(shash **h, shash_hash_fn h_fn, uint32_t key_len, uint32_t value_len, uint32_t sz, uint flags);
146 
147 /**
148  * Place a value into the hash
149  * Value will be copied into the hash
150  */
151 int shash_put(shash *h, void *key, void *value);
152 
153 /**
154  * Place a unique value into the hash
155  * Value will be copied into the hash
156  */
157 int shash_put_unique(shash *h, void *key, void *value);
158 
159 /**
160  * Place a duplicate value into the hash
161  * Value will be copied into the hash
162  */
163 int shash_put_duplicate(shash *h, void *key, void *value);
164 
165 /**
166  * call with the buffer you want filled; if you just want to check for
167  * existence, call with value set to NULL
168  */
169 int shash_get(shash *h, void *key, void *value);
170 
171 /**
172  * Returns the pointer to the internal item, and a locked-lock
173  * which allows the touching of internal state. If non-lock hash table,
174  * vlock param will be ignored
175  *
176  * Note that the vlock is passed back only when the return code is BB_OK.
177  * In the case where nothing is found, no lock is held.
178  * It might be better to do it the other way, but you can change it later if you want
179  */
180 int shash_get_vlock(shash *h, void *key, void **value,pthread_mutex_t **vlock);
181 
182 /**
183  * Does a get and delete at the same time so you can make sure only one person
184  * gets what was inserted
185  */
186 int shash_get_and_delete(shash *h, void *key, void *value);
187 
188 /**
189  * Atomically update an entry in the hash table using a user-supplied update function and user data.
190  * The update function performs the merge of the old and new values, with respect to the user data
191  * and returns the new value.
192  */
193 int shash_update(shash *h, void *key, void *value_old, void *value_new, shash_update_fn update_fn, void *udata);
194 
195 /**
196  * Got a key you want removed - this is the function to call
197  */
198 int shash_delete(shash *h, void *key);
199 
200 /**
201  * Special function you can call when you already have the lock - such as
202  * a vlock get
203  */
204 int shash_delete_lockfree(shash *h, void *key);
205 
206 /**
207  * Get the number of elements currently in the hash
208  */
209 uint32_t shash_get_size(shash *h);
210 
211 /**
212  * An interesting idea: readv / writev for these functions?
213  */
214 
215 /**
216  * Find / get a value from the hash
217  * But take the reference count on the object; must be returned with the
218  * return call
219  */
220 int shash_grab(shash *h, void *key, uint32_t key_len, void **value, uint32_t *value_len);
221 
222 /**
223  * Return a value that has been gotten
224  */
225 int shash_return(shash *h, void *value);
226 
227 /**
228  * Map/Reduce pattern - call the callback on every element in the hash
229  * Warning: the entire traversal can hold the lock in the 'biglock' case,
230  * so make the reduce_fn lightweight! Consider queuing or soemthing if you
231  * want to do something fancy
232  */
233 int shash_reduce(shash *h, shash_reduce_fn reduce_fn, void *udata);
234 
235 /**
236  * Map/Reduce pattern - call the callback on every element in the hash
237  * This instance allows deletion of hash elements during the reduce:
238  * return -1 to cause the deletion of the element visisted
239  */
240 int shash_reduce_delete(shash *h, shash_reduce_fn reduce_fn, void *udata);
241 
242 /**
243  * Delete all the data from the entire hash - complete cleanup
244  */
245 void shash_deleteall_lockfree(shash *h);
246 
247 /**
248  * Destroy the entire hash - all memory will be freed
249  */
250 void shash_destroy(shash *h);
251 
252 /******************************************************************************
253  * MACROS
254  ******************************************************************************/
255 
256 #define SHASH_ELEM_KEY_PTR(_h, _e) ( (void *) _e->data )
257 #define SHASH_ELEM_VALUE_PTR(_h, _e) ( (void *) (_e->data + _h->key_len) )
258 #define SHASH_ELEM_SZ(_h) ( sizeof(shash_elem) + (_h->key_len) + (_h->value_len) )
259 
260 /******************************************************************************/
261 
262 #ifdef __cplusplus
263 } // end extern "C"
264 #endif