📄 btr0sea.c
字号:
rw_lock_s_unlock(&btr_search_latch); btr_search_drop_page_hash_index(page); } else { rw_lock_s_unlock(&btr_search_latch); } n_recs = page_get_n_recs(page); if (n_recs == 0) { return; } /* Check that the values for hash index build are sensible */ if (n_fields + n_bytes == 0) { return; } if (dict_index_get_n_unique_in_tree(index) < n_fields || (dict_index_get_n_unique_in_tree(index) == n_fields && n_bytes > 0)) { return; } /* Calculate and cache fold values and corresponding records into an array for fast insertion to the hash index */ folds = mem_alloc(n_recs * sizeof(ulint)); recs = mem_alloc(n_recs * sizeof(rec_t*)); n_cached = 0; tree_id = btr_page_get_index_id(page); rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); offsets = rec_get_offsets(rec, index, offsets, n_fields + (n_bytes > 0), &heap); if (!page_rec_is_supremum(rec)) { ut_a(n_fields <= rec_offs_n_fields(offsets)); if (n_bytes > 0) { ut_a(n_fields < rec_offs_n_fields(offsets)); } } /* FIXME: in a mixed tree, all records may not have enough ordering fields: */ fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id); if (side == BTR_SEARCH_LEFT_SIDE) { folds[n_cached] = fold; recs[n_cached] = rec; n_cached++; } for (;;) { next_rec = page_rec_get_next(rec); if (page_rec_is_supremum(next_rec)) { if (side == BTR_SEARCH_RIGHT_SIDE) { folds[n_cached] = fold; recs[n_cached] = rec; n_cached++; } break; } offsets = rec_get_offsets(next_rec, index, offsets, n_fields + (n_bytes > 0), &heap); next_fold = rec_fold(next_rec, offsets, n_fields, n_bytes, tree_id); if (fold != next_fold) { /* Insert an entry into the hash index */ if (side == BTR_SEARCH_LEFT_SIDE) { folds[n_cached] = next_fold; recs[n_cached] = next_rec; n_cached++; } else { folds[n_cached] = fold; recs[n_cached] = rec; n_cached++; } } rec = next_rec; fold = next_fold; } btr_search_check_free_space_in_heap(); rw_lock_x_lock(&btr_search_latch); if (block->is_hashed && ((block->curr_n_fields != n_fields) || (block->curr_n_bytes != n_bytes) || (block->curr_side != side))) { goto exit_func; } block->is_hashed = TRUE; block->n_hash_helps = 0; block->curr_n_fields = n_fields; block->curr_n_bytes = n_bytes; block->curr_side = side; block->index = index; for (i = 0; i < n_cached; i++) { ha_insert_for_fold(table, folds[i], recs[i]); }exit_func: rw_lock_x_unlock(&btr_search_latch); mem_free(folds); mem_free(recs); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); }}/************************************************************************Moves or deletes hash entries for moved records. If new_page is already hashed,then the hash index for page, if any, is dropped. If new_page is not hashed,and page is hashed, then a new hash index is built to new_page with the sameparameters as page (this often happens when a page is split). */voidbtr_search_move_or_delete_hash_entries(/*===================================*/ page_t* new_page, /* in: records are copied to this page */ page_t* page, /* in: index page from which records were copied, and the copied records will be deleted from this page */ dict_index_t* index) /* in: record descriptor */{ buf_block_t* block; buf_block_t* new_block; ulint n_fields; ulint n_bytes; ulint side; block = buf_block_align(page); new_block = buf_block_align(new_page); ut_a(page_is_comp(page) == page_is_comp(new_page));#ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)); ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));#endif /* UNIV_SYNC_DEBUG */ ut_a(!new_block->is_hashed || new_block->index == index); ut_a(!block->is_hashed || block->index == index); rw_lock_s_lock(&btr_search_latch); if (new_block->is_hashed) { rw_lock_s_unlock(&btr_search_latch); btr_search_drop_page_hash_index(page); return; } if (block->is_hashed) { n_fields = block->curr_n_fields; n_bytes = block->curr_n_bytes; side = block->curr_side; new_block->n_fields = block->curr_n_fields; new_block->n_bytes = block->curr_n_bytes; new_block->side = block->curr_side; rw_lock_s_unlock(&btr_search_latch); ut_a(n_fields + n_bytes > 0); btr_search_build_page_hash_index(index, new_page, n_fields, n_bytes, side); ut_a(n_fields == block->curr_n_fields); ut_a(n_bytes == block->curr_n_bytes); ut_a(side == block->curr_side); return; } rw_lock_s_unlock(&btr_search_latch);}/************************************************************************Updates the page hash index when a single record is deleted from a page. */voidbtr_search_update_hash_on_delete(/*=============================*/ btr_cur_t* cursor) /* in: cursor which was positioned on the record to delete using btr_cur_search_..., the record is not yet deleted */{ hash_table_t* table; buf_block_t* block; rec_t* rec; ulint fold; dulint tree_id; ibool found; ulint offsets_[REC_OFFS_NORMAL_SIZE]; mem_heap_t* heap = NULL; *offsets_ = (sizeof offsets_) / sizeof *offsets_; rec = btr_cur_get_rec(cursor); block = buf_block_align(rec);#ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));#endif /* UNIV_SYNC_DEBUG */ if (!block->is_hashed) { return; } ut_a(block->index == cursor->index); ut_a(block->curr_n_fields + block->curr_n_bytes > 0); table = btr_search_sys->hash_index; tree_id = cursor->index->tree->id; fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_, ULINT_UNDEFINED, &heap), block->curr_n_fields, block->curr_n_bytes, tree_id); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } rw_lock_x_lock(&btr_search_latch); found = ha_search_and_delete_if_found(table, fold, rec); rw_lock_x_unlock(&btr_search_latch);}/************************************************************************Updates the page hash index when a single record is inserted on a page. */voidbtr_search_update_hash_node_on_insert(/*==================================*/ btr_cur_t* cursor) /* in: cursor which was positioned to the place to insert using btr_cur_search_..., and the new record has been inserted next to the cursor */{ hash_table_t* table; buf_block_t* block; rec_t* rec; rec = btr_cur_get_rec(cursor); block = buf_block_align(rec);#ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));#endif /* UNIV_SYNC_DEBUG */ if (!block->is_hashed) { return; } ut_a(block->index == cursor->index); rw_lock_x_lock(&btr_search_latch); if ((cursor->flag == BTR_CUR_HASH) && (cursor->n_fields == block->curr_n_fields) && (cursor->n_bytes == block->curr_n_bytes) && (block->curr_side == BTR_SEARCH_RIGHT_SIDE)) { table = btr_search_sys->hash_index; ha_search_and_update_if_found(table, cursor->fold, rec, page_rec_get_next(rec)); rw_lock_x_unlock(&btr_search_latch); } else { rw_lock_x_unlock(&btr_search_latch); btr_search_update_hash_on_insert(cursor); }}/************************************************************************Updates the page hash index when a single record is inserted on a page. */voidbtr_search_update_hash_on_insert(/*=============================*/ btr_cur_t* cursor) /* in: cursor which was positioned to the place to insert using btr_cur_search_..., and the new record has been inserted next to the cursor */{ hash_table_t* table; buf_block_t* block; rec_t* rec; rec_t* ins_rec; rec_t* next_rec; dulint tree_id; ulint fold; ulint ins_fold; ulint next_fold = 0; /* remove warning (??? bug ???) */ ulint n_fields; ulint n_bytes; ulint side; ibool locked = FALSE; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_; table = btr_search_sys->hash_index; btr_search_check_free_space_in_heap(); rec = btr_cur_get_rec(cursor); block = buf_block_align(rec);#ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));#endif /* UNIV_SYNC_DEBUG */ if (!block->is_hashed) { return; } ut_a(block->index == cursor->index); tree_id = ((cursor->index)->tree)->id; n_fields = block->curr_n_fields; n_bytes = block->curr_n_bytes; side = block->curr_side; ins_rec = page_rec_get_next(rec); next_rec = page_rec_get_next(ins_rec); offsets = rec_get_offsets(ins_rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, tree_id); if (!page_rec_is_supremum(next_rec)) { offsets = rec_get_offsets(next_rec, cursor->index, offsets, n_fields + (n_bytes > 0), &heap); next_fold = rec_fold(next_rec, offsets, n_fields, n_bytes, tree_id); } if (!page_rec_is_infimum(rec)) { offsets = rec_get_offsets(rec, cursor->index, offsets, n_fields + (n_bytes > 0), &heap); fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id); } else { if (side == BTR_SEARCH_LEFT_SIDE) { rw_lock_x_lock(&btr_search_latch); locked = TRUE; ha_insert_for_fold(table, ins_fold, ins_rec); } goto check_next_rec; } if (fold != ins_fold) { if (!locked) { rw_lock_x_lock(&btr_search_latch); locked = TRUE; } if (side == BTR_SEARCH_RIGHT_SIDE) { ha_insert_for_fold(table, fold, rec); } else { ha_insert_for_fold(table, ins_fold, ins_rec); } }check_next_rec: if (page_rec_is_supremum(next_rec)) { if (side == BTR_SEARCH_RIGHT_SIDE) { if (!locked) { rw_lock_x_lock(&btr_search_latch); locked = TRUE; } ha_insert_for_fold(table, ins_fold, ins_rec); } goto function_exit; } if (ins_fold != next_fold) { if (!locked) { rw_lock_x_lock(&btr_search_latch); locked = TRUE; } if (side == BTR_SEARCH_RIGHT_SIDE) { ha_insert_for_fold(table, ins_fold, ins_rec);/* fputs("Hash insert for ", stderr); dict_index_name_print(stderr, cursor->index); fprintf(stderr, " fold %lu\n", ins_fold);*/ } else { ha_insert_for_fold(table, next_fold, next_rec); } } function_exit: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } if (locked) { rw_lock_x_unlock(&btr_search_latch); }}/************************************************************************Validates the search system. */iboolbtr_search_validate(void)/*=====================*/ /* out: TRUE if ok */{ buf_block_t* block; page_t* page; ha_node_t* node; ulint n_page_dumps = 0; ibool ok = TRUE; ulint i; ulint cell_count; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_; rw_lock_x_lock(&btr_search_latch); cell_count = hash_get_n_cells(btr_search_sys->hash_index); for (i = 0; i < cell_count; i++) { /* We release btr_search_latch every once in a while to give other queries a chance to run. */ if ((i != 0) && ((i % BTR_CHUNK_SIZE) == 0)) { rw_lock_x_unlock(&btr_search_latch); os_thread_yield(); rw_lock_x_lock(&btr_search_latch); } node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node; while (node != NULL) { block = buf_block_align(node->data); page = buf_frame_align(node->data); offsets = rec_get_offsets((rec_t*) node->data, block->index, offsets, block->curr_n_fields + (block->curr_n_bytes > 0), &heap); if (!block->is_hashed || node->fold != rec_fold((rec_t*)(node->data), offsets, block->curr_n_fields, block->curr_n_bytes, btr_page_get_index_id(page))) { ok = FALSE; ut_print_timestamp(stderr); fprintf(stderr," InnoDB: Error in an adaptive hash index pointer to page %lu\n""ptr mem address %p index id %lu %lu, node fold %lu, rec fold %lu\n", (ulong) buf_frame_get_page_no(page), node->data, (ulong) ut_dulint_get_high(btr_page_get_index_id(page)), (ulong) ut_dulint_get_low(btr_page_get_index_id(page)), (ulong) node->fold, (ulong) rec_fold((rec_t*)(node->data), offsets, block->curr_n_fields, block->curr_n_bytes, btr_page_get_index_id(page))); fputs("InnoDB: Record ", stderr); rec_print_new(stderr, (rec_t*)node->data, offsets); fprintf(stderr, "\nInnoDB: on that page.""Page mem address %p, is hashed %lu, n fields %lu, n bytes %lu\n""side %lu\n", page, (ulong) block->is_hashed, (ulong) block->curr_n_fields, (ulong) block->curr_n_bytes, (ulong) block->curr_side); if (n_page_dumps < 20) { buf_page_print(page); n_page_dumps++; } } node = node->next; } } for (i = 0; i < cell_count; i += BTR_CHUNK_SIZE) { ulint end_index = ut_min(i + BTR_CHUNK_SIZE - 1, cell_count - 1); /* We release btr_search_latch every once in a while to give other queries a chance to run. */ if (i != 0) { rw_lock_x_unlock(&btr_search_latch); os_thread_yield(); rw_lock_x_lock(&btr_search_latch); } if (!ha_validate(btr_search_sys->hash_index, i, end_index)) { ok = FALSE; } } rw_lock_x_unlock(&btr_search_latch); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(ok);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -