diff options
Diffstat (limited to 'storage/innobase/btr')
-rw-r--r-- | storage/innobase/btr/btr0btr.c | 439 | ||||
-rw-r--r-- | storage/innobase/btr/btr0cur.c | 448 | ||||
-rw-r--r-- | storage/innobase/btr/btr0pcur.c | 96 | ||||
-rw-r--r-- | storage/innobase/btr/btr0sea.c | 357 |
4 files changed, 699 insertions, 641 deletions
diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index c27fb73ff8d..4ece0e36b19 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/storage/innobase/btr/btr0btr.c @@ -5,7 +5,7 @@ The B-tree Created 6/2/1994 Heikki Tuuri *******************************************************/ - + #include "btr0btr.h" #ifdef UNIV_NONINL @@ -56,7 +56,7 @@ field. To the child page we can store node pointers or index records which are >= P in the alphabetical order, but < P1 if there is a next node pointer on the level, and P1 is its prefix. -If a node pointer with a prefix P points to a non-leaf child, +If a node pointer with a prefix P points to a non-leaf child, then the leftmost record in the child must have the same prefix P. If it points to a leaf node, the child is not required to contain any record with a prefix equal to P. The leaf case @@ -138,14 +138,14 @@ btr_root_get( ulint space; ulint root_page_no; page_t* root; - + space = dict_tree_get_space(tree); root_page_no = dict_tree_get_page(tree); root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr); ut_a((ibool)!!page_is_comp(root) == - UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp); - + dict_table_is_comp(UT_LIST_GET_FIRST(tree->tree_indexes)->table)); + return(root); } @@ -175,20 +175,20 @@ btr_get_prev_user_rec( return(prev_rec); } } - + page = buf_frame_align(rec); prev_page_no = btr_page_get_prev(page, mtr); space = buf_frame_get_space_id(page); - + if (prev_page_no != FIL_NULL) { prev_page = buf_page_get_with_no_latch(space, prev_page_no, mtr); /* The caller must already have a latch to the brother */ ut_ad((mtr_memo_contains(mtr, buf_block_align(prev_page), - MTR_MEMO_PAGE_S_FIX)) - || (mtr_memo_contains(mtr, buf_block_align(prev_page), - MTR_MEMO_PAGE_X_FIX))); + MTR_MEMO_PAGE_S_FIX)) + || (mtr_memo_contains(mtr, buf_block_align(prev_page), + MTR_MEMO_PAGE_X_FIX))); ut_a(page_is_comp(prev_page) == page_is_comp(page)); return(page_rec_get_prev(page_get_supremum_rec(prev_page))); @@ -223,20 +223,20 @@ btr_get_next_user_rec( return(next_rec); } } - + page = buf_frame_align(rec); next_page_no = btr_page_get_next(page, mtr); space = buf_frame_get_space_id(page); - + if (next_page_no != FIL_NULL) { next_page = buf_page_get_with_no_latch(space, next_page_no, mtr); /* The caller must already have a latch to the brother */ ut_ad((mtr_memo_contains(mtr, buf_block_align(next_page), - MTR_MEMO_PAGE_S_FIX)) - || (mtr_memo_contains(mtr, buf_block_align(next_page), - MTR_MEMO_PAGE_X_FIX))); + MTR_MEMO_PAGE_S_FIX)) + || (mtr_memo_contains(mtr, buf_block_align(next_page), + MTR_MEMO_PAGE_X_FIX))); ut_a(page_is_comp(next_page) == page_is_comp(page)); return(page_rec_get_next(page_get_infimum_rec(next_page))); @@ -257,11 +257,11 @@ btr_page_create( mtr_t* mtr) /* in: mtr */ { ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); page_create(page, mtr, - UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp); + dict_table_is_comp(UT_LIST_GET_FIRST(tree->tree_indexes)->table)); buf_block_align(page)->check_index_page_at_flush = TRUE; - + btr_page_set_index_id(page, tree->id, mtr); } @@ -281,7 +281,7 @@ btr_page_alloc_for_ibuf( page_t* new_page; root = btr_root_get(tree, mtr); - + node_addr = flst_get_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr); ut_a(node_addr.page != FIL_NULL); @@ -293,7 +293,7 @@ btr_page_alloc_for_ibuf( #endif /* UNIV_SYNC_DEBUG */ flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, - new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, + new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr)); @@ -328,7 +328,7 @@ btr_page_alloc( } root = btr_root_get(tree, mtr); - + if (level == 0) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; } else { @@ -338,7 +338,7 @@ btr_page_alloc( /* Parameter TRUE below states that the caller has made the reservation for free extents, and thus we know that a page can be allocated: */ - + new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no, file_direction, TRUE, mtr); if (new_page_no == FIL_NULL) { @@ -351,9 +351,9 @@ btr_page_alloc( #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(new_page, SYNC_TREE_NODE_NEW); #endif /* UNIV_SYNC_DEBUG */ - + return(new_page); -} +} /****************************************************************** Gets the number of pages in a B-tree. */ @@ -376,20 +376,20 @@ btr_get_size( mtr_s_lock(dict_tree_get_lock(index->tree), &mtr); root = btr_root_get(index->tree, &mtr); - + if (flag == BTR_N_LEAF_PAGES) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; - + fseg_n_reserved_pages(seg_header, &n, &mtr); - + } else if (flag == BTR_TOTAL_SIZE) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP; n = fseg_n_reserved_pages(seg_header, &dummy, &mtr); - + seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; - - n += fseg_n_reserved_pages(seg_header, &dummy, &mtr); + + n += fseg_n_reserved_pages(seg_header, &dummy, &mtr); } else { ut_error; } @@ -397,7 +397,7 @@ btr_get_size( mtr_commit(&mtr); return(n); -} +} /****************************************************************** Frees a page used in an ibuf tree. Puts the page to the free list of the @@ -407,17 +407,17 @@ void btr_page_free_for_ibuf( /*===================*/ dict_tree_t* tree, /* in: index tree */ - page_t* page, /* in: page to be freed, x-latched */ + page_t* page, /* in: page to be freed, x-latched */ mtr_t* mtr) /* in: mtr */ { page_t* root; ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); root = btr_root_get(tree, mtr); - + flst_add_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, - page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); + page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr)); @@ -432,7 +432,7 @@ void btr_page_free_low( /*==============*/ dict_tree_t* tree, /* in: index tree */ - page_t* page, /* in: page to be freed, x-latched */ + page_t* page, /* in: page to be freed, x-latched */ ulint level, /* in: page level */ mtr_t* mtr) /* in: mtr */ { @@ -442,12 +442,12 @@ btr_page_free_low( ulint page_no; ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); /* The page gets invalid for optimistic searches: increment the frame modify clock */ buf_frame_modify_clock_inc(page); - + if (tree->type & DICT_IBUF) { btr_page_free_for_ibuf(tree, page, mtr); @@ -456,7 +456,7 @@ btr_page_free_low( } root = btr_root_get(tree, mtr); - + if (level == 0) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; } else { @@ -465,9 +465,9 @@ btr_page_free_low( space = buf_frame_get_space_id(page); page_no = buf_frame_get_page_no(page); - + fseg_free_page(seg_header, space, page_no, mtr); -} +} /****************************************************************** Frees a file page used in an index tree. NOTE: cannot free field external @@ -477,17 +477,17 @@ void btr_page_free( /*==========*/ dict_tree_t* tree, /* in: index tree */ - page_t* page, /* in: page to be freed, x-latched */ + page_t* page, /* in: page to be freed, x-latched */ mtr_t* mtr) /* in: mtr */ { ulint level; ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); level = btr_page_get_level(page, mtr); - + btr_page_free_low(tree, page, level, mtr); -} +} /****************************************************************** Sets the child node file address in a node pointer. */ @@ -507,12 +507,12 @@ btr_node_ptr_set_child_page_no( ut_ad(0 < btr_page_get_level(buf_frame_align(rec), mtr)); ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec)); - /* The child address is in the last field */ + /* The child address is in the last field */ field = rec_get_nth_field(rec, offsets, rec_offs_n_fields(offsets) - 1, &len); ut_ad(len == 4); - + mlog_write_ulint(field, page_no, MLOG_4BYTES, mtr); } @@ -536,7 +536,7 @@ btr_node_ptr_get_child( page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); page = btr_page_get(space, page_no, RW_X_LATCH, mtr); - + return(page); } @@ -567,7 +567,7 @@ btr_page_get_father_for_rec( ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); ut_a(page_rec_is_user_rec(user_rec)); - + ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page)); heap = mem_heap_create(100); @@ -589,7 +589,7 @@ btr_page_get_father_for_rec( ULINT_UNDEFINED, &heap); if (btr_node_ptr_get_child_page_no(node_ptr, offsets) != - buf_frame_get_page_no(page)) { + buf_frame_get_page_no(page)) { rec_t* print_rec; fputs("InnoDB: Dump of the child page:\n", stderr); buf_page_print(buf_frame_align(page)); @@ -677,13 +677,13 @@ btr_create( buf_page_dbg_add_level(ibuf_hdr_frame, SYNC_TREE_NODE_NEW); #endif /* UNIV_SYNC_DEBUG */ ut_ad(buf_frame_get_page_no(ibuf_hdr_frame) - == IBUF_HEADER_PAGE_NO); + == IBUF_HEADER_PAGE_NO); /* Allocate then the next page to the segment: it will be the - tree root page */ + tree root page */ - page_no = fseg_alloc_free_page( + page_no = fseg_alloc_free_page( ibuf_hdr_frame + IBUF_HEADER - + IBUF_TREE_SEG_HEADER, IBUF_TREE_ROOT_PAGE_NO, + + IBUF_TREE_SEG_HEADER, IBUF_TREE_ROOT_PAGE_NO, FSP_UP, mtr); ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO); @@ -692,14 +692,14 @@ btr_create( frame = fseg_create(space, 0, PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr); } - + if (frame == NULL) { return(FIL_NULL); } page_no = buf_frame_get_page_no(frame); - + #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW); #endif /* UNIV_SYNC_DEBUG */ @@ -708,9 +708,9 @@ btr_create( /* It is an insert buffer tree: initialize the free list */ ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO); - + flst_init(frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr); - } else { + } else { /* It is a non-ibuf tree: create a file segment for leaf pages */ fseg_create(space, page_no, PAGE_HEADER + PAGE_BTR_SEG_LEAF, @@ -721,7 +721,7 @@ btr_create( buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW); #endif /* UNIV_SYNC_DEBUG */ } - + /* Create a new index page on the the allocated segment page */ page = page_create(frame, mtr, comp); buf_block_align(page)->check_index_page_at_flush = TRUE; @@ -731,7 +731,7 @@ btr_create( /* Set the level of the new index page */ btr_page_set_level(page, 0, mtr); - + /* Set the next node and previous node fields */ btr_page_set_next(page, FIL_NULL, mtr); btr_page_set_prev(page, FIL_NULL, mtr); @@ -739,7 +739,7 @@ btr_create( /* We reset the free bits for the page to allow creation of several trees in the same mtr, otherwise the latch on a bitmap page would prevent it because of the latching order */ - + ibuf_reset_free_bits_with_type(type, page); /* In the following assertion we test that two records of maximum @@ -765,10 +765,10 @@ btr_free_but_not_root( page_t* root; mtr_t mtr; -leaf_loop: +leaf_loop: mtr_start(&mtr); - - root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr); + + root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr); /* NOTE: page hash indexes are dropped when a page is freed inside fsp0fsp. */ @@ -783,8 +783,8 @@ leaf_loop: } top_loop: mtr_start(&mtr); - - root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr); + + root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr); finished = fseg_free_step_not_header( root + PAGE_HEADER + PAGE_BTR_SEG_TOP, &mtr); @@ -793,7 +793,7 @@ top_loop: if (!finished) { goto top_loop; - } + } } /**************************************************************** @@ -812,14 +812,14 @@ btr_free_root( root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr); - btr_search_drop_page_hash_index(root); -top_loop: + btr_search_drop_page_hash_index(root); +top_loop: finished = fseg_free_step( root + PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr); if (!finished) { goto top_loop; - } + } } /***************************************************************** @@ -845,8 +845,8 @@ btr_page_reorganize_low( ulint max_ins_size2; ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); - ut_ad(!!page_is_comp(page) == index->table->comp); + MTR_MEMO_PAGE_X_FIX)); + ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); data_size1 = page_get_data_size(page); max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1); @@ -872,7 +872,7 @@ btr_page_reorganize_low( page_create(page, mtr, page_is_comp(page)); buf_block_align(page)->check_index_page_at_flush = TRUE; - + /* Copy the records from the temporary space to the recreated page; do not copy the lock bits yet */ @@ -880,7 +880,7 @@ btr_page_reorganize_low( page_get_infimum_rec(new_page), index, mtr); /* Copy max trx id to recreated page */ page_set_max_trx_id(page, page_get_max_trx_id(new_page)); - + if (!recovery) { /* Update the record lock bitmaps */ lock_move_reorganize_page(page, new_page); @@ -892,7 +892,7 @@ btr_page_reorganize_low( if (data_size1 != data_size2 || max_ins_size1 != max_ins_size2) { buf_page_print(page); buf_page_print(new_page); - fprintf(stderr, + fprintf(stderr, "InnoDB: Error: page old data size %lu new data size %lu\n" "InnoDB: Error: page old max ins size %lu new max ins size %lu\n" "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", @@ -955,7 +955,7 @@ btr_page_empty( mtr_t* mtr) /* in: mtr */ { ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); btr_search_drop_page_hash_index(page); /* Recreate the page: note that global data on page (possible @@ -990,10 +990,10 @@ btr_root_raise_and_insert( rec_t* rec; mem_heap_t* heap; dtuple_t* node_ptr; - ulint level; + ulint level; rec_t* node_ptr_rec; page_cur_t* page_cursor; - + root = btr_cur_get_page(cursor); tree = btr_cur_get_tree(cursor); @@ -1001,24 +1001,24 @@ btr_root_raise_and_insert( ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); ut_ad(mtr_memo_contains(mtr, buf_block_align(root), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); btr_search_drop_page_hash_index(root); /* Allocate a new page to the tree. Root splitting is done by first moving the root records to the new page, emptying the root, putting a node pointer to the new page, and then splitting the new page. */ - + new_page = btr_page_alloc(tree, 0, FSP_NO_DIR, btr_page_get_level(root, mtr), mtr); btr_page_create(new_page, tree, mtr); level = btr_page_get_level(root, mtr); - + /* Set the levels of the new index page and root page */ btr_page_set_level(new_page, level, mtr); btr_page_set_level(root, level + 1, mtr); - + /* Set the next node and previous node fields of new page */ btr_page_set_next(new_page, FIL_NULL, mtr); btr_page_set_prev(new_page, FIL_NULL, mtr); @@ -1031,7 +1031,7 @@ btr_root_raise_and_insert( perform a pessimistic update then we have stored the lock information of the record to be inserted on the infimum of the root page: we cannot discard the lock structs on the root page */ - + lock_update_root_raise(new_page, root); /* Create a memory heap where the node pointer is stored */ @@ -1039,17 +1039,17 @@ btr_root_raise_and_insert( rec = page_rec_get_next(page_get_infimum_rec(new_page)); new_page_no = buf_frame_get_page_no(new_page); - + /* Build the node pointer (= node key and page address) for the child */ node_ptr = dict_tree_build_node_ptr(tree, rec, new_page_no, heap, - level); + level); /* Reorganize the root to get free space */ btr_page_reorganize(root, cursor->index, mtr); page_cursor = btr_cur_get_page_cur(cursor); - + /* Insert node pointer to the root */ page_cur_set_before_first(root, page_cursor); @@ -1064,7 +1064,7 @@ btr_root_raise_and_insert( node of a level: */ btr_set_min_rec_mark(node_ptr_rec, page_is_comp(root), mtr); - + /* Free the memory heap */ mem_heap_free(heap); @@ -1078,10 +1078,10 @@ btr_root_raise_and_insert( /* Reposition the cursor to the child node */ page_cur_search(new_page, cursor->index, tuple, PAGE_CUR_LE, page_cursor); - + /* Split the child and insert tuple */ return(btr_page_split_and_insert(cursor, tuple, mtr)); -} +} /***************************************************************** Decides if the page should be split at the convergence point of inserts @@ -1105,22 +1105,22 @@ btr_page_get_split_rec_to_left( insert_point = btr_cur_get_rec(cursor); if (page_header_get_ptr(page, PAGE_LAST_INSERT) - == page_rec_get_next(insert_point)) { + == page_rec_get_next(insert_point)) { + + infimum = page_get_infimum_rec(page); - infimum = page_get_infimum_rec(page); - /* If the convergence is in the middle of a page, include also the record immediately before the new insert to the upper page. Otherwise, we could repeatedly move from page to page lots of records smaller than the convergence point. */ if (infimum != insert_point - && page_rec_get_next(infimum) != insert_point) { + && page_rec_get_next(infimum) != insert_point) { *split_rec = insert_point; } else { - *split_rec = page_rec_get_next(insert_point); - } + *split_rec = page_rec_get_next(insert_point); + } return(TRUE); } @@ -1162,7 +1162,7 @@ btr_page_get_split_rec_to_right( if (page_rec_is_supremum(next_rec)) { split_at_new: /* Split at the new record to insert */ - *split_rec = NULL; + *split_rec = NULL; } else { rec_t* next_next_rec = page_rec_get_next(next_rec); if (page_rec_is_supremum(next_next_rec)) { @@ -1176,7 +1176,7 @@ split_at_new: index, as they can do the necessary checks of the right search position just by looking at the records on this page. */ - + *split_rec = next_next_rec; } @@ -1199,7 +1199,7 @@ btr_page_get_sure_split_rec( upper half-page */ btr_cur_t* cursor, /* in: cursor at which insert should be made */ - dtuple_t* tuple) /* in: tuple to insert */ + dtuple_t* tuple) /* in: tuple to insert */ { page_t* page; ulint insert_size; @@ -1216,7 +1216,7 @@ btr_page_get_sure_split_rec( ulint* offsets; page = btr_cur_get_page(cursor); - + insert_size = rec_get_converted_size(cursor->index, tuple); free_space = page_get_free_space_of_empty(page_is_comp(page)); @@ -1263,15 +1263,15 @@ btr_page_get_sure_split_rec( } n++; - + if (incl_data + page_dir_calc_reserved_space(n) - >= total_space / 2) { + >= total_space / 2) { - if (incl_data + page_dir_calc_reserved_space(n) - <= free_space) { - /* The next record will be the first on - the right half page if it is not the - supremum record of page */ + if (incl_data + page_dir_calc_reserved_space(n) + <= free_space) { + /* The next record will be the first on + the right half page if it is not the + supremum record of page */ if (rec == ins_rec) { rec = NULL; @@ -1286,7 +1286,7 @@ btr_page_get_sure_split_rec( if (!page_rec_is_supremum(next_rec)) { rec = next_rec; } - } + } func_exit: if (UNIV_LIKELY_NULL(heap)) { @@ -1295,7 +1295,7 @@ func_exit: return(rec); } } -} +} /***************************************************************** Returns TRUE if the insert fits on the appropriate half-page with the @@ -1323,7 +1323,7 @@ btr_page_insert_fits( rec_t* rec; rec_t* end_rec; ulint* offs; - + page = btr_cur_get_page(cursor); ut_ad(!split_rec == !offsets); @@ -1339,11 +1339,11 @@ btr_page_insert_fits( total_data = page_get_data_size(page) + insert_size; total_n_recs = page_get_n_recs(page) + 1; - + /* We determine which records (from rec to end_rec, not including end_rec) will end up on the other half page from tuple when it is inserted. */ - + if (split_rec == NULL) { rec = page_rec_get_next(page_get_infimum_rec(page)); end_rec = page_rec_get_next(btr_cur_get_rec(cursor)); @@ -1351,14 +1351,14 @@ btr_page_insert_fits( } else if (cmp_dtuple_rec(tuple, split_rec, offsets) >= 0) { rec = page_rec_get_next(page_get_infimum_rec(page)); - end_rec = split_rec; + end_rec = split_rec; } else { rec = split_rec; end_rec = page_get_supremum_rec(page); } if (total_data + page_dir_calc_reserved_space(total_n_recs) - <= free_space) { + <= free_space) { /* Ok, there will be enough available space on the half page where the tuple is inserted */ @@ -1379,7 +1379,7 @@ btr_page_insert_fits( total_n_recs--; if (total_data + page_dir_calc_reserved_space(total_n_recs) - <= free_space) { + <= free_space) { /* Ok, there will be enough available space on the half page where the tuple is inserted */ @@ -1391,7 +1391,7 @@ btr_page_insert_fits( } return(FALSE); -} +} /*********************************************************** Inserts a data tuple to a tree on a non-leaf level. It is assumed @@ -1406,25 +1406,22 @@ btr_insert_on_non_leaf_level( mtr_t* mtr) /* in: mtr */ { big_rec_t* dummy_big_rec; - btr_cur_t cursor; + btr_cur_t cursor; ulint err; rec_t* rec; ut_ad(level > 0); - + /* In the following, choose just any index from the tree as the first parameter for btr_cur_search_to_nth_level. */ btr_cur_search_to_nth_level(UT_LIST_GET_FIRST(tree->tree_indexes), - level, tuple, PAGE_CUR_LE, - BTR_CONT_MODIFY_TREE, - &cursor, 0, mtr); + level, tuple, PAGE_CUR_LE, BTR_CONT_MODIFY_TREE, + &cursor, 0, mtr); err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG - | BTR_KEEP_SYS_FLAG - | BTR_NO_UNDO_LOG_FLAG, - &cursor, tuple, - &rec, &dummy_big_rec, NULL, mtr); + | BTR_KEEP_SYS_FLAG | BTR_NO_UNDO_LOG_FLAG, + &cursor, tuple, &rec, &dummy_big_rec, NULL, mtr); ut_a(err == DB_SUCCESS); } @@ -1455,12 +1452,12 @@ btr_attach_half_pages( ulint lower_page_no; ulint upper_page_no; dtuple_t* node_ptr_upper; - mem_heap_t* heap; + mem_heap_t* heap; ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains(mtr, buf_block_align(new_page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); ut_a(page_is_comp(page) == page_is_comp(new_page)); /* Create a memory heap where the data tuple is stored */ @@ -1477,7 +1474,7 @@ btr_attach_half_pages( /* Look from the tree for the node pointer to page */ node_ptr = btr_page_get_father_node_ptr(tree, page, mtr); - /* Replace the address of the old child node (= page) with the + /* Replace the address of the old child node (= page) with the address of the new lower half */ btr_node_ptr_set_child_page_no(node_ptr, @@ -1492,7 +1489,7 @@ btr_attach_half_pages( lower_page = page; upper_page = new_page; } - + /* Get the level of the split pages */ level = btr_page_get_level(page, mtr); @@ -1500,13 +1497,13 @@ btr_attach_half_pages( half */ node_ptr_upper = dict_tree_build_node_ptr(tree, split_rec, - upper_page_no, heap, level); + upper_page_no, heap, level); /* Insert it next to the pointer to the lower half. Note that this may generate recursion leading to a split on the higher level. */ btr_insert_on_non_leaf_level(tree, level + 1, node_ptr_upper, mtr); - + /* Free the memory heap */ mem_heap_free(heap); @@ -1515,9 +1512,9 @@ btr_attach_half_pages( prev_page_no = btr_page_get_prev(page, mtr); next_page_no = btr_page_get_next(page, mtr); space = buf_frame_get_space_id(page); - + /* Update page links of the level */ - + if (prev_page_no != FIL_NULL) { prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr); @@ -1533,7 +1530,7 @@ btr_attach_half_pages( btr_page_set_prev(next_page, upper_page_no, mtr); } - + btr_page_set_prev(lower_page, prev_page_no, mtr); btr_page_set_next(lower_page, upper_page_no, mtr); btr_page_set_level(lower_page, level, mtr); @@ -1590,7 +1587,7 @@ func_start: mem_heap_empty(heap); offsets = NULL; tree = btr_cur_get_tree(cursor); - + ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); #ifdef UNIV_SYNC_DEBUG @@ -1600,9 +1597,9 @@ func_start: page = btr_cur_get_page(cursor); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); ut_ad(page_get_n_recs(page) >= 2); - + page_no = buf_frame_get_page_no(page); /* 1. Decide the split record; split_rec == NULL means that the @@ -1613,7 +1610,7 @@ func_start: direction = FSP_UP; hint_page_no = page_no + 1; split_rec = btr_page_get_sure_split_rec(cursor, tuple); - + } else if (btr_page_get_split_rec_to_right(cursor, &split_rec)) { direction = FSP_UP; hint_page_no = page_no + 1; @@ -1631,7 +1628,7 @@ func_start: new_page = btr_page_alloc(tree, hint_page_no, direction, btr_page_get_level(page, mtr), mtr); btr_page_create(new_page, tree, mtr); - + /* 3. Calculate the first record on the upper half-page, and the first record (move_limit) on original page which ends up on the upper half */ @@ -1646,7 +1643,7 @@ func_start: cursor->index, tuple); move_limit = page_rec_get_next(btr_cur_get_rec(cursor)); } - + /* 4. Do first the modifications in the tree structure */ btr_attach_half_pages(tree, page, first_rec, new_page, direction, mtr); @@ -1670,7 +1667,7 @@ func_start: insert_will_fit = btr_page_insert_fits(cursor, NULL, NULL, tuple, heap); } - + if (insert_will_fit && (btr_page_get_level(page, mtr) == 0)) { mtr_memo_release(mtr, dict_tree_get_lock(tree), @@ -1737,7 +1734,7 @@ func_start: mem_heap_free(heap); return(rec); } - + /* 8. If insert did not fit, try page reorganization */ btr_page_reorganize(insert_page, cursor->index, mtr); @@ -1749,7 +1746,7 @@ func_start: if (rec == NULL) { /* The insert did not fit on the page: loop back to the start of the function for a new split */ - + /* We play safe and reset the free bits for new_page */ ibuf_reset_free_bits(cursor->index, new_page); @@ -1787,24 +1784,24 @@ btr_level_list_remove( dict_tree_t* tree __attribute__((unused)), /* in: index tree */ page_t* page, /* in: page to remove */ mtr_t* mtr) /* in: mtr */ -{ +{ ulint space; ulint prev_page_no; page_t* prev_page; ulint next_page_no; page_t* next_page; - + ut_ad(tree && page && mtr); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); /* Get the previous and next page numbers of page */ prev_page_no = btr_page_get_prev(page, mtr); next_page_no = btr_page_get_next(page, mtr); space = buf_frame_get_space_id(page); - + /* Update page links of the level */ - + if (prev_page_no != FIL_NULL) { prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr); @@ -1821,7 +1818,7 @@ btr_level_list_remove( btr_page_set_prev(next_page, prev_page_no, mtr); } } - + /******************************************************************** Writes the redo log record for setting an index record as the predefined minimum record. */ @@ -1906,7 +1903,7 @@ btr_node_ptr_delete( btr_cur_t cursor; ibool compressed; ulint err; - + ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); /* Delete node pointer on father page */ @@ -1945,33 +1942,33 @@ btr_lift_page_up( ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL); ut_ad(btr_page_get_next(page, mtr) == FIL_NULL); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); father_page = buf_frame_align( btr_page_get_father_node_ptr(tree, page, mtr)); - + page_level = btr_page_get_level(page, mtr); index = UT_LIST_GET_FIRST(tree->tree_indexes); btr_search_drop_page_hash_index(page); - + /* Make the father empty */ btr_page_empty(father_page, mtr); /* Move records to the father */ - page_copy_rec_list_end(father_page, page, page_get_infimum_rec(page), + page_copy_rec_list_end(father_page, page, page_get_infimum_rec(page), index, mtr); lock_update_copy_and_discard(father_page, page); btr_page_set_level(father_page, page_level, mtr); /* Free the file page */ - btr_page_free(tree, page, mtr); + btr_page_free(tree, page, mtr); /* We play safe and reset the free bits for the father */ ibuf_reset_free_bits(index, father_page); ut_ad(page_validate(father_page, index)); ut_ad(btr_check_node_ptr(tree, father_page, mtr)); -} +} /***************************************************************** Tries to merge the page first to the left immediate brother if such a @@ -2014,7 +2011,7 @@ btr_compress( page = btr_cur_get_page(cursor); tree = btr_cur_get_tree(cursor); comp = page_is_comp(page); - ut_a((ibool)!!comp == cursor->index->table->comp); + ut_a((ibool)!!comp == dict_table_is_comp(cursor->index->table)); ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); @@ -2054,7 +2051,7 @@ btr_compress( return; } - + n_recs = page_get_n_recs(page); data_size = page_get_data_size(page); ut_a(page_is_comp(merge_page) == comp); @@ -2071,7 +2068,7 @@ btr_compress( ut_ad(page_validate(merge_page, cursor->index)); max_ins_size = page_get_max_insert_size(merge_page, n_recs); - + if (data_size > max_ins_size) { /* We have to reorganize merge_page */ @@ -2103,7 +2100,7 @@ btr_compress( mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; *offsets_ = (sizeof offsets_) / sizeof *offsets_; - /* Replace the address of the old child node (= page) with the + /* Replace the address of the old child node (= page) with the address of the merge page to the right */ btr_node_ptr_set_child_page_no(node_ptr, @@ -2115,7 +2112,7 @@ btr_compress( } btr_node_ptr_delete(tree, merge_page, mtr); } - + /* Move records to the merge page */ if (is_left) { orig_pred = page_rec_get_prev( @@ -2136,14 +2133,14 @@ btr_compress( /* We have added new records to merge_page: update its free bits */ ibuf_update_free_bits_if_full(cursor->index, merge_page, UNIV_PAGE_SIZE, ULINT_UNDEFINED); - + ut_ad(page_validate(merge_page, cursor->index)); /* Free the file page */ - btr_page_free(tree, page, mtr); + btr_page_free(tree, page, mtr); ut_ad(btr_check_node_ptr(tree, merge_page, mtr)); -} +} /***************************************************************** Discards a page that is the only page on its level. */ @@ -2158,7 +2155,7 @@ btr_discard_only_page_on_level( rec_t* node_ptr; page_t* father_page; ulint page_level; - + ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL); ut_ad(btr_page_get_next(page, mtr) == FIL_NULL); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), @@ -2175,7 +2172,7 @@ btr_discard_only_page_on_level( btr_page_set_level(father_page, page_level, mtr); /* Free the file page */ - btr_page_free(tree, page, mtr); + btr_page_free(tree, page, mtr); if (buf_frame_get_page_no(father_page) == dict_tree_get_page(tree)) { /* The father is the root page */ @@ -2190,7 +2187,7 @@ btr_discard_only_page_on_level( btr_discard_only_page_on_level(tree, father_page, mtr); } -} +} /***************************************************************** Discards a page from a B-tree. This is used to remove the last record from @@ -2212,7 +2209,7 @@ btr_discard_page( ibool is_left; page_t* page; rec_t* node_ptr; - + page = btr_cur_get_page(cursor); tree = btr_cur_get_tree(cursor); @@ -2222,7 +2219,7 @@ btr_discard_page( ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); space = dict_tree_get_space(tree); - + /* Decide the page which will inherit the locks */ left_page_no = btr_page_get_prev(page, mtr); @@ -2244,7 +2241,7 @@ btr_discard_page( ut_a(page_is_comp(merge_page) == page_is_comp(page)); btr_search_drop_page_hash_index(page); - + if (left_page_no == FIL_NULL && btr_page_get_level(page, mtr) > 0) { /* We have to mark the leftmost node pointer on the right @@ -2255,8 +2252,8 @@ btr_discard_page( ut_ad(page_rec_is_user_rec(node_ptr)); btr_set_min_rec_mark(node_ptr, page_is_comp(merge_page), mtr); - } - + } + btr_node_ptr_delete(tree, page, mtr); /* Remove the page from the level list */ @@ -2266,14 +2263,14 @@ btr_discard_page( lock_update_discard(page_get_supremum_rec(merge_page), page); } else { lock_update_discard(page_rec_get_next( - page_get_infimum_rec(merge_page)), page); + page_get_infimum_rec(merge_page)), page); } /* Free the file page */ - btr_page_free(tree, page, mtr); + btr_page_free(tree, page, mtr); ut_ad(btr_check_node_ptr(tree, merge_page, mtr)); -} +} #ifdef UNIV_BTR_PRINT /***************************************************************** @@ -2297,7 +2294,7 @@ btr_print_size( } mtr_start(&mtr); - + root = btr_root_get(tree, &mtr); seg = root + PAGE_HEADER + PAGE_BTR_SEG_TOP; @@ -2313,7 +2310,7 @@ btr_print_size( fseg_print(seg, &mtr); } - mtr_commit(&mtr); + mtr_commit(&mtr); } /**************************************************************** @@ -2341,14 +2338,14 @@ btr_print_recursive( ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); fprintf(stderr, "NODE ON LEVEL %lu page number %lu\n", - (ulong) btr_page_get_level(page, mtr), - (ulong) buf_frame_get_page_no(page)); - + (ulong) btr_page_get_level(page, mtr), + (ulong) buf_frame_get_page_no(page)); + index = UT_LIST_GET_FIRST(tree->tree_indexes); page_print(page, index, width, width); - + n_recs = page_get_n_recs(page); - + page_cur_set_before_first(page, &cursor); page_cur_move_to_next(&cursor); @@ -2413,6 +2410,7 @@ btr_print_tree( } #endif /* UNIV_BTR_PRINT */ +#ifdef UNIV_DEBUG /**************************************************************** Checks that the node pointer to a page is appropriate. */ @@ -2436,19 +2434,19 @@ btr_check_node_ptr( } node_ptr = btr_page_get_father_node_ptr(tree, page, mtr); - + if (btr_page_get_level(page, mtr) == 0) { return(TRUE); } - + heap = mem_heap_create(256); - + node_ptr_tuple = dict_tree_build_node_ptr( tree, page_rec_get_next(page_get_infimum_rec(page)), 0, heap, btr_page_get_level(page, mtr)); - + ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr, rec_get_offsets(node_ptr, dict_tree_find_index(tree, node_ptr), @@ -2458,6 +2456,7 @@ btr_check_node_ptr( return(TRUE); } +#endif /* UNIV_DEBUG */ /**************************************************************** Display identification information for a record. */ @@ -2481,7 +2480,7 @@ the index. */ ibool btr_index_rec_validate( -/*====================*/ +/*===================*/ /* out: TRUE if ok */ rec_t* rec, /* in: index record */ dict_index_t* index, /* in: index */ @@ -2501,18 +2500,20 @@ btr_index_rec_validate( page = buf_frame_align(rec); if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) { - /* The insert buffer index tree can contain records from any - other index: we cannot check the number of fields or - their length */ + /* The insert buffer index tree can contain records from any + other index: we cannot check the number of fields or + their length */ - return(TRUE); + return(TRUE); } - if (UNIV_UNLIKELY((ibool)!!page_is_comp(page) != index->table->comp)) { + if (UNIV_UNLIKELY((ibool)!!page_is_comp(page) + != dict_table_is_comp(index->table))) { btr_index_rec_validate_report(page, rec, index); fprintf(stderr, "InnoDB: compact flag=%lu, should be %lu\n", (ulong) !!page_is_comp(page), - (ulong) index->table->comp); + (ulong) dict_table_is_comp(index->table)); + return(FALSE); } @@ -2546,12 +2547,12 @@ btr_index_rec_validate( their type is CHAR. */ if ((dict_index_get_nth_field(index, i)->prefix_len == 0 - && len != UNIV_SQL_NULL && fixed_size - && len != fixed_size) + && len != UNIV_SQL_NULL && fixed_size + && len != fixed_size) || (dict_index_get_nth_field(index, i)->prefix_len > 0 - && len != UNIV_SQL_NULL - && len > + && len != UNIV_SQL_NULL + && len > dict_index_get_nth_field(index, i)->prefix_len)) { btr_index_rec_validate_report(page, rec, index); @@ -2576,7 +2577,7 @@ btr_index_rec_validate( if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } - return(TRUE); + return(TRUE); } /**************************************************************** @@ -2590,9 +2591,9 @@ btr_index_page_validate( page_t* page, /* in: index page */ dict_index_t* index) /* in: index */ { - page_cur_t cur; + page_cur_t cur; ibool ret = TRUE; - + page_cur_set_before_first(page, &cur); page_cur_move_to_next(&cur); @@ -2610,7 +2611,7 @@ btr_index_page_validate( page_cur_move_to_next(&cur); } - return(ret); + return(ret); } /**************************************************************** @@ -2686,7 +2687,7 @@ btr_validate_level( mtr_start(&mtr); mtr_x_lock(dict_tree_get_lock(tree), &mtr); - + page = btr_root_get(tree, &mtr); space = buf_frame_get_space_id(page); @@ -2733,14 +2734,14 @@ loop: ret = FALSE; } } - + ut_a(btr_page_get_level(page, &mtr) == level); right_page_no = btr_page_get_next(page, &mtr); left_page_no = btr_page_get_prev(page, &mtr); ut_a((page_get_n_recs(page) > 0) - || ((level == 0) && + || ((level == 0) && (buf_frame_get_page_no(page) == dict_tree_get_page(tree)))); if (right_page_no != FIL_NULL) { @@ -2776,10 +2777,10 @@ loop: rec_print(stderr, rec, index); putc('\n', stderr); - ret = FALSE; - } + ret = FALSE; + } } - + if (level > 0 && left_page_no == FIL_NULL) { ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits( page_rec_get_next(page_get_infimum_rec(page)), @@ -2789,7 +2790,7 @@ loop: if (buf_frame_get_page_no(page) != dict_tree_get_page(tree)) { /* Check father node pointers */ - + node_ptr = btr_page_get_father_node_ptr(tree, page, &mtr); father_page = buf_frame_align(node_ptr); offsets = rec_get_offsets(node_ptr, index, @@ -2822,25 +2823,25 @@ loop: &mtr); rec_print(stderr, rec, index); putc('\n', stderr); - ret = FALSE; + ret = FALSE; - goto node_ptr_fails; + goto node_ptr_fails; } if (btr_page_get_level(page, &mtr) > 0) { offsets = rec_get_offsets(node_ptr, index, offsets, ULINT_UNDEFINED, &heap); - + node_ptr_tuple = dict_tree_build_node_ptr( tree, page_rec_get_next( page_get_infimum_rec(page)), 0, heap, - btr_page_get_level(page, &mtr)); + btr_page_get_level(page, &mtr)); if (cmp_dtuple_rec(node_ptr_tuple, node_ptr, offsets)) { - rec_t* first_rec = page_rec_get_next( + rec_t* first_rec = page_rec_get_next( page_get_infimum_rec(page)); btr_validate_report1(index, level, page); @@ -2855,9 +2856,9 @@ loop: fputs("InnoDB: first rec ", stderr); rec_print(stderr, first_rec, index); putc('\n', stderr); - ret = FALSE; + ret = FALSE; - goto node_ptr_fails; + goto node_ptr_fails; } } @@ -2897,9 +2898,9 @@ loop: } else { right_father_page = buf_frame_align( right_node_ptr); - + if (right_node_ptr != page_rec_get_next( - page_get_infimum_rec( + page_get_infimum_rec( right_father_page))) { ret = FALSE; fputs( @@ -2931,7 +2932,7 @@ loop: buf_page_print(page); buf_page_print(right_page); } - } + } } } @@ -2941,7 +2942,7 @@ node_ptr_fails: if (right_page_no != FIL_NULL) { ulint comp = page_is_comp(page); mtr_start(&mtr); - + page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr); ut_a(page_is_comp(page) == comp); diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index f81cce5b8e9..14e991bb3c6 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/storage/innobase/btr/btr0cur.c @@ -116,7 +116,7 @@ btr_rec_get_externally_stored_len( const ulint* offsets);/* in: array returned by rec_get_offsets() */ /*==================== B-TREE SEARCH =========================*/ - + /************************************************************************ Latches the leaf page or pages requested. */ static @@ -128,17 +128,17 @@ btr_cur_latch_leaves( ulint space, /* in: space id */ ulint page_no, /* in: page number of the leaf */ ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */ - btr_cur_t* cursor, /* in: cursor */ + btr_cur_t* cursor, /* in: cursor */ mtr_t* mtr) /* in: mtr */ { ulint left_page_no; ulint right_page_no; page_t* get_page; - + ut_ad(page && mtr); if (latch_mode == BTR_SEARCH_LEAF) { - + get_page = btr_page_get(space, page_no, RW_S_LATCH, mtr); ut_a(page_is_comp(get_page) == page_is_comp(page)); buf_block_align(get_page)->check_index_page_at_flush = TRUE; @@ -161,7 +161,7 @@ btr_cur_latch_leaves( buf_block_align(get_page)->check_index_page_at_flush = TRUE; } - + get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr); ut_a(page_is_comp(get_page) == page_is_comp(page)); buf_block_align(get_page)->check_index_page_at_flush = TRUE; @@ -261,7 +261,7 @@ btr_cur_search_to_nth_level( ulint up_match; ulint up_bytes; ulint low_match; - ulint low_bytes; + ulint low_bytes; ulint height; ulint savepoint; ulint rw_latch; @@ -289,7 +289,7 @@ btr_cur_search_to_nth_level( #ifdef UNIV_DEBUG cursor->up_match = ULINT_UNDEFINED; cursor->low_match = ULINT_UNDEFINED; -#endif +#endif insert_planned = latch_mode & BTR_INSERT; estimate = latch_mode & BTR_ESTIMATE; ignore_sec_unique = latch_mode & BTR_IGNORE_SEC_UNIQUE; @@ -297,7 +297,7 @@ btr_cur_search_to_nth_level( | BTR_IGNORE_SEC_UNIQUE); ut_ad(!insert_planned || (mode == PAGE_CUR_LE)); - + cursor->flag = BTR_CUR_BINARY; cursor->index = index; @@ -312,7 +312,7 @@ btr_cur_search_to_nth_level( #ifdef UNIV_SEARCH_PERF_STAT info->n_searches++; -#endif +#endif if (btr_search_latch.writer == RW_LOCK_NOT_LOCKED && latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ && !estimate @@ -320,7 +320,7 @@ btr_cur_search_to_nth_level( && mode != PAGE_CUR_LE_OR_EXTENDS #endif /* PAGE_CUR_LE_OR_EXTENDS */ && srv_use_adaptive_hash_indexes - && btr_search_guess_on_hash(index, info, tuple, mode, + && btr_search_guess_on_hash(index, info, tuple, mode, latch_mode, cursor, has_search_latch, mtr)) { @@ -334,7 +334,7 @@ btr_cur_search_to_nth_level( || mode != PAGE_CUR_LE); btr_cur_n_sea++; - return; + return; } #endif #endif @@ -354,7 +354,7 @@ btr_cur_search_to_nth_level( savepoint = mtr_set_savepoint(mtr); tree = index->tree; - + if (latch_mode == BTR_MODIFY_TREE) { mtr_x_lock(dict_tree_get_lock(tree), mtr); @@ -365,7 +365,7 @@ btr_cur_search_to_nth_level( } else { mtr_s_lock(dict_tree_get_lock(tree), mtr); } - + page_cursor = btr_cur_get_page_cur(cursor); space = dict_tree_get_space(tree); @@ -411,14 +411,14 @@ btr_cur_search_to_nth_level( if (insert_planned && ibuf_should_try(index, ignore_sec_unique)) { - + /* Try insert to the insert buffer if the page is not in the buffer pool */ buf_mode = BUF_GET_IF_IN_POOL; } } -retry_page_get: +retry_page_get: page = buf_page_get_gen(space, page_no, rw_latch, guess, buf_mode, __FILE__, __LINE__, @@ -451,8 +451,8 @@ retry_page_get: } buf_block_align(page)->check_index_page_at_flush = TRUE; - -#ifdef UNIV_SYNC_DEBUG + +#ifdef UNIV_SYNC_DEBUG if (rw_latch != RW_NO_LATCH) { buf_page_dbg_add_level(page, SYNC_TREE_NODE); } @@ -469,10 +469,10 @@ retry_page_get: #ifdef BTR_CUR_ADAPT if (page != guess) { info->root_guess = page; - } + } #endif } - + if (height == 0) { if (rw_latch == RW_NO_LATCH) { @@ -482,7 +482,7 @@ retry_page_get: } if ((latch_mode != BTR_MODIFY_TREE) - && (latch_mode != BTR_CONT_MODIFY_TREE)) { + && (latch_mode != BTR_CONT_MODIFY_TREE)) { /* Release the tree s-latch */ @@ -499,7 +499,7 @@ retry_page_get: &low_match, &low_bytes, page_cursor); if (estimate) { btr_cur_add_path_info(cursor, height, root_height); - } + } /* If this is the desired level, leave the loop */ @@ -513,7 +513,7 @@ retry_page_get: page = btr_page_get(space, page_no, RW_X_LATCH, mtr); ut_a((ibool)!!page_is_comp(page) - == index->table->comp); + == dict_table_is_comp(index->table)); } break; @@ -541,7 +541,7 @@ retry_page_get: cursor->up_match = up_match; cursor->up_bytes = up_bytes; -#ifdef BTR_CUR_ADAPT +#ifdef BTR_CUR_ADAPT if (srv_use_adaptive_hash_indexes) { btr_search_info_update(index, cursor); @@ -556,7 +556,7 @@ retry_page_get: } if (has_search_latch) { - + rw_lock_s_lock(&btr_search_latch); } } @@ -583,7 +583,7 @@ btr_cur_open_at_index_side( ulint root_height = 0; /* remove warning */ rec_t* node_ptr; ulint estimate; - ulint savepoint; + ulint savepoint; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; @@ -591,9 +591,9 @@ btr_cur_open_at_index_side( estimate = latch_mode & BTR_ESTIMATE; latch_mode = latch_mode & ~BTR_ESTIMATE; - + tree = index->tree; - + /* Store the position of the tree latch we push to mtr so that we know how to release it when we have latched the leaf node */ @@ -604,7 +604,7 @@ btr_cur_open_at_index_side( } else { mtr_s_lock(dict_tree_get_lock(tree), mtr); } - + page_cursor = btr_cur_get_page_cur(cursor); cursor->index = index; @@ -639,9 +639,9 @@ btr_cur_open_at_index_side( we had to scan far to find a record visible to the current transaction, that could starve others waiting for the tree latch. */ - + if ((latch_mode != BTR_MODIFY_TREE) - && (latch_mode != BTR_CONT_MODIFY_TREE)) { + && (latch_mode != BTR_CONT_MODIFY_TREE)) { /* Release the tree s-latch */ @@ -650,7 +650,7 @@ btr_cur_open_at_index_side( dict_tree_get_lock(tree)); } } - + if (from_left) { page_cur_set_before_first(page, page_cursor); } else { @@ -658,10 +658,10 @@ btr_cur_open_at_index_side( } if (height == 0) { - if (estimate) { - btr_cur_add_path_info(cursor, height, - root_height); - } + if (estimate) { + btr_cur_add_path_info(cursor, height, + root_height); + } break; } @@ -691,7 +691,7 @@ btr_cur_open_at_index_side( mem_heap_free(heap); } } - + /************************************************************************** Positions a cursor at a randomly chosen position within a B-tree. */ @@ -716,13 +716,13 @@ btr_cur_open_at_rnd_pos( *offsets_ = (sizeof offsets_) / sizeof *offsets_; tree = index->tree; - + if (latch_mode == BTR_MODIFY_TREE) { mtr_x_lock(dict_tree_get_lock(tree), mtr); } else { mtr_s_lock(dict_tree_get_lock(tree), mtr); } - + page_cursor = btr_cur_get_page_cur(cursor); cursor->index = index; @@ -730,7 +730,7 @@ btr_cur_open_at_rnd_pos( page_no = dict_tree_get_page(tree); height = ULINT_UNDEFINED; - + for (;;) { page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL, BUF_GET, @@ -750,7 +750,7 @@ btr_cur_open_at_rnd_pos( latch_mode, cursor, mtr); } - page_cur_open_on_rnd_user_rec(page, page_cursor); + page_cur_open_on_rnd_user_rec(page, page_cursor); if (height == 0) { @@ -771,7 +771,7 @@ btr_cur_open_at_rnd_pos( if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } -} +} /*==================== B-TREE INSERT =========================*/ @@ -798,7 +798,7 @@ btr_cur_insert_if_possible( rec_t* rec; ut_ad(dtuple_check_typed(tuple)); - + *reorg = FALSE; page = btr_cur_get_page(cursor); @@ -806,7 +806,7 @@ btr_cur_insert_if_possible( ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); page_cursor = btr_cur_get_page_cur(cursor); - + /* Now, try the insert */ rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index, mtr); @@ -855,9 +855,9 @@ btr_cur_ins_lock_and_undo( rec = btr_cur_get_rec(cursor); index = cursor->index; - + err = lock_rec_insert_check_and_lock(flags, rec, index, thr, inherit); - + if (err != DB_SUCCESS) { return(err); @@ -942,7 +942,7 @@ btr_cur_optimistic_insert( ibool inherit; ulint rec_size; ulint type; - ulint err; + ulint err; *big_rec = NULL; @@ -975,11 +975,11 @@ calculate_sizes_again: /* The record is so big that we have to store some fields externally on separate database pages */ - - big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0); + + big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0); if (big_rec_vec == NULL) { - + return(DB_TOO_BIG_RECORD); } @@ -991,38 +991,38 @@ calculate_sizes_again: for future updates of records. */ type = index->type; - + if ((type & DICT_CLUSTERED) - && (dict_tree_get_space_reserve(index->tree) + rec_size > max_size) - && (page_get_n_recs(page) >= 2) - && (0 == level) - && (btr_page_get_split_rec_to_right(cursor, &dummy_rec) - || btr_page_get_split_rec_to_left(cursor, &dummy_rec))) { + && (dict_tree_get_space_reserve(index->tree) + rec_size > max_size) + && (page_get_n_recs(page) >= 2) + && (0 == level) + && (btr_page_get_split_rec_to_right(cursor, &dummy_rec) + || btr_page_get_split_rec_to_left(cursor, &dummy_rec))) { - if (big_rec_vec) { + if (big_rec_vec) { dtuple_convert_back_big_rec(index, entry, big_rec_vec); } return(DB_FAIL); } - + if (!(((max_size >= rec_size) - && (max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT)) - || (page_get_max_insert_size(page, 1) >= rec_size) - || (page_get_n_recs(page) <= 1))) { + && (max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT)) + || (page_get_max_insert_size(page, 1) >= rec_size) + || (page_get_n_recs(page) <= 1))) { - if (big_rec_vec) { + if (big_rec_vec) { dtuple_convert_back_big_rec(index, entry, big_rec_vec); } return(DB_FAIL); } - /* Check locks and write to the undo log, if specified */ - err = btr_cur_ins_lock_and_undo(flags, cursor, entry, thr, &inherit); + /* Check locks and write to the undo log, if specified */ + err = btr_cur_ins_lock_and_undo(flags, cursor, entry, thr, &inherit); if (err != DB_SUCCESS) { - if (big_rec_vec) { + if (big_rec_vec) { dtuple_convert_back_big_rec(index, entry, big_rec_vec); } return(err); @@ -1041,7 +1041,7 @@ calculate_sizes_again: btr_page_reorganize(page, index, mtr); ut_ad(page_get_max_insert_size(page, 1) == max_size); - + reorg = TRUE; page_cur_search(page, index, entry, PAGE_CUR_LE, page_cursor); @@ -1076,7 +1076,7 @@ calculate_sizes_again: " rec %lu ind type %lu\n", buf_frame_get_page_no(page), max_size, rec_size + PAGE_DIR_SLOT_SIZE, type); -*/ +*/ if (!(type & DICT_CLUSTERED)) { /* We have added a record to page: update its free bits */ ibuf_update_free_bits_if_full(cursor->index, page, max_size, @@ -1123,7 +1123,7 @@ btr_cur_pessimistic_insert( ibool success; ulint n_extents = 0; ulint n_reserved; - + ut_ad(dtuple_check_typed(entry)); *big_rec = NULL; @@ -1158,7 +1158,7 @@ btr_cur_pessimistic_insert( return(err); } - if (!(flags & BTR_NO_UNDO_LOG_FLAG)) { + if (!(flags & BTR_NO_UNDO_LOG_FLAG)) { /* First reserve enough free space for the file segments of the index tree, so that the insert will not fail because of lack of space */ @@ -1180,13 +1180,13 @@ btr_cur_pessimistic_insert( /* The record is so big that we have to store some fields externally on separate database pages */ - - big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0); + + big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0); if (big_rec_vec == NULL) { - + if (n_extents > 0) { - fil_space_release_free_extents(index->space, + fil_space_release_free_extents(index->space, n_reserved); } return(DB_TOO_BIG_RECORD); @@ -1202,7 +1202,7 @@ btr_cur_pessimistic_insert( *rec = btr_page_split_and_insert(cursor, entry, mtr); } - btr_cur_position(index, page_rec_get_prev(*rec), cursor); + btr_cur_position(index, page_rec_get_prev(*rec), cursor); #ifdef BTR_CUR_ADAPT btr_search_update_hash_on_insert(cursor); @@ -1244,12 +1244,12 @@ btr_cur_upd_lock_and_undo( dict_index_t* index; rec_t* rec; ulint err; - + ut_ad(cursor && update && thr && roll_ptr); rec = btr_cur_get_rec(cursor); index = cursor->index; - + if (!(index->type & DICT_CLUSTERED)) { /* We do undo logging only when we update a clustered index record */ @@ -1304,7 +1304,7 @@ btr_cur_update_in_place_log( byte* log_ptr; page_t* page = ut_align_down(rec, UNIV_PAGE_SIZE); ut_ad(flags < 256); - ut_ad(!!page_is_comp(page) == index->table->comp); + ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); log_ptr = mlog_open_and_write_index(mtr, rec, index, page_is_comp(page) ? MLOG_COMP_REC_UPDATE_IN_PLACE @@ -1332,7 +1332,7 @@ btr_cur_update_in_place_log( log_ptr += 2; row_upd_index_write_log(update, log_ptr, mtr); -} +} /*************************************************************** Parses a redo log record of updating a record in-place. */ @@ -1360,7 +1360,7 @@ btr_cur_parse_update_in_place( return(NULL); } - + flags = mach_read_from_1(ptr); ptr++; @@ -1382,7 +1382,7 @@ btr_cur_parse_update_in_place( ut_a(rec_offset <= UNIV_PAGE_SIZE); heap = mem_heap_create(256); - + ptr = row_upd_index_parse(ptr, end_ptr, heap, &update); if (!ptr || !page) { @@ -1390,9 +1390,9 @@ btr_cur_parse_update_in_place( goto func_exit; } - ut_a((ibool)!!page_is_comp(page) == index->table->comp); + ut_a((ibool)!!page_is_comp(page) == dict_table_is_comp(index->table)); rec = page + rec_offset; - + /* We do not need to reserve btr_search_latch, as the page is only being recovered, and there cannot be a hash index to it. */ @@ -1443,7 +1443,7 @@ btr_cur_update_in_place( rec = btr_cur_get_rec(cursor); index = cursor->index; - ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); trx = thr_get_trx(thr); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); #ifdef UNIV_DEBUG @@ -1466,19 +1466,19 @@ btr_cur_update_in_place( block = buf_block_align(rec); ut_ad(!!page_is_comp(buf_block_get_frame(block)) - == index->table->comp); + == dict_table_is_comp(index->table)); if (block->is_hashed) { /* The function row_upd_changes_ord_field_binary works only if the update vector was built for a clustered index, we must NOT call it if index is secondary */ - if (!(index->type & DICT_CLUSTERED) - || row_upd_changes_ord_field_binary(NULL, index, update)) { + if (!(index->type & DICT_CLUSTERED) + || row_upd_changes_ord_field_binary(NULL, index, update)) { - /* Remove possible hash index pointer to this record */ - btr_search_update_hash_on_delete(cursor); - } + /* Remove possible hash index pointer to this record */ + btr_search_update_hash_on_delete(cursor); + } rw_lock_x_lock(&btr_search_latch); } @@ -1558,8 +1558,8 @@ btr_cur_optimistic_update( page = btr_cur_get_page(cursor); rec = btr_cur_get_rec(cursor); index = cursor->index; - ut_ad(!!page_rec_is_comp(rec) == index->table->comp); - + ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); + heap = mem_heap_create(1024); offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); @@ -1600,20 +1600,20 @@ btr_cur_optimistic_update( mem_heap_free(heap); return(DB_OVERFLOW); } - + page_cursor = btr_cur_get_page_cur(cursor); - + new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, NULL); old_rec_size = rec_offs_size(offsets); new_rec_size = rec_get_converted_size(index, new_entry); - + if (UNIV_UNLIKELY(new_rec_size >= page_get_free_space_of_empty( page_is_comp(page)) / 2)) { - mem_heap_free(heap); + mem_heap_free(heap); return(DB_OVERFLOW); } @@ -1633,14 +1633,14 @@ btr_cur_optimistic_update( } if (!(((max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT) - && (max_size >= new_rec_size)) - || (page_get_n_recs(page) <= 1))) { + && (max_size >= new_rec_size)) + || (page_get_n_recs(page) <= 1))) { /* There was not enough space, or it did not pay to reorganize: for simplicity, we decide what to do assuming a reorganization is needed, though it might not be necessary */ - mem_heap_free(heap); + mem_heap_free(heap); return(DB_OVERFLOW); } @@ -1654,8 +1654,8 @@ btr_cur_optimistic_update( return(err); } - - /* Ok, we may do the replacement. Store on the page infimum the + + /* Ok, we may do the replacement. Store on the page infimum the explicit locks on rec, before deleting rec (see the comment in .._pessimistic_update). */ @@ -1666,7 +1666,7 @@ btr_cur_optimistic_update( page_cur_delete_rec(page_cursor, index, offsets, mtr); page_cur_move_to_prev(page_cursor); - + trx = thr_get_trx(thr); if (!(flags & BTR_KEEP_SYS_FLAG)) { @@ -1693,9 +1693,9 @@ btr_cur_optimistic_update( lock_rec_restore_from_page_infimum(rec, page); - page_cur_move_to_next(page_cursor); + page_cur_move_to_next(page_cursor); - mem_heap_free(heap); + mem_heap_free(heap); return(DB_SUCCESS); } @@ -1717,24 +1717,24 @@ btr_cur_pess_upd_restore_supremum( page_t* prev_page; ulint space; ulint prev_page_no; - + page = buf_frame_align(rec); if (page_rec_get_next(page_get_infimum_rec(page)) != rec) { - /* Updated record is not the first user record on its page */ - + /* Updated record is not the first user record on its page */ + return; } space = buf_frame_get_space_id(page); prev_page_no = btr_page_get_prev(page, mtr); - + ut_ad(prev_page_no != FIL_NULL); prev_page = buf_page_get_with_no_latch(space, prev_page_no, mtr); /* We must already have an x-latch to prev_page! */ ut_ad(mtr_memo_contains(mtr, buf_block_align(prev_page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_X_FIX)); lock_rec_reset_and_inherit_gap_locks(page_get_supremum_rec(prev_page), rec); @@ -1786,9 +1786,9 @@ btr_cur_pessimistic_update( ulint n_ext_vect; ulint reserve_flag; ulint* offsets = NULL; - + *big_rec = NULL; - + page = btr_cur_get_page(cursor); rec = btr_cur_get_rec(cursor); index = cursor->index; @@ -1827,7 +1827,7 @@ btr_cur_pessimistic_update( } else { reserve_flag = FSP_NORMAL; } - + success = fsp_reserve_free_extents(&n_reserved, index->space, n_extents, reserve_flag, mtr); @@ -1837,12 +1837,12 @@ btr_cur_pessimistic_update( return(err); } } - + heap = mem_heap_create(1024); offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); trx = thr_get_trx(thr); - + new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, @@ -1863,7 +1863,7 @@ btr_cur_pessimistic_update( update it back again. */ ut_a(big_rec_vec == NULL); - + btr_rec_free_updated_extern_fields(index, rec, offsets, update, TRUE, mtr); } @@ -1882,8 +1882,8 @@ btr_cur_pessimistic_update( ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2, REC_MAX_DATA_SIZE))) { - big_rec_vec = dtuple_convert_big_rec(index, new_entry, - ext_vect, n_ext_vect); + big_rec_vec = dtuple_convert_big_rec(index, new_entry, + ext_vect, n_ext_vect); if (big_rec_vec == NULL) { err = DB_TOO_BIG_RECORD; @@ -1921,7 +1921,7 @@ btr_cur_pessimistic_update( lock_rec_restore_from_page_infimum(rec, page); rec_set_field_extern_bits(rec, index, ext_vect, n_ext_vect, mtr); - + if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) { /* The new inserted record owns its possible externally stored fields */ @@ -2009,7 +2009,7 @@ btr_cur_del_mark_set_clust_rec_log( ut_ad(flags < 256); ut_ad(val <= 1); - ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); log_ptr = mlog_open_and_write_index(mtr, rec, index, page_rec_is_comp(rec) @@ -2056,13 +2056,14 @@ btr_cur_parse_del_mark_set_clust_rec( ulint offset; rec_t* rec; - ut_ad(!page || !!page_is_comp(page) == index->table->comp); + ut_ad(!page + || !!page_is_comp(page) == dict_table_is_comp(index->table)); if (end_ptr < ptr + 2) { return(NULL); } - + flags = mach_read_from_1(ptr); ptr++; val = mach_read_from_1(ptr); @@ -2087,7 +2088,7 @@ btr_cur_parse_del_mark_set_clust_rec( if (page) { rec = page + offset; - + if (!(flags & BTR_KEEP_SYS_FLAG)) { mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; @@ -2108,7 +2109,7 @@ btr_cur_parse_del_mark_set_clust_rec( rec_set_deleted_flag(rec, page_is_comp(page), val); } - + return(ptr); } @@ -2142,7 +2143,7 @@ btr_cur_del_mark_set_clust_rec( rec = btr_cur_get_rec(cursor); index = cursor->index; - ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); #ifdef UNIV_DEBUG @@ -2186,11 +2187,11 @@ btr_cur_del_mark_set_clust_rec( rec_set_deleted_flag(rec, rec_offs_comp(offsets), val); trx = thr_get_trx(thr); - + if (!(flags & BTR_KEEP_SYS_FLAG)) { row_upd_rec_sys_fields(rec, index, offsets, trx, roll_ptr); } - + if (block->is_hashed) { rw_lock_x_unlock(&btr_search_latch); } @@ -2256,7 +2257,7 @@ btr_cur_parse_del_mark_set_sec_rec( return(NULL); } - + val = mach_read_from_1(ptr); ptr++; @@ -2267,17 +2268,17 @@ btr_cur_parse_del_mark_set_sec_rec( if (page) { rec = page + offset; - + /* We do not need to reserve btr_search_latch, as the page is only being recovered, and there cannot be a hash index to it. */ rec_set_deleted_flag(rec, page_is_comp(page), val); } - + return(ptr); } - + /*************************************************************** Sets a secondary index record delete mark to TRUE or FALSE. */ @@ -2315,8 +2316,8 @@ btr_cur_del_mark_set_sec_rec( block = buf_block_align(rec); ut_ad(!!page_is_comp(buf_block_get_frame(block)) - == cursor->index->table->comp); - + == dict_table_is_comp(cursor->index->table)); + if (block->is_hashed) { rw_lock_x_lock(&btr_search_latch); } @@ -2375,7 +2376,7 @@ btr_cur_compress( MTR_MEMO_PAGE_X_FIX)); ut_ad(btr_page_get_level(btr_cur_get_page(cursor), mtr) == 0); - btr_compress(cursor, mtr); + btr_compress(cursor, mtr); } /***************************************************************** @@ -2441,7 +2442,7 @@ btr_cur_optimistic_delete( /* This is intended only for leaf page deletions */ page = btr_cur_get_page(cursor); - + ut_ad(btr_page_get_level(page, mtr) == 0); rec = btr_cur_get_rec(cursor); @@ -2513,7 +2514,7 @@ btr_cur_pessimistic_delete( ulint level; mem_heap_t* heap; ulint* offsets; - + page = btr_cur_get_page(cursor); tree = btr_cur_get_tree(cursor); @@ -2555,26 +2556,26 @@ btr_cur_pessimistic_delete( } if (UNIV_UNLIKELY(page_get_n_recs(page) < 2) - && UNIV_UNLIKELY(dict_tree_get_page(btr_cur_get_tree(cursor)) - != buf_frame_get_page_no(page))) { + && UNIV_UNLIKELY(dict_tree_get_page(btr_cur_get_tree(cursor)) + != buf_frame_get_page_no(page))) { /* If there is only one record, drop the whole page in btr_discard_page, if this is not the root page */ - + btr_discard_page(cursor, mtr); *err = DB_SUCCESS; ret = TRUE; - goto return_after_reservations; + goto return_after_reservations; } lock_update_delete(rec); level = btr_page_get_level(page, mtr); if (level > 0 - && UNIV_UNLIKELY(rec == page_rec_get_next( - page_get_infimum_rec(page)))) { + && UNIV_UNLIKELY(rec == page_rec_get_next( + page_get_infimum_rec(page)))) { rec_t* next_rec = page_rec_get_next(rec); @@ -2602,7 +2603,7 @@ btr_cur_pessimistic_delete( btr_insert_on_non_leaf_level(tree, level + 1, node_ptr, mtr); } - } + } btr_search_update_hash_on_delete(cursor); @@ -2612,7 +2613,7 @@ btr_cur_pessimistic_delete( ut_ad(btr_check_node_ptr(tree, page, mtr)); *err = DB_SUCCESS; - + return_after_reservations: mem_heap_free(heap); @@ -2661,7 +2662,7 @@ btr_cur_add_path_info( } rec = btr_cur_get_rec(cursor); - + slot = cursor->path_arr + (root_height - height); slot->nth_rec = page_rec_get_n_recs_before(rec); @@ -2687,8 +2688,8 @@ btr_estimate_n_rows_in_range( btr_path_t* slot1; btr_path_t* slot2; ibool diverged; - ibool diverged_lot; - ulint divergence_level; + ibool diverged_lot; + ulint divergence_level; ib_longlong n_rows; ulint i; mtr_t mtr; @@ -2698,7 +2699,7 @@ btr_estimate_n_rows_in_range( cursor.path_arr = path1; if (dtuple_get_n_fields(tuple1) > 0) { - + btr_cur_search_to_nth_level(index, 0, tuple1, mode1, BTR_SEARCH_LEAF | BTR_ESTIMATE, &cursor, 0, &mtr); @@ -2707,7 +2708,7 @@ btr_estimate_n_rows_in_range( BTR_SEARCH_LEAF | BTR_ESTIMATE, &cursor, &mtr); } - + mtr_commit(&mtr); mtr_start(&mtr); @@ -2715,7 +2716,7 @@ btr_estimate_n_rows_in_range( cursor.path_arr = path2; if (dtuple_get_n_fields(tuple2) > 0) { - + btr_cur_search_to_nth_level(index, 0, tuple2, mode2, BTR_SEARCH_LEAF | BTR_ESTIMATE, &cursor, 0, &mtr); @@ -2724,48 +2725,48 @@ btr_estimate_n_rows_in_range( BTR_SEARCH_LEAF | BTR_ESTIMATE, &cursor, &mtr); } - + mtr_commit(&mtr); /* We have the path information for the range in path1 and path2 */ n_rows = 1; - diverged = FALSE; /* This becomes true when the path is not - the same any more */ - diverged_lot = FALSE; /* This becomes true when the paths are - not the same or adjacent any more */ + diverged = FALSE; /* This becomes true when the path is not + the same any more */ + diverged_lot = FALSE; /* This becomes true when the paths are + not the same or adjacent any more */ divergence_level = 1000000; /* This is the level where paths diverged - a lot */ - for (i = 0; ; i++) { + a lot */ + for (i = 0; ; i++) { ut_ad(i < BTR_PATH_ARRAY_N_SLOTS); - + slot1 = path1 + i; slot2 = path2 + i; if (slot1->nth_rec == ULINT_UNDEFINED || slot2->nth_rec == ULINT_UNDEFINED) { - if (i > divergence_level + 1) { - /* In trees whose height is > 1 our algorithm - tends to underestimate: multiply the estimate - by 2: */ + if (i > divergence_level + 1) { + /* In trees whose height is > 1 our algorithm + tends to underestimate: multiply the estimate + by 2: */ - n_rows = n_rows * 2; - } + n_rows = n_rows * 2; + } /* Do not estimate the number of rows in the range - to over 1 / 2 of the estimated rows in the whole + to over 1 / 2 of the estimated rows in the whole table */ if (n_rows > index->table->stat_n_rows / 2) { - n_rows = index->table->stat_n_rows / 2; + n_rows = index->table->stat_n_rows / 2; /* If there are just 0 or 1 rows in the table, then we estimate all rows are in the range */ - - if (n_rows == 0) { - n_rows = index->table->stat_n_rows; - } + + if (n_rows == 0) { + n_rows = index->table->stat_n_rows; + } } return(n_rows); @@ -2779,7 +2780,7 @@ btr_estimate_n_rows_in_range( n_rows = slot2->nth_rec - slot1->nth_rec; if (n_rows > 1) { - diverged_lot = TRUE; + diverged_lot = TRUE; divergence_level = i; } } else { @@ -2791,28 +2792,28 @@ btr_estimate_n_rows_in_range( } else if (diverged && !diverged_lot) { - if (slot1->nth_rec < slot1->n_recs - || slot2->nth_rec > 1) { + if (slot1->nth_rec < slot1->n_recs + || slot2->nth_rec > 1) { - diverged_lot = TRUE; + diverged_lot = TRUE; divergence_level = i; n_rows = 0; - if (slot1->nth_rec < slot1->n_recs) { - n_rows += slot1->n_recs - - slot1->nth_rec; + if (slot1->nth_rec < slot1->n_recs) { + n_rows += slot1->n_recs + - slot1->nth_rec; } if (slot2->nth_rec > 1) { - n_rows += slot2->nth_rec - 1; + n_rows += slot2->nth_rec - 1; } - } + } } else if (diverged_lot) { n_rows = (n_rows * (slot1->n_recs + slot2->n_recs)) / 2; - } + } } } @@ -2855,13 +2856,13 @@ btr_estimate_number_of_different_key_vals( memset(n_diff, 0, (n_cols + 1) * sizeof(ib_longlong)); /* We sample some pages in the index to get an estimate */ - + for (i = 0; i < BTR_KEY_VAL_ESTIMATE_N_PAGES; i++) { rec_t* supremum; mtr_start(&mtr); btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr); - + /* Count the number of different key values for each prefix of the key on this index page. If the prefix does not determine the index record uniquely in te B-tree, then we subtract one @@ -2906,7 +2907,7 @@ btr_estimate_number_of_different_key_vals( total_external_size += btr_rec_get_externally_stored_len( rec, offsets_rec); - + rec = next_rec; /* Initialize offsets_rec for the next round and assign the old offsets_rec buffer to @@ -2917,7 +2918,7 @@ btr_estimate_number_of_different_key_vals( offsets_next_rec = offsets_tmp; } } - + if (n_cols == dict_index_get_n_unique_in_tree(index)) { @@ -2931,7 +2932,7 @@ btr_estimate_number_of_different_key_vals( in the table. */ if (btr_page_get_prev(page, &mtr) != FIL_NULL - || btr_page_get_next(page, &mtr) != FIL_NULL) { + || btr_page_get_next(page, &mtr) != FIL_NULL) { n_diff[n_cols]++; } @@ -2948,10 +2949,10 @@ btr_estimate_number_of_different_key_vals( /* If we saw k borders between different key values on BTR_KEY_VAL_ESTIMATE_N_PAGES leaf pages, we can estimate how many there will be in index->stat_n_leaf_pages */ - + /* We must take into account that our sample actually represents also the pages used for external storage of fields (those pages are - included in index->stat_n_leaf_pages) */ + included in index->stat_n_leaf_pages) */ for (j = 0; j <= n_cols; j++) { index->stat_n_diff_key_vals[j] = @@ -2960,9 +2961,9 @@ btr_estimate_number_of_different_key_vals( + BTR_KEY_VAL_ESTIMATE_N_PAGES - 1 + total_external_size + not_empty_flag) - / (BTR_KEY_VAL_ESTIMATE_N_PAGES - + total_external_size); - + / (BTR_KEY_VAL_ESTIMATE_N_PAGES + + total_external_size); + /* If the tree is small, smaller than < 10 * BTR_KEY_VAL_ESTIMATE_N_PAGES + total_external_size, then the above estimate is ok. For bigger trees it is common that we @@ -2977,10 +2978,10 @@ btr_estimate_number_of_different_key_vals( if (add_on > BTR_KEY_VAL_ESTIMATE_N_PAGES) { add_on = BTR_KEY_VAL_ESTIMATE_N_PAGES; } - + index->stat_n_diff_key_vals[j] += add_on; } - + mem_free(n_diff); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -3016,7 +3017,7 @@ btr_rec_get_externally_stored_len( data = rec_get_nth_field(rec, offsets, i, &local_len); local_len -= BTR_EXTERN_FIELD_REF_SIZE; - + extern_len = mach_read_from_4(data + local_len + BTR_EXTERN_LEN + 4); @@ -3045,7 +3046,7 @@ btr_cur_set_ownership_of_extern_field( ulint byte_val; data = rec_get_nth_field(rec, offsets, i, &local_len); - + ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); local_len -= BTR_EXTERN_FIELD_REF_SIZE; @@ -3057,7 +3058,7 @@ btr_cur_set_ownership_of_extern_field( } else { byte_val = byte_val | BTR_EXTERN_OWNER_FLAG; } - + mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val, MLOG_1BYTE, mtr); } @@ -3087,7 +3088,7 @@ btr_cur_mark_extern_inherited_fields( for (i = 0; i < n; i++) { if (rec_offs_nth_extern(offsets, i)) { - + /* Check it is not in updated fields */ is_updated = FALSE; @@ -3136,7 +3137,7 @@ btr_cur_mark_dtuple_inherited_extern( return; } - + for (i = 0; i < n_ext_vec; i++) { /* Check ext_vec[i] is in updated fields */ @@ -3154,14 +3155,14 @@ btr_cur_mark_dtuple_inherited_extern( data = (byte*) dfield_get_data(dfield); len = dfield_get_len(dfield); - + len -= BTR_EXTERN_FIELD_REF_SIZE; byte_val = mach_read_from_1(data + len + BTR_EXTERN_LEN); byte_val = byte_val | BTR_EXTERN_INHERITED_FLAG; - + mach_write_to_1(data + len + BTR_EXTERN_LEN, byte_val); } } @@ -3191,7 +3192,7 @@ btr_cur_unmark_extern_fields( btr_cur_set_ownership_of_extern_field(rec, offsets, i, TRUE, mtr); } - } + } } /*********************************************************************** @@ -3216,15 +3217,15 @@ btr_cur_unmark_dtuple_extern_fields( data = (byte*) dfield_get_data(dfield); len = dfield_get_len(dfield); - + len -= BTR_EXTERN_FIELD_REF_SIZE; byte_val = mach_read_from_1(data + len + BTR_EXTERN_LEN); byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG); - + mach_write_to_1(data + len + BTR_EXTERN_LEN, byte_val); - } + } } /*********************************************************************** @@ -3251,7 +3252,7 @@ btr_push_update_extern_fields( if (update) { n = upd_get_n_fields(update); - + for (i = 0; i < n; i++) { if (upd_get_nth_field(update, i)->extern_storage) { @@ -3268,7 +3269,7 @@ btr_push_update_extern_fields( for (i = 0; i < n; i++) { if (rec_offs_nth_extern(offsets, i)) { - + /* Check it is not in updated fields */ is_updated = FALSE; @@ -3287,7 +3288,7 @@ btr_push_update_extern_fields( n_pushed++; } } - } + } return(n_pushed); } @@ -3333,8 +3334,8 @@ btr_store_big_rec_extern_fields( big_rec_t* big_rec_vec, /* in: vector containing fields to be stored externally */ mtr_t* local_mtr __attribute__((unused))) /* in: mtr - containing the latch to rec and to the - tree */ + containing the latch to rec and to the + tree */ { byte* data; ulint local_len; @@ -3356,9 +3357,9 @@ btr_store_big_rec_extern_fields( ut_ad(mtr_memo_contains(local_mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)); ut_a(index->type & DICT_CLUSTERED); - + space_id = buf_frame_get_space_id(rec); - + /* We have to create a file segment to the tablespace for each field and put the pointer to the field in rec */ @@ -3382,7 +3383,7 @@ btr_store_big_rec_extern_fields( } else { hint_page_no = prev_page_no + 1; } - + page = btr_page_alloc(index->tree, hint_page_no, FSP_NO_DIR, 0, &mtr); if (page == NULL) { @@ -3392,6 +3393,9 @@ btr_store_big_rec_extern_fields( return(DB_OUT_OF_FILE_SPACE); } + mlog_write_ulint(page + FIL_PAGE_TYPE, + FIL_PAGE_TYPE_BLOB, MLOG_2BYTES, &mtr); + page_no = buf_frame_get_page_no(page); if (prev_page_no != FIL_NULL) { @@ -3403,7 +3407,7 @@ btr_store_big_rec_extern_fields( buf_page_dbg_add_level(prev_page, SYNC_EXTERN_STORAGE); #endif /* UNIV_SYNC_DEBUG */ - + mlog_write_ulint(prev_page + FIL_PAGE_DATA + BTR_BLOB_HDR_NEXT_PAGE_NO, page_no, MLOG_4BYTES, &mtr); @@ -3431,7 +3435,7 @@ btr_store_big_rec_extern_fields( mlog_write_ulint(page + FIL_PAGE_DATA + BTR_BLOB_HDR_NEXT_PAGE_NO, FIL_NULL, MLOG_4BYTES, &mtr); - + extern_len -= store_len; rec_page = buf_page_get(space_id, @@ -3457,7 +3461,7 @@ btr_store_big_rec_extern_fields( + BTR_EXTERN_PAGE_NO, page_no, MLOG_4BYTES, &mtr); - + mlog_write_ulint(data + local_len + BTR_EXTERN_OFFSET, FIL_PAGE_DATA, @@ -3504,9 +3508,9 @@ btr_free_externally_stored_field( ibool do_not_free_inherited,/* in: TRUE if called in a rollback and we do not want to free inherited fields */ - mtr_t* local_mtr __attribute__((unused))) /* in: mtr - containing the latch to data an an - X-latch to the index tree */ + mtr_t* local_mtr __attribute__((unused))) /* in: mtr + containing the latch to data an an + X-latch to the index tree */ { page_t* page; page_t* rec_page; @@ -3525,7 +3529,7 @@ btr_free_externally_stored_field( MTR_MEMO_PAGE_X_FIX)); ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); local_len -= BTR_EXTERN_FIELD_REF_SIZE; - + for (;;) { mtr_start(&mtr); @@ -3574,7 +3578,7 @@ btr_free_externally_stored_field( return; } - + page = buf_page_get(space_id, page_no, RW_X_LATCH, &mtr); #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_EXTERN_STORAGE); @@ -3637,7 +3641,7 @@ btr_rec_free_externally_stored_fields( MTR_MEMO_PAGE_X_FIX)); /* Free possible externally stored fields in the record */ - ut_ad(index->table->comp == !!rec_offs_comp(offsets)); + ut_ad(dict_table_is_comp(index->table) == !!rec_offs_comp(offsets)); n_fields = rec_offs_n_fields(offsets); for (i = 0; i < n_fields; i++) { @@ -3684,7 +3688,7 @@ btr_rec_free_updated_extern_fields( for (i = 0; i < n_fields; i++) { ufield = upd_get_nth_field(update, i); - + if (rec_offs_nth_extern(offsets, ufield->field_no)) { data = rec_get_nth_field(rec, offsets, @@ -3735,7 +3739,7 @@ btr_copy_externally_stored_field( /* Currently a BLOB cannot be bigger that 4 GB; we leave the 4 upper bytes in the length field unused */ - + extern_len = mach_read_from_4(data + local_len + BTR_EXTERN_LEN + 4); buf = mem_heap_alloc(heap, local_len + extern_len); @@ -3745,11 +3749,11 @@ btr_copy_externally_stored_field( if (extern_len == 0) { *len = copied_len; - + return(buf); } - for (;;) { + for (;;) { mtr_start(&mtr); page = buf_page_get(space_id, page_no, RW_S_LATCH, &mtr); @@ -3777,7 +3781,7 @@ btr_copy_externally_stored_field( ut_a(copied_len == local_len + extern_len); *len = copied_len; - + return(buf); } diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index 5dbbca0b17d..e3ba50a2d5b 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/innobase/btr/btr0pcur.c @@ -30,7 +30,7 @@ btr_pcur_create_for_mysql(void) pcur->btr_cur.index = NULL; btr_pcur_init(pcur); - + return(pcur); } @@ -53,7 +53,7 @@ btr_pcur_free_for_mysql( cursor->old_rec = NULL; cursor->old_n_fields = 0; cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; - + cursor->latch_mode = BTR_NO_LATCHES; cursor->pos_state = BTR_PCUR_NOT_POSITIONED; @@ -79,7 +79,7 @@ btr_pcur_store_position( dict_tree_t* tree; page_t* page; ulint offs; - + ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); @@ -92,9 +92,9 @@ btr_pcur_store_position( offs = ut_align_offset(rec, UNIV_PAGE_SIZE); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_S_FIX) - || mtr_memo_contains(mtr, buf_block_align(page), - MTR_MEMO_PAGE_X_FIX)); + MTR_MEMO_PAGE_S_FIX) + || mtr_memo_contains(mtr, buf_block_align(page), + MTR_MEMO_PAGE_X_FIX)); ut_a(cursor->latch_mode != BTR_NO_LATCHES); if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) { @@ -115,7 +115,7 @@ btr_pcur_store_position( } return; - } + } if (page_rec_is_supremum_low(offs)) { @@ -138,7 +138,7 @@ btr_pcur_store_position( &cursor->old_rec_buf, &cursor->buf_size); - cursor->block_when_stored = buf_block_align(page); + cursor->block_when_stored = buf_block_align(page); cursor->modify_clock = buf_block_get_modify_clock( cursor->block_when_stored); } @@ -158,17 +158,17 @@ btr_pcur_copy_stored_position( mem_free(pcur_receive->old_rec_buf); } - ut_memcpy((byte*)pcur_receive, (byte*)pcur_donate, sizeof(btr_pcur_t)); + ut_memcpy(pcur_receive, pcur_donate, sizeof(btr_pcur_t)); if (pcur_donate->old_rec_buf) { pcur_receive->old_rec_buf = mem_alloc(pcur_donate->buf_size); - + ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf, pcur_donate->buf_size); pcur_receive->old_rec = pcur_receive->old_rec_buf + (pcur_donate->old_rec - pcur_donate->old_rec_buf); - } + } pcur_receive->old_n_fields = pcur_donate->old_n_fields; } @@ -195,7 +195,7 @@ btr_pcur_restore_position( whose ordering fields are identical to the ones of the original user record */ ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */ - btr_pcur_t* cursor, /* in: detached persistent cursor */ + btr_pcur_t* cursor, /* in: detached persistent cursor */ mtr_t* mtr) /* in: mtr */ { dict_tree_t* tree; @@ -206,21 +206,21 @@ btr_pcur_restore_position( mem_heap_t* heap; if (UNIV_UNLIKELY(cursor->old_stored != BTR_PCUR_OLD_STORED) - || UNIV_UNLIKELY(cursor->pos_state != BTR_PCUR_WAS_POSITIONED - && cursor->pos_state != BTR_PCUR_IS_POSITIONED)) { - ut_print_buf(stderr, (const byte*)cursor, sizeof(btr_pcur_t)); + || UNIV_UNLIKELY(cursor->pos_state != BTR_PCUR_WAS_POSITIONED + && cursor->pos_state != BTR_PCUR_IS_POSITIONED)) { + ut_print_buf(stderr, cursor, sizeof(btr_pcur_t)); if (cursor->trx_if_known) { trx_print(stderr, cursor->trx_if_known, 0); } - + ut_error; } if (UNIV_UNLIKELY(cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) { - /* In these cases we do not try an optimistic restoration, - but always do a search */ + /* In these cases we do not try an optimistic restoration, + but always do a search */ btr_cur_open_at_index_side( cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE, @@ -232,7 +232,7 @@ btr_pcur_restore_position( return(FALSE); } - + ut_a(cursor->old_rec); ut_a(cursor->old_n_fields); @@ -241,10 +241,10 @@ btr_pcur_restore_position( if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF) || UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) { /* Try optimistic restoration */ - + if (UNIV_LIKELY(buf_page_optimistic_get(latch_mode, - cursor->block_when_stored, page, - cursor->modify_clock, mtr))) { + cursor->block_when_stored, page, + cursor->modify_clock, mtr))) { cursor->pos_state = BTR_PCUR_IS_POSITIONED; #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_TREE_NODE); @@ -285,14 +285,14 @@ btr_pcur_restore_position( /* If optimistic restoration did not succeed, open the cursor anew */ heap = mem_heap_create(256); - + tree = btr_cur_get_tree(btr_pcur_get_btr_cur(cursor)); tuple = dict_tree_build_data_tuple(tree, cursor->old_rec, cursor->old_n_fields, heap); /* Save the old search mode of the cursor */ old_mode = cursor->search_mode; - + if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) { mode = PAGE_CUR_LE; } else if (cursor->rel_pos == BTR_PCUR_AFTER) { @@ -304,13 +304,13 @@ btr_pcur_restore_position( btr_pcur_open_with_no_init(btr_pcur_get_btr_cur(cursor)->index, tuple, mode, latch_mode, cursor, 0, mtr); - + /* Restore the old search mode */ cursor->search_mode = old_mode; if (cursor->rel_pos == BTR_PCUR_ON - && btr_pcur_is_on_user_rec(cursor, mtr) - && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), + && btr_pcur_is_on_user_rec(cursor, mtr) + && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), rec_get_offsets(btr_pcur_get_rec(cursor), btr_pcur_get_btr_cur(cursor)->index, NULL, ULINT_UNDEFINED, &heap))) { @@ -335,7 +335,7 @@ btr_pcur_restore_position( /* We have to store new position information, modify_clock etc., to the cursor because it can now be on a different page, the record under it may have been removed, etc. */ - + btr_pcur_store_position(cursor, mtr); return(FALSE); @@ -358,12 +358,12 @@ btr_pcur_release_leaf( ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor)); - + btr_leaf_page_release(page, cursor->latch_mode, mtr); - - cursor->latch_mode = BTR_NO_LATCHES; + + cursor->latch_mode = BTR_NO_LATCHES; cursor->pos_state = BTR_PCUR_WAS_POSITIONED; } @@ -386,25 +386,25 @@ btr_pcur_move_to_next_page( page_t* page; page_t* next_page; - ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); + ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - ut_ad(btr_pcur_is_after_last_on_page(cursor, mtr)); + ut_ad(btr_pcur_is_after_last_on_page(cursor, mtr)); cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; - + page = btr_pcur_get_page(cursor); next_page_no = btr_page_get_next(page, mtr); space = buf_frame_get_space_id(page); - ut_ad(next_page_no != FIL_NULL); + ut_ad(next_page_no != FIL_NULL); next_page = btr_page_get(space, next_page_no, cursor->latch_mode, mtr); ut_a(page_is_comp(next_page) == page_is_comp(page)); buf_block_align(next_page)->check_index_page_at_flush = TRUE; btr_leaf_page_release(page, cursor->latch_mode, mtr); - + page_cur_set_before_first(next_page, btr_pcur_get_page_cur(cursor)); page_check_dir(next_page); @@ -436,11 +436,11 @@ btr_pcur_move_backward_from_page( ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - ut_ad(btr_pcur_is_before_first_on_page(cursor, mtr)); - ut_ad(!btr_pcur_is_before_first_in_tree(cursor, mtr)); - + ut_ad(btr_pcur_is_before_first_on_page(cursor, mtr)); + ut_ad(!btr_pcur_is_before_first_in_tree(cursor, mtr)); + latch_mode = cursor->latch_mode; - + if (latch_mode == BTR_SEARCH_LEAF) { latch_mode2 = BTR_SEARCH_PREV; @@ -459,7 +459,7 @@ btr_pcur_move_backward_from_page( mtr_start(mtr); - btr_pcur_restore_position(latch_mode2, cursor, mtr); + btr_pcur_restore_position(latch_mode2, cursor, mtr); page = btr_pcur_get_page(cursor); @@ -467,7 +467,7 @@ btr_pcur_move_backward_from_page( space = buf_frame_get_space_id(page); if (btr_pcur_is_before_first_on_page(cursor, mtr) - && (prev_page_no != FIL_NULL)) { + && (prev_page_no != FIL_NULL)) { prev_page = btr_pcur_get_btr_cur(cursor)->left_page; @@ -476,11 +476,11 @@ btr_pcur_move_backward_from_page( page_cur_set_after_last(prev_page, btr_pcur_get_page_cur(cursor)); } else if (prev_page_no != FIL_NULL) { - + /* The repositioned cursor did not end on an infimum record on a page. Cursor repositioning acquired a latch also on the previous page, but we do not need the latch: release it. */ - + prev_page = btr_pcur_get_btr_cur(cursor)->left_page; btr_leaf_page_release(prev_page, latch_mode, mtr); @@ -506,7 +506,7 @@ btr_pcur_move_to_prev( { ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - + cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; if (btr_pcur_is_before_first_on_page(cursor, mtr)) { @@ -542,14 +542,14 @@ btr_pcur_open_on_user_rec( ulint mode, /* in: PAGE_CUR_L, ... */ ulint latch_mode, /* in: BTR_SEARCH_LEAF or BTR_MODIFY_LEAF */ - btr_pcur_t* cursor, /* in: memory buffer for persistent + btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */ mtr_t* mtr) /* in: mtr */ { btr_pcur_open(index, tuple, mode, latch_mode, cursor, mtr); if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) { - + if (btr_pcur_is_after_last_on_page(cursor, mtr)) { btr_pcur_move_to_next_user_rec(cursor, mtr); diff --git a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c index 7a4e92a672a..a2f571f11e9 100644 --- a/storage/innobase/btr/btr0sea.c +++ b/storage/innobase/btr/btr0sea.c @@ -103,7 +103,7 @@ btr_search_check_free_space_in_heap(void) table = btr_search_sys->hash_index; heap = table->heap; - + /* Note that we peek the value of heap->free_block without reserving the latch: this is ok, because we will not guarantee that there will be enough free space in the hash table. */ @@ -133,9 +133,9 @@ btr_search_sys_create( { /* We allocate the search latch from dynamic memory: see above at the global variable definition */ - + btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t)); - + rw_lock_create(&btr_search_latch); btr_search_sys = mem_alloc(sizeof(btr_search_sys_t)); @@ -169,10 +169,10 @@ btr_search_info_create( info->last_hash_succ = FALSE; - info->n_hash_succ = 0; - info->n_hash_fail = 0; - info->n_patt_succ = 0; - info->n_searches = 0; + info->n_hash_succ = 0; + info->n_hash_fail = 0; + info->n_patt_succ = 0; + info->n_searches = 0; /* Set some sensible values */ info->n_fields = 1; @@ -191,7 +191,7 @@ static void btr_search_info_update_hash( /*========================*/ - btr_search_t* info, /* in: search info */ + btr_search_t* info, /* in/out: search info */ btr_cur_t* cursor) /* in: cursor which was just positioned */ { dict_index_t* index; @@ -223,7 +223,7 @@ btr_search_info_update_hash( hash prefix */ if (info->n_fields >= n_unique && cursor->up_match >= n_unique) { - + info->n_hash_potential++; return; @@ -244,20 +244,20 @@ btr_search_info_update_hash( if ((info->side == BTR_SEARCH_LEFT_SIDE && cmp > 0) || (info->side == BTR_SEARCH_RIGHT_SIDE && cmp <= 0)) { - goto set_new_recomm; + goto set_new_recomm; } info->n_hash_potential++; return; - + set_new_recomm: /* We have to set a new recommendation; skip the hash analysis for a while to avoid unnecessary CPU time usage when there is no chance for success */ - + info->hash_analysis = 0; - + cmp = ut_pair_cmp(cursor->up_match, cursor->up_bytes, cursor->low_match, cursor->low_bytes); if (cmp == 0) { @@ -282,7 +282,7 @@ set_new_recomm: info->n_fields = cursor->low_match + 1; info->n_bytes = 0; - } else { + } else { info->n_fields = cursor->low_match; info->n_bytes = cursor->low_bytes + 1; } @@ -300,7 +300,7 @@ set_new_recomm: info->n_fields = cursor->up_match + 1; info->n_bytes = 0; - } else { + } else { info->n_fields = cursor->up_match; info->n_bytes = cursor->up_bytes + 1; } @@ -308,7 +308,7 @@ set_new_recomm: info->side = BTR_SEARCH_RIGHT_SIDE; } } - + /************************************************************************* Updates the block search info on hash successes. NOTE that info and block->n_hash_helps, n_fields, n_bytes, side are NOT protected by any @@ -337,19 +337,19 @@ btr_search_update_block_hash_info( ut_a(info->magic_n == BTR_SEARCH_MAGIC_N); if ((block->n_hash_helps > 0) - && (info->n_hash_potential > 0) - && (block->n_fields == info->n_fields) - && (block->n_bytes == info->n_bytes) - && (block->side == info->side)) { - + && (info->n_hash_potential > 0) + && (block->n_fields == info->n_fields) + && (block->n_bytes == info->n_bytes) + && (block->side == info->side)) { + if ((block->is_hashed) - && (block->curr_n_fields == info->n_fields) - && (block->curr_n_bytes == info->n_bytes) - && (block->curr_side == info->side)) { + && (block->curr_n_fields == info->n_fields) + && (block->curr_n_bytes == info->n_bytes) + && (block->curr_side == info->side)) { /* The search would presumably have succeeded using the hash index */ - + info->last_hash_succ = TRUE; } @@ -366,19 +366,19 @@ btr_search_update_block_hash_info( } if ((block->n_hash_helps > page_get_n_recs(block->frame) - / BTR_SEARCH_PAGE_BUILD_LIMIT) - && (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) { + / BTR_SEARCH_PAGE_BUILD_LIMIT) + && (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) { - if ((!block->is_hashed) - || (block->n_hash_helps + if ((!block->is_hashed) + || (block->n_hash_helps > 2 * page_get_n_recs(block->frame)) - || (block->n_fields != block->curr_n_fields) - || (block->n_bytes != block->curr_n_bytes) - || (block->side != block->curr_side)) { + || (block->n_fields != block->curr_n_fields) + || (block->n_bytes != block->curr_n_bytes) + || (block->side != block->curr_side)) { - /* Build a new hash index on the page */ + /* Build a new hash index on the page */ - return(TRUE); + return(TRUE); } } @@ -415,21 +415,21 @@ btr_search_update_hash_ref( ut_a(!block->is_hashed || block->index == cursor->index); if (block->is_hashed - && (info->n_hash_potential > 0) - && (block->curr_n_fields == info->n_fields) - && (block->curr_n_bytes == info->n_bytes) - && (block->curr_side == info->side)) { + && (info->n_hash_potential > 0) + && (block->curr_n_fields == info->n_fields) + && (block->curr_n_bytes == info->n_bytes) + && (block->curr_side == info->side)) { mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; *offsets_ = (sizeof offsets_) / sizeof *offsets_; - rec = btr_cur_get_rec(cursor); + rec = btr_cur_get_rec(cursor); + + if (!page_rec_is_user_rec(rec)) { - if (!page_rec_is_user_rec(rec)) { + return; + } - return; - } - tree_id = ((cursor->index)->tree)->id; fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_, ULINT_UNDEFINED, &heap), @@ -444,22 +444,22 @@ btr_search_update_hash_ref( ha_insert_for_fold(btr_search_sys->hash_index, fold, rec); } -} - +} + /************************************************************************* Updates the search info. */ void btr_search_info_update_slow( /*========================*/ - btr_search_t* info, /* in: search info */ + btr_search_t* info, /* in/out: search info */ btr_cur_t* cursor) /* in: cursor which was just positioned */ { buf_block_t* block; ibool build_index; ulint* params; ulint* params2; - + #ifdef UNIV_SYNC_DEBUG ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); @@ -480,7 +480,7 @@ btr_search_info_update_slow( btr_search_check_free_space_in_heap(); } - + if (cursor->flag == BTR_CUR_HASH_FAIL) { /* Update the hash node reference, if appropriate */ @@ -511,7 +511,7 @@ btr_search_info_update_slow( optimizations */ params2 = params + btr_search_this_is_zero; - + btr_search_build_page_hash_index(cursor->index, block->frame, params2[0], @@ -531,15 +531,15 @@ btr_search_check_guess( /*===================*/ /* out: TRUE if success */ btr_cur_t* cursor, /* in: guessed cursor position */ - ibool can_only_compare_to_cursor_rec, - /* in: if we do not have a latch on the page + ibool can_only_compare_to_cursor_rec, + /* in: if we do not have a latch on the page of cursor, but only a latch on - btr_search_latch, then ONLY the columns + btr_search_latch, then ONLY the columns of the record UNDER the cursor are protected, not the next or previous record in the chain: we cannot look at the next or previous record to check our guess! */ - dtuple_t* tuple, /* in: data tuple */ + dtuple_t* tuple, /* in: data tuple */ ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_GE */ mtr_t* mtr) /* in: mtr */ @@ -556,7 +556,7 @@ btr_search_check_guess( *offsets_ = (sizeof offsets_) / sizeof *offsets_; n_unique = dict_index_get_n_unique_in_tree(cursor->index); - + rec = btr_cur_get_rec(cursor); ut_ad(page_rec_is_user_rec(rec)); @@ -579,7 +579,7 @@ btr_search_check_guess( if (match >= n_unique) { success = TRUE; goto exit_func; - } + } } else if (mode == PAGE_CUR_LE) { if (cmp == -1) { goto exit_func; @@ -598,8 +598,8 @@ btr_search_check_guess( } if (can_only_compare_to_cursor_rec) { - /* Since we could not determine if our guess is right just by - looking at the record under the cursor, return FALSE */ + /* Since we could not determine if our guess is right just by + looking at the record under the cursor, return FALSE */ goto exit_func; } @@ -610,7 +610,7 @@ btr_search_check_guess( rec_t* prev_rec; ut_ad(!page_rec_is_infimum(rec)); - + prev_rec = page_rec_get_prev(rec); if (page_rec_is_infimum(prev_rec)) { @@ -635,7 +635,7 @@ btr_search_check_guess( rec_t* next_rec; ut_ad(!page_rec_is_supremum(rec)); - + next_rec = page_rec_get_next(rec); if (page_rec_is_supremum(next_rec)) { @@ -676,18 +676,18 @@ both have sensible values. */ ibool btr_search_guess_on_hash( /*=====================*/ - /* out: TRUE if succeeded */ + /* out: TRUE if succeeded */ dict_index_t* index, /* in: index */ btr_search_t* info, /* in: index search info */ dtuple_t* tuple, /* in: logical record */ ulint mode, /* in: PAGE_CUR_L, ... */ - ulint latch_mode, /* in: BTR_SEARCH_LEAF, ...; + ulint latch_mode, /* in: BTR_SEARCH_LEAF, ...; NOTE that only if has_search_latch is 0, we will have a latch set on the cursor page, otherwise we assume the caller uses his search latch to protect the record! */ - btr_cur_t* cursor, /* out: tree cursor */ + btr_cur_t* cursor, /* out: tree cursor */ ulint has_search_latch,/* in: latch mode the caller currently has on btr_search_latch: RW_S_LATCH, RW_X_LATCH, or 0 */ @@ -699,7 +699,7 @@ btr_search_guess_on_hash( ulint fold; ulint tuple_n_fields; dulint tree_id; - ibool can_only_compare_to_cursor_rec = TRUE; + ibool can_only_compare_to_cursor_rec = TRUE; #ifdef notdefined btr_cur_t cursor2; btr_pcur_t pcur; @@ -729,7 +729,7 @@ btr_search_guess_on_hash( if (UNIV_UNLIKELY(tuple_n_fields == cursor->n_fields) && (cursor->n_bytes > 0)) { - return(FALSE); + return(FALSE); } tree_id = (index->tree)->id; @@ -741,7 +741,7 @@ btr_search_guess_on_hash( cursor->fold = fold; cursor->flag = BTR_CUR_HASH; - + if (UNIV_LIKELY(!has_search_latch)) { rw_lock_s_lock(&btr_search_latch); } @@ -778,7 +778,7 @@ btr_search_guess_on_hash( if (UNIV_UNLIKELY(block->state == BUF_BLOCK_REMOVE_HASH)) { if (UNIV_LIKELY(!has_search_latch)) { - + btr_leaf_page_release(page, latch_mode, mtr); } @@ -798,29 +798,29 @@ btr_search_guess_on_hash( record to determine if our guess for the cursor position is right. */ if (UNIV_EXPECT(ut_dulint_cmp(tree_id, btr_page_get_index_id(page)), 0) - || !btr_search_check_guess(cursor, can_only_compare_to_cursor_rec, - tuple, mode, mtr)) { + || !btr_search_check_guess(cursor, + can_only_compare_to_cursor_rec, tuple, mode, mtr)) { if (UNIV_LIKELY(!has_search_latch)) { - btr_leaf_page_release(page, latch_mode, mtr); + btr_leaf_page_release(page, latch_mode, mtr); } goto failure; } if (UNIV_LIKELY(info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5)) { - + info->n_hash_potential++; } #ifdef notdefined /* These lines of code can be used in a debug version to check the correctness of the searched cursor position: */ - + info->last_hash_succ = FALSE; /* Currently, does not work if the following fails: */ ut_ad(!has_search_latch); - + btr_leaf_page_release(page, latch_mode, mtr); btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode, @@ -831,7 +831,7 @@ btr_search_guess_on_hash( /* If mode is PAGE_CUR_GE, then the binary search in the index tree may actually take us to the supremum of the previous page */ - + info->last_hash_succ = FALSE; btr_pcur_open_on_user_rec(index, tuple, mode, latch_mode, @@ -854,14 +854,14 @@ btr_search_guess_on_hash( && buf_block_peek_if_too_old(block)) { buf_page_make_young(page); - } + } /* Increment the page get statistics though we did not really fix the page: for user info only */ buf_pool->n_page_gets++; - return(TRUE); + return(TRUE); /*-------------------------------------------*/ failure_unlock: @@ -889,7 +889,8 @@ Drops a page hash index. */ void btr_search_drop_page_hash_index( /*============================*/ - page_t* page) /* in: index page, s- or x-latched */ + page_t* page) /* in: index page, s- or x-latched, or an index page + for which we know that block->buf_fix_count == 0 */ { hash_table_t* table; buf_block_t* block; @@ -904,18 +905,19 @@ btr_search_drop_page_hash_index( ulint* folds; ulint i; mem_heap_t* heap; + dict_index_t* index; ulint* offsets; #ifdef UNIV_SYNC_DEBUG ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - +retry: rw_lock_s_lock(&btr_search_latch); block = buf_block_align(page); - if (!block->is_hashed) { + if (UNIV_LIKELY(!block->is_hashed)) { rw_lock_s_unlock(&btr_search_latch); @@ -926,17 +928,22 @@ btr_search_drop_page_hash_index( #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED) - || rw_lock_own(&(block->lock), RW_LOCK_EX) - || (block->buf_fix_count == 0)); + || rw_lock_own(&(block->lock), RW_LOCK_EX) + || (block->buf_fix_count == 0)); #endif /* UNIV_SYNC_DEBUG */ n_fields = block->curr_n_fields; n_bytes = block->curr_n_bytes; + index = block->index; - ut_a(n_fields + n_bytes > 0); + /* NOTE: The fields of block must not be accessed after + releasing btr_search_latch, as the index page might only + be s-latched! */ rw_lock_s_unlock(&btr_search_latch); - + + ut_a(n_fields + n_bytes > 0); + n_recs = page_get_n_recs(page); /* Calculate and cache fold values into an array for fast deletion @@ -949,33 +956,21 @@ btr_search_drop_page_hash_index( rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); - if (!page_rec_is_supremum(rec)) { - ut_a(n_fields <= rec_get_n_fields(rec, block->index)); + tree_id = btr_page_get_index_id(page); - if (n_bytes > 0) { - ut_a(n_fields < rec_get_n_fields(rec, block->index)); - } - } + ut_a(0 == ut_dulint_cmp(tree_id, index->id)); - tree_id = btr_page_get_index_id(page); - prev_fold = 0; heap = NULL; offsets = NULL; - if (block->index == NULL) { - - mem_analyze_corruption((byte*)block); - - ut_a(block->index != NULL); - } - while (!page_rec_is_supremum(rec)) { /* FIXME: in a mixed tree, not all records may have enough ordering fields: */ - offsets = rec_get_offsets(rec, block->index, - offsets, n_fields + (n_bytes > 0), &heap); + offsets = rec_get_offsets(rec, index, offsets, + n_fields + (n_bytes > 0), &heap); + ut_a(rec_offs_n_fields(offsets) == n_fields + (n_bytes > 0)); fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id); if (fold == prev_fold && prev_fold != 0) { @@ -999,6 +994,26 @@ next_rec: rw_lock_x_lock(&btr_search_latch); + if (UNIV_UNLIKELY(!block->is_hashed)) { + /* Someone else has meanwhile dropped the hash index */ + + goto cleanup; + } + + ut_a(block->index == index); + + if (UNIV_UNLIKELY(block->curr_n_fields != n_fields) + || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) { + + /* Someone else has meanwhile built a new hash index on the + page, with different parameters */ + + rw_lock_x_unlock(&btr_search_latch); + + mem_free(folds); + goto retry; + } + for (i = 0; i < n_cached; i++) { ha_remove_all_nodes_to_page(table, folds[i], page); @@ -1006,8 +1021,20 @@ next_rec: block->is_hashed = FALSE; block->index = NULL; +cleanup: + if (UNIV_UNLIKELY(block->n_pointers)) { + /* Corruption */ + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: Corruption of adaptive hash index. After dropping\n" +"InnoDB: the hash index to a page of %s, still %lu hash nodes remain.\n", + index->name, (ulong) block->n_pointers); + rw_lock_x_unlock(&btr_search_latch); - rw_lock_x_unlock(&btr_search_latch); + btr_search_validate(); + } else { + rw_lock_x_unlock(&btr_search_latch); + } mem_free(folds); } @@ -1032,14 +1059,14 @@ btr_search_drop_page_hash_when_freed( return; } - + mtr_start(&mtr); /* We assume that if the caller has a latch on the page, then the caller has already dropped the hash index for the page, and we never get here. Therefore we can acquire the s-latch to the page without having to fear a deadlock. */ - + page = buf_page_get_gen(space, page_no, RW_S_LATCH, NULL, BUF_GET_IF_IN_POOL, __FILE__, __LINE__, &mtr); @@ -1098,10 +1125,10 @@ btr_search_build_page_hash_index( #endif /* UNIV_SYNC_DEBUG */ rw_lock_s_lock(&btr_search_latch); - + if (block->is_hashed && ((block->curr_n_fields != n_fields) - || (block->curr_n_bytes != n_bytes) - || (block->curr_side != side))) { + || (block->curr_n_bytes != n_bytes) + || (block->curr_side != side))) { rw_lock_s_unlock(&btr_search_latch); @@ -1118,15 +1145,15 @@ btr_search_build_page_hash_index( } /* 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)) { + || (dict_index_get_n_unique_in_tree(index) == n_fields + && n_bytes > 0)) { return; } @@ -1164,20 +1191,20 @@ btr_search_build_page_hash_index( 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; + break; } offsets = rec_get_offsets(next_rec, index, offsets, @@ -1209,21 +1236,21 @@ btr_search_build_page_hash_index( 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))) { + || (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]); } @@ -1272,7 +1299,7 @@ btr_search_move_or_delete_hash_entries( 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); @@ -1393,13 +1420,13 @@ btr_search_update_hash_node_on_insert( 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)) { + && (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; - table = btr_search_sys->hash_index; - - ha_search_and_update_if_found(table, cursor->fold, rec, + ha_search_and_update_if_found(table, cursor->fold, rec, page_rec_get_next(rec)); rw_lock_x_unlock(&btr_search_latch); @@ -1421,7 +1448,7 @@ btr_search_update_hash_on_insert( and the new record has been inserted next to the cursor */ { - hash_table_t* table; + hash_table_t* table; buf_block_t* block; rec_t* rec; rec_t* ins_rec; @@ -1450,7 +1477,7 @@ btr_search_update_hash_on_insert( #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - + if (!block->is_hashed) { return; @@ -1494,10 +1521,10 @@ btr_search_update_hash_on_insert( goto check_next_rec; } - - if (fold != ins_fold) { - if (!locked) { + if (fold != ins_fold) { + + if (!locked) { rw_lock_x_lock(&btr_search_latch); @@ -1516,22 +1543,22 @@ check_next_rec: if (side == BTR_SEARCH_RIGHT_SIDE) { - if (!locked) { + 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) { - + if (!locked) { + rw_lock_x_lock(&btr_search_latch); locked = TRUE; @@ -1548,8 +1575,8 @@ check_next_rec: } else { ha_insert_for_fold(table, next_fold, next_rec); } - } - + } + function_exit: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -1573,14 +1600,29 @@ btr_search_validate(void) 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_; - + + /* How many cells to check before temporarily releasing + btr_search_latch. */ + ulint chunk_size = 10000; + rw_lock_x_lock(&btr_search_latch); - for (i = 0; i < hash_get_n_cells(btr_search_sys->hash_index); i++) { + 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 % 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) { @@ -1592,11 +1634,11 @@ btr_search_validate(void) + (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))) { + || 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); @@ -1610,9 +1652,9 @@ btr_search_validate(void) (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))); + 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, @@ -1620,11 +1662,11 @@ btr_search_validate(void) 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); + page, (ulong) block->is_hashed, + (ulong) block->curr_n_fields, + (ulong) block->curr_n_bytes, (ulong) block->curr_side); - if (n_page_dumps < 20) { + if (n_page_dumps < 20) { buf_page_print(page); n_page_dumps++; } @@ -1633,10 +1675,21 @@ btr_search_validate(void) node = node->next; } } - - if (!ha_validate(btr_search_sys->hash_index)) { - ok = FALSE; + for (i = 0; i < cell_count; i += chunk_size) { + ulint end_index = ut_min(i + 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); |