diff options
Diffstat (limited to 'innobase/btr')
-rw-r--r-- | innobase/btr/btr0btr.c | 174 | ||||
-rw-r--r-- | innobase/btr/btr0cur.c | 251 | ||||
-rw-r--r-- | innobase/btr/btr0pcur.c | 66 | ||||
-rw-r--r-- | innobase/btr/btr0sea.c | 191 |
4 files changed, 350 insertions, 332 deletions
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 1744fc36f4d..2d84586216a 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -20,6 +20,7 @@ Created 6/2/1994 Heikki Tuuri #include "rem0cmp.h" #include "lock0lock.h" #include "ibuf0ibuf.h" +#include "trx0trx.h" /* Latching strategy of the InnoDB B-tree @@ -137,13 +138,13 @@ btr_root_get( ulint space; ulint root_page_no; page_t* root; - ibool comp = UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp; 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(page_is_comp(root) == comp); + ut_a(!!page_is_comp(root) == + UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp); return(root); } @@ -163,21 +164,19 @@ btr_get_prev_user_rec( page_t* page; page_t* prev_page; ulint prev_page_no; - rec_t* prev_rec; ulint space; - page = buf_frame_align(rec); - - if (page_get_infimum_rec(page) != rec) { + if (!page_rec_is_infimum(rec)) { - prev_rec = page_rec_get_prev(rec); + rec_t* prev_rec = page_rec_get_prev(rec); - if (page_get_infimum_rec(page) != prev_rec) { + if (!page_rec_is_infimum(prev_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); @@ -192,9 +191,7 @@ btr_get_prev_user_rec( MTR_MEMO_PAGE_X_FIX))); ut_a(page_is_comp(prev_page) == page_is_comp(page)); - prev_rec = page_rec_get_prev(page_get_supremum_rec(prev_page)); - - return(prev_rec); + return(page_rec_get_prev(page_get_supremum_rec(prev_page))); } return(NULL); @@ -215,21 +212,19 @@ btr_get_next_user_rec( page_t* page; page_t* next_page; ulint next_page_no; - rec_t* next_rec; ulint space; - page = buf_frame_align(rec); - - if (page_get_supremum_rec(page) != rec) { + if (!page_rec_is_supremum(rec)) { - next_rec = page_rec_get_next(rec); + rec_t* next_rec = page_rec_get_next(rec); - if (page_get_supremum_rec(page) != next_rec) { + if (!page_rec_is_supremum(next_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); @@ -244,9 +239,7 @@ btr_get_next_user_rec( MTR_MEMO_PAGE_X_FIX))); ut_a(page_is_comp(next_page) == page_is_comp(page)); - next_rec = page_rec_get_next(page_get_infimum_rec(next_page)); - - return(next_rec); + return(page_rec_get_next(page_get_infimum_rec(next_page))); } return(NULL); @@ -573,8 +566,7 @@ btr_page_get_father_for_rec( ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); - ut_a(user_rec != page_get_supremum_rec(page)); - ut_a(user_rec != page_get_infimum_rec(page)); + ut_a(page_rec_is_user_rec(user_rec)); ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page)); @@ -598,6 +590,7 @@ btr_page_get_father_for_rec( if (btr_node_ptr_get_child_page_no(node_ptr, offsets) != 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)); fputs("InnoDB: Dump of the parent page:\n", stderr); @@ -612,11 +605,10 @@ btr_page_get_father_for_rec( (ulong) btr_node_ptr_get_child_page_no(node_ptr, offsets), (ulong) buf_frame_get_page_no(page)); - offsets = rec_get_offsets(page_rec_get_next( - page_get_infimum_rec(page)), index, + print_rec = page_rec_get_next(page_get_infimum_rec(page)); + offsets = rec_get_offsets(print_rec, index, offsets, ULINT_UNDEFINED, &heap); - page_rec_print(page_rec_get_next(page_get_infimum_rec(page)), - offsets); + page_rec_print(print_rec, offsets); offsets = rec_get_offsets(node_ptr, index, offsets, ULINT_UNDEFINED, &heap); page_rec_print(node_ptr, offsets); @@ -663,7 +655,7 @@ btr_create( ulint type, /* in: type of the index */ ulint space, /* in: space where created */ dulint index_id,/* in: index id */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ mtr_t* mtr) /* in: mini-transaction handle */ { ulint page_no; @@ -854,11 +846,12 @@ btr_page_reorganize_low( ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); + ut_ad(!!page_is_comp(page) == index->table->comp); data_size1 = page_get_data_size(page); max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1); /* Write the log record */ - mlog_open_and_write_index(mtr, page, index, index->table->comp + mlog_open_and_write_index(mtr, page, index, page_is_comp(page) ? MLOG_COMP_PAGE_REORGANIZE : MLOG_PAGE_REORGANIZE, 0); @@ -877,7 +870,7 @@ btr_page_reorganize_low( /* Recreate the page: note that global data on page (possible segment headers, next page-field, etc.) is preserved intact */ - page_create(page, mtr, index->table->comp); + 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; @@ -1070,7 +1063,7 @@ btr_root_raise_and_insert( as there is no lower alphabetical limit to records in the leftmost node of a level: */ - btr_set_min_rec_mark(node_ptr_rec, cursor->index->table->comp, mtr); + btr_set_min_rec_mark(node_ptr_rec, page_is_comp(root), mtr); /* Free the memory heap */ mem_heap_free(heap); @@ -1151,7 +1144,6 @@ btr_page_get_split_rec_to_right( { page_t* page; rec_t* insert_point; - rec_t* supremum; page = btr_cur_get_page(cursor); insert_point = btr_cur_get_rec(cursor); @@ -1160,13 +1152,23 @@ btr_page_get_split_rec_to_right( the previous insert on the same page, we assume that there is a pattern of sequential inserts here. */ - if (page_header_get_ptr(page, PAGE_LAST_INSERT) == insert_point) { + if (UNIV_LIKELY(page_header_get_ptr(page, PAGE_LAST_INSERT) + == insert_point)) { + + rec_t* next_rec; + + next_rec = page_rec_get_next(insert_point); - supremum = page_get_supremum_rec(page); - - if (page_rec_get_next(insert_point) != supremum - && page_rec_get_next(page_rec_get_next(insert_point)) - != supremum) { + if (page_rec_is_supremum(next_rec)) { +split_at_new: + /* Split at the new record to insert */ + *split_rec = NULL; + } else { + rec_t* next_next_rec = page_rec_get_next(next_rec); + if (page_rec_is_supremum(next_next_rec)) { + + goto split_at_new; + } /* If there are >= 2 user records up from the insert point, split all but 1 off. We want to keep one because @@ -1175,12 +1177,8 @@ btr_page_get_split_rec_to_right( search position just by looking at the records on this page. */ - *split_rec = page_rec_get_next( - page_rec_get_next(insert_point)); - } else { - /* Else split at the new record to insert */ - *split_rec = NULL; - } + *split_rec = next_next_rec; + } return(TRUE); } @@ -1220,7 +1218,7 @@ btr_page_get_sure_split_rec( page = btr_cur_get_page(cursor); insert_size = rec_get_converted_size(cursor->index, tuple); - free_space = page_get_free_space_of_empty(cursor->index->table->comp); + free_space = page_get_free_space_of_empty(page_is_comp(page)); /* free_space is now the free space of a created new page */ @@ -1276,21 +1274,22 @@ btr_page_get_sure_split_rec( supremum record of page */ if (rec == ins_rec) { - next_rec = NULL; + rec = NULL; + + goto func_exit; } else if (rec == NULL) { next_rec = page_rec_get_next(ins_rec); } else { next_rec = page_rec_get_next(rec); } - if (next_rec != page_get_supremum_rec(page)) { - if (heap) { - mem_heap_free(heap); - } - return(next_rec); + ut_ad(next_rec); + if (!page_rec_is_supremum(next_rec)) { + rec = next_rec; } } - if (heap) { +func_exit: + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(rec); @@ -1329,13 +1328,12 @@ btr_page_insert_fits( ut_ad(!split_rec == !offsets); ut_ad(!offsets - || cursor->index->table->comp == rec_offs_comp(offsets)); + || !page_is_comp(page) == !rec_offs_comp(offsets)); ut_ad(!offsets || rec_offs_validate(split_rec, cursor->index, offsets)); - ut_ad(page_is_comp(page) == cursor->index->table->comp); insert_size = rec_get_converted_size(cursor->index, tuple); - free_space = page_get_free_space_of_empty(cursor->index->table->comp); + free_space = page_get_free_space_of_empty(page_is_comp(page)); /* free_space is now the free space of a created new page */ @@ -1832,14 +1830,15 @@ void btr_set_min_rec_mark_log( /*=====================*/ rec_t* rec, /* in: record */ - ibool comp, /* TRUE=compact record format */ + ulint comp, /* nonzero=compact record format */ mtr_t* mtr) /* in: mtr */ { mlog_write_initial_log_record(rec, comp ? MLOG_COMP_REC_MIN_MARK : MLOG_REC_MIN_MARK, mtr); /* Write rec offset as a 2-byte ulint */ - mlog_catenate_ulint(mtr, rec - buf_frame_align(rec), MLOG_2BYTES); + mlog_catenate_ulint(mtr, ut_align_offset(rec, UNIV_PAGE_SIZE), + MLOG_2BYTES); } /******************************************************************** @@ -1852,7 +1851,7 @@ btr_parse_set_min_rec_mark( /* out: end of log record or NULL */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ page_t* page, /* in: page or NULL */ mtr_t* mtr) /* in: mtr or NULL */ { @@ -1864,6 +1863,8 @@ btr_parse_set_min_rec_mark( } if (page) { + ut_a(!page_is_comp(page) == !comp); + rec = page + mach_read_from_2(ptr); btr_set_min_rec_mark(rec, comp, mtr); @@ -1879,7 +1880,7 @@ void btr_set_min_rec_mark( /*=================*/ rec_t* rec, /* in: record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ mtr_t* mtr) /* in: mtr */ { ulint info_bits; @@ -2008,11 +2009,12 @@ btr_compress( ulint max_ins_size; ulint max_ins_size_reorg; ulint level; - ibool comp = cursor->index->table->comp; + ulint comp; page = btr_cur_get_page(cursor); tree = btr_cur_get_tree(cursor); - ut_a(comp == page_is_comp(page)); + comp = page_is_comp(page); + ut_a(!!comp == cursor->index->table->comp); ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); @@ -2055,7 +2057,7 @@ btr_compress( n_recs = page_get_n_recs(page); data_size = page_get_data_size(page); - ut_a(page_is_comp(merge_page) == page_is_comp(page)); + ut_a(page_is_comp(merge_page) == comp); max_ins_size_reorg = page_get_max_insert_size_after_reorganize( merge_page, n_recs); @@ -2108,7 +2110,7 @@ btr_compress( rec_get_offsets(node_ptr, cursor->index, offsets_, ULINT_UNDEFINED, &heap), right_page_no, mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } btr_node_ptr_delete(tree, merge_page, mtr); @@ -2250,10 +2252,9 @@ btr_discard_page( node_ptr = page_rec_get_next(page_get_infimum_rec(merge_page)); - ut_ad(node_ptr != page_get_supremum_rec(merge_page)); + ut_ad(page_rec_is_user_rec(node_ptr)); - btr_set_min_rec_mark(node_ptr, - cursor->index->table->comp, mtr); + btr_set_min_rec_mark(node_ptr, page_is_comp(merge_page), mtr); } btr_node_ptr_delete(tree, page, mtr); @@ -2274,6 +2275,7 @@ btr_discard_page( ut_ad(btr_check_node_ptr(tree, merge_page, mtr)); } +#ifdef UNIV_BTR_PRINT /***************************************************************** Prints size info of a B-tree. */ @@ -2401,14 +2403,15 @@ btr_print_tree( root = btr_root_get(tree, &mtr); btr_print_recursive(tree, root, width, &heap, &offsets, &mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } mtr_commit(&mtr); - btr_validate_tree(tree); + btr_validate_tree(tree, NULL); } +#endif /* UNIV_BTR_PRINT */ /**************************************************************** Checks that the node pointer to a page is appropriate. */ @@ -2496,8 +2499,8 @@ btr_index_rec_validate( *offsets_ = (sizeof offsets_) / sizeof *offsets_; page = buf_frame_align(rec); - - if (index->type & DICT_UNIVERSAL) { + + 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 */ @@ -2505,9 +2508,18 @@ btr_index_rec_validate( return(TRUE); } + if (UNIV_UNLIKELY(!!page_is_comp(page) != index->table->comp)) { + 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); + return(FALSE); + } + n = dict_index_get_n_fields(index); - if (!index->table->comp && rec_get_n_fields_old(rec) != n) { + if (!page_is_comp(page) + && UNIV_UNLIKELY(rec_get_n_fields_old(rec) != n)) { btr_index_rec_validate_report(page, rec, index); fprintf(stderr, "InnoDB: has %lu fields, should have %lu\n", (ulong) rec_get_n_fields_old(rec), (ulong) n); @@ -2554,14 +2566,14 @@ btr_index_rec_validate( rec_print_new(stderr, rec, offsets); putc('\n', stderr); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(FALSE); } } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(TRUE); @@ -2649,6 +2661,7 @@ btr_validate_level( /*===============*/ /* out: TRUE if ok */ dict_tree_t* tree, /* in: index tree */ + trx_t* trx, /* in: transaction or NULL */ ulint level) /* in: level number */ { ulint space; @@ -2696,6 +2709,11 @@ btr_validate_level( /* Now we are on the desired level. Loop through the pages on that level. */ loop: + if (trx_is_interrupted(trx)) { + mtr_commit(&mtr); + mem_heap_free(heap); + return(ret); + } mem_heap_empty(heap); offsets = offsets2 = NULL; mtr_x_lock(dict_tree_get_lock(tree), &mtr); @@ -2765,7 +2783,7 @@ loop: 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)), - index->table->comp)); + page_is_comp(page))); } if (buf_frame_get_page_no(page) != dict_tree_get_page(tree)) { @@ -2921,7 +2939,7 @@ node_ptr_fails: mtr_commit(&mtr); if (right_page_no != FIL_NULL) { - ibool comp = page_is_comp(page); + ulint comp = page_is_comp(page); mtr_start(&mtr); page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr); @@ -2941,7 +2959,8 @@ ibool btr_validate_tree( /*==============*/ /* out: TRUE if ok */ - dict_tree_t* tree) /* in: tree */ + dict_tree_t* tree, /* in: tree */ + trx_t* trx) /* in: transaction or NULL */ { mtr_t mtr; page_t* root; @@ -2954,9 +2973,8 @@ btr_validate_tree( root = btr_root_get(tree, &mtr); n = btr_page_get_level(root, &mtr); - for (i = 0; i <= n; i++) { - - if (!btr_validate_level(tree, n - i)) { + for (i = 0; i <= n && !trx_is_interrupted(trx); i++) { + if (!btr_validate_level(tree, trx, n - i)) { mtr_commit(&mtr); diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index e093c911f22..98d90ecf18a 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -36,11 +36,11 @@ Created 10/16/1994 Heikki Tuuri #include "ibuf0ibuf.h" #include "lock0lock.h" +#ifdef UNIV_DEBUG /* If the following is set to TRUE, this module prints a lot of trace information of individual record operations */ ibool btr_cur_print_record_ops = FALSE; - -ulint btr_cur_rnd = 0; +#endif /* UNIV_DEBUG */ ulint btr_cur_n_non_sea = 0; ulint btr_cur_n_sea = 0; @@ -431,7 +431,7 @@ retry_page_get: cursor->thr)) { /* Insertion to the insert buffer succeeded */ cursor->flag = BTR_CUR_INSERT_TO_IBUF; - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return; @@ -505,8 +505,9 @@ retry_page_get: if (level > 0) { /* x-latch the page */ - ut_a(page_is_comp(btr_page_get(space, - page_no, RW_X_LATCH, mtr)) + page = btr_page_get(space, + page_no, RW_X_LATCH, mtr); + ut_a(!!page_is_comp(page) == index->table->comp); } @@ -525,7 +526,7 @@ retry_page_get: page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -681,7 +682,7 @@ btr_cur_open_at_index_side( page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -762,7 +763,7 @@ btr_cur_open_at_rnd_pos( page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -879,6 +880,7 @@ btr_cur_ins_lock_and_undo( return(DB_SUCCESS); } +#ifdef UNIV_DEBUG /***************************************************************** Report information about a transaction. */ static @@ -896,6 +898,7 @@ btr_cur_trx_report( dict_index_name_print(stderr, trx, index); putc('\n', stderr); } +#endif /* UNIV_DEBUG */ /***************************************************************** Tries to perform an insert to a page in an index tree, next to cursor. @@ -945,12 +948,13 @@ btr_cur_optimistic_insert( fputs("InnoDB: Error in a tuple to insert into ", stderr); dict_index_name_print(stderr, thr_get_trx(thr), index); } - +#ifdef UNIV_DEBUG if (btr_cur_print_record_ops && thr) { btr_cur_trx_report(thr_get_trx(thr), index, "insert into "); dtuple_print(stderr, entry); } - +#endif /* UNIV_DEBUG */ + ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); max_size = page_get_max_insert_size_after_reorganize(page, 1); @@ -961,7 +965,7 @@ calculate_sizes_again: rec_size = rec_get_converted_size(index, entry); if (rec_size >= - ut_min(page_get_free_space_of_empty(index->table->comp) / 2, + ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2, REC_MAX_DATA_SIZE)) { /* The record is so big that we have to store some fields @@ -1027,7 +1031,7 @@ calculate_sizes_again: *rec = page_cur_insert_rec_low(page_cursor, entry, index, NULL, NULL, mtr); - if (!(*rec)) { + if (UNIV_UNLIKELY(!(*rec))) { /* If the record did not fit, reorganize */ btr_page_reorganize(page, index, mtr); @@ -1039,7 +1043,7 @@ calculate_sizes_again: *rec = page_cur_tuple_insert(page_cursor, entry, index, mtr); - if (!*rec) { + if (UNIV_UNLIKELY(!*rec)) { fputs("InnoDB: Error: cannot insert tuple ", stderr); dtuple_print(stderr, entry); fputs(" into ", stderr); @@ -1166,7 +1170,7 @@ btr_cur_pessimistic_insert( } if (rec_get_converted_size(index, entry) >= - ut_min(page_get_free_space_of_empty(index->table->comp) / 2, + ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2, REC_MAX_DATA_SIZE)) { /* The record is so big that we have to store some fields @@ -1261,7 +1265,7 @@ btr_cur_upd_lock_and_undo( err = lock_clust_rec_modify_check_and_lock(flags, rec, index, rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap), thr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } if (err != DB_SUCCESS) { @@ -1293,9 +1297,11 @@ btr_cur_update_in_place_log( mtr_t* mtr) /* in: mtr */ { 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); - log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp + log_ptr = mlog_open_and_write_index(mtr, rec, index, page_is_comp(page) ? MLOG_COMP_REC_UPDATE_IN_PLACE : MLOG_REC_UPDATE_IN_PLACE, 1 + DATA_ROLL_PTR_LEN + 14 + 2 + MLOG_BUF_MARGIN); @@ -1317,7 +1323,7 @@ btr_cur_update_in_place_log( log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr, mtr); - mach_write_to_2(log_ptr, rec - buf_frame_align(rec)); + mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE)); log_ptr += 2; row_upd_index_write_log(update, log_ptr, mtr); @@ -1374,18 +1380,12 @@ btr_cur_parse_update_in_place( ptr = row_upd_index_parse(ptr, end_ptr, heap, &update); - if (ptr == NULL) { - mem_heap_free(heap); - - return(NULL); - } - - if (!page) { - mem_heap_free(heap); + if (!ptr || !page) { - return(ptr); + goto func_exit; } - + + ut_a(!!page_is_comp(page) == index->table->comp); rec = page + rec_offset; /* We do not need to reserve btr_search_latch, as the page is only @@ -1400,6 +1400,7 @@ btr_cur_parse_update_in_place( row_upd_rec_in_place(rec, offsets, update); +func_exit: mem_heap_free(heap); return(ptr); @@ -1429,7 +1430,7 @@ btr_cur_update_in_place( rec_t* rec; dulint roll_ptr = ut_dulint_zero; trx_t* trx; - ibool was_delete_marked; + ulint was_delete_marked; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; @@ -1437,27 +1438,30 @@ btr_cur_update_in_place( rec = btr_cur_get_rec(cursor); index = cursor->index; + ut_ad(!!page_rec_is_comp(rec) == index->table->comp); trx = thr_get_trx(thr); - heap = mem_heap_create(100); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); - +#ifdef UNIV_DEBUG if (btr_cur_print_record_ops && thr) { btr_cur_trx_report(trx, index, "update "); rec_print_new(stderr, rec, offsets); } +#endif /* UNIV_DEBUG */ /* Do lock checking and undo logging */ err = btr_cur_upd_lock_and_undo(flags, cursor, update, cmpl_info, thr, &roll_ptr); - if (err != DB_SUCCESS) { + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); } block = buf_block_align(rec); + ut_ad(!!page_is_comp(buf_block_get_frame(block)) + == index->table->comp); if (block->is_hashed) { /* The function row_upd_changes_ord_field_binary works only @@ -1481,7 +1485,8 @@ btr_cur_update_in_place( /* FIXME: in a mixed tree, all records may not have enough ordering fields for btr search: */ - was_delete_marked = rec_get_deleted_flag(rec, index->table->comp); + was_delete_marked = rec_get_deleted_flag(rec, + page_is_comp(buf_block_get_frame(block))); row_upd_rec_in_place(rec, offsets, update); @@ -1491,14 +1496,15 @@ btr_cur_update_in_place( btr_cur_update_in_place_log(flags, rec, index, update, trx, roll_ptr, mtr); - if (was_delete_marked && !rec_get_deleted_flag(rec, index->table->comp)) { + if (was_delete_marked && !rec_get_deleted_flag(rec, + page_is_comp(buf_block_get_frame(block)))) { /* The new updated record owns its possible externally stored fields */ btr_cur_unmark_extern_fields(rec, mtr, offsets); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(DB_SUCCESS); @@ -1547,14 +1553,17 @@ 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); heap = mem_heap_create(1024); offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); +#ifdef UNIV_DEBUG if (btr_cur_print_record_ops && thr) { btr_cur_trx_report(thr_get_trx(thr), index, "update "); rec_print_new(stderr, rec, offsets); } +#endif /* UNIV_DEBUG */ ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); @@ -1596,8 +1605,8 @@ btr_cur_optimistic_update( old_rec_size = rec_offs_size(offsets); new_rec_size = rec_get_converted_size(index, new_entry); - if (new_rec_size >= - page_get_free_space_of_empty(index->table->comp) / 2) { + if (UNIV_UNLIKELY(new_rec_size >= page_get_free_space_of_empty( + page_is_comp(page)) / 2)) { mem_heap_free(heap); @@ -1607,8 +1616,9 @@ btr_cur_optimistic_update( max_size = old_rec_size + page_get_max_insert_size_after_reorganize(page, 1); - if (page_get_data_size(page) - old_rec_size + new_rec_size - < BTR_CUR_PAGE_COMPRESS_LIMIT) { + if (UNIV_UNLIKELY(page_get_data_size(page) + - old_rec_size + new_rec_size + < BTR_CUR_PAGE_COMPRESS_LIMIT)) { /* The page would become too empty */ @@ -1644,7 +1654,7 @@ btr_cur_optimistic_update( explicit locks on rec, before deleting rec (see the comment in .._pessimistic_update). */ - lock_rec_store_on_page_infimum(rec); + lock_rec_store_on_page_infimum(page, rec); btr_search_update_hash_on_delete(cursor); @@ -1665,7 +1675,7 @@ btr_cur_optimistic_update( ut_a(rec); /* <- We calculated above the insert would fit */ - if (!rec_get_deleted_flag(rec, index->table->comp)) { + if (!rec_get_deleted_flag(rec, page_is_comp(page))) { /* The new inserted record owns its possible externally stored fields */ @@ -1814,7 +1824,7 @@ btr_cur_pessimistic_update( } success = fsp_reserve_free_extents(&n_reserved, - cursor->index->space, + index->space, n_extents, reserve_flag, mtr); if (!success) { err = DB_OUT_OF_FILE_SPACE; @@ -1858,14 +1868,14 @@ btr_cur_pessimistic_update( ext_vect = mem_heap_alloc(heap, sizeof(ulint) * dict_index_get_n_fields(index)); - ut_ad(!cursor->index->table->comp || !rec_get_node_ptr_flag(rec)); + ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec)); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets, update); - if (rec_get_converted_size(index, new_entry) >= - ut_min(page_get_free_space_of_empty(index->table->comp) / 2, - REC_MAX_DATA_SIZE)) { + if (UNIV_UNLIKELY(rec_get_converted_size(index, new_entry) >= + 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); @@ -1887,7 +1897,7 @@ btr_cur_pessimistic_update( delete the lock structs set on the root page even if the root page carries just node pointers. */ - lock_rec_store_on_page_infimum(rec); + lock_rec_store_on_page_infimum(buf_frame_align(rec), rec); btr_search_update_hash_on_delete(cursor); @@ -1965,8 +1975,7 @@ return_after_reservations: mem_heap_free(heap); if (n_extents > 0) { - fil_space_release_free_extents(cursor->index->space, - n_reserved); + fil_space_release_free_extents(index->space, n_reserved); } *big_rec = big_rec_vec; @@ -1995,7 +2004,10 @@ btr_cur_del_mark_set_clust_rec_log( ut_ad(flags < 256); ut_ad(val <= 1); - log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp + ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + + log_ptr = mlog_open_and_write_index(mtr, rec, index, + page_rec_is_comp(rec) ? MLOG_COMP_REC_CLUST_DELETE_MARK : MLOG_REC_CLUST_DELETE_MARK, 1 + 1 + DATA_ROLL_PTR_LEN + 14 + 2); @@ -2012,7 +2024,7 @@ btr_cur_del_mark_set_clust_rec_log( log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr, mtr); - mach_write_to_2(log_ptr, rec - buf_frame_align(rec)); + mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE)); log_ptr += 2; mlog_close(mtr, log_ptr); @@ -2032,13 +2044,15 @@ btr_cur_parse_del_mark_set_clust_rec( page_t* page) /* in: page or NULL */ { ulint flags; - ibool val; + ulint val; ulint pos; dulint trx_id; dulint roll_ptr; ulint offset; rec_t* rec; + ut_ad(!page || !!page_is_comp(page) == index->table->comp); + if (end_ptr < ptr + 2) { return(NULL); @@ -2078,7 +2092,7 @@ btr_cur_parse_del_mark_set_clust_rec( rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap), pos, trx_id, roll_ptr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -2087,7 +2101,7 @@ btr_cur_parse_del_mark_set_clust_rec( is only being recovered, and there cannot be a hash index to it. */ - rec_set_deleted_flag(rec, index->table->comp, val); + rec_set_deleted_flag(rec, page_is_comp(page), val); } return(ptr); @@ -2123,22 +2137,25 @@ 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); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); +#ifdef UNIV_DEBUG if (btr_cur_print_record_ops && thr) { btr_cur_trx_report(thr_get_trx(thr), index, "del mark "); rec_print_new(stderr, rec, offsets); } +#endif /* UNIV_DEBUG */ ut_ad(index->type & DICT_CLUSTERED); - ut_ad(rec_get_deleted_flag(rec, index->table->comp) == FALSE); + ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets))); err = lock_clust_rec_modify_check_and_lock(flags, rec, index, offsets, thr); if (err != DB_SUCCESS) { - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); @@ -2149,7 +2166,7 @@ btr_cur_del_mark_set_clust_rec( &roll_ptr); if (err != DB_SUCCESS) { - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); @@ -2161,7 +2178,7 @@ btr_cur_del_mark_set_clust_rec( rw_lock_x_lock(&btr_search_latch); } - rec_set_deleted_flag(rec, index->table->comp, val); + rec_set_deleted_flag(rec, rec_offs_comp(offsets), val); trx = thr_get_trx(thr); @@ -2175,7 +2192,7 @@ btr_cur_del_mark_set_clust_rec( btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx, roll_ptr, mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(DB_SUCCESS); @@ -2189,17 +2206,13 @@ void btr_cur_del_mark_set_sec_rec_log( /*=============================*/ rec_t* rec, /* in: record */ - dict_index_t* index, /* in: record descriptor */ ibool val, /* in: value to set */ mtr_t* mtr) /* in: mtr */ { byte* log_ptr; ut_ad(val <= 1); - log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp - ? MLOG_COMP_REC_SEC_DELETE_MARK - : MLOG_REC_SEC_DELETE_MARK, - 1 + 2); + log_ptr = mlog_open(mtr, 11 + 1 + 2); if (!log_ptr) { /* Logging in mtr is switched off during crash recovery: @@ -2207,10 +2220,12 @@ btr_cur_del_mark_set_sec_rec_log( return; } + log_ptr = mlog_write_initial_log_record_fast( + rec, MLOG_REC_SEC_DELETE_MARK, log_ptr, mtr); mach_write_to_1(log_ptr, val); log_ptr++; - mach_write_to_2(log_ptr, rec - buf_frame_align(rec)); + mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE)); log_ptr += 2; mlog_close(mtr, log_ptr); @@ -2226,10 +2241,9 @@ btr_cur_parse_del_mark_set_sec_rec( /* out: end of log record or NULL */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ - dict_index_t* index, /* in: record descriptor */ page_t* page) /* in: page or NULL */ { - ibool val; + ulint val; ulint offset; rec_t* rec; @@ -2253,7 +2267,7 @@ btr_cur_parse_del_mark_set_sec_rec( is only being recovered, and there cannot be a hash index to it. */ - rec_set_deleted_flag(rec, index->table->comp, val); + rec_set_deleted_flag(rec, page_is_comp(page), val); } return(ptr); @@ -2279,11 +2293,13 @@ btr_cur_del_mark_set_sec_rec( rec = btr_cur_get_rec(cursor); +#ifdef UNIV_DEBUG if (btr_cur_print_record_ops && thr) { btr_cur_trx_report(thr_get_trx(thr), cursor->index, "del mark "); rec_print(stderr, rec, cursor->index); } +#endif /* UNIV_DEBUG */ err = lock_sec_rec_modify_check_and_lock(flags, rec, cursor->index, thr); @@ -2293,18 +2309,21 @@ 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); if (block->is_hashed) { rw_lock_x_lock(&btr_search_latch); } - rec_set_deleted_flag(rec, cursor->index->table->comp, val); + rec_set_deleted_flag(rec, page_is_comp(buf_block_get_frame(block)), + val); if (block->is_hashed) { rw_lock_x_unlock(&btr_search_latch); } - btr_cur_del_mark_set_sec_rec_log(rec, cursor->index, val, mtr); + btr_cur_del_mark_set_sec_rec_log(rec, val, mtr); return(DB_SUCCESS); } @@ -2317,15 +2336,14 @@ void btr_cur_del_unmark_for_ibuf( /*========================*/ rec_t* rec, /* in: record to delete unmark */ - dict_index_t* index, /* in: record descriptor */ mtr_t* mtr) /* in: mtr */ { /* We do not need to reserve btr_search_latch, as the page has just been read to the buffer pool and there cannot be a hash index to it. */ - rec_set_deleted_flag(rec, index->table->comp, FALSE); + rec_set_deleted_flag(rec, page_is_comp(buf_frame_align(rec)), FALSE); - btr_cur_del_mark_set_sec_rec_log(rec, index, FALSE, mtr); + btr_cur_del_mark_set_sec_rec_log(rec, FALSE, mtr); } /*==================== B-TREE RECORD REMOVE =========================*/ @@ -2444,7 +2462,7 @@ btr_cur_optimistic_delete( mtr); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -2487,6 +2505,7 @@ btr_cur_pessimistic_delete( ulint n_reserved; ibool success; ibool ret = FALSE; + ulint level; mem_heap_t* heap; ulint* offsets; @@ -2523,15 +2542,15 @@ btr_cur_pessimistic_delete( /* Free externally stored fields if the record is neither a node pointer nor in two-byte format. This avoids an unnecessary loop. */ - if (cursor->index->table->comp + if (page_is_comp(page) ? !rec_get_node_ptr_flag(rec) : !rec_get_1byte_offs_flag(rec)) { btr_rec_free_externally_stored_fields(cursor->index, rec, offsets, in_rollback, mtr); } - if ((page_get_n_recs(page) < 2) - && (dict_tree_get_page(btr_cur_get_tree(cursor)) + 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))) { /* If there is only one record, drop the whole page in @@ -2546,9 +2565,13 @@ btr_cur_pessimistic_delete( } lock_update_delete(rec); + level = btr_page_get_level(page, mtr); - if ((btr_page_get_level(page, mtr) > 0) - && (page_rec_get_next(page_get_infimum_rec(page)) == rec)) { + if (level > 0 + && UNIV_UNLIKELY(rec == page_rec_get_next( + page_get_infimum_rec(page)))) { + + rec_t* next_rec = page_rec_get_next(rec); if (btr_page_get_prev(page, mtr) == FIL_NULL) { @@ -2556,8 +2579,8 @@ btr_cur_pessimistic_delete( non-leaf level, we must mark the new leftmost node pointer as the predefined minimum record */ - btr_set_min_rec_mark(page_rec_get_next(rec), - cursor->index->table->comp, mtr); + btr_set_min_rec_mark(next_rec, page_is_comp(page), + mtr); } else { /* Otherwise, if we delete the leftmost node pointer on a page, we have to change the father node pointer @@ -2567,13 +2590,12 @@ btr_cur_pessimistic_delete( btr_node_ptr_delete(tree, page, mtr); node_ptr = dict_tree_build_node_ptr( - tree, page_rec_get_next(rec), + tree, next_rec, buf_frame_get_page_no(page), - heap, btr_page_get_level(page, mtr)); + heap, level); btr_insert_on_non_leaf_level(tree, - btr_page_get_level(page, mtr) + 1, - node_ptr, mtr); + level + 1, node_ptr, mtr); } } @@ -2813,12 +2835,13 @@ btr_estimate_number_of_different_key_vals( ulint add_on; mtr_t mtr; mem_heap_t* heap = NULL; - ulint offsets1_[REC_OFFS_NORMAL_SIZE]; - ulint offsets2_[REC_OFFS_NORMAL_SIZE]; - ulint* offsets1 = offsets1_; - ulint* offsets2 = offsets2_; - *offsets1_ = (sizeof offsets1_) / sizeof *offsets1_; - *offsets2_ = (sizeof offsets2_) / sizeof *offsets2_; + ulint offsets_rec_[REC_OFFS_NORMAL_SIZE]; + ulint offsets_next_rec_[REC_OFFS_NORMAL_SIZE]; + ulint* offsets_rec = offsets_rec_; + ulint* offsets_next_rec= offsets_next_rec_; + *offsets_rec_ = (sizeof offsets_rec_) / sizeof *offsets_rec_; + *offsets_next_rec_ = + (sizeof offsets_next_rec_) / sizeof *offsets_next_rec_; n_cols = dict_index_get_n_unique(index); @@ -2831,6 +2854,7 @@ btr_estimate_number_of_different_key_vals( /* 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); @@ -2843,26 +2867,29 @@ btr_estimate_number_of_different_key_vals( page = btr_cur_get_page(&cursor); - rec = page_get_infimum_rec(page); - rec = page_rec_get_next(rec); + supremum = page_get_supremum_rec(page); + rec = page_rec_get_next(page_get_infimum_rec(page)); - if (rec != page_get_supremum_rec(page)) { + if (rec != supremum) { not_empty_flag = 1; + offsets_rec = rec_get_offsets(rec, index, offsets_rec, + ULINT_UNDEFINED, &heap); } - - while (rec != page_get_supremum_rec(page) - && page_rec_get_next(rec) - != page_get_supremum_rec(page)) { + + while (rec != supremum) { rec_t* next_rec = page_rec_get_next(rec); + if (next_rec == supremum) { + break; + } + matched_fields = 0; matched_bytes = 0; - offsets1 = rec_get_offsets(rec, index, offsets1, - ULINT_UNDEFINED, &heap); - offsets2 = rec_get_offsets(next_rec, index, offsets2, + offsets_next_rec = rec_get_offsets(next_rec, index, + offsets_next_rec, n_cols, &heap); cmp_rec_rec_with_match(rec, next_rec, - offsets1, offsets2, + offsets_rec, offsets_next_rec, index, &matched_fields, &matched_bytes); @@ -2875,9 +2902,17 @@ btr_estimate_number_of_different_key_vals( total_external_size += btr_rec_get_externally_stored_len( - rec, offsets1); + rec, offsets_rec); - rec = page_rec_get_next(rec); + rec = next_rec; + /* Initialize offsets_rec for the next round + and assign the old offsets_rec buffer to + offsets_next_rec. */ + { + ulint* offsets_tmp = offsets_rec; + offsets_rec = offsets_next_rec; + offsets_next_rec = offsets_tmp; + } } @@ -2899,11 +2934,11 @@ btr_estimate_number_of_different_key_vals( } } - offsets1 = rec_get_offsets(rec, index, offsets1, + offsets_rec = rec_get_offsets(rec, index, offsets_rec, ULINT_UNDEFINED, &heap); total_external_size += btr_rec_get_externally_stored_len(rec, - offsets1); + offsets_rec); mtr_commit(&mtr); } @@ -2944,7 +2979,7 @@ btr_estimate_number_of_different_key_vals( } mem_free(n_diff); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -3599,7 +3634,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(index->table->comp == !!rec_offs_comp(offsets)); n_fields = rec_offs_n_fields(offsets); for (i = 0; i < n_fields; i++) { diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c index 74feff8653c..cb398b4afab 100644 --- a/innobase/btr/btr0pcur.c +++ b/innobase/btr/btr0pcur.c @@ -78,6 +78,7 @@ btr_pcur_store_position( rec_t* rec; 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); @@ -87,7 +88,8 @@ btr_pcur_store_position( page_cursor = btr_pcur_get_page_cur(cursor); rec = page_cur_get_rec(page_cursor); - page = buf_frame_align(rec); + page = ut_align_down(rec, UNIV_PAGE_SIZE); + offs = ut_align_offset(rec, UNIV_PAGE_SIZE); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_S_FIX) @@ -95,35 +97,33 @@ btr_pcur_store_position( MTR_MEMO_PAGE_X_FIX)); ut_a(cursor->latch_mode != BTR_NO_LATCHES); - if (page_get_n_recs(page) == 0) { + if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) { /* It must be an empty index tree; NOTE that in this case we do not store the modify_clock, but always do a search if we restore the cursor position */ - ut_a(btr_page_get_next(page, mtr) == FIL_NULL - && btr_page_get_prev(page, mtr) == FIL_NULL); + ut_a(btr_page_get_next(page, mtr) == FIL_NULL); + ut_a(btr_page_get_prev(page, mtr) == FIL_NULL); - if (rec == page_get_supremum_rec(page)) { + cursor->old_stored = BTR_PCUR_OLD_STORED; - cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE; - cursor->old_stored = BTR_PCUR_OLD_STORED; + if (page_rec_is_supremum_low(offs)) { - return; + cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE; + } else { + cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE; } - cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE; - cursor->old_stored = BTR_PCUR_OLD_STORED; - return; } - if (rec == page_get_supremum_rec(page)) { + if (page_rec_is_supremum_low(offs)) { rec = page_rec_get_prev(rec); cursor->rel_pos = BTR_PCUR_AFTER; - } else if (rec == page_get_infimum_rec(page)) { + } else if (page_rec_is_infimum_low(offs)) { rec = page_rec_get_next(rec); @@ -139,7 +139,8 @@ btr_pcur_store_position( &cursor->buf_size); cursor->block_when_stored = buf_block_align(page); - cursor->modify_clock = buf_frame_get_modify_clock(page); + cursor->modify_clock = buf_block_get_modify_clock( + cursor->block_when_stored); } /****************************************************************** @@ -202,33 +203,27 @@ btr_pcur_restore_position( dtuple_t* tuple; ulint mode; ulint old_mode; - ibool from_left; mem_heap_t* heap; - ut_a(cursor->pos_state == BTR_PCUR_WAS_POSITIONED - || cursor->pos_state == BTR_PCUR_IS_POSITIONED); - if (cursor->old_stored != BTR_PCUR_OLD_STORED) { + 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)); if (cursor->trx_if_known) { trx_print(stderr, cursor->trx_if_known); } - ut_a(0); + ut_error; } - if (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE - || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) { + 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 */ - if (cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) { - from_left = TRUE; - } else { - from_left = FALSE; - } - - btr_cur_open_at_index_side(from_left, + btr_cur_open_at_index_side( + cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE, btr_pcur_get_btr_cur(cursor)->index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr); @@ -243,12 +238,13 @@ btr_pcur_restore_position( page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor)); - if (latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF) { + if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF) + || UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) { /* Try optimistic restoration */ - if (buf_page_optimistic_get(latch_mode, + if (UNIV_LIKELY(buf_page_optimistic_get(latch_mode, cursor->block_when_stored, page, - cursor->modify_clock, mtr)) { + cursor->modify_clock, mtr))) { cursor->pos_state = BTR_PCUR_IS_POSITIONED; #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_TREE_NODE); @@ -297,7 +293,7 @@ btr_pcur_restore_position( /* Save the old search mode of the cursor */ old_mode = cursor->search_mode; - if (cursor->rel_pos == BTR_PCUR_ON) { + if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) { mode = PAGE_CUR_LE; } else if (cursor->rel_pos == BTR_PCUR_AFTER) { mode = PAGE_CUR_G; @@ -323,12 +319,10 @@ btr_pcur_restore_position( the cursor can now be on a different page! But we can retain the value of old_rec */ - cursor->modify_clock = - buf_frame_get_modify_clock(btr_pcur_get_page(cursor)); - cursor->block_when_stored = buf_block_align(btr_pcur_get_page(cursor)); - + cursor->modify_clock = + buf_block_get_modify_clock(cursor->block_when_stored); cursor->old_stored = BTR_PCUR_OLD_STORED; mem_heap_free(heap); diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 97fdce2df75..f705fee4275 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -435,7 +435,7 @@ btr_search_update_hash_ref( offsets_, ULINT_UNDEFINED, &heap), block->curr_n_fields, block->curr_n_bytes, tree_id); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } #ifdef UNIV_SYNC_DEBUG @@ -544,10 +544,7 @@ btr_search_check_guess( or PAGE_CUR_GE */ mtr_t* mtr) /* in: mtr */ { - page_t* page; rec_t* rec; - rec_t* prev_rec; - rec_t* next_rec; ulint n_unique; ulint match; ulint bytes; @@ -561,7 +558,6 @@ btr_search_check_guess( n_unique = dict_index_get_n_unique_in_tree(cursor->index); rec = btr_cur_get_rec(cursor); - page = buf_frame_align(rec); ut_ad(page_rec_is_user_rec(rec)); @@ -611,13 +607,16 @@ btr_search_check_guess( bytes = 0; if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)) { + rec_t* prev_rec; - ut_ad(rec != page_get_infimum_rec(page)); + ut_ad(!page_rec_is_infimum(rec)); prev_rec = page_rec_get_prev(rec); - if (prev_rec == page_get_infimum_rec(page)) { - success = btr_page_get_prev(page, mtr) == FIL_NULL; + if (page_rec_is_infimum(prev_rec)) { + success = btr_page_get_prev( + buf_frame_align(prev_rec), mtr) == FIL_NULL; + goto exit_func; } @@ -632,34 +631,37 @@ btr_search_check_guess( } goto exit_func; - } - - ut_ad(rec != page_get_supremum_rec(page)); + } else { + rec_t* next_rec; + + ut_ad(!page_rec_is_supremum(rec)); - next_rec = page_rec_get_next(rec); + next_rec = page_rec_get_next(rec); - if (next_rec == page_get_supremum_rec(page)) { - if (btr_page_get_next(page, mtr) == FIL_NULL) { + if (page_rec_is_supremum(next_rec)) { + if (btr_page_get_next( + buf_frame_align(next_rec), mtr) == FIL_NULL) { - cursor->up_match = 0; - success = TRUE; - } + cursor->up_match = 0; + success = TRUE; + } - goto exit_func; - } + goto exit_func; + } - offsets = rec_get_offsets(next_rec, cursor->index, offsets, + offsets = rec_get_offsets(next_rec, cursor->index, offsets, n_unique, &heap); - cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, - offsets, &match, &bytes); - if (mode == PAGE_CUR_LE) { - success = cmp == -1; - cursor->up_match = match; - } else { - success = cmp != 1; + cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, + offsets, &match, &bytes); + if (mode == PAGE_CUR_LE) { + success = cmp == -1; + cursor->up_match = match; + } else { + success = cmp != 1; + } } exit_func: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(success); @@ -694,7 +696,6 @@ btr_search_guess_on_hash( buf_block_t* block; rec_t* rec; page_t* page; - ibool success; ulint fold; ulint tuple_n_fields; dulint tree_id; @@ -710,7 +711,7 @@ btr_search_guess_on_hash( /* Note that, for efficiency, the struct info may not be protected by any latch here! */ - if (info->n_hash_potential == 0) { + if (UNIV_UNLIKELY(info->n_hash_potential == 0)) { return(FALSE); } @@ -720,12 +721,13 @@ btr_search_guess_on_hash( tuple_n_fields = dtuple_get_n_fields(tuple); - if (tuple_n_fields < cursor->n_fields) { + if (UNIV_UNLIKELY(tuple_n_fields < cursor->n_fields)) { return(FALSE); } - if ((cursor->n_bytes > 0) && (tuple_n_fields <= cursor->n_fields)) { + if (UNIV_UNLIKELY(tuple_n_fields == cursor->n_fields) + && (cursor->n_bytes > 0)) { return(FALSE); } @@ -740,39 +742,31 @@ btr_search_guess_on_hash( cursor->fold = fold; cursor->flag = BTR_CUR_HASH; - if (!has_search_latch) { + if (UNIV_LIKELY(!has_search_latch)) { rw_lock_s_lock(&btr_search_latch); } - ut_a(btr_search_latch.writer != RW_LOCK_EX); - ut_a(btr_search_latch.reader_count > 0); + ut_ad(btr_search_latch.writer != RW_LOCK_EX); + ut_ad(btr_search_latch.reader_count > 0); rec = ha_search_and_get_data(btr_search_sys->hash_index, fold); - if (!rec) { - if (!has_search_latch) { - rw_lock_s_unlock(&btr_search_latch); - } - - goto failure; + if (UNIV_UNLIKELY(!rec)) { + goto failure_unlock; } page = buf_frame_align(rec); - if (!has_search_latch) { + if (UNIV_LIKELY(!has_search_latch)) { - success = buf_page_get_known_nowait(latch_mode, page, + if (UNIV_UNLIKELY(!buf_page_get_known_nowait(latch_mode, page, BUF_MAKE_YOUNG, __FILE__, __LINE__, - mtr); - - rw_lock_s_unlock(&btr_search_latch); - - if (!success) { - - goto failure; + mtr))) { + goto failure_unlock; } + rw_lock_s_unlock(&btr_search_latch); can_only_compare_to_cursor_rec = FALSE; #ifdef UNIV_SYNC_DEBUG @@ -782,8 +776,8 @@ btr_search_guess_on_hash( block = buf_block_align(page); - if (block->state == BUF_BLOCK_REMOVE_HASH) { - if (!has_search_latch) { + if (UNIV_UNLIKELY(block->state == BUF_BLOCK_REMOVE_HASH)) { + if (UNIV_LIKELY(!has_search_latch)) { btr_leaf_page_release(page, latch_mode, mtr); } @@ -791,51 +785,33 @@ btr_search_guess_on_hash( goto failure; } - ut_a(block->state == BUF_BLOCK_FILE_PAGE); - ut_a(page_rec_is_user_rec(rec)); + ut_ad(block->state == BUF_BLOCK_FILE_PAGE); + ut_ad(page_rec_is_user_rec(rec)); btr_cur_position(index, rec, cursor); /* Check the validity of the guess within the page */ - if (0 != ut_dulint_cmp(tree_id, btr_page_get_index_id(page))) { - - success = FALSE; -/* - fprintf(stderr, "Tree id %lu, page index id %lu fold %lu\n", - ut_dulint_get_low(tree_id), - ut_dulint_get_low(btr_page_get_index_id(page)), - fold); -*/ - } else { - /* If we only have the latch on btr_search_latch, not on the - page, it only protects the columns of the record the cursor - is positioned on. We cannot look at the next of the previous - record to determine if our guess for the cursor position is - right. */ - - success = btr_search_check_guess(cursor, - can_only_compare_to_cursor_rec, - tuple, mode, mtr); - } - - if (!success) { - if (!has_search_latch) { + /* If we only have the latch on btr_search_latch, not on the + page, it only protects the columns of the record the cursor + is positioned on. We cannot look at the next of the previous + 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)) { + if (UNIV_LIKELY(!has_search_latch)) { btr_leaf_page_release(page, latch_mode, mtr); } goto failure; } - if (info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5) { + if (UNIV_LIKELY(info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5)) { info->n_hash_potential++; } - if (info->last_hash_succ != TRUE) { - info->last_hash_succ = TRUE; - } - #ifdef notdefined /* These lines of code can be used in a debug version to check the correctness of the searched cursor position: */ @@ -843,15 +819,14 @@ btr_search_guess_on_hash( info->last_hash_succ = FALSE; /* Currently, does not work if the following fails: */ - ut_a(!has_search_latch); + 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, &cursor2, 0, mtr); if (mode == PAGE_CUR_GE - && btr_cur_get_rec(&cursor2) == page_get_supremum_rec( - buf_frame_align(btr_cur_get_rec(&cursor2)))) { + && page_rec_is_supremum(btr_cur_get_rec(&cursor2))) { /* If mode is PAGE_CUR_GE, then the binary search in the index tree may actually take us to the supremum @@ -861,22 +836,22 @@ btr_search_guess_on_hash( btr_pcur_open_on_user_rec(index, tuple, mode, latch_mode, &pcur, mtr); - ut_a(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor)); + ut_ad(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor)); } else { - ut_a(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor)); + ut_ad(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor)); } /* NOTE that it is theoretically possible that the above assertions fail if the page of the cursor gets removed from the buffer pool meanwhile! Thus it might not be a bug. */ - - info->last_hash_succ = TRUE; #endif + info->last_hash_succ = TRUE; #ifdef UNIV_SEARCH_PERF_STAT btr_search_n_succ++; #endif - if (!has_search_latch && buf_block_peek_if_too_old(block)) { + if (UNIV_LIKELY(!has_search_latch) + && buf_block_peek_if_too_old(block)) { buf_page_make_young(page); } @@ -889,6 +864,10 @@ btr_search_guess_on_hash( return(TRUE); /*-------------------------------------------*/ +failure_unlock: + if (UNIV_LIKELY(!has_search_latch)) { + rw_lock_s_unlock(&btr_search_latch); + } failure: info->n_hash_fail++; @@ -917,7 +896,6 @@ btr_search_drop_page_hash_index( ulint n_fields; ulint n_bytes; rec_t* rec; - rec_t* sup; ulint fold; ulint prev_fold; dulint tree_id; @@ -968,12 +946,10 @@ btr_search_drop_page_hash_index( n_cached = 0; - sup = page_get_supremum_rec(page); - rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); - if (rec != sup) { + if (!page_rec_is_supremum(rec)) { ut_a(n_fields <= rec_get_n_fields(rec, block->index)); if (n_bytes > 0) { @@ -988,7 +964,7 @@ btr_search_drop_page_hash_index( heap = NULL; offsets = NULL; - while (rec != sup) { + 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, @@ -1010,7 +986,7 @@ next_rec: prev_fold = fold; } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -1090,7 +1066,6 @@ btr_search_build_page_hash_index( buf_block_t* block; rec_t* rec; rec_t* next_rec; - rec_t* sup; ulint fold; ulint next_fold; dulint tree_id; @@ -1158,15 +1133,13 @@ btr_search_build_page_hash_index( tree_id = btr_page_get_index_id(page); - sup = page_get_supremum_rec(page); - rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); offsets = rec_get_offsets(rec, index, offsets, n_fields + (n_bytes > 0), &heap); - if (rec != sup) { + if (!page_rec_is_supremum(rec)) { ut_a(n_fields <= rec_offs_n_fields(offsets)); if (n_bytes > 0) { @@ -1188,7 +1161,7 @@ btr_search_build_page_hash_index( for (;;) { next_rec = page_rec_get_next(rec); - if (next_rec == sup) { + if (page_rec_is_supremum(next_rec)) { if (side == BTR_SEARCH_RIGHT_SIDE) { @@ -1252,7 +1225,7 @@ exit_func: mem_free(folds); mem_free(recs); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -1370,7 +1343,7 @@ btr_search_update_hash_on_delete( fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_, ULINT_UNDEFINED, &heap), block->curr_n_fields, block->curr_n_bytes, tree_id); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } rw_lock_x_lock(&btr_search_latch); @@ -1443,7 +1416,6 @@ btr_search_update_hash_on_insert( { hash_table_t* table; buf_block_t* block; - page_t* page; rec_t* rec; rec_t* ins_rec; rec_t* next_rec; @@ -1488,19 +1460,18 @@ btr_search_update_hash_on_insert( ins_rec = page_rec_get_next(rec); next_rec = page_rec_get_next(ins_rec); - page = buf_frame_align(rec); offsets = rec_get_offsets(ins_rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, tree_id); - if (next_rec != page_get_supremum_rec(page)) { + if (!page_rec_is_supremum(next_rec)) { offsets = rec_get_offsets(next_rec, cursor->index, offsets, n_fields + (n_bytes > 0), &heap); next_fold = rec_fold(next_rec, offsets, n_fields, n_bytes, tree_id); } - if (rec != page_get_infimum_rec(page)) { + if (!page_rec_is_infimum(rec)) { offsets = rec_get_offsets(rec, cursor->index, offsets, n_fields + (n_bytes > 0), &heap); fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id); @@ -1534,7 +1505,7 @@ btr_search_update_hash_on_insert( } check_next_rec: - if (next_rec == page_get_supremum_rec(page)) { + if (page_rec_is_supremum(next_rec)) { if (side == BTR_SEARCH_RIGHT_SIDE) { @@ -1573,7 +1544,7 @@ check_next_rec: } function_exit: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } if (locked) { @@ -1662,7 +1633,7 @@ btr_search_validate(void) } rw_lock_x_unlock(&btr_search_latch); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } |