1 /*****************************************************************************
3 Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *****************************************************************************/
19 /**************************************************//**
20 @file include/hash0hash.h
21 The simple hash table utility
23 Created 5/20/1997 Heikki Tuuri
24 *******************************************************/
31 #ifndef UNIV_HOTBACKUP
32 # include "sync0sync.h"
33 #endif /* !UNIV_HOTBACKUP */
35 typedef struct hash_table_struct hash_table_t
;
36 typedef struct hash_cell_struct hash_cell_t
;
38 typedef void* hash_node_t
;
40 /* Fix Bug #13859: symbol collision between imap/mysql */
41 #define hash_create hash0_create
43 /*************************************************************//**
44 Creates a hash table with >= n array cells. The actual number
45 of cells is chosen to be a prime number slightly bigger than n.
46 @return own: created table */
51 ulint n
); /*!< in: number of array cells */
52 #ifndef UNIV_HOTBACKUP
53 /*************************************************************//**
54 Creates a mutex array to protect a hash table. */
57 hash_create_mutexes_func(
58 /*=====================*/
59 hash_table_t
* table
, /*!< in: hash table */
60 #ifdef UNIV_SYNC_DEBUG
61 ulint sync_level
, /*!< in: latching order level of the
62 mutexes: used in the debug version */
63 #endif /* UNIV_SYNC_DEBUG */
64 ulint n_mutexes
); /*!< in: number of mutexes */
65 #ifdef UNIV_SYNC_DEBUG
66 # define hash_create_mutexes(t,n,level) hash_create_mutexes_func(t,level,n)
67 #else /* UNIV_SYNC_DEBUG */
68 # define hash_create_mutexes(t,n,level) hash_create_mutexes_func(t,n)
69 #endif /* UNIV_SYNC_DEBUG */
70 #endif /* !UNIV_HOTBACKUP */
72 /*************************************************************//**
73 Frees a hash table. */
78 hash_table_t
* table
); /*!< in, own: hash table */
79 /**************************************************************//**
80 Calculates the hash value from a folded value.
81 @return hashed value */
86 ulint fold
, /*!< in: folded value */
87 hash_table_t
* table
); /*!< in: hash table */
88 #ifndef UNIV_HOTBACKUP
89 /********************************************************************//**
90 Assert that the mutex for the table in a hash operation is owned. */
91 # define HASH_ASSERT_OWNED(TABLE, FOLD) \
92 ut_ad(!(TABLE)->mutexes || mutex_own(hash_get_mutex(TABLE, FOLD)));
93 #else /* !UNIV_HOTBACKUP */
94 # define HASH_ASSERT_OWNED(TABLE, FOLD)
95 #endif /* !UNIV_HOTBACKUP */
97 /*******************************************************************//**
98 Inserts a struct to a hash table. */
100 #define HASH_INSERT(TYPE, NAME, TABLE, FOLD, DATA)\
102 hash_cell_t* cell3333;\
105 HASH_ASSERT_OWNED(TABLE, FOLD)\
107 (DATA)->NAME = NULL;\
109 cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\
111 if (cell3333->node == NULL) {\
112 cell3333->node = DATA;\
114 struct3333 = (TYPE*) cell3333->node;\
116 while (struct3333->NAME != NULL) {\
118 struct3333 = (TYPE*) struct3333->NAME;\
121 struct3333->NAME = DATA;\
125 #ifdef UNIV_HASH_DEBUG
126 # define HASH_ASSERT_VALID(DATA) ut_a((void*) (DATA) != (void*) -1)
127 # define HASH_INVALIDATE(DATA, NAME) DATA->NAME = (void*) -1
129 # define HASH_ASSERT_VALID(DATA) do {} while (0)
130 # define HASH_INVALIDATE(DATA, NAME) do {} while (0)
133 /*******************************************************************//**
134 Deletes a struct from a hash table. */
136 #define HASH_DELETE(TYPE, NAME, TABLE, FOLD, DATA)\
138 hash_cell_t* cell3333;\
141 HASH_ASSERT_OWNED(TABLE, FOLD)\
143 cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\
145 if (cell3333->node == DATA) {\
146 HASH_ASSERT_VALID(DATA->NAME);\
147 cell3333->node = DATA->NAME;\
149 struct3333 = (TYPE*) cell3333->node;\
151 while (struct3333->NAME != DATA) {\
153 struct3333 = (TYPE*) struct3333->NAME;\
157 struct3333->NAME = DATA->NAME;\
159 HASH_INVALIDATE(DATA, NAME);\
162 /*******************************************************************//**
163 Gets the first struct in a hash chain, NULL if none. */
165 #define HASH_GET_FIRST(TABLE, HASH_VAL)\
166 (hash_get_nth_cell(TABLE, HASH_VAL)->node)
168 /*******************************************************************//**
169 Gets the next struct in a hash chain, NULL if none. */
171 #define HASH_GET_NEXT(NAME, DATA) ((DATA)->NAME)
173 /********************************************************************//**
174 Looks for a struct in a hash table. */
175 #define HASH_SEARCH(NAME, TABLE, FOLD, TYPE, DATA, ASSERTION, TEST)\
178 HASH_ASSERT_OWNED(TABLE, FOLD)\
180 (DATA) = (TYPE) HASH_GET_FIRST(TABLE, hash_calc_hash(FOLD, TABLE));\
181 HASH_ASSERT_VALID(DATA);\
183 while ((DATA) != NULL) {\
188 HASH_ASSERT_VALID(HASH_GET_NEXT(NAME, DATA));\
189 (DATA) = (TYPE) HASH_GET_NEXT(NAME, DATA);\
194 /********************************************************************//**
195 Looks for an item in all hash buckets. */
196 #define HASH_SEARCH_ALL(NAME, TABLE, TYPE, DATA, ASSERTION, TEST) \
200 for (i3333 = (TABLE)->n_cells; i3333--; ) { \
201 (DATA) = (TYPE) HASH_GET_FIRST(TABLE, i3333); \
203 while ((DATA) != NULL) { \
204 HASH_ASSERT_VALID(DATA); \
211 (DATA) = (TYPE) HASH_GET_NEXT(NAME, DATA); \
214 if ((DATA) != NULL) { \
220 /************************************************************//**
221 Gets the nth cell in a hash table.
222 @return pointer to cell */
227 hash_table_t
* table
, /*!< in: hash table */
228 ulint n
); /*!< in: cell index */
230 /*************************************************************//**
231 Clears a hash table so that all the cells become empty. */
236 hash_table_t
* table
); /*!< in/out: hash table */
238 /*************************************************************//**
239 Returns the number of cells in a hash table.
240 @return number of cells */
245 hash_table_t
* table
); /*!< in: table */
246 /*******************************************************************//**
247 Deletes a struct which is stored in the heap of the hash table, and compacts
248 the heap. The fold value must be stored in the struct NODE in a field named
251 #define HASH_DELETE_AND_COMPACT(TYPE, NAME, TABLE, NODE)\
255 hash_cell_t* cell111;\
258 fold111 = (NODE)->fold;\
260 HASH_DELETE(TYPE, NAME, TABLE, fold111, NODE);\
262 top_node111 = (TYPE*)mem_heap_get_top(\
263 hash_get_heap(TABLE, fold111),\
266 /* If the node to remove is not the top node in the heap, compact the\
267 heap of nodes by moving the top node in the place of NODE. */\
269 if (NODE != top_node111) {\
271 /* Copy the top node in place of NODE */\
273 *(NODE) = *top_node111;\
275 cell111 = hash_get_nth_cell(TABLE,\
276 hash_calc_hash(top_node111->fold, TABLE));\
278 /* Look for the pointer to the top node, to update it */\
280 if (cell111->node == top_node111) {\
281 /* The top node is the first in the chain */\
283 cell111->node = NODE;\
285 /* We have to look for the predecessor of the top\
287 node111 = cell111->node;\
289 while (top_node111 != HASH_GET_NEXT(NAME, node111)) {\
291 node111 = HASH_GET_NEXT(NAME, node111);\
294 /* Now we have the predecessor node */\
296 node111->NAME = NODE;\
300 /* Free the space occupied by the top node */\
302 mem_heap_free_top(hash_get_heap(TABLE, fold111), sizeof(TYPE));\
305 #ifndef UNIV_HOTBACKUP
306 /****************************************************************//**
307 Move all hash table entries from OLD_TABLE to NEW_TABLE. */
309 #define HASH_MIGRATE(OLD_TABLE, NEW_TABLE, NODE_TYPE, PTR_NAME, FOLD_FUNC) \
312 ulint cell_count2222;\
314 cell_count2222 = hash_get_n_cells(OLD_TABLE);\
316 for (i2222 = 0; i2222 < cell_count2222; i2222++) {\
317 NODE_TYPE* node2222 = HASH_GET_FIRST((OLD_TABLE), i2222);\
320 NODE_TYPE* next2222 = node2222->PTR_NAME;\
321 ulint fold2222 = FOLD_FUNC(node2222);\
323 HASH_INSERT(NODE_TYPE, PTR_NAME, (NEW_TABLE),\
324 fold2222, node2222);\
326 node2222 = next2222;\
331 /************************************************************//**
332 Gets the mutex index for a fold value in a hash table.
333 @return mutex number */
338 hash_table_t
* table
, /*!< in: hash table */
339 ulint fold
); /*!< in: fold */
340 /************************************************************//**
341 Gets the nth heap in a hash table.
347 hash_table_t
* table
, /*!< in: hash table */
348 ulint i
); /*!< in: index of the heap */
349 /************************************************************//**
350 Gets the heap for a fold value in a hash table.
356 hash_table_t
* table
, /*!< in: hash table */
357 ulint fold
); /*!< in: fold */
358 /************************************************************//**
359 Gets the nth mutex in a hash table.
365 hash_table_t
* table
, /*!< in: hash table */
366 ulint i
); /*!< in: index of the mutex */
367 /************************************************************//**
368 Gets the mutex for a fold value in a hash table.
374 hash_table_t
* table
, /*!< in: hash table */
375 ulint fold
); /*!< in: fold */
376 /************************************************************//**
377 Reserves the mutex for a fold value in a hash table. */
382 hash_table_t
* table
, /*!< in: hash table */
383 ulint fold
); /*!< in: fold */
384 /************************************************************//**
385 Releases the mutex for a fold value in a hash table. */
390 hash_table_t
* table
, /*!< in: hash table */
391 ulint fold
); /*!< in: fold */
392 /************************************************************//**
393 Reserves all the mutexes of a hash table, in an ascending order. */
396 hash_mutex_enter_all(
397 /*=================*/
398 hash_table_t
* table
); /*!< in: hash table */
399 /************************************************************//**
400 Releases all the mutexes of a hash table. */
405 hash_table_t
* table
); /*!< in: hash table */
406 #else /* !UNIV_HOTBACKUP */
407 # define hash_get_heap(table, fold) ((table)->heap)
408 # define hash_mutex_enter(table, fold) ((void) 0)
409 # define hash_mutex_exit(table, fold) ((void) 0)
410 #endif /* !UNIV_HOTBACKUP */
412 struct hash_cell_struct
{
413 void* node
; /*!< hash chain node, NULL if none */
416 /* The hash table structure */
417 struct hash_table_struct
{
418 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
419 # ifndef UNIV_HOTBACKUP
420 ibool adaptive
;/* TRUE if this is the hash table of the
421 adaptive hash index */
422 # endif /* !UNIV_HOTBACKUP */
423 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
424 ulint n_cells
;/* number of cells in the hash table */
425 hash_cell_t
* array
; /*!< pointer to cell array */
426 #ifndef UNIV_HOTBACKUP
427 ulint n_mutexes
;/* if mutexes != NULL, then the number of
428 mutexes, must be a power of 2 */
429 mutex_t
* mutexes
;/* NULL, or an array of mutexes used to
430 protect segments of the hash table */
431 mem_heap_t
** heaps
; /*!< if this is non-NULL, hash chain nodes for
432 external chaining can be allocated from these
433 memory heaps; there are then n_mutexes many of
435 #endif /* !UNIV_HOTBACKUP */
439 # define HASH_TABLE_MAGIC_N 76561114
440 #endif /* UNIV_DEBUG */
444 #include "hash0hash.ic"