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"