1
/*****************************************************************************
3
Copyright (C) 1994, 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., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/********************************************************************//**
1
/************************************************************************
21
2
The hash table with external chains
4
(c) 1994-1997 Innobase Oy
23
6
Created 8/22/1994 Heikki Tuuri
24
7
*************************************************************************/
32
15
# include "buf0buf.h"
33
16
#endif /* UNIV_DEBUG */
17
#ifdef UNIV_SYNC_DEBUG
19
#endif /* UNIV_SYNC_DEBUG */
35
20
#include "page0page.h"
37
/*************************************************************//**
38
Creates a hash table with at least n array cells. The actual number
39
of cells is chosen to be a prime number slightly bigger than n.
40
@return own: created table */
22
/*****************************************************************
23
Creates a hash table with >= n array cells. The actual number of cells is
24
chosen to be a prime number slightly bigger than n. */
45
ulint n, /*!< in: number of array cells */
29
/* out, own: created table */
30
ulint n, /* in: number of array cells */
46
31
#ifdef UNIV_SYNC_DEBUG
47
ulint mutex_level, /*!< in: level of the mutexes in the latching
32
ulint mutex_level, /* in: level of the mutexes in the latching
48
33
order: this is used in the debug version */
49
34
#endif /* UNIV_SYNC_DEBUG */
50
ulint n_mutexes) /*!< in: number of mutexes to protect the
35
ulint n_mutexes) /* in: number of mutexes to protect the
51
36
hash table: must be a power of 2, or 0 */
53
38
hash_table_t* table;
54
#ifndef UNIV_HOTBACKUP
56
#endif /* !UNIV_HOTBACKUP */
58
ut_ad(ut_is_2pow(n_mutexes));
59
41
table = hash_create(n);
61
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
62
# ifndef UNIV_HOTBACKUP
63
44
table->adaptive = TRUE;
64
# endif /* !UNIV_HOTBACKUP */
65
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
45
#endif /* UNIV_DEBUG */
66
46
/* Creating MEM_HEAP_BTR_SEARCH type heaps can potentially fail,
67
47
but in practise it never should in this case, hence the asserts. */
77
#ifndef UNIV_HOTBACKUP
78
57
hash_create_mutexes(table, n_mutexes, mutex_level);
80
table->heaps = static_cast<mem_block_info_t **>(mem_alloc(n_mutexes * sizeof(mem_block_info_t *)));
59
table->heaps = mem_alloc(n_mutexes * sizeof(void*));
82
61
for (i = 0; i < n_mutexes; i++) {
83
62
table->heaps[i] = mem_heap_create_in_btr_search(4096);
84
63
ut_a(table->heaps[i]);
86
#endif /* !UNIV_HOTBACKUP */
91
/*************************************************************//**
69
/*****************************************************************
92
70
Empties a hash table and frees the memory heaps. */
97
hash_table_t* table) /*!< in, own: hash table */
75
hash_table_t* table) /* in, own: hash table */
103
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
104
80
#ifdef UNIV_SYNC_DEBUG
105
81
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
106
82
#endif /* UNIV_SYNC_DEBUG */
108
#ifndef UNIV_HOTBACKUP
109
84
/* Free the memory heaps. */
110
85
n = table->n_mutexes;
112
87
for (i = 0; i < n; i++) {
113
88
mem_heap_free(table->heaps[i]);
115
#endif /* !UNIV_HOTBACKUP */
117
91
/* Clear the hash table. */
118
92
n = hash_get_n_cells(table);
125
/*************************************************************//**
99
/*****************************************************************
126
100
Inserts an entry into a hash table. If an entry with the same fold number
127
101
is found, its node is updated to point to the new data, and no new node
128
is inserted. If btr_search_enabled is set to FALSE, we will only allow
129
updating existing nodes, but no new node is allowed to be added.
130
@return TRUE if succeed, FALSE if no more memory could be allocated */
133
105
ha_insert_for_fold_func(
134
106
/*====================*/
135
hash_table_t* table, /*!< in: hash table */
136
ulint fold, /*!< in: folded value of data; if a node with
107
/* out: TRUE if succeed, FALSE if no more
108
memory could be allocated */
109
hash_table_t* table, /* in: hash table */
110
ulint fold, /* in: folded value of data; if a node with
137
111
the same fold value already exists, it is
138
112
updated to point to the same data, and no new
139
113
node is created! */
140
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
141
buf_block_t* block, /*!< in: buffer block containing the data */
142
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
143
void* data) /*!< in: data, must not be NULL */
115
buf_block_t* block, /* in: buffer block containing the data */
116
#endif /* UNIV_DEBUG */
117
void* data) /* in: data, must not be NULL */
145
119
hash_cell_t* cell;
147
121
ha_node_t* prev_node;
152
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
153
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
154
ut_a(block->frame == page_align(data));
155
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
156
ASSERT_HASH_MUTEX_OWN(table, fold);
124
ut_ad(table && data);
125
ut_ad(block->frame == page_align(data));
126
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
158
128
hash = hash_calc_hash(fold, table);
160
130
cell = hash_get_nth_cell(table, hash);
162
prev_node = static_cast<ha_node_t *>(cell->node);
132
prev_node = cell->node;
164
134
while (prev_node != NULL) {
165
135
if (prev_node->fold == fold) {
166
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
167
# ifndef UNIV_HOTBACKUP
168
137
if (table->adaptive) {
169
138
buf_block_t* prev_block = prev_node->block;
170
139
ut_a(prev_block->frame
242
/***********************************************************//**
199
/***************************************************************
243
200
Deletes a hash node. */
246
203
ha_delete_hash_node(
247
204
/*================*/
248
hash_table_t* table, /*!< in: hash table */
249
ha_node_t* del_node) /*!< in: node to be deleted */
205
hash_table_t* table, /* in: hash table */
206
ha_node_t* del_node) /* in: node to be deleted */
252
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
253
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
254
# ifndef UNIV_HOTBACKUP
255
209
if (table->adaptive) {
256
210
ut_a(del_node->block->frame = page_align(del_node->data));
257
211
ut_a(del_node->block->n_pointers > 0);
258
212
del_node->block->n_pointers--;
260
# endif /* !UNIV_HOTBACKUP */
261
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
214
#endif /* UNIV_DEBUG */
263
215
HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node);
266
/*********************************************************//**
218
/*****************************************************************
219
Deletes an entry from a hash table. */
224
hash_table_t* table, /* in: hash table */
225
ulint fold, /* in: folded value of data */
226
void* data) /* in: data, must not be NULL and must exist
231
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
233
node = ha_search_with_data(table, fold, data);
237
ha_delete_hash_node(table, node);
240
/*************************************************************
267
241
Looks for an element when we know the pointer to the data, and updates
268
242
the pointer to data, if found. */
271
245
ha_search_and_update_if_found_func(
272
246
/*===============================*/
273
hash_table_t* table, /*!< in/out: hash table */
274
ulint fold, /*!< in: folded value of the searched data */
275
void* data, /*!< in: pointer to the data */
276
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
277
buf_block_t* new_block,/*!< in: block containing new_data */
278
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
279
void* new_data)/*!< in: new pointer to the data */
247
hash_table_t* table, /* in: hash table */
248
ulint fold, /* in: folded value of the searched data */
249
void* data, /* in: pointer to the data */
251
buf_block_t* new_block,/* in: block containing new_data */
253
void* new_data)/* in: new pointer to the data */
284
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
285
ASSERT_HASH_MUTEX_OWN(table, fold);
286
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
287
ut_a(new_block->frame == page_align(new_data));
288
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
257
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
258
ut_ad(new_block->frame == page_align(new_data));
290
260
node = ha_search_with_data(table, fold, data);
293
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
294
# ifndef UNIV_HOTBACKUP
295
264
if (table->adaptive) {
296
265
ut_a(node->block->n_pointers > 0);
297
266
node->block->n_pointers--;
298
267
new_block->n_pointers++;
300
# endif /* !UNIV_HOTBACKUP */
302
270
node->block = new_block;
303
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
271
#endif /* UNIV_DEBUG */
304
272
node->data = new_data;
308
#ifndef UNIV_HOTBACKUP
309
/*****************************************************************//**
276
/*********************************************************************
310
277
Removes from the chain determined by fold all nodes whose data pointer
311
278
points to the page given. */
314
281
ha_remove_all_nodes_to_page(
315
282
/*========================*/
316
hash_table_t* table, /*!< in: hash table */
317
ulint fold, /*!< in: fold value */
318
const page_t* page) /*!< in: buffer page */
283
hash_table_t* table, /* in: hash table */
284
ulint fold, /* in: fold value */
285
const page_t* page) /* in: buffer page */
323
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
324
ASSERT_HASH_MUTEX_OWN(table, fold);
289
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
326
291
node = ha_chain_get_first(table, fold);
357
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
358
/*************************************************************//**
359
Validates a given range of the cells in hash table.
360
@return TRUE if ok */
322
/*****************************************************************
323
Validates a given range of the cells in hash table. */
365
hash_table_t* table, /*!< in: hash table */
366
ulint start_index, /*!< in: start index */
367
ulint end_index) /*!< in: end index */
328
/* out: TRUE if ok */
329
hash_table_t* table, /* in: hash table */
330
ulint start_index, /* in: start index */
331
ulint end_index) /* in: end index */
369
333
hash_cell_t* cell;
375
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
376
338
ut_a(start_index <= end_index);
377
339
ut_a(start_index < hash_get_n_cells(table));
378
340
ut_a(end_index < hash_get_n_cells(table));