00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "ha0ha.h"
00027 #ifdef UNIV_NONINL
00028 #include "ha0ha.ic"
00029 #endif
00030
00031 #ifdef UNIV_DEBUG
00032 # include "buf0buf.h"
00033 #endif
00034 #include "btr0sea.h"
00035 #include "page0page.h"
00036
00037
00041 UNIV_INTERN
00042 hash_table_t*
00043 ha_create_func(
00044
00045 ulint n,
00046 #ifdef UNIV_SYNC_DEBUG
00047 ulint mutex_level,
00049 #endif
00050 ulint n_mutexes)
00052 {
00053 hash_table_t* table;
00054 #ifndef UNIV_HOTBACKUP
00055 ulint i;
00056 #endif
00057
00058 ut_ad(ut_is_2pow(n_mutexes));
00059 table = hash_create(n);
00060
00061 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
00062 # ifndef UNIV_HOTBACKUP
00063 table->adaptive = TRUE;
00064 # endif
00065 #endif
00066
00067
00068
00069 if (n_mutexes == 0) {
00070 table->heap = mem_heap_create_in_btr_search(
00071 ut_min(4096, MEM_MAX_ALLOC_IN_BUF));
00072 ut_a(table->heap);
00073
00074 return(table);
00075 }
00076
00077 #ifndef UNIV_HOTBACKUP
00078 hash_create_mutexes(table, n_mutexes, mutex_level);
00079
00080 table->heaps = static_cast<mem_block_info_t **>(mem_alloc(n_mutexes * sizeof(mem_block_info_t *)));
00081
00082 for (i = 0; i < n_mutexes; i++) {
00083 table->heaps[i] = mem_heap_create_in_btr_search(4096);
00084 ut_a(table->heaps[i]);
00085 }
00086 #endif
00087
00088 return(table);
00089 }
00090
00091
00093 UNIV_INTERN
00094 void
00095 ha_clear(
00096
00097 hash_table_t* table)
00098 {
00099 ulint i;
00100 ulint n;
00101
00102 ut_ad(table);
00103 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
00104 #ifdef UNIV_SYNC_DEBUG
00105 ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
00106 #endif
00107
00108 #ifndef UNIV_HOTBACKUP
00109
00110 n = table->n_mutexes;
00111
00112 for (i = 0; i < n; i++) {
00113 mem_heap_free(table->heaps[i]);
00114 }
00115 #endif
00116
00117
00118 n = hash_get_n_cells(table);
00119
00120 for (i = 0; i < n; i++) {
00121 hash_get_nth_cell(table, i)->node = NULL;
00122 }
00123 }
00124
00125
00131 UNIV_INTERN
00132 ibool
00133 ha_insert_for_fold_func(
00134
00135 hash_table_t* table,
00136 ulint fold,
00140 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
00141 buf_block_t* block,
00142 #endif
00143 void* data)
00144 {
00145 hash_cell_t* cell;
00146 ha_node_t* node;
00147 ha_node_t* prev_node;
00148 ulint hash;
00149
00150 ut_ad(data);
00151 ut_ad(table);
00152 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
00153 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
00154 ut_a(block->frame == page_align(data));
00155 #endif
00156 ASSERT_HASH_MUTEX_OWN(table, fold);
00157
00158 hash = hash_calc_hash(fold, table);
00159
00160 cell = hash_get_nth_cell(table, hash);
00161
00162 prev_node = static_cast<ha_node_t *>(cell->node);
00163
00164 while (prev_node != NULL) {
00165 if (prev_node->fold == fold) {
00166 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
00167 # ifndef UNIV_HOTBACKUP
00168 if (table->adaptive) {
00169 buf_block_t* prev_block = prev_node->block;
00170 ut_a(prev_block->frame
00171 == page_align(prev_node->data));
00172 ut_a(prev_block->n_pointers > 0);
00173 prev_block->n_pointers--;
00174 block->n_pointers++;
00175 }
00176 ut_ad(!btr_search_fully_disabled);
00177 # endif
00178
00179 prev_node->block = block;
00180 #endif
00181 prev_node->data = data;
00182
00183 return(TRUE);
00184 }
00185
00186 prev_node = prev_node->next;
00187 }
00188
00189
00190
00191 if (!btr_search_enabled) {
00192 ut_ad(!btr_search_fully_disabled);
00193 return(TRUE);
00194 }
00195
00196
00197
00198 node = static_cast<ha_node_t *>(mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t)));
00199
00200 if (node == NULL) {
00201
00202
00203
00204 ut_ad(hash_get_heap(table, fold)->type & MEM_HEAP_BTR_SEARCH);
00205
00206 return(FALSE);
00207 }
00208
00209 ha_node_set_data(node, block, data);
00210
00211 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
00212 # ifndef UNIV_HOTBACKUP
00213 if (table->adaptive) {
00214 block->n_pointers++;
00215 }
00216 # endif
00217 #endif
00218
00219 node->fold = fold;
00220
00221 node->next = NULL;
00222
00223 prev_node = static_cast<ha_node_t *>(cell->node);
00224
00225 if (prev_node == NULL) {
00226
00227 cell->node = node;
00228
00229 return(TRUE);
00230 }
00231
00232 while (prev_node->next != NULL) {
00233
00234 prev_node = prev_node->next;
00235 }
00236
00237 prev_node->next = node;
00238
00239 return(TRUE);
00240 }
00241
00242
00244 UNIV_INTERN
00245 void
00246 ha_delete_hash_node(
00247
00248 hash_table_t* table,
00249 ha_node_t* del_node)
00250 {
00251 ut_ad(table);
00252 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
00253 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
00254 # ifndef UNIV_HOTBACKUP
00255 if (table->adaptive) {
00256 ut_a(del_node->block->frame = page_align(del_node->data));
00257 ut_a(del_node->block->n_pointers > 0);
00258 del_node->block->n_pointers--;
00259 }
00260 # endif
00261 #endif
00262
00263 HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node);
00264 }
00265
00266
00269 UNIV_INTERN
00270 void
00271 ha_search_and_update_if_found_func(
00272
00273 hash_table_t* table,
00274 ulint fold,
00275 void* data,
00276 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
00277 buf_block_t* new_block,
00278 #endif
00279 void* new_data)
00280 {
00281 ha_node_t* node;
00282
00283 ut_ad(table);
00284 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
00285 ASSERT_HASH_MUTEX_OWN(table, fold);
00286 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
00287 ut_a(new_block->frame == page_align(new_data));
00288 #endif
00289
00290 node = ha_search_with_data(table, fold, data);
00291
00292 if (node) {
00293 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
00294 # ifndef UNIV_HOTBACKUP
00295 if (table->adaptive) {
00296 ut_a(node->block->n_pointers > 0);
00297 node->block->n_pointers--;
00298 new_block->n_pointers++;
00299 }
00300 # endif
00301
00302 node->block = new_block;
00303 #endif
00304 node->data = new_data;
00305 }
00306 }
00307
00308 #ifndef UNIV_HOTBACKUP
00309
00312 UNIV_INTERN
00313 void
00314 ha_remove_all_nodes_to_page(
00315
00316 hash_table_t* table,
00317 ulint fold,
00318 const page_t* page)
00319 {
00320 ha_node_t* node;
00321
00322 ut_ad(table);
00323 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
00324 ASSERT_HASH_MUTEX_OWN(table, fold);
00325
00326 node = ha_chain_get_first(table, fold);
00327
00328 while (node) {
00329 if (page_align(ha_node_get_data(node)) == page) {
00330
00331
00332
00333 ha_delete_hash_node(table, node);
00334
00335
00336
00337
00338
00339 node = ha_chain_get_first(table, fold);
00340 } else {
00341 node = ha_chain_get_next(node);
00342 }
00343 }
00344 #ifdef UNIV_DEBUG
00345
00346
00347 node = ha_chain_get_first(table, fold);
00348
00349 while (node) {
00350 ut_a(page_align(ha_node_get_data(node)) != page);
00351
00352 node = ha_chain_get_next(node);
00353 }
00354 #endif
00355 }
00356
00357 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
00358
00361 UNIV_INTERN
00362 ibool
00363 ha_validate(
00364
00365 hash_table_t* table,
00366 ulint start_index,
00367 ulint end_index)
00368 {
00369 hash_cell_t* cell;
00370 ha_node_t* node;
00371 ibool ok = TRUE;
00372 ulint i;
00373
00374 ut_ad(table);
00375 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
00376 ut_a(start_index <= end_index);
00377 ut_a(start_index < hash_get_n_cells(table));
00378 ut_a(end_index < hash_get_n_cells(table));
00379
00380 for (i = start_index; i <= end_index; i++) {
00381
00382 cell = hash_get_nth_cell(table, i);
00383
00384 node = cell->node;
00385
00386 while (node) {
00387 if (hash_calc_hash(node->fold, table) != i) {
00388 ut_print_timestamp(stderr);
00389 fprintf(stderr,
00390 "InnoDB: Error: hash table node"
00391 " fold value %lu does not\n"
00392 "InnoDB: match the cell number %lu.\n",
00393 (ulong) node->fold, (ulong) i);
00394
00395 ok = FALSE;
00396 }
00397
00398 node = node->next;
00399 }
00400 }
00401
00402 return(ok);
00403 }
00404 #endif
00405
00406
00408 UNIV_INTERN
00409 void
00410 ha_print_info(
00411
00412 FILE* file,
00413 hash_table_t* table)
00414 {
00415 ut_ad(table);
00416 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
00417 #ifdef UNIV_DEBUG
00418
00419
00420 #define PRINT_USED_CELLS
00421 #endif
00422
00423 #ifdef PRINT_USED_CELLS
00424 hash_cell_t* cell;
00425 ulint cells = 0;
00426 ulint i;
00427 #endif
00428 ulint n_bufs;
00429
00430 #ifdef PRINT_USED_CELLS
00431 for (i = 0; i < hash_get_n_cells(table); i++) {
00432
00433 cell = hash_get_nth_cell(table, i);
00434
00435 if (cell->node) {
00436
00437 cells++;
00438 }
00439 }
00440 #endif
00441
00442 fprintf(file, "Hash table size %lu",
00443 (ulong) hash_get_n_cells(table));
00444
00445 #ifdef PRINT_USED_CELLS
00446 fprintf(file, ", used cells %lu", (ulong) cells);
00447 #endif
00448
00449 if (table->heaps == NULL && table->heap != NULL) {
00450
00451
00452
00453
00454 n_bufs = UT_LIST_GET_LEN(table->heap->base) - 1;
00455
00456 if (table->heap->free_block) {
00457 n_bufs++;
00458 }
00459
00460 fprintf(file, ", node heap has %lu buffer(s)\n",
00461 (ulong) n_bufs);
00462 }
00463 }
00464 #endif