~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/ha/ha0ha.c

  • Committer: Monty Taylor
  • Date: 2009-03-08 23:45:12 UTC
  • mto: (923.2.1 mordred)
  • mto: This revision was merged to the branch mainline in revision 921.
  • Revision ID: mordred@inaugust.com-20090308234512-tqkygxtu1iaig23s
Removed C99 isnan() usage, which allows us to remove the util/math.{cc,h} workarounds. Yay for standards!

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (C) 1994, 2009, Innobase Oy. All Rights Reserved.
4
 
 
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.
8
 
 
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.
12
 
 
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
16
 
 
17
 
*****************************************************************************/
18
 
 
19
 
/********************************************************************//**
20
 
@file ha/ha0ha.c
 
1
/************************************************************************
21
2
The hash table with external chains
22
3
 
 
4
(c) 1994-1997 Innobase Oy
 
5
 
23
6
Created 8/22/1994 Heikki Tuuri
24
7
*************************************************************************/
25
8
 
31
14
#ifdef UNIV_DEBUG
32
15
# include "buf0buf.h"
33
16
#endif /* UNIV_DEBUG */
34
 
#include "btr0sea.h"
 
17
#ifdef UNIV_SYNC_DEBUG
 
18
# include "btr0sea.h"
 
19
#endif /* UNIV_SYNC_DEBUG */
35
20
#include "page0page.h"
36
21
 
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. */
41
25
UNIV_INTERN
42
26
hash_table_t*
43
27
ha_create_func(
44
28
/*===========*/
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 */
52
37
{
53
38
        hash_table_t*   table;
54
 
#ifndef UNIV_HOTBACKUP
55
39
        ulint           i;
56
 
#endif /* !UNIV_HOTBACKUP */
57
40
 
58
 
        ut_ad(ut_is_2pow(n_mutexes));
59
41
        table = hash_create(n);
60
42
 
61
 
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
62
 
# ifndef UNIV_HOTBACKUP
 
43
#ifdef UNIV_DEBUG
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. */
68
48
 
74
54
                return(table);
75
55
        }
76
56
 
77
 
#ifndef UNIV_HOTBACKUP
78
57
        hash_create_mutexes(table, n_mutexes, mutex_level);
79
58
 
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*));
81
60
 
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]);
85
64
        }
86
 
#endif /* !UNIV_HOTBACKUP */
87
65
 
88
66
        return(table);
89
67
}
90
68
 
91
 
/*************************************************************//**
 
69
/*****************************************************************
92
70
Empties a hash table and frees the memory heaps. */
93
71
UNIV_INTERN
94
72
void
95
73
ha_clear(
96
74
/*=====*/
97
 
        hash_table_t*   table)  /*!< in, own: hash table */
 
75
        hash_table_t*   table)  /* in, own: hash table */
98
76
{
99
77
        ulint   i;
100
78
        ulint   n;
101
79
 
102
 
        ut_ad(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 */
107
83
 
108
 
#ifndef UNIV_HOTBACKUP
109
84
        /* Free the memory heaps. */
110
85
        n = table->n_mutexes;
111
86
 
112
87
        for (i = 0; i < n; i++) {
113
88
                mem_heap_free(table->heaps[i]);
114
89
        }
115
 
#endif /* !UNIV_HOTBACKUP */
116
90
 
117
91
        /* Clear the hash table. */
118
92
        n = hash_get_n_cells(table);
122
96
        }
123
97
}
124
98
 
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 */
 
102
is inserted. */
131
103
UNIV_INTERN
132
104
ibool
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 */
 
114
#ifdef UNIV_DEBUG
 
115
        buf_block_t*    block,  /* in: buffer block containing the data */
 
116
#endif /* UNIV_DEBUG */
 
117
        void*           data)   /* in: data, must not be NULL */
144
118
{
145
119
        hash_cell_t*    cell;
146
120
        ha_node_t*      node;
147
121
        ha_node_t*      prev_node;
148
122
        ulint           hash;
149
123
 
150
 
        ut_ad(data);
151
 
        ut_ad(table);
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)));
157
127
 
158
128
        hash = hash_calc_hash(fold, table);
159
129
 
160
130
        cell = hash_get_nth_cell(table, hash);
161
131
 
162
 
        prev_node = static_cast<ha_node_t *>(cell->node);
 
132
        prev_node = cell->node;
163
133
 
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
 
136
#ifdef UNIV_DEBUG
168
137
                        if (table->adaptive) {
169
138
                                buf_block_t* prev_block = prev_node->block;
170
139
                                ut_a(prev_block->frame
173
142
                                prev_block->n_pointers--;
174
143
                                block->n_pointers++;
175
144
                        }
176
 
                        ut_ad(!btr_search_fully_disabled);
177
 
# endif /* !UNIV_HOTBACKUP */
178
145
 
179
146
                        prev_node->block = block;
180
 
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
 
147
#endif /* UNIV_DEBUG */
181
148
                        prev_node->data = data;
182
149
 
183
150
                        return(TRUE);
186
153
                prev_node = prev_node->next;
187
154
        }
188
155
 
189
 
        /* We are in the process of disabling hash index, do not add
190
 
        new chain node */
191
 
        if (!btr_search_enabled) {
192
 
                ut_ad(!btr_search_fully_disabled);
193
 
                return(TRUE);
194
 
        }
195
 
 
196
156
        /* We have to allocate a new chain node */
197
157
 
198
 
        node = static_cast<ha_node_t *>(mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t)));
 
158
        node = mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t));
199
159
 
200
160
        if (node == NULL) {
201
161
                /* It was a btr search type memory heap and at the moment
208
168
 
209
169
        ha_node_set_data(node, block, data);
210
170
 
211
 
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
212
 
# ifndef UNIV_HOTBACKUP
 
171
#ifdef UNIV_DEBUG
213
172
        if (table->adaptive) {
214
173
                block->n_pointers++;
215
174
        }
216
 
# endif /* !UNIV_HOTBACKUP */
217
 
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
218
 
 
 
175
#endif /* UNIV_DEBUG */
219
176
        node->fold = fold;
220
177
 
221
178
        node->next = NULL;
222
179
 
223
 
        prev_node = static_cast<ha_node_t *>(cell->node);
 
180
        prev_node = cell->node;
224
181
 
225
182
        if (prev_node == NULL) {
226
183
 
239
196
        return(TRUE);
240
197
}
241
198
 
242
 
/***********************************************************//**
 
199
/***************************************************************
243
200
Deletes a hash node. */
244
201
UNIV_INTERN
245
202
void
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 */
250
207
{
251
 
        ut_ad(table);
252
 
        ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
253
 
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
254
 
# ifndef UNIV_HOTBACKUP
 
208
#ifdef UNIV_DEBUG
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--;
259
213
        }
260
 
# endif /* !UNIV_HOTBACKUP */
261
 
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
262
 
 
 
214
#endif /* UNIV_DEBUG */
263
215
        HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node);
264
216
}
265
217
 
266
 
/*********************************************************//**
 
218
/*****************************************************************
 
219
Deletes an entry from a hash table. */
 
220
UNIV_INTERN
 
221
void
 
222
ha_delete(
 
223
/*======*/
 
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
 
227
                                in the hash table */
 
228
{
 
229
        ha_node_t*      node;
 
230
 
 
231
        ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
 
232
 
 
233
        node = ha_search_with_data(table, fold, data);
 
234
 
 
235
        ut_a(node);
 
236
 
 
237
        ha_delete_hash_node(table, node);
 
238
}
 
239
 
 
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. */
269
243
UNIV_INTERN
270
244
void
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 */
 
250
#ifdef UNIV_DEBUG
 
251
        buf_block_t*    new_block,/* in: block containing new_data */
 
252
#endif
 
253
        void*           new_data)/* in: new pointer to the data */
280
254
{
281
255
        ha_node_t*      node;
282
256
 
283
 
        ut_ad(table);
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));
289
259
 
290
260
        node = ha_search_with_data(table, fold, data);
291
261
 
292
262
        if (node) {
293
 
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
294
 
# ifndef UNIV_HOTBACKUP
 
263
#ifdef UNIV_DEBUG
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++;
299
268
                }
300
 
# endif /* !UNIV_HOTBACKUP */
301
269
 
302
270
                node->block = new_block;
303
 
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
 
271
#endif /* UNIV_DEBUG */
304
272
                node->data = new_data;
305
273
        }
306
274
}
307
275
 
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. */
312
279
UNIV_INTERN
313
280
void
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 */
319
286
{
320
287
        ha_node_t*      node;
321
288
 
322
 
        ut_ad(table);
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)));
325
290
 
326
291
        node = ha_chain_get_first(table, fold);
327
292
 
354
319
#endif
355
320
}
356
321
 
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. */
361
324
UNIV_INTERN
362
325
ibool
363
326
ha_validate(
364
327
/*========*/
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 */
368
332
{
369
333
        hash_cell_t*    cell;
370
334
        ha_node_t*      node;
371
335
        ibool           ok      = TRUE;
372
336
        ulint           i;
373
337
 
374
 
        ut_ad(table);
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));
401
363
 
402
364
        return(ok);
403
365
}
404
 
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
405
366
 
406
 
/*************************************************************//**
 
367
/*****************************************************************
407
368
Prints info of a hash table. */
408
369
UNIV_INTERN
409
370
void
410
371
ha_print_info(
411
372
/*==========*/
412
 
        FILE*           file,   /*!< in: file where to print */
413
 
        hash_table_t*   table)  /*!< in: hash table */
 
373
        FILE*           file,   /* in: file where to print */
 
374
        hash_table_t*   table)  /* in: hash table */
414
375
{
415
 
        ut_ad(table);
416
 
        ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
417
376
#ifdef UNIV_DEBUG
418
377
/* Some of the code here is disabled for performance reasons in production
419
378
builds, see http://bugs.mysql.com/36941 */
461
420
                        (ulong) n_bufs);
462
421
        }
463
422
}
464
 
#endif /* !UNIV_HOTBACKUP */