1 /******************************************************
2 The simple hash table utility
6 Created 5/20/1997 Heikki Tuuri
7 *******************************************************/
14 #include "sync0sync.h"
16 typedef struct hash_table_struct hash_table_t
;
17 typedef struct hash_cell_struct hash_cell_t
;
19 typedef void* hash_node_t
;
21 /* Fix Bug #13859: symbol collision between imap/mysql */
22 #define hash_create hash0_create
24 /*****************************************************************
25 Creates a hash table with >= n array cells. The actual number
26 of cells is chosen to be a prime number slightly bigger than n. */
31 /* out, own: created table */
32 ulint n
); /* in: number of array cells */
33 /*****************************************************************
34 Creates a mutex array to protect a hash table. */
37 hash_create_mutexes_func(
38 /*=====================*/
39 hash_table_t
* table
, /* in: hash table */
40 #ifdef UNIV_SYNC_DEBUG
41 ulint sync_level
, /* in: latching order level of the
42 mutexes: used in the debug version */
43 #endif /* UNIV_SYNC_DEBUG */
44 ulint n_mutexes
); /* in: number of mutexes */
45 #ifdef UNIV_SYNC_DEBUG
46 # define hash_create_mutexes(t,n,level) hash_create_mutexes_func(t,level,n)
47 #else /* UNIV_SYNC_DEBUG */
48 # define hash_create_mutexes(t,n,level) hash_create_mutexes_func(t,n)
49 #endif /* UNIV_SYNC_DEBUG */
51 /*****************************************************************
52 Frees a hash table. */
57 hash_table_t
* table
); /* in, own: hash table */
58 /******************************************************************
59 Calculates the hash value from a folded value. */
64 /* out: hashed value */
65 ulint fold
, /* in: folded value */
66 hash_table_t
* table
); /* in: hash table */
67 /************************************************************************
68 Assert that the mutex for the table in a hash operation is owned. */
69 #ifdef UNIV_SYNC_DEBUG
70 # define HASH_ASSERT_OWNED(TABLE, FOLD) \
71 ut_ad(!(TABLE)->mutexes || mutex_own(hash_get_mutex(TABLE, FOLD)));
73 # define HASH_ASSERT_OWNED(TABLE, FOLD)
76 /***********************************************************************
77 Inserts a struct to a hash table. */
79 #define HASH_INSERT(TYPE, NAME, TABLE, FOLD, DATA)\
81 hash_cell_t* cell3333;\
84 HASH_ASSERT_OWNED(TABLE, FOLD)\
88 cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\
90 if (cell3333->node == NULL) {\
91 cell3333->node = DATA;\
93 struct3333 = cell3333->node;\
95 while (struct3333->NAME != NULL) {\
97 struct3333 = struct3333->NAME;\
100 struct3333->NAME = DATA;\
104 /***********************************************************************
105 Deletes a struct from a hash table. */
107 #define HASH_DELETE(TYPE, NAME, TABLE, FOLD, DATA)\
109 hash_cell_t* cell3333;\
112 HASH_ASSERT_OWNED(TABLE, FOLD)\
114 cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\
116 if (cell3333->node == DATA) {\
117 cell3333->node = DATA->NAME;\
119 struct3333 = cell3333->node;\
121 while (struct3333->NAME != DATA) {\
123 struct3333 = struct3333->NAME;\
127 struct3333->NAME = DATA->NAME;\
131 /***********************************************************************
132 Gets the first struct in a hash chain, NULL if none. */
134 #define HASH_GET_FIRST(TABLE, HASH_VAL)\
135 (hash_get_nth_cell(TABLE, HASH_VAL)->node)
137 /***********************************************************************
138 Gets the next struct in a hash chain, NULL if none. */
140 #define HASH_GET_NEXT(NAME, DATA) ((DATA)->NAME)
142 /************************************************************************
143 Looks for a struct in a hash table. */
144 #define HASH_SEARCH(NAME, TABLE, FOLD, DATA, TEST)\
147 HASH_ASSERT_OWNED(TABLE, FOLD)\
149 (DATA) = HASH_GET_FIRST(TABLE, hash_calc_hash(FOLD, TABLE));\
151 while ((DATA) != NULL) {\
155 (DATA) = HASH_GET_NEXT(NAME, DATA);\
160 /****************************************************************
161 Gets the nth cell in a hash table. */
166 /* out: pointer to cell */
167 hash_table_t
* table
, /* in: hash table */
168 ulint n
); /* in: cell index */
169 /*****************************************************************
170 Returns the number of cells in a hash table. */
175 /* out: number of cells */
176 hash_table_t
* table
); /* in: table */
177 /***********************************************************************
178 Deletes a struct which is stored in the heap of the hash table, and compacts
179 the heap. The fold value must be stored in the struct NODE in a field named
182 #define HASH_DELETE_AND_COMPACT(TYPE, NAME, TABLE, NODE)\
186 hash_cell_t* cell111;\
189 fold111 = (NODE)->fold;\
191 HASH_DELETE(TYPE, NAME, TABLE, fold111, NODE);\
193 top_node111 = (TYPE*)mem_heap_get_top(\
194 hash_get_heap(TABLE, fold111),\
197 /* If the node to remove is not the top node in the heap, compact the\
198 heap of nodes by moving the top node in the place of NODE. */\
200 if (NODE != top_node111) {\
202 /* Copy the top node in place of NODE */\
204 *(NODE) = *top_node111;\
206 cell111 = hash_get_nth_cell(TABLE,\
207 hash_calc_hash(top_node111->fold, TABLE));\
209 /* Look for the pointer to the top node, to update it */\
211 if (cell111->node == top_node111) {\
212 /* The top node is the first in the chain */\
214 cell111->node = NODE;\
216 /* We have to look for the predecessor of the top\
218 node111 = cell111->node;\
220 while (top_node111 != HASH_GET_NEXT(NAME, node111)) {\
222 node111 = HASH_GET_NEXT(NAME, node111);\
225 /* Now we have the predecessor node */\
227 node111->NAME = NODE;\
231 /* Free the space occupied by the top node */\
233 mem_heap_free_top(hash_get_heap(TABLE, fold111), sizeof(TYPE));\
236 /********************************************************************
237 Move all hash table entries from OLD_TABLE to NEW_TABLE.*/
239 #define HASH_MIGRATE(OLD_TABLE, NEW_TABLE, NODE_TYPE, PTR_NAME, FOLD_FUNC) \
242 ulint cell_count2222;\
244 cell_count2222 = hash_get_n_cells(OLD_TABLE);\
246 for (i2222 = 0; i2222 < cell_count2222; i2222++) {\
247 NODE_TYPE* node2222 = HASH_GET_FIRST((OLD_TABLE), i2222);\
250 NODE_TYPE* next2222 = node2222->PTR_NAME;\
251 ulint fold2222 = FOLD_FUNC(node2222);\
253 HASH_INSERT(NODE_TYPE, PTR_NAME, (NEW_TABLE),\
254 fold2222, node2222);\
256 node2222 = next2222;\
262 /****************************************************************
263 Gets the mutex index for a fold value in a hash table. */
268 /* out: mutex number */
269 hash_table_t
* table
, /* in: hash table */
270 ulint fold
); /* in: fold */
271 /****************************************************************
272 Gets the nth heap in a hash table. */
278 hash_table_t
* table
, /* in: hash table */
279 ulint i
); /* in: index of the heap */
280 /****************************************************************
281 Gets the heap for a fold value in a hash table. */
287 hash_table_t
* table
, /* in: hash table */
288 ulint fold
); /* in: fold */
289 /****************************************************************
290 Gets the nth mutex in a hash table. */
296 hash_table_t
* table
, /* in: hash table */
297 ulint i
); /* in: index of the mutex */
298 /****************************************************************
299 Gets the mutex for a fold value in a hash table. */
305 hash_table_t
* table
, /* in: hash table */
306 ulint fold
); /* in: fold */
307 /****************************************************************
308 Reserves the mutex for a fold value in a hash table. */
313 hash_table_t
* table
, /* in: hash table */
314 ulint fold
); /* in: fold */
315 /****************************************************************
316 Releases the mutex for a fold value in a hash table. */
321 hash_table_t
* table
, /* in: hash table */
322 ulint fold
); /* in: fold */
323 /****************************************************************
324 Reserves all the mutexes of a hash table, in an ascending order. */
327 hash_mutex_enter_all(
328 /*=================*/
329 hash_table_t
* table
); /* in: hash table */
330 /****************************************************************
331 Releases all the mutexes of a hash table. */
336 hash_table_t
* table
); /* in: hash table */
339 struct hash_cell_struct
{
340 void* node
; /* hash chain node, NULL if none */
343 /* The hash table structure */
344 struct hash_table_struct
{
345 ibool adaptive
;/* TRUE if this is the hash table of the
346 adaptive hash index */
347 ulint n_cells
;/* number of cells in the hash table */
348 hash_cell_t
* array
; /* pointer to cell array */
349 ulint n_mutexes
;/* if mutexes != NULL, then the number of
350 mutexes, must be a power of 2 */
351 mutex_t
* mutexes
;/* NULL, or an array of mutexes used to
352 protect segments of the hash table */
353 mem_heap_t
** heaps
; /* if this is non-NULL, hash chain nodes for
354 external chaining can be allocated from these
355 memory heaps; there are then n_mutexes many of
361 #define HASH_TABLE_MAGIC_N 76561114
364 #include "hash0hash.ic"