diff options
author | unknown <tulin@dl145b.mysql.com> | 2005-06-21 08:49:21 +0200 |
---|---|---|
committer | unknown <tulin@dl145b.mysql.com> | 2005-06-21 08:49:21 +0200 |
commit | cee82bca2970bfe36e17a84cad27a238900f7f81 (patch) | |
tree | 021f00d0d8d4e312b7cc20166e879b5052187631 /storage | |
parent | ca2e8ed7f372351fbf290445b2f5afd4840d7b45 (diff) | |
parent | bf6a86afcafc559aed642d10da692c94584d258b (diff) | |
download | mariadb-git-cee82bca2970bfe36e17a84cad27a238900f7f81.tar.gz |
Merge tulin@bk-internal.mysql.com:/home/bk/mysql-5.0
into dl145b.mysql.com:/home/ndbdev/tomas/mysql-5.1
sql/ha_innodb.cc:
Auto merged
sql/ha_innodb.h:
Auto merged
sql/mysqld.cc:
Auto merged
storage/innobase/btr/btr0btr.c:
Auto merged
storage/innobase/btr/btr0cur.c:
Auto merged
storage/innobase/btr/btr0pcur.c:
Auto merged
storage/innobase/btr/btr0sea.c:
Auto merged
storage/innobase/buf/buf0buf.c:
Auto merged
storage/innobase/buf/buf0flu.c:
Auto merged
storage/innobase/buf/buf0lru.c:
Auto merged
storage/innobase/buf/buf0rea.c:
Auto merged
storage/innobase/data/data0data.c:
Auto merged
storage/innobase/data/data0type.c:
Auto merged
storage/innobase/dict/dict0boot.c:
Auto merged
storage/innobase/dict/dict0crea.c:
Auto merged
storage/innobase/dict/dict0dict.c:
Auto merged
storage/innobase/dict/dict0mem.c:
Auto merged
storage/innobase/fil/fil0fil.c:
Auto merged
storage/innobase/fsp/fsp0fsp.c:
Auto merged
storage/innobase/ibuf/ibuf0ibuf.c:
Auto merged
storage/innobase/include/btr0btr.h:
Auto merged
storage/innobase/include/btr0btr.ic:
Auto merged
storage/innobase/include/btr0cur.h:
Auto merged
storage/innobase/include/btr0cur.ic:
Auto merged
storage/innobase/include/buf0buf.h:
Auto merged
storage/innobase/include/buf0buf.ic:
Auto merged
storage/innobase/include/buf0lru.h:
Auto merged
storage/innobase/include/data0type.h:
Auto merged
storage/innobase/include/data0type.ic:
Auto merged
storage/innobase/include/dyn0dyn.h:
Auto merged
storage/innobase/include/dyn0dyn.ic:
Auto merged
storage/innobase/include/lock0lock.h:
Auto merged
storage/innobase/include/log0log.h:
Auto merged
storage/innobase/include/mach0data.h:
Auto merged
storage/innobase/include/mach0data.ic:
Auto merged
storage/innobase/include/mem0mem.ic:
Auto merged
storage/innobase/include/mtr0log.h:
Auto merged
storage/innobase/include/mtr0mtr.h:
Auto merged
storage/innobase/include/os0file.h:
Auto merged
storage/innobase/include/page0cur.h:
Auto merged
storage/innobase/include/page0cur.ic:
Auto merged
storage/innobase/include/page0page.h:
Auto merged
storage/innobase/include/page0page.ic:
Auto merged
storage/innobase/include/read0read.ic:
Auto merged
storage/innobase/include/rem0rec.h:
Auto merged
storage/innobase/include/rem0rec.ic:
Auto merged
storage/innobase/include/row0mysql.h:
Auto merged
storage/innobase/include/row0sel.ic:
Auto merged
storage/innobase/include/row0upd.ic:
Auto merged
storage/innobase/include/sync0rw.ic:
Auto merged
storage/innobase/include/trx0rseg.ic:
Auto merged
storage/innobase/include/trx0trx.h:
Auto merged
storage/innobase/include/univ.i:
Auto merged
storage/innobase/include/ut0dbg.h:
Auto merged
storage/innobase/include/ut0rnd.ic:
Auto merged
storage/innobase/lock/lock0lock.c:
Auto merged
storage/innobase/log/log0log.c:
Auto merged
storage/innobase/log/log0recv.c:
Auto merged
storage/innobase/mtr/mtr0log.c:
Auto merged
storage/innobase/mtr/mtr0mtr.c:
Auto merged
storage/innobase/os/os0file.c:
Auto merged
storage/innobase/page/page0cur.c:
Auto merged
storage/innobase/page/page0page.c:
Auto merged
storage/innobase/rem/rem0cmp.c:
Auto merged
storage/innobase/rem/rem0rec.c:
Auto merged
storage/innobase/row/row0ins.c:
Auto merged
storage/innobase/row/row0mysql.c:
Auto merged
storage/innobase/row/row0purge.c:
Auto merged
storage/innobase/row/row0row.c:
Auto merged
storage/innobase/row/row0sel.c:
Auto merged
storage/innobase/row/row0undo.c:
Auto merged
storage/innobase/row/row0upd.c:
Auto merged
storage/innobase/row/row0vers.c:
Auto merged
storage/innobase/srv/srv0start.c:
Auto merged
storage/innobase/sync/sync0sync.c:
Auto merged
storage/innobase/trx/trx0rec.c:
Auto merged
storage/innobase/trx/trx0roll.c:
Auto merged
storage/innobase/trx/trx0trx.c:
Auto merged
storage/innobase/ut/ut0dbg.c:
Auto merged
Diffstat (limited to 'storage')
76 files changed, 1812 insertions, 1675 deletions
diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index 1744fc36f4d..2d84586216a 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/storage/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/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index e093c911f22..98d90ecf18a 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/storage/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/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index 74feff8653c..cb398b4afab 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/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/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c index 97fdce2df75..f705fee4275 100644 --- a/storage/innobase/btr/btr0sea.c +++ b/storage/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); } diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index 89f851709db..78189617aab 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -223,13 +223,14 @@ in the free list to the frames. buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */ +#ifdef UNIV_DEBUG ulint buf_dbg_counter = 0; /* This is used to insert validation operations in excution in the debug version */ ibool buf_debug_prints = FALSE; /* If this is set TRUE, the program prints info whenever read-ahead or flush occurs */ - +#endif /* UNIV_DEBUG */ /************************************************************************ Calculates a page checksum which is stored to the page when it is written to a file. Note that we must be careful to calculate the same value on @@ -1286,8 +1287,9 @@ buf_page_optimistic_get_func( /* If AWE is used, block may have a different frame now, e.g., NULL */ - if (block->state != BUF_BLOCK_FILE_PAGE || block->frame != guess) { - + if (UNIV_UNLIKELY(block->state != BUF_BLOCK_FILE_PAGE) + || UNIV_UNLIKELY(block->frame != guess)) { + exit_func: mutex_exit(&(buf_pool->mutex)); return(FALSE); @@ -1320,19 +1322,17 @@ buf_page_optimistic_get_func( fix_type = MTR_MEMO_PAGE_X_FIX; } - if (!success) { + if (UNIV_UNLIKELY(!success)) { mutex_enter(&(buf_pool->mutex)); block->buf_fix_count--; #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); -#endif - mutex_exit(&(buf_pool->mutex)); - - return(FALSE); +#endif + goto exit_func; } - if (!UT_DULINT_EQ(modify_clock, block->modify_clock)) { + if (UNIV_UNLIKELY(!UT_DULINT_EQ(modify_clock, block->modify_clock))) { #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(block->frame, SYNC_NO_ORDER_CHECK); #endif /* UNIV_SYNC_DEBUG */ @@ -1347,10 +1347,8 @@ buf_page_optimistic_get_func( block->buf_fix_count--; #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); -#endif - mutex_exit(&(buf_pool->mutex)); - - return(FALSE); +#endif + goto exit_func; } mtr_memo_push(mtr, block, fix_type); @@ -1368,7 +1366,7 @@ buf_page_optimistic_get_func( #ifdef UNIV_DEBUG_FILE_ACCESSES ut_a(block->file_page_was_freed == FALSE); #endif - if (!accessed) { + if (UNIV_UNLIKELY(!accessed)) { /* In the case of a first access, try to apply linear read-ahead */ @@ -1742,10 +1740,12 @@ buf_page_create( /* If we get here, the page was not in buf_pool: init it there */ +#ifdef UNIV_DEBUG if (buf_debug_prints) { fprintf(stderr, "Creating space %lu page %lu to buffer\n", (ulong) space, (ulong) offset); } +#endif /* UNIV_DEBUG */ block = free_block; @@ -1896,9 +1896,11 @@ buf_page_io_complete( rw_lock_x_unlock_gen(&(block->lock), BUF_IO_READ); +#ifdef UNIV_DEBUG if (buf_debug_prints) { fputs("Has read ", stderr); } +#endif /* UNIV_DEBUG */ } else { ut_ad(io_type == BUF_IO_WRITE); @@ -1911,17 +1913,21 @@ buf_page_io_complete( buf_pool->n_pages_written++; +#ifdef UNIV_DEBUG if (buf_debug_prints) { fputs("Has written ", stderr); } +#endif /* UNIV_DEBUG */ } mutex_exit(&(buf_pool->mutex)); +#ifdef UNIV_DEBUG if (buf_debug_prints) { fprintf(stderr, "page space %lu page no %lu\n", (ulong) block->space, (ulong) block->offset); } +#endif /* UNIV_DEBUG */ } /************************************************************************* @@ -1950,6 +1956,7 @@ buf_pool_invalidate(void) mutex_exit(&(buf_pool->mutex)); } +#ifdef UNIV_DEBUG /************************************************************************* Validates the buffer buf_pool data structure. */ @@ -2149,6 +2156,7 @@ buf_print(void) ut_a(buf_validate()); } +#endif /* UNIV_DEBUG */ /************************************************************************* Returns the number of latched pages in the buffer pool. */ diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c index 592ed972376..ffb16790b2d 100644 --- a/storage/innobase/buf/buf0flu.c +++ b/storage/innobase/buf/buf0flu.c @@ -586,11 +586,13 @@ buf_flush_try_page( rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE); } +#ifdef UNIV_DEBUG if (buf_debug_prints) { fprintf(stderr, "Flushing page space %lu, page no %lu \n", (ulong) block->space, (ulong) block->offset); } +#endif /* UNIV_DEBUG */ buf_flush_write_block_low(block); @@ -674,12 +676,14 @@ buf_flush_try_page( rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE); +#ifdef UNIV_DEBUG if (buf_debug_prints) { fprintf(stderr, "Flushing single page space %lu, page no %lu \n", (ulong) block->space, (ulong) block->offset); } +#endif /* UNIV_DEBUG */ buf_flush_write_block_low(block); @@ -906,6 +910,7 @@ buf_flush_batch( buf_flush_buffered_writes(); +#ifdef UNIV_DEBUG if (buf_debug_prints && page_count > 0) { ut_a(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); @@ -914,6 +919,7 @@ buf_flush_batch( : "Flushed %lu pages in flush list flush\n", (ulong) page_count); } +#endif /* UNIV_DEBUG */ if (page_count != ULINT_UNDEFINED) srv_buf_pool_flushed+= page_count; diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c index 18c4f8c10fb..a0157da2d42 100644 --- a/storage/innobase/buf/buf0lru.c +++ b/storage/innobase/buf/buf0lru.c @@ -213,12 +213,14 @@ buf_LRU_search_and_free_block( ut_a(block->in_LRU_list); if (buf_flush_ready_for_replace(block)) { +#ifdef UNIV_DEBUG if (buf_debug_prints) { fprintf(stderr, "Putting space %lu page %lu to free list\n", (ulong) block->space, (ulong) block->offset); } +#endif /* UNIV_DEBUG */ buf_LRU_block_remove_hashed_page(block); @@ -919,7 +921,8 @@ buf_LRU_block_free_hashed_page( buf_LRU_block_free_non_file_page(block); } - + +#ifdef UNIV_DEBUG /************************************************************************** Validates the LRU list. */ @@ -1050,3 +1053,4 @@ buf_LRU_print(void) mutex_exit(&(buf_pool->mutex)); } +#endif /* UNIV_DEBUG */ diff --git a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c index d9dc2ca93f5..813ca589907 100644 --- a/storage/innobase/buf/buf0rea.c +++ b/storage/innobase/buf/buf0rea.c @@ -288,12 +288,14 @@ buf_read_ahead_random( os_aio_simulated_wake_handler_threads(); +#ifdef UNIV_DEBUG if (buf_debug_prints && (count > 0)) { fprintf(stderr, "Random read-ahead space %lu offset %lu pages %lu\n", (ulong) space, (ulong) offset, (ulong) count); } +#endif /* UNIV_DEBUG */ ++srv_read_ahead_rnd; return(count); @@ -575,11 +577,13 @@ buf_read_ahead_linear( /* Flush pages from the end of the LRU list if necessary */ buf_flush_free_margin(); +#ifdef UNIV_DEBUG if (buf_debug_prints && (count > 0)) { fprintf(stderr, "LINEAR read-ahead space %lu offset %lu pages %lu\n", (ulong) space, (ulong) offset, (ulong) count); } +#endif /* UNIV_DEBUG */ ++srv_read_ahead_seq; return(count); @@ -641,11 +645,13 @@ buf_read_ibuf_merge_pages( /* Flush pages from the end of the LRU list if necessary */ buf_flush_free_margin(); +#ifdef UNIV_DEBUG if (buf_debug_prints) { fprintf(stderr, "Ibuf merge read-ahead space %lu pages %lu\n", (ulong) space_ids[0], (ulong) n_stored); } +#endif /* UNIV_DEBUG */ } /************************************************************************ @@ -711,8 +717,10 @@ buf_read_recv_pages( /* Flush pages from the end of the LRU list if necessary */ buf_flush_free_margin(); +#ifdef UNIV_DEBUG if (buf_debug_prints) { fprintf(stderr, "Recovery applies read-ahead pages %lu\n", (ulong) n_stored); } +#endif /* UNIV_DEBUG */ } diff --git a/storage/innobase/data/data0data.c b/storage/innobase/data/data0data.c index 5f74dde8710..194213a04e1 100644 --- a/storage/innobase/data/data0data.c +++ b/storage/innobase/data/data0data.c @@ -502,7 +502,7 @@ dtuple_convert_big_rec( size = rec_get_converted_size(index, entry); - if (size > 1000000000) { + if (UNIV_UNLIKELY(size > 1000000000)) { fprintf(stderr, "InnoDB: Warning: tuple size very big: %lu\n", (ulong) size); fputs("InnoDB: Tuple contents: ", stderr); diff --git a/storage/innobase/data/data0type.c b/storage/innobase/data/data0type.c index 3fcd666b5a5..d4264ad2926 100644 --- a/storage/innobase/data/data0type.c +++ b/storage/innobase/data/data0type.c @@ -39,7 +39,6 @@ column definitions, or records in the insert buffer, we use this charset-collation code for them. */ ulint data_mysql_default_charset_coll = 99999999; -ulint data_mysql_latin1_swedish_charset_coll = 99999999; dtype_t dtype_binary_val = {DATA_BINARY, 0, 0, 0, 0, 0}; dtype_t* dtype_binary = &dtype_binary_val; @@ -64,9 +63,10 @@ dtype_get_at_most_n_mbchars( { #ifndef UNIV_HOTBACKUP ut_a(data_len != UNIV_SQL_NULL); - ut_a(!(prefix_len % dtype->mbmaxlen)); + ut_ad(!dtype->mbmaxlen || !(prefix_len % dtype->mbmaxlen)); if (dtype->mbminlen != dtype->mbmaxlen) { + ut_a(!(prefix_len % dtype->mbmaxlen)); return(innobase_get_at_most_n_mbchars( dtype_get_charset_coll(dtype->prtype), prefix_len, data_len, str)); diff --git a/storage/innobase/dict/dict0boot.c b/storage/innobase/dict/dict0boot.c index 0f6d55c9341..18a707a1b93 100644 --- a/storage/innobase/dict/dict0boot.c +++ b/storage/innobase/dict/dict0boot.c @@ -66,15 +66,6 @@ dict_hdr_get_new_id( dict_hdr = dict_hdr_get(&mtr); id = mtr_read_dulint(dict_hdr + type, &mtr); - - /* Add some dummy code here because otherwise pgcc seems to - compile wrong */ - - if (0 == ut_dulint_cmp(id, ut_dulint_max)) { - /* TO DO: remove this code, or make it conditional */ - ut_dbg_null_ptr = 0; - } - id = ut_dulint_add(id, 1); mlog_write_dulint(dict_hdr + type, id, &mtr); diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c index 1f12386e413..c7d6ffd2c22 100644 --- a/storage/innobase/dict/dict0crea.c +++ b/storage/innobase/dict/dict0crea.c @@ -736,7 +736,7 @@ dict_truncate_index_tree( dulint index_id; byte* ptr; ulint len; - ibool comp; + ulint comp; dict_index_t* index; #ifdef UNIV_SYNC_DEBUG diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index 0c39defeada..9580a80e7e7 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -1453,7 +1453,7 @@ dict_index_add_to_cache( /* Increment the ord_part counts in columns which are ordering */ - if (index->type & DICT_UNIVERSAL) { + if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) { n_ord = new_index->n_fields; } else { n_ord = dict_index_get_n_unique(new_index); @@ -1482,7 +1482,7 @@ dict_index_add_to_cache( new_index->tree = tree; } - if (!(new_index->type & DICT_UNIVERSAL)) { + if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) { new_index->stat_n_diff_key_vals = mem_heap_alloc(new_index->heap, @@ -1683,7 +1683,7 @@ dict_index_copy_types( dtype_t* type; ulint i; - if (index->type & DICT_UNIVERSAL) { + if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) { dtuple_set_types_binary(tuple, n_fields); return; @@ -1779,7 +1779,7 @@ dict_index_build_internal_clust( dict_index_copy(new_index, index, 0, index->n_fields); } - if (index->type & DICT_UNIVERSAL) { + if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) { /* No fixed number of fields determines an entry uniquely */ new_index->n_uniq = ULINT_MAX; @@ -3682,7 +3682,7 @@ dict_tree_find_index_low( table = index->table; if ((index->type & DICT_CLUSTERED) - && (table->type != DICT_TABLE_ORDINARY)) { + && UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) { /* Get the mix id of the record */ ut_a(!table->comp); @@ -3838,7 +3838,7 @@ dict_tree_build_node_ptr( ind = dict_tree_find_index_low(tree, rec); - if (tree->type & DICT_UNIVERSAL) { + if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) { /* In a universal index tree, we take the whole record as the node pointer if the reord is on the leaf level, on non-leaf levels we remove the last field, which @@ -3903,9 +3903,10 @@ dict_tree_copy_rec_order_prefix( dict_index_t* index; ulint n; + UNIV_PREFETCH_R(rec); index = dict_tree_find_index_low(tree, rec); - if (tree->type & DICT_UNIVERSAL) { + if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) { ut_a(!index->table->comp); n = rec_get_n_fields_old(rec); } else { @@ -3957,7 +3958,7 @@ dict_index_calc_min_rec_len( ulint sum = 0; ulint i; - if (index->table->comp) { + if (UNIV_LIKELY(index->table->comp)) { ulint nullable = 0; sum = REC_N_NEW_EXTRA_BYTES; for (i = 0; i < dict_index_get_n_fields(index); i++) { @@ -4277,9 +4278,11 @@ dict_index_print_low( putc('\n', stderr); -/* btr_print_size(tree); */ +#ifdef UNIV_BTR_PRINT + btr_print_size(tree); -/* btr_print_tree(tree, 7); */ + btr_print_tree(tree, 7); +#endif /* UNIV_BTR_PRINT */ } /************************************************************************** diff --git a/storage/innobase/dict/dict0mem.c b/storage/innobase/dict/dict0mem.c index 48b9f28d292..eec35310039 100644 --- a/storage/innobase/dict/dict0mem.c +++ b/storage/innobase/dict/dict0mem.c @@ -42,6 +42,7 @@ dict_mem_table_create( mem_heap_t* heap; ut_ad(name); + ut_ad(comp == FALSE || comp == TRUE); heap = mem_heap_create(DICT_HEAP_SIZE); diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index 8600f583dbd..299b55f3d2b 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -99,7 +99,6 @@ ulint fil_n_pending_tablespace_flushes = 0; fil_addr_t fil_addr_null = {FIL_NULL, 0}; /* File node of a tablespace or the log data space */ -typedef struct fil_node_struct fil_node_t; struct fil_node_struct { fil_space_t* space; /* backpointer to the space where this node belongs */ @@ -4046,7 +4045,7 @@ fil_aio_wait( } else { srv_set_io_thread_op_info(segment, "simulated aio handle"); - ret = os_aio_simulated_handle(segment, (void**) &fil_node, + ret = os_aio_simulated_handle(segment, &fil_node, &message, &type); } diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c index ef8e70646c6..ad4228f6797 100644 --- a/storage/innobase/fsp/fsp0fsp.c +++ b/storage/innobase/fsp/fsp0fsp.c @@ -2325,7 +2325,6 @@ fseg_alloc_free_page_low( dulint seg_id; ulint used; ulint reserved; - fil_addr_t first; xdes_t* descr; /* extent of the hinted page */ ulint ret_page; /* the allocated page offset, FIL_NULL if could not be allocated */ @@ -2428,6 +2427,8 @@ fseg_alloc_free_page_low( } else if (reserved - used > 0) { /* 5. We take any unused page from the segment ==============================================*/ + fil_addr_t first; + if (flst_get_len(seg_inode + FSEG_NOT_FULL, mtr) > 0) { first = flst_get_first(seg_inode + FSEG_NOT_FULL, mtr); @@ -2435,6 +2436,7 @@ fseg_alloc_free_page_low( first = flst_get_first(seg_inode + FSEG_FREE, mtr); } else { ut_error; + return(FIL_NULL); } ret_descr = xdes_lst_get_descriptor(space, first, mtr); diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index 5ad61e2590f..712d43f916c 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -1889,7 +1889,7 @@ ibuf_get_merge_page_nos( contract the tree, FALSE if this is called when a single page becomes full and we look if it pays to read also nearby pages */ - rec_t* first_rec,/* in: record from which we read up and down + rec_t* rec, /* in: record from which we read up and down in the chain of records */ ulint* space_ids,/* in/out: space id's of the pages */ ib_longlong* space_versions,/* in/out: tablespace version @@ -1907,47 +1907,42 @@ ibuf_get_merge_page_nos( ulint first_space_id; ulint rec_page_no; ulint rec_space_id; - rec_t* rec; ulint sum_volumes; ulint volume_for_page; ulint rec_volume; ulint limit; - page_t* page; ulint n_pages; *n_stored = 0; limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool->curr_size / 4); - page = buf_frame_align(first_rec); - - if (first_rec == page_get_supremum_rec(page)) { + if (page_rec_is_supremum(rec)) { - first_rec = page_rec_get_prev(first_rec); + rec = page_rec_get_prev(rec); } - if (first_rec == page_get_infimum_rec(page)) { + if (page_rec_is_infimum(rec)) { - first_rec = page_rec_get_next(first_rec); + rec = page_rec_get_next(rec); } - if (first_rec == page_get_supremum_rec(page)) { + if (page_rec_is_supremum(rec)) { return(0); } - rec = first_rec; - first_page_no = ibuf_rec_get_page_no(first_rec); - first_space_id = ibuf_rec_get_space(first_rec); + first_page_no = ibuf_rec_get_page_no(rec); + first_space_id = ibuf_rec_get_space(rec); n_pages = 0; prev_page_no = 0; prev_space_id = 0; - /* Go backwards from the first_rec until we reach the border of the + /* Go backwards from the first rec until we reach the border of the 'merge area', or the page start or the limit of storeable pages is reached */ - while ((rec != page_get_infimum_rec(page)) && (n_pages < limit)) { + while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) { rec_page_no = ibuf_rec_get_page_no(rec); rec_space_id = ibuf_rec_get_space(rec); @@ -1982,7 +1977,7 @@ ibuf_get_merge_page_nos( volume_for_page = 0; while (*n_stored < limit) { - if (rec == page_get_supremum_rec(page)) { + if (page_rec_is_supremum(rec)) { /* When no more records available, mark this with another 'impossible' pair of space id, page no */ rec_page_no = 1; @@ -2311,12 +2306,12 @@ ibuf_get_volume_buffered( page = buf_frame_align(rec); - if (rec == page_get_supremum_rec(page)) { + if (page_rec_is_supremum(rec)) { rec = page_rec_get_prev(rec); } for (;;) { - if (rec == page_get_infimum_rec(page)) { + if (page_rec_is_infimum(rec)) { break; } @@ -2351,7 +2346,7 @@ ibuf_get_volume_buffered( rec = page_rec_get_prev(rec); for (;;) { - if (rec == page_get_infimum_rec(prev_page)) { + if (page_rec_is_infimum(rec)) { /* We cannot go to yet a previous page, because we do not have the x-latch on it, and cannot acquire one @@ -2374,12 +2369,12 @@ ibuf_get_volume_buffered( count_later: rec = btr_pcur_get_rec(pcur); - if (rec != page_get_supremum_rec(page)) { + if (!page_rec_is_supremum(rec)) { rec = page_rec_get_next(rec); } for (;;) { - if (rec == page_get_supremum_rec(page)) { + if (page_rec_is_supremum(rec)) { break; } @@ -2414,7 +2409,7 @@ count_later: rec = page_rec_get_next(rec); for (;;) { - if (rec == page_get_supremum_rec(next_page)) { + if (page_rec_is_supremum(rec)) { /* We give up */ @@ -2815,7 +2810,7 @@ ibuf_insert_to_index_page( ut_ad(ibuf_inside()); ut_ad(dtuple_check_typed(entry)); - if (index->table->comp != page_is_comp(page)) { + if (UNIV_UNLIKELY(index->table->comp != !!page_is_comp(page))) { fputs( "InnoDB: Trying to insert a record from the insert buffer to an index page\n" "InnoDB: but the 'compact' flag does not match!\n", stderr); @@ -2824,7 +2819,8 @@ ibuf_insert_to_index_page( rec = page_rec_get_next(page_get_infimum_rec(page)); - if (rec_get_n_fields(rec, index) != dtuple_get_n_fields(entry)) { + if (UNIV_UNLIKELY(rec_get_n_fields(rec, index) + != dtuple_get_n_fields(entry))) { fputs( "InnoDB: Trying to insert a record from the insert buffer to an index page\n" "InnoDB: but the number of fields does not match!\n", stderr); @@ -2848,7 +2844,7 @@ ibuf_insert_to_index_page( if (low_match == dtuple_get_n_fields(entry)) { rec = page_cur_get_rec(&page_cur); - btr_cur_del_unmark_for_ibuf(rec, index, mtr); + btr_cur_del_unmark_for_ibuf(rec, mtr); } else { rec = page_cur_tuple_insert(&page_cur, entry, index, mtr); @@ -2861,8 +2857,8 @@ ibuf_insert_to_index_page( PAGE_CUR_LE, &page_cur); /* This time the record must fit */ - if (!page_cur_tuple_insert(&page_cur, entry, - index, mtr)) { + if (UNIV_UNLIKELY(!page_cur_tuple_insert( + &page_cur, entry, index, mtr))) { ut_print_timestamp(stderr); @@ -2969,7 +2965,9 @@ ibuf_delete_rec( btr_pcur_commit_specify_mtr(pcur, mtr); fputs("InnoDB: Validating insert buffer tree:\n", stderr); - ut_a(btr_validate_tree(ibuf_data->index->tree)); + if (!btr_validate_tree(ibuf_data->index->tree, NULL)) { + ut_error; + } fprintf(stderr, "InnoDB: ibuf tree ok\n"); fflush(stderr); diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index 0b19e64d4e0..1f3a32fa70c 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -168,7 +168,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 */ /**************************************************************** Frees a B-tree except the root page, which MUST be freed after this @@ -276,7 +276,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 */ /***************************************************************** Deletes on the upper level the node pointer to a page. */ @@ -336,7 +336,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 */ /*************************************************************** @@ -398,6 +398,7 @@ btr_page_free_low( page_t* page, /* in: page to be freed, x-latched */ ulint level, /* in: page level */ mtr_t* mtr); /* in: mtr */ +#ifdef UNIV_BTR_PRINT /***************************************************************** Prints size info of a B-tree. */ @@ -414,6 +415,7 @@ btr_print_tree( dict_tree_t* tree, /* in: tree */ ulint width); /* in: print this many entries from start and end */ +#endif /* UNIV_BTR_PRINT */ /**************************************************************** Checks the size and number of fields in a record based on the definition of the index. */ @@ -434,7 +436,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 */ #define BTR_N_LEAF_PAGES 1 #define BTR_TOTAL_SIZE 2 diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic index 1d1f97d3668..a0860b1c3a7 100644 --- a/storage/innobase/include/btr0btr.ic +++ b/storage/innobase/include/btr0btr.ic @@ -200,10 +200,10 @@ btr_node_ptr_get_child_page_no( page_no = mach_read_from_4(field); - if (page_no == 0) { + if (UNIV_UNLIKELY(page_no == 0)) { fprintf(stderr, "InnoDB: a nonsensical page number 0 in a node ptr record at offset %lu\n", - (unsigned long)(rec - buf_frame_align(rec))); + (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE)); buf_page_print(buf_frame_align(rec)); } diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index 0a8d8ceaeb7..352d1739b6a 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -284,7 +284,6 @@ 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 */ /***************************************************************** Tries to compress a page of the tree on the leaf level. It is assumed @@ -389,7 +388,6 @@ 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: index corresponding to page */ page_t* page); /* in: page or NULL */ /*********************************************************************** Estimates the number of rows in a given index range. */ diff --git a/storage/innobase/include/btr0cur.ic b/storage/innobase/include/btr0cur.ic index dcad3e9e14d..bf8a6efb68d 100644 --- a/storage/innobase/include/btr0cur.ic +++ b/storage/innobase/include/btr0cur.ic @@ -52,7 +52,9 @@ btr_cur_get_page( /* out: pointer to page */ btr_cur_t* cursor) /* in: tree cursor */ { - return(buf_frame_align(page_cur_get_rec(&(cursor->page_cur)))); + page_t* page = buf_frame_align(page_cur_get_rec(&(cursor->page_cur))); + ut_ad(!!page_is_comp(page) == cursor->index->table->comp); + return(page); } /************************************************************* diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 5ee323f1b1e..ae8d0411c12 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -56,9 +56,11 @@ Created 11/5/1995 Heikki Tuuri #define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL extern buf_pool_t* buf_pool; /* The buffer pool of the database */ +#ifdef UNIV_DEBUG extern ibool buf_debug_prints;/* If this is set TRUE, the program prints info whenever read or flush occurs */ +#endif /* UNIV_DEBUG */ extern ulint srv_buf_pool_write_requests; /* variable to count write request issued */ @@ -382,10 +384,10 @@ Returns the value of the modify clock. The caller must have an s-lock or x-lock on the block. */ UNIV_INLINE dulint -buf_frame_get_modify_clock( +buf_block_get_modify_clock( /*=======================*/ /* out: value */ - buf_frame_t* frame); /* in: pointer to a frame */ + buf_block_t* block); /* in: block */ /************************************************************************ Calculates a page checksum which is stored to the page when it is written to a file. Note that we must be careful to calculate the same value @@ -480,12 +482,20 @@ buf_pool_is_block( /*==============*/ /* out: TRUE if pointer to block */ void* ptr); /* in: pointer to memory */ +#ifdef UNIV_DEBUG /************************************************************************* Validates the buffer pool data structure. */ ibool buf_validate(void); /*==============*/ +/************************************************************************* +Prints info of the buffer pool data structure. */ + +void +buf_print(void); +/*============*/ +#endif /* UNIV_DEBUG */ /************************************************************************ Prints a page to stderr. */ @@ -494,12 +504,6 @@ buf_page_print( /*===========*/ byte* read_buf); /* in: a database page */ /************************************************************************* -Prints info of the buffer pool data structure. */ - -void -buf_print(void); -/*============*/ -/************************************************************************* Returns the number of latched pages in the buffer pool. */ ulint diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index 681a0ef000a..d949254d47d 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -11,10 +11,11 @@ Created 11/5/1995 Heikki Tuuri #include "buf0rea.h" #include "mtr0mtr.h" +#ifdef UNIV_DEBUG extern ulint buf_dbg_counter; /* This is used to insert validation operations in execution in the debug version */ - +#endif /* UNIV_DEBUG */ /************************************************************************ Recommends a move of a block to the start of the LRU list if there is danger of dropping from the buffer pool. NOTE: does not reserve the buffer pool @@ -26,12 +27,8 @@ buf_block_peek_if_too_old( /* out: TRUE if should be made younger */ buf_block_t* block) /* in: block to make younger */ { - if (buf_pool->freed_page_clock >= block->freed_page_clock - + 1 + (buf_pool->curr_size / 1024)) { - return(TRUE); - } - - return(FALSE); + return(buf_pool->freed_page_clock >= block->freed_page_clock + + 1 + (buf_pool->curr_size / 1024)); } /************************************************************************* @@ -210,8 +207,8 @@ buf_block_align( frame_zero = buf_pool->frame_zero; - if ((ulint)ptr < (ulint)frame_zero - || (ulint)ptr > (ulint)(buf_pool->high_end)) { + if (UNIV_UNLIKELY((ulint)ptr < (ulint)frame_zero) + || UNIV_UNLIKELY((ulint)ptr > (ulint)(buf_pool->high_end))) { ut_print_timestamp(stderr); fprintf(stderr, @@ -246,8 +243,8 @@ buf_frame_align( frame = ut_align_down(ptr, UNIV_PAGE_SIZE); - if (((ulint)frame < (ulint)(buf_pool->frame_zero)) - || (ulint)frame >= (ulint)(buf_pool->high_end)) { + if (UNIV_UNLIKELY((ulint)frame < (ulint)(buf_pool->frame_zero)) + || UNIV_UNLIKELY((ulint)frame >= (ulint)(buf_pool->high_end))) { ut_print_timestamp(stderr); fprintf(stderr, @@ -485,17 +482,11 @@ Returns the value of the modify clock. The caller must have an s-lock or x-lock on the block. */ UNIV_INLINE dulint -buf_frame_get_modify_clock( +buf_block_get_modify_clock( /*=======================*/ /* out: value */ - buf_frame_t* frame) /* in: pointer to a frame */ + buf_block_t* block) /* in: block */ { - buf_block_t* block; - - ut_ad(frame); - - block = buf_block_align(frame); - #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED) || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE)); diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h index 45164dd561e..fb29b44ba98 100644 --- a/storage/innobase/include/buf0lru.h +++ b/storage/innobase/include/buf0lru.h @@ -122,6 +122,7 @@ void buf_LRU_make_block_old( /*===================*/ buf_block_t* block); /* in: control block */ +#ifdef UNIV_DEBUG /************************************************************************** Validates the LRU list. */ @@ -134,6 +135,7 @@ Prints the LRU list. */ void buf_LRU_print(void); /*===============*/ +#endif /* UNIV_DEBUG */ #ifndef UNIV_NONINL #include "buf0lru.ic" diff --git a/storage/innobase/include/data0type.h b/storage/innobase/include/data0type.h index a4d2c1a2e1d..7e9692eca5a 100644 --- a/storage/innobase/include/data0type.h +++ b/storage/innobase/include/data0type.h @@ -12,7 +12,7 @@ Created 1/16/1996 Heikki Tuuri #include "univ.i" extern ulint data_mysql_default_charset_coll; -extern ulint data_mysql_latin1_swedish_charset_coll; +#define DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL 8 /* SQL data type struct */ typedef struct dtype_struct dtype_t; diff --git a/storage/innobase/include/data0type.ic b/storage/innobase/include/data0type.ic index a87a08ca582..06d45dd5501 100644 --- a/storage/innobase/include/data0type.ic +++ b/storage/innobase/include/data0type.ic @@ -388,8 +388,8 @@ dtype_get_fixed_size( dtype_get_charset_coll(type->prtype), &mbminlen, &mbmaxlen); - if (type->mbminlen != mbminlen - || type->mbmaxlen != mbmaxlen) { + if (UNIV_UNLIKELY(type->mbminlen != mbminlen) + || UNIV_UNLIKELY(type->mbmaxlen != mbmaxlen)) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: " diff --git a/storage/innobase/include/dyn0dyn.h b/storage/innobase/include/dyn0dyn.h index abee62300e3..1df976a5301 100644 --- a/storage/innobase/include/dyn0dyn.h +++ b/storage/innobase/include/dyn0dyn.h @@ -132,7 +132,7 @@ void dyn_push_string( /*============*/ dyn_array_t* arr, /* in: dyn array */ - byte* str, /* in: string to write */ + const byte* str, /* in: string to write */ ulint len); /* in: string length */ /*#################################################################*/ diff --git a/storage/innobase/include/dyn0dyn.ic b/storage/innobase/include/dyn0dyn.ic index b6c4808398b..c1b8f2cb8ce 100644 --- a/storage/innobase/include/dyn0dyn.ic +++ b/storage/innobase/include/dyn0dyn.ic @@ -324,10 +324,9 @@ void dyn_push_string( /*============*/ dyn_array_t* arr, /* in: dyn array */ - byte* str, /* in: string to write */ + const byte* str, /* in: string to write */ ulint len) /* in: string length */ { - byte* ptr; ulint n_copied; while (len > 0) { @@ -337,9 +336,7 @@ dyn_push_string( n_copied = len; } - ptr = (byte*) dyn_array_push(arr, n_copied); - - ut_memcpy(ptr, str, n_copied); + memcpy(dyn_array_push(arr, n_copied), str, n_copied); str += n_copied; len -= n_copied; diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 45a81a4ac77..20b1f1d7145 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -19,7 +19,9 @@ Created 5/7/1996 Heikki Tuuri #include "read0types.h" #include "hash0hash.h" +#ifdef UNIV_DEBUG extern ibool lock_print_waits; +#endif /* UNIV_DEBUG */ /* Buffer for storing information about the most recent deadlock error */ extern FILE* lock_latest_err_file; @@ -216,6 +218,7 @@ actual record is being moved. */ void lock_rec_store_on_page_infimum( /*===========================*/ + page_t* page, /* in: page containing the record */ rec_t* rec); /* in: record whose lock state is stored on the infimum record of the same page; lock bits are reset on the record */ @@ -412,9 +415,7 @@ lock_table( /* out: DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, - does nothing; - if LOCK_TABLE_EXP bits are set, - creates an explicit table lock */ + does nothing */ dict_table_t* table, /* in: database table in dictionary cache */ ulint mode, /* in: lock mode */ que_thr_t* thr); /* in: query thread */ @@ -451,15 +452,6 @@ lock_release_off_kernel( /*====================*/ trx_t* trx); /* in: transaction */ /************************************************************************* -Releases table locks explicitly requested with LOCK TABLES (indicated by -lock type LOCK_TABLE_EXP), and releases possible other transactions waiting -because of these locks. */ - -void -lock_release_tables_off_kernel( -/*===========================*/ - trx_t* trx); /* in: transaction */ -/************************************************************************* Cancels a waiting lock request and releases possible other transactions waiting behind it. */ @@ -618,9 +610,6 @@ extern lock_sys_t* lock_sys; /* Lock types */ #define LOCK_TABLE 16 /* these type values should be so high that */ #define LOCK_REC 32 /* they can be ORed to the lock mode */ -#define LOCK_TABLE_EXP 80 /* explicit table lock (80 = 16 + 64) */ -#define LOCK_TABLE_TRANSACTIONAL 144 - /* transactional table lock (144 = 16 + 128)*/ #define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the type_mode field in a lock */ /* Waiting lock flag */ diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index d14a116072d..7f3f10438b4 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -17,8 +17,12 @@ Created 12/9/1995 Heikki Tuuri typedef struct log_struct log_t; typedef struct log_group_struct log_group_t; +#ifdef UNIV_DEBUG extern ibool log_do_write; extern ibool log_debug_writes; +#else /* UNIV_DEBUG */ +# define log_do_write TRUE +#endif /* UNIV_DEBUG */ /* Wait modes for log_write_up_to */ #define LOG_NO_WAIT 91 diff --git a/storage/innobase/include/mach0data.h b/storage/innobase/include/mach0data.h index 7ad760cd60f..f9a3ff521d5 100644 --- a/storage/innobase/include/mach0data.h +++ b/storage/innobase/include/mach0data.h @@ -52,6 +52,27 @@ mach_read_from_2( /*=============*/ /* out: ulint integer, >= 0, < 64k */ byte* b); /* in: pointer to two bytes */ + +/************************************************************ +The following function is used to convert a 16-bit data item +to the canonical format, for fast bytewise equality test +against memory. */ +UNIV_INLINE +uint16 +mach_encode_2( +/*==========*/ + /* out: 16-bit integer in canonical format */ + ulint n); /* in: integer in machine-dependent format */ +/************************************************************ +The following function is used to convert a 16-bit data item +from the canonical format, for fast bytewise equality test +against memory. */ +UNIV_INLINE +ulint +mach_decode_2( +/*==========*/ + /* out: integer in machine-dependent format */ + uint16 n); /* in: 16-bit integer in canonical format */ /*********************************************************** The following function is used to store data in 3 consecutive bytes. We store the most significant byte to the lowest address. */ diff --git a/storage/innobase/include/mach0data.ic b/storage/innobase/include/mach0data.ic index 3ffb9baa344..888f3f743e4 100644 --- a/storage/innobase/include/mach0data.ic +++ b/storage/innobase/include/mach0data.ic @@ -68,6 +68,37 @@ mach_read_from_2( ); } +/************************************************************ +The following function is used to convert a 16-bit data item +to the canonical format, for fast bytewise equality test +against memory. */ +UNIV_INLINE +uint16 +mach_encode_2( +/*==========*/ + /* out: 16-bit integer in canonical format */ + ulint n) /* in: integer in machine-dependent format */ +{ + uint16 ret; + ut_ad(2 == sizeof ret); + mach_write_to_2((byte*) &ret, n); + return(ret); +} +/************************************************************ +The following function is used to convert a 16-bit data item +from the canonical format, for fast bytewise equality test +against memory. */ +UNIV_INLINE +ulint +mach_decode_2( +/*==========*/ + /* out: integer in machine-dependent format */ + uint16 n) /* in: 16-bit integer in canonical format */ +{ + ut_ad(2 == sizeof n); + return(mach_read_from_2((byte*) &n)); +} + /*********************************************************** The following function is used to store data in 3 consecutive bytes. We store the most significant byte to the lowest address. */ diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic index 82d88099c3f..8c87c884d78 100644 --- a/storage/innobase/include/mem0mem.ic +++ b/storage/innobase/include/mem0mem.ic @@ -623,7 +623,7 @@ mem_strdupq( } *d++ = q; *d++ = '\0'; - ut_ad(len == d - dst); + ut_ad((ssize_t) len == d - dst); return(dst); } diff --git a/storage/innobase/include/mtr0log.h b/storage/innobase/include/mtr0log.h index c0636ea1e1e..6a3920aa8a1 100644 --- a/storage/innobase/include/mtr0log.h +++ b/storage/innobase/include/mtr0log.h @@ -41,10 +41,10 @@ corresponding log record to the mini-transaction log. */ void mlog_write_string( /*==============*/ - byte* ptr, /* in: pointer where to write */ - byte* str, /* in: string to write */ - ulint len, /* in: string length */ - mtr_t* mtr); /* in: mini-transaction handle */ + byte* ptr, /* in: pointer where to write */ + const byte* str, /* in: string to write */ + ulint len, /* in: string length */ + mtr_t* mtr); /* in: mini-transaction handle */ /************************************************************ Writes initial part of a log record consisting of one-byte item type and four-byte space and page numbers. */ @@ -85,9 +85,9 @@ Catenates n bytes to the mtr log. */ void mlog_catenate_string( /*=================*/ - mtr_t* mtr, /* in: mtr */ - byte* str, /* in: string to write */ - ulint len); /* in: string length */ + mtr_t* mtr, /* in: mtr */ + const byte* str, /* in: string to write */ + ulint len); /* in: string length */ /************************************************************ Catenates a compressed ulint to mlog. */ UNIV_INLINE diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 071279d5259..f44e813cf6b 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -112,7 +112,11 @@ flag value must give the length also! */ /* mark compact clustered index record deleted */ #define MLOG_COMP_REC_SEC_DELETE_MARK ((byte)40)/* mark compact secondary index - record deleted */ + record deleted; this log + record type is redundant, as + MLOG_REC_SEC_DELETE_MARK is + independent of the record + format. */ #define MLOG_COMP_REC_UPDATE_IN_PLACE ((byte)41)/* update of a compact record, preserves record field sizes */ #define MLOG_COMP_REC_DELETE ((byte)42) /* delete a compact record diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index f55c345537e..e75281dd93c 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -17,6 +17,8 @@ Created 10/21/1995 Heikki Tuuri #include <time.h> #endif +typedef struct fil_node_struct fil_node_t; + extern ibool os_do_not_call_flush_at_each_write; extern ibool os_has_said_disk_full; extern ibool os_aio_print_debug; @@ -563,7 +565,7 @@ os_aio( ulint offset_high, /* in: most significant 32 bits of offset */ ulint n, /* in: number of bytes to read or write */ - void* message1,/* in: messages for the aio handler (these + fil_node_t* message1,/* in: messages for the aio handler (these can be used to identify a completed aio operation); if mode is OS_AIO_SYNC, these are ignored */ @@ -621,7 +623,7 @@ os_aio_windows_handle( ignored */ ulint pos, /* this parameter is used only in sync aio: wait for the aio slot at this position */ - void** message1, /* out: the messages passed with the aio + fil_node_t**message1, /* out: the messages passed with the aio request; note that also in the case where the aio operation failed, these output parameters are valid and can be used to @@ -641,7 +643,7 @@ os_aio_posix_handle( /*================*/ /* out: TRUE if the aio operation succeeded */ ulint array_no, /* in: array number 0 - 3 */ - void** message1, /* out: the messages passed with the aio + fil_node_t**message1, /* out: the messages passed with the aio request; note that also in the case where the aio operation failed, these output parameters are valid and can be used to @@ -661,7 +663,7 @@ os_aio_simulated_handle( i/o thread, segment 1 the log i/o thread, then follow the non-ibuf read threads, and as the last are the non-ibuf write threads */ - void** message1, /* out: the messages passed with the aio + fil_node_t**message1, /* out: the messages passed with the aio request; note that also in the case where the aio operation failed, these output parameters are valid and can be used to @@ -688,6 +690,8 @@ Refreshes the statistics used to print per-second averages. */ void os_aio_refresh_stats(void); /*======================*/ + +#ifdef UNIV_DEBUG /************************************************************************** Checks that all slots in the system have been freed, that is, there are no pending io operations. */ @@ -695,6 +699,7 @@ no pending io operations. */ ibool os_aio_all_slots_free(void); /*=======================*/ +#endif /* UNIV_DEBUG */ /*********************************************************************** This function returns information about the specified file */ diff --git a/storage/innobase/include/page0cur.h b/storage/innobase/include/page0cur.h index 4fc62f37db7..e89e740e775 100644 --- a/storage/innobase/include/page0cur.h +++ b/storage/innobase/include/page0cur.h @@ -78,16 +78,16 @@ UNIV_INLINE ibool page_cur_is_before_first( /*=====================*/ - /* out: TRUE if at start */ - page_cur_t* cur); /* in: cursor */ + /* out: TRUE if at start */ + const page_cur_t* cur); /* in: cursor */ /************************************************************* Returns TRUE if the cursor is after last user record. */ UNIV_INLINE ibool page_cur_is_after_last( /*===================*/ - /* out: TRUE if at end */ - page_cur_t* cur); /* in: cursor */ + /* out: TRUE if at end */ + const page_cur_t* cur); /* in: cursor */ /************************************************************** Positions the cursor on the given record. */ UNIV_INLINE diff --git a/storage/innobase/include/page0cur.ic b/storage/innobase/include/page0cur.ic index e99d799b372..f8346819e84 100644 --- a/storage/innobase/include/page0cur.ic +++ b/storage/innobase/include/page0cur.ic @@ -69,15 +69,10 @@ UNIV_INLINE ibool page_cur_is_before_first( /*=====================*/ - /* out: TRUE if at start */ - page_cur_t* cur) /* in: cursor */ + /* out: TRUE if at start */ + const page_cur_t* cur) /* in: cursor */ { - if (page_get_infimum_rec(page_cur_get_page(cur)) == cur->rec) { - - return(TRUE); - } - - return(FALSE); + return(page_rec_is_infimum(cur->rec)); } /************************************************************* @@ -86,15 +81,10 @@ UNIV_INLINE ibool page_cur_is_after_last( /*===================*/ - /* out: TRUE if at end */ - page_cur_t* cur) /* in: cursor */ + /* out: TRUE if at end */ + const page_cur_t* cur) /* in: cursor */ { - if (page_get_supremum_rec(page_cur_get_page(cur)) == cur->rec) { - - return(TRUE); - } - - return(FALSE); + return(page_rec_is_supremum(cur->rec)); } /************************************************************** diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index 144c297b811..c4ffa39d3ac 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -373,13 +373,21 @@ page_dir_find_owner_slot( /**************************************************************** Determine whether the page is in new-style compact format. */ UNIV_INLINE -ibool +ulint page_is_comp( /*=========*/ - /* out: TRUE if the page is in compact format - FALSE if it is in old-style format */ + /* out: nonzero if the page is in compact + format, zero if it is in old-style format */ page_t* page); /* in: index page */ /**************************************************************** +TRUE if the record is on a page in compact format. */ +UNIV_INLINE +ulint +page_rec_is_comp( +/*=============*/ + /* out: nonzero if in compact format */ + const rec_t* rec); /* in: record */ +/**************************************************************** Gets the pointer to the next record on the page. */ UNIV_INLINE rec_t* @@ -407,47 +415,55 @@ page_rec_get_prev( /* out: pointer to previous record */ rec_t* rec); /* in: pointer to record, must not be page infimum */ - /**************************************************************** TRUE if the record is a user record on the page. */ UNIV_INLINE ibool -page_rec_is_user_rec( -/*=================*/ +page_rec_is_user_rec_low( +/*=====================*/ /* out: TRUE if a user record */ - rec_t* rec); /* in: record */ + ulint offset);/* in: record offset on page */ /**************************************************************** TRUE if the record is the supremum record on a page. */ UNIV_INLINE ibool -page_rec_is_supremum( -/*=================*/ +page_rec_is_supremum_low( +/*=====================*/ /* out: TRUE if the supremum record */ - rec_t* rec); /* in: record */ + ulint offset);/* in: record offset on page */ /**************************************************************** TRUE if the record is the infimum record on a page. */ UNIV_INLINE ibool -page_rec_is_infimum( -/*================*/ +page_rec_is_infimum_low( +/*=====================*/ /* out: TRUE if the infimum record */ - rec_t* rec); /* in: record */ + ulint offset);/* in: record offset on page */ + /**************************************************************** -TRUE if the record is the first user record on the page. */ +TRUE if the record is a user record on the page. */ UNIV_INLINE ibool -page_rec_is_first_user_rec( -/*=======================*/ - /* out: TRUE if first user record */ - rec_t* rec); /* in: record */ +page_rec_is_user_rec( +/*=================*/ + /* out: TRUE if a user record */ + const rec_t* rec); /* in: record */ /**************************************************************** -TRUE if the record is the last user record on the page. */ +TRUE if the record is the supremum record on a page. */ UNIV_INLINE ibool -page_rec_is_last_user_rec( -/*======================*/ - /* out: TRUE if last user record */ - rec_t* rec); /* in: record */ +page_rec_is_supremum( +/*=================*/ + /* out: TRUE if the supremum record */ + const rec_t* rec); /* in: record */ +/**************************************************************** +TRUE if the record is the infimum record on a page. */ +UNIV_INLINE +ibool +page_rec_is_infimum( +/*================*/ + /* out: TRUE if the infimum record */ + const rec_t* rec); /* in: record */ /******************************************************************* Looks for the record which owns the given record. */ UNIV_INLINE @@ -495,7 +511,7 @@ ulint page_get_free_space_of_empty( /*=========================*/ /* out: free space */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ __attribute__((const)); /**************************************************************** Returns the sum of the sizes of the records in the record list @@ -539,7 +555,7 @@ page_create( buf_frame_t* frame, /* in: a buffer frame where the page is created */ mtr_t* mtr, /* in: mini-transaction handle */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /***************************************************************** Differs from page_copy_rec_list_end, because this function does not touch the lock table and max trx id on page. */ @@ -673,7 +689,7 @@ page_parse_create( /* 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 */ /**************************************************************** diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index bc0805ca30c..fd5281fdbec 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -155,14 +155,27 @@ page_header_reset_last_insert( /**************************************************************** Determine whether the page is in new-style compact format. */ UNIV_INLINE -ibool +ulint page_is_comp( /*=========*/ - /* out: TRUE if the page is in compact format - FALSE if it is in old-style format */ - page_t* page) /* in: index page */ + /* out: nonzero if the page is in compact + format, zero if it is in old-style format */ + page_t* page) /* in: index page */ +{ + return(UNIV_EXPECT(page_header_get_field(page, PAGE_N_HEAP) & 0x8000, + 0x8000)); +} + +/**************************************************************** +TRUE if the record is on a page in compact format. */ +UNIV_INLINE +ulint +page_rec_is_comp( +/*=============*/ + /* out: nonzero if in compact format */ + const rec_t* rec) /* in: record */ { - return(!!(page_header_get_field(page, PAGE_N_HEAP) & 0x8000)); + return(page_is_comp(ut_align_down((rec_t*) rec, UNIV_PAGE_SIZE))); } /**************************************************************** @@ -205,112 +218,107 @@ page_get_supremum_rec( TRUE if the record is a user record on the page. */ UNIV_INLINE ibool -page_rec_is_user_rec( -/*=================*/ +page_rec_is_user_rec_low( +/*=====================*/ /* out: TRUE if a user record */ - rec_t* rec) /* in: record */ + ulint offset) /* in: record offset on page */ { - ut_ad(rec); - - if (rec == page_get_supremum_rec(buf_frame_align(rec))) { - - return(FALSE); - } - - if (rec == page_get_infimum_rec(buf_frame_align(rec))) { - - return(FALSE); - } + ut_ad(offset >= PAGE_NEW_INFIMUM); +#if PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM +# error "PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM" +#endif +#if PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM +# error "PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM" +#endif +#if PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM +# error "PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM" +#endif +#if PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM +# error "PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM" +#endif +#if PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END +# error "PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END" +#endif +#if PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END +# error "PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END" +#endif + ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START); - return(TRUE); + return(UNIV_LIKELY(offset != PAGE_NEW_SUPREMUM) + && UNIV_LIKELY(offset != PAGE_NEW_INFIMUM) + && UNIV_LIKELY(offset != PAGE_OLD_INFIMUM) + && UNIV_LIKELY(offset != PAGE_OLD_SUPREMUM)); } /**************************************************************** TRUE if the record is the supremum record on a page. */ UNIV_INLINE ibool -page_rec_is_supremum( -/*=================*/ +page_rec_is_supremum_low( +/*=====================*/ /* out: TRUE if the supremum record */ - rec_t* rec) /* in: record */ + ulint offset) /* in: record offset on page */ { - ut_ad(rec); + ut_ad(offset >= PAGE_NEW_INFIMUM); + ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START); - if (rec == page_get_supremum_rec(buf_frame_align(rec))) { - - return(TRUE); - } - - return(FALSE); + return(UNIV_UNLIKELY(offset == PAGE_NEW_SUPREMUM) + || UNIV_UNLIKELY(offset == PAGE_OLD_SUPREMUM)); } /**************************************************************** TRUE if the record is the infimum record on a page. */ UNIV_INLINE ibool -page_rec_is_infimum( -/*================*/ +page_rec_is_infimum_low( +/*=====================*/ /* out: TRUE if the infimum record */ - rec_t* rec) /* in: record */ + ulint offset) /* in: record offset on page */ { - ut_ad(rec); - - if (rec == page_get_infimum_rec(buf_frame_align(rec))) { - - return(TRUE); - } + ut_ad(offset >= PAGE_NEW_INFIMUM); + ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START); - return(FALSE); + return(UNIV_UNLIKELY(offset == PAGE_NEW_INFIMUM) + || UNIV_UNLIKELY(offset == PAGE_OLD_INFIMUM)); } /**************************************************************** -TRUE if the record is the first user record on the page. */ +TRUE if the record is a user record on the page. */ UNIV_INLINE ibool -page_rec_is_first_user_rec( -/*=======================*/ - /* out: TRUE if first user record */ - rec_t* rec) /* in: record */ +page_rec_is_user_rec( +/*=================*/ + /* out: TRUE if a user record */ + const rec_t* rec) /* in: record */ { - ut_ad(rec); - - if (rec == page_get_supremum_rec(buf_frame_align(rec))) { - - return(FALSE); - } - - if (rec == page_rec_get_next( - page_get_infimum_rec(buf_frame_align(rec)))) { - - return(TRUE); - } - - return(FALSE); + return(page_rec_is_user_rec_low( + ut_align_offset(rec, UNIV_PAGE_SIZE))); } /**************************************************************** -TRUE if the record is the last user record on the page. */ +TRUE if the record is the supremum record on a page. */ UNIV_INLINE ibool -page_rec_is_last_user_rec( -/*======================*/ - /* out: TRUE if last user record */ - rec_t* rec) /* in: record */ +page_rec_is_supremum( +/*=================*/ + /* out: TRUE if the supremum record */ + const rec_t* rec) /* in: record */ { - ut_ad(rec); - - if (rec == page_get_supremum_rec(buf_frame_align(rec))) { - - return(FALSE); - } - - if (page_rec_get_next(rec) - == page_get_supremum_rec(buf_frame_align(rec))) { - - return(TRUE); - } + return(page_rec_is_supremum_low( + ut_align_offset(rec, UNIV_PAGE_SIZE))); +} - return(FALSE); +/**************************************************************** +TRUE if the record is the infimum record on a page. */ +UNIV_INLINE +ibool +page_rec_is_infimum( +/*================*/ + /* out: TRUE if the infimum record */ + const rec_t* rec) /* in: record */ +{ + return(page_rec_is_infimum_low( + ut_align_offset(rec, UNIV_PAGE_SIZE))); } /***************************************************************** @@ -340,22 +348,26 @@ page_cmp_dtuple_rec_with_match( matched; when function returns contains the value for current comparison */ { - page_t* page; + ulint rec_offset; ut_ad(dtuple_check_typed(dtuple)); ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(!rec_offs_comp(offsets) == !page_rec_is_comp(rec)); - page = buf_frame_align(rec); + rec_offset = ut_align_offset(rec, UNIV_PAGE_SIZE); - if (rec == page_get_infimum_rec(page)) { + if (UNIV_UNLIKELY(rec_offset == PAGE_NEW_INFIMUM) + || UNIV_UNLIKELY(rec_offset == PAGE_OLD_INFIMUM)) { return(1); - } else if (rec == page_get_supremum_rec(page)) { + } + if (UNIV_UNLIKELY(rec_offset == PAGE_NEW_SUPREMUM) + || UNIV_UNLIKELY(rec_offset == PAGE_OLD_SUPREMUM)) { return(-1); - } else { - return(cmp_dtuple_rec_with_match(dtuple, rec, offsets, + } + + return(cmp_dtuple_rec_with_match(dtuple, rec, offsets, matched_fields, matched_bytes)); - } } /***************************************************************** @@ -482,7 +494,7 @@ page_dir_slot_set_rec( { ut_ad(page_rec_check(rec)); - mach_write_to_2(slot, rec - buf_frame_align(rec)); + mach_write_to_2(slot, ut_align_offset(rec, UNIV_PAGE_SIZE)); } /******************************************************************* @@ -494,8 +506,8 @@ page_dir_slot_get_n_owned( /* out: number of records */ page_dir_slot_t* slot) /* in: page directory slot */ { - return(rec_get_n_owned(page_dir_slot_get_rec(slot), - page_is_comp(buf_frame_align(slot)))); + rec_t* rec = page_dir_slot_get_rec(slot); + return(rec_get_n_owned(rec, page_rec_is_comp(rec))); } /******************************************************************* @@ -508,8 +520,8 @@ page_dir_slot_set_n_owned( ulint n) /* in: number of records owned by the slot */ { - rec_set_n_owned(page_dir_slot_get_rec(slot), - page_is_comp(buf_frame_align(slot)), n); + rec_t* rec = page_dir_slot_get_rec(slot); + rec_set_n_owned(rec, page_rec_is_comp(rec), n); } /**************************************************************** @@ -540,26 +552,25 @@ page_rec_get_next( ut_ad(page_rec_check(rec)); - page = buf_frame_align(rec); + page = ut_align_down(rec, UNIV_PAGE_SIZE); offs = rec_get_next_offs(rec, page_is_comp(page)); - if (offs >= UNIV_PAGE_SIZE) { - fprintf(stderr, -"InnoDB: Next record offset is nonsensical %lu in record at offset %lu\n", - (ulong)offs, (ulong)(rec - page)); + if (UNIV_UNLIKELY(offs >= UNIV_PAGE_SIZE)) { fprintf(stderr, -"\nInnoDB: rec address %p, first buffer frame %p\n" +"InnoDB: Next record offset is nonsensical %lu in record at offset %lu\n" +"InnoDB: rec address %p, first buffer frame %p\n" "InnoDB: buffer pool high end %p, buf fix count %lu\n", + (ulong)offs, (ulong)(rec - page), rec, buf_pool->frame_zero, buf_pool->high_end, (ulong)buf_block_align(rec)->buf_fix_count); buf_page_print(page); - ut_a(0); + ut_error; } - if (offs == 0) { + if (UNIV_UNLIKELY(offs == 0)) { return(NULL); } @@ -581,15 +592,12 @@ page_rec_set_next( ulint offs; ut_ad(page_rec_check(rec)); - ut_a((next == NULL) - || (buf_frame_align(rec) == buf_frame_align(next))); - - page = buf_frame_align(rec); - - ut_ad(rec != page_get_supremum_rec(page)); - ut_ad(next != page_get_infimum_rec(page)); + ut_ad(!page_rec_is_supremum(rec)); + page = ut_align_down(rec, UNIV_PAGE_SIZE); if (next) { + ut_ad(!page_rec_is_infimum(next)); + ut_ad(page == ut_align_down(next, UNIV_PAGE_SIZE)); offs = (ulint) (next - page); } else { offs = 0; @@ -613,13 +621,12 @@ page_rec_get_prev( rec_t* rec2; rec_t* prev_rec = NULL; page_t* page; - ibool comp; ut_ad(page_rec_check(rec)); - page = buf_frame_align(rec); + page = ut_align_down(rec, UNIV_PAGE_SIZE); - ut_ad(rec != page_get_infimum_rec(page)); + ut_ad(!page_rec_is_infimum(rec)); slot_no = page_dir_find_owner_slot(rec); @@ -628,7 +635,6 @@ page_rec_get_prev( slot = page_dir_get_nth_slot(page, slot_no - 1); rec2 = page_dir_slot_get_rec(slot); - comp = page_is_comp(page); while (rec != rec2) { prev_rec = rec2; @@ -649,13 +655,16 @@ page_rec_find_owner_rec( /* out: the owner record */ rec_t* rec) /* in: the physical record */ { - ibool comp; - ut_ad(page_rec_check(rec)); - comp = page_is_comp(buf_frame_align(rec)); - while (rec_get_n_owned(rec, comp) == 0) { - rec = page_rec_get_next(rec); + if (page_rec_is_comp(rec)) { + while (rec_get_n_owned(rec, TRUE) == 0) { + rec = page_rec_get_next(rec); + } + } else { + while (rec_get_n_owned(rec, FALSE) == 0) { + rec = page_rec_get_next(rec); + } } return(rec); @@ -691,10 +700,17 @@ ulint page_get_free_space_of_empty( /*=========================*/ /* out: free space */ - ibool comp) /* in: TRUE=compact page layout */ + ulint comp) /* in: nonzero=compact page layout */ { + if (UNIV_LIKELY(comp)) { + return((ulint)(UNIV_PAGE_SIZE + - PAGE_NEW_SUPREMUM_END + - PAGE_DIR + - 2 * PAGE_DIR_SLOT_SIZE)); + } + return((ulint)(UNIV_PAGE_SIZE - - (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END) + - PAGE_OLD_SUPREMUM_END - PAGE_DIR - 2 * PAGE_DIR_SLOT_SIZE)); } @@ -716,17 +732,21 @@ page_get_max_insert_size( { ulint occupied; ulint free_space; - ibool comp; - comp = page_is_comp(page); + if (page_is_comp(page)) { + occupied = page_header_get_field(page, PAGE_HEAP_TOP) + - PAGE_NEW_SUPREMUM_END + page_dir_calc_reserved_space( + n_recs + page_dir_get_n_heap(page) - 2); - occupied = page_header_get_field(page, PAGE_HEAP_TOP) - - (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END) - + page_dir_calc_reserved_space( + free_space = page_get_free_space_of_empty(TRUE); + } else { + occupied = page_header_get_field(page, PAGE_HEAP_TOP) + - PAGE_OLD_SUPREMUM_END + page_dir_calc_reserved_space( n_recs + page_dir_get_n_heap(page) - 2); - free_space = page_get_free_space_of_empty(comp); - + free_space = page_get_free_space_of_empty(FALSE); + } + /* Above the 'n_recs +' part reserves directory space for the new inserted records; the '- 2' excludes page infimum and supremum records */ @@ -752,14 +772,11 @@ page_get_max_insert_size_after_reorganize( { ulint occupied; ulint free_space; - ibool comp; - comp = page_is_comp(page); - occupied = page_get_data_size(page) + page_dir_calc_reserved_space(n_recs + page_get_n_recs(page)); - free_space = page_get_free_space_of_empty(comp); + free_space = page_get_free_space_of_empty(page_is_comp(page)); if (occupied > free_space) { @@ -783,6 +800,7 @@ page_mem_free( ulint garbage; ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(!rec_offs_comp(offsets) == !page_rec_is_comp(rec)); free = page_header_get_ptr(page, PAGE_FREE); page_rec_set_next(rec, free); diff --git a/storage/innobase/include/read0read.ic b/storage/innobase/include/read0read.ic index 03d84ee0c51..ec9ef5814bb 100644 --- a/storage/innobase/include/read0read.ic +++ b/storage/innobase/include/read0read.ic @@ -71,13 +71,8 @@ read_view_sees_trx_id( cmp = ut_dulint_cmp(trx_id, read_view_get_nth_trx_id(view, n_ids - i - 1)); - if (0 == cmp) { - - return(FALSE); - - } else if (cmp < 0) { - - return(TRUE); + if (cmp <= 0) { + return(cmp < 0); } } diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 134c37c8030..c068f4cb73c 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -51,7 +51,7 @@ rec_get_next_offs( /* out: the page offset of the next chained record */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the next record offset field of the record. */ @@ -60,7 +60,7 @@ void rec_set_next_offs( /*==============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint next); /* in: offset of the next record */ /********************************************************** The following function is used to get the number of fields @@ -90,7 +90,7 @@ rec_get_n_owned( /*============*/ /* out: number of owned records */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the number of owned records. */ @@ -99,7 +99,7 @@ void rec_set_n_owned( /*============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint n_owned); /* in: the number of owned */ /********************************************************** The following function is used to retrieve the info bits of @@ -110,7 +110,7 @@ rec_get_info_bits( /*==============*/ /* out: info bits */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the info bits of a record. */ UNIV_INLINE @@ -118,7 +118,7 @@ void rec_set_info_bits( /*==============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint bits); /* in: info bits */ /********************************************************** The following function retrieves the status bits of a new-style record. */ @@ -147,7 +147,7 @@ rec_get_info_and_status_bits( /*=========================*/ /* out: info bits */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the info and status bits of a record. (Only compact records have status bits.) */ @@ -156,18 +156,18 @@ void rec_set_info_and_status_bits( /*=========================*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint bits); /* in: info bits */ /********************************************************** The following function tells if record is delete marked. */ UNIV_INLINE -ibool +ulint rec_get_deleted_flag( /*=================*/ - /* out: TRUE if delete marked */ + /* out: nonzero if delete marked */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the deleted bit. */ UNIV_INLINE @@ -175,8 +175,8 @@ void rec_set_deleted_flag( /*=================*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ - ibool flag); /* in: TRUE if delete marked */ + ulint comp, /* in: nonzero=compact page format */ + ulint flag); /* in: nonzero if delete marked */ /********************************************************** The following function tells if a new-style record is a node pointer. */ UNIV_INLINE @@ -186,14 +186,6 @@ rec_get_node_ptr_flag( /* out: TRUE if node pointer */ rec_t* rec); /* in: physical record */ /********************************************************** -The following function is used to flag a record as a node pointer. */ -UNIV_INLINE -void -rec_set_node_ptr_flag( -/*=================*/ - rec_t* rec, /* in: physical record */ - ibool flag); /* in: TRUE if the record is a node pointer */ -/********************************************************** The following function is used to get the order number of the record in the heap of the index page. */ UNIV_INLINE @@ -202,7 +194,7 @@ rec_get_heap_no( /*=============*/ /* out: heap order number */ rec_t* rec, /* in: physical record */ - ibool comp); /* in: TRUE=compact page format */ + ulint comp); /* in: nonzero=compact page format */ /********************************************************** The following function is used to set the heap number field in the record. */ @@ -211,7 +203,7 @@ void rec_set_heap_no( /*=============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint heap_no);/* in: the heap number */ /********************************************************** The following function is used to test whether the data offsets @@ -305,27 +297,18 @@ rec_get_nth_field( Determine if the offsets are for a record in the new compact format. */ UNIV_INLINE -ibool +ulint rec_offs_comp( /*==========*/ - /* out: TRUE if compact format */ + /* out: nonzero if compact format */ const ulint* offsets);/* in: array returned by rec_get_offsets() */ /********************************************************** -Returns TRUE if the nth field of rec is SQL NULL. */ +Returns nonzero if the extern bit is set in nth field of rec. */ UNIV_INLINE -ibool -rec_offs_nth_null( -/*==============*/ - /* out: TRUE if SQL NULL */ - const ulint* offsets,/* in: array returned by rec_get_offsets() */ - ulint n); /* in: nth field */ -/********************************************************** -Returns TRUE if the extern bit is set in nth field of rec. */ -UNIV_INLINE -ibool +ulint rec_offs_nth_extern( /*================*/ - /* out: TRUE if externally stored */ + /* out: nonzero if externally stored */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ ulint n); /* in: nth field */ /********************************************************** diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index 2593fb8edeb..d60fb3b9eda 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -265,7 +265,7 @@ rec_get_next_offs( /* out: the page offset of the next chained record, or 0 if none */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { ulint field_value; @@ -312,7 +312,7 @@ void rec_set_next_offs( /*==============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint next) /* in: offset of the next record, or 0 if none */ { ut_ad(rec); @@ -414,7 +414,7 @@ rec_get_n_fields( { ut_ad(rec); ut_ad(index); - if (!index->table->comp) { + if (UNIV_UNLIKELY(!index->table->comp)) { return(rec_get_n_fields_old(rec)); } switch (rec_get_status(rec)) { @@ -440,7 +440,7 @@ rec_get_n_owned( /*============*/ /* out: number of owned records */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { ulint ret; @@ -461,7 +461,7 @@ void rec_set_n_owned( /*============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint n_owned) /* in: the number of owned */ { ut_ad(rec); @@ -480,7 +480,7 @@ rec_get_info_bits( /*==============*/ /* out: info bits */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { ulint ret; @@ -501,7 +501,7 @@ void rec_set_info_bits( /*==============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint bits) /* in: info bits */ { ut_ad(rec); @@ -537,14 +537,14 @@ rec_get_info_and_status_bits( /*=========================*/ /* out: info bits */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { ulint bits; #if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \ & (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT) # error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap" #endif - if (comp) { + if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) { bits = rec_get_info_bits(rec, TRUE) | rec_get_status(rec); } else { bits = rec_get_info_bits(rec, FALSE); @@ -560,7 +560,7 @@ void rec_set_info_and_status_bits( /*=========================*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint bits) /* in: info bits */ { #if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \ @@ -578,19 +578,22 @@ rec_set_info_and_status_bits( /********************************************************** The following function tells if record is delete marked. */ UNIV_INLINE -ibool +ulint rec_get_deleted_flag( /*=================*/ - /* out: TRUE if delete marked */ + /* out: nonzero if delete marked */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { - if (REC_INFO_DELETED_FLAG & rec_get_info_bits(rec, comp)) { - - return(TRUE); + if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) { + return(UNIV_UNLIKELY(rec_get_bit_field_1(rec, + REC_NEW_INFO_BITS, REC_INFO_DELETED_FLAG, + REC_INFO_BITS_SHIFT))); + } else { + return(UNIV_UNLIKELY(rec_get_bit_field_1(rec, + REC_OLD_INFO_BITS, REC_INFO_DELETED_FLAG, + REC_INFO_BITS_SHIFT))); } - - return(FALSE); } /********************************************************** @@ -600,24 +603,20 @@ void rec_set_deleted_flag( /*=================*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ - ibool flag) /* in: TRUE if delete marked */ + ulint comp, /* in: nonzero=compact page format */ + ulint flag) /* in: nonzero if delete marked */ { - ulint old_val; - ulint new_val; - - ut_ad(TRUE == 1); - ut_ad(flag <= TRUE); + ulint val; - old_val = rec_get_info_bits(rec, comp); + val = rec_get_info_bits(rec, comp); if (flag) { - new_val = REC_INFO_DELETED_FLAG | old_val; + val |= REC_INFO_DELETED_FLAG; } else { - new_val = ~REC_INFO_DELETED_FLAG & old_val; + val &= ~REC_INFO_DELETED_FLAG; } - rec_set_info_bits(rec, comp, new_val); + rec_set_info_bits(rec, comp, val); } /********************************************************** @@ -633,26 +632,6 @@ rec_get_node_ptr_flag( } /********************************************************** -The following function is used to flag a record as a node pointer. */ -UNIV_INLINE -void -rec_set_node_ptr_flag( -/*=================*/ - rec_t* rec, /* in: physical record */ - ibool flag) /* in: TRUE if the record is a node pointer */ -{ - ulint status; - ut_ad(flag <= TRUE); - ut_ad(REC_STATUS_NODE_PTR >= rec_get_status(rec)); - if (flag) { - status = REC_STATUS_NODE_PTR; - } else { - status = REC_STATUS_ORDINARY; - } - rec_set_status(rec, status); -} - -/********************************************************** The following function is used to get the order number of the record in the heap of the index page. */ UNIV_INLINE @@ -661,7 +640,7 @@ rec_get_heap_no( /*=============*/ /* out: heap order number */ rec_t* rec, /* in: physical record */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { ulint ret; @@ -682,7 +661,7 @@ void rec_set_heap_no( /*=============*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ulint heap_no)/* in: the heap number */ { ut_ad(heap_no <= REC_MAX_HEAP_NO); @@ -843,7 +822,7 @@ rec_offs_validate( { ulint i = rec_offs_n_fields(offsets); ulint last = ULINT_MAX; - ibool comp = (*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0; + ulint comp = *rec_offs_base(offsets) & REC_OFFS_COMPACT; if (rec) { ut_ad((ulint) rec == offsets[2]); @@ -926,7 +905,7 @@ rec_get_nth_field( ut_ad(n < rec_offs_n_fields(offsets)); ut_ad(len); - if (n == 0) { + if (UNIV_UNLIKELY(n == 0)) { field = rec; } else { field = rec + (rec_offs_base(offsets)[n] & REC_OFFS_MASK); @@ -949,43 +928,30 @@ rec_get_nth_field( Determine if the offsets are for a record in the new compact format. */ UNIV_INLINE -ibool +ulint rec_offs_comp( /*==========*/ - /* out: TRUE if compact format */ + /* out: nonzero if compact format */ const ulint* offsets)/* in: array returned by rec_get_offsets() */ { ut_ad(rec_offs_validate(NULL, NULL, offsets)); - return((*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0); + return(*rec_offs_base(offsets) & REC_OFFS_COMPACT); } /********************************************************** -Returns TRUE if the nth field of rec is SQL NULL. */ -UNIV_INLINE -ibool -rec_offs_nth_null( -/*==============*/ - /* out: TRUE if SQL NULL */ - const ulint* offsets,/* in: array returned by rec_get_offsets() */ - ulint n) /* in: nth field */ -{ - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - ut_ad(n < rec_offs_n_fields(offsets)); - return((rec_offs_base(offsets)[1 + n] & REC_OFFS_SQL_NULL) != 0); -} -/********************************************************** -Returns TRUE if the extern bit is set in nth field of rec. */ +Returns nonzero if the extern bit is set in nth field of rec. */ UNIV_INLINE -ibool +ulint rec_offs_nth_extern( /*================*/ - /* out: TRUE if externally stored */ + /* out: nonzero if externally stored */ const ulint* offsets,/* in: array returned by rec_get_offsets() */ ulint n) /* in: nth field */ { ut_ad(rec_offs_validate(NULL, NULL, offsets)); ut_ad(n < rec_offs_n_fields(offsets)); - return((rec_offs_base(offsets)[1 + n] & REC_OFFS_EXTERNAL) != 0); + return(UNIV_UNLIKELY(rec_offs_base(offsets)[1 + n] + & REC_OFFS_EXTERNAL)); } /********************************************************** @@ -1037,7 +1003,7 @@ rec_set_nth_field_extern_bit( where rec is, or NULL; in the NULL case we do not write to log about the change */ { - if (index->table->comp) { + if (UNIV_LIKELY(index->table->comp)) { rec_set_nth_field_extern_bit_new(rec, index, i, val, mtr); } else { rec_set_nth_field_extern_bit_old(rec, i, val, mtr); @@ -1048,7 +1014,7 @@ rec_set_nth_field_extern_bit( Returns the offset of n - 1th field end if the record is stored in the 1-byte offsets form. If the field is SQL null, the flag is ORed in the returned value. This function and the 2-byte counterpart are defined here because the -C-compilerwas not able to sum negative and positive constant offsets, and +C-compiler was not able to sum negative and positive constant offsets, and warned of constant arithmetic overflow within the compiler. */ UNIV_INLINE ulint @@ -1452,7 +1418,7 @@ rec_get_converted_size( ? dict_index_get_n_unique_in_tree(index) + 1 : dict_index_get_n_fields(index))); - if (index->table->comp) { + if (UNIV_LIKELY(index->table->comp)) { return(rec_get_converted_size_new(index, dtuple)); } diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index e44d689b88b..4bb9fa63cd1 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -110,7 +110,7 @@ row_mysql_store_col_in_innobase_format( necessarily the length of the actual payload data; if the column is a true VARCHAR then this is irrelevant */ - ibool comp); /* in: TRUE = compact format */ + ulint comp); /* in: nonzero=compact format */ /******************************************************************** Handles user errors and lock waits detected by the database engine. */ @@ -172,14 +172,6 @@ row_lock_table_autoinc_for_mysql( row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL table handle */ /************************************************************************* -Unlocks all table locks explicitly requested by trx (with LOCK TABLES, -lock type LOCK_TABLE_EXP). */ - -void -row_unlock_tables_for_mysql( -/*========================*/ - trx_t* trx); /* in: transaction */ -/************************************************************************* Sets a table lock on the table mentioned in prebuilt. */ int @@ -190,9 +182,10 @@ row_lock_table_for_mysql( table handle */ dict_table_t* table, /* in: table to lock, or NULL if prebuilt->table should be - locked as LOCK_TABLE_EXP | + locked as prebuilt->select_lock_type */ - ulint mode); /* in: lock mode of table */ + ulint mode); /* in: lock mode of table + (ignored if table==NULL) */ /************************************************************************* Does an insert for MySQL. */ @@ -599,6 +592,8 @@ struct row_prebuilt_struct { that was decided in ha_innodb.cc, ::store_lock(), ::external_lock(), etc. */ + ulint mysql_prefix_len;/* byte offset of the end of + the last requested column */ ulint mysql_row_len; /* length in bytes of a row in the MySQL format */ ulint n_rows_fetched; /* number of rows fetched after diff --git a/storage/innobase/include/row0sel.ic b/storage/innobase/include/row0sel.ic index 595cea1138b..600c6204571 100644 --- a/storage/innobase/include/row0sel.ic +++ b/storage/innobase/include/row0sel.ic @@ -75,7 +75,7 @@ open_step( } } - if (err != DB_SUCCESS) { + if (UNIV_EXPECT(err, DB_SUCCESS) != DB_SUCCESS) { /* SQL error detected */ fprintf(stderr, "SQL error %lu\n", (ulong) err); diff --git a/storage/innobase/include/row0upd.ic b/storage/innobase/include/row0upd.ic index e2d81a39cfa..acbb11aa1c7 100644 --- a/storage/innobase/include/row0upd.ic +++ b/storage/innobase/include/row0upd.ic @@ -83,7 +83,7 @@ upd_field_set_field_no( { upd_field->field_no = field_no; - if (field_no >= dict_index_get_n_fields(index)) { + if (UNIV_UNLIKELY(field_no >= dict_index_get_n_fields(index))) { fprintf(stderr, "InnoDB: Error: trying to access field %lu in ", (ulong) field_no); diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic index 3a92100ba01..b1ae636010a 100644 --- a/storage/innobase/include/sync0rw.ic +++ b/storage/innobase/include/sync0rw.ic @@ -138,7 +138,7 @@ rw_lock_s_lock_low( #endif /* UNIV_SYNC_DEBUG */ /* Check if the writer field is free */ - if (lock->writer == RW_LOCK_NOT_LOCKED) { + if (UNIV_LIKELY(lock->writer == RW_LOCK_NOT_LOCKED)) { /* Set the shared lock by incrementing the reader count */ lock->reader_count++; @@ -243,7 +243,7 @@ rw_lock_s_lock_func( mutex_enter(rw_lock_get_mutex(lock)); - if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) { + if (UNIV_LIKELY(rw_lock_s_lock_low(lock, pass, file_name, line))) { mutex_exit(rw_lock_get_mutex(lock)); return; /* Success */ @@ -307,21 +307,18 @@ rw_lock_x_lock_func_nowait( const char* file_name,/* in: file name where lock requested */ ulint line) /* in: line where requested */ { - ibool success = FALSE; - + ibool success = FALSE; + os_thread_id_t curr_thread = os_thread_get_curr_id(); mutex_enter(rw_lock_get_mutex(lock)); - if ((rw_lock_get_reader_count(lock) == 0) - && ((rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) - || ((rw_lock_get_writer(lock) == RW_LOCK_EX) - && (lock->pass == 0) - && os_thread_eq(lock->writer_thread, - os_thread_get_curr_id())))) { - + if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) { + } else if (UNIV_LIKELY(rw_lock_get_writer(lock) + == RW_LOCK_NOT_LOCKED)) { rw_lock_set_writer(lock, RW_LOCK_EX); - lock->writer_thread = os_thread_get_curr_id(); - lock->writer_count++; + lock->writer_thread = curr_thread; lock->pass = 0; + relock: + lock->writer_count++; #ifdef UNIV_SYNC_DEBUG rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line); @@ -331,6 +328,10 @@ rw_lock_x_lock_func_nowait( lock->last_x_line = line; success = TRUE; + } else if (rw_lock_get_writer(lock) == RW_LOCK_EX + && lock->pass == 0 + && os_thread_eq(lock->writer_thread, curr_thread)) { + goto relock; } mutex_exit(rw_lock_get_mutex(lock)); @@ -361,7 +362,7 @@ rw_lock_s_unlock_func( /* Reset the shared lock by decrementing the reader count */ - ut_a(lock->reader_count > 0); + ut_ad(lock->reader_count > 0); lock->reader_count--; #ifdef UNIV_SYNC_DEBUG @@ -371,7 +372,8 @@ rw_lock_s_unlock_func( /* If there may be waiters and this was the last s-lock, signal the object */ - if (lock->waiters && (lock->reader_count == 0)) { + if (UNIV_UNLIKELY(lock->waiters) + && lock->reader_count == 0) { sg = TRUE; rw_lock_set_waiters(lock, 0); @@ -379,7 +381,7 @@ rw_lock_s_unlock_func( mutex_exit(mutex); - if (sg == TRUE) { + if (UNIV_UNLIKELY(sg)) { sync_array_signal_object(sync_primary_wait_array, lock); } @@ -450,7 +452,8 @@ rw_lock_x_unlock_func( #endif /* If there may be waiters, signal the lock */ - if (lock->waiters && (lock->writer_count == 0)) { + if (UNIV_UNLIKELY(lock->waiters) + && lock->writer_count == 0) { sg = TRUE; rw_lock_set_waiters(lock, 0); @@ -458,7 +461,7 @@ rw_lock_x_unlock_func( mutex_exit(&(lock->mutex)); - if (sg == TRUE) { + if (UNIV_UNLIKELY(sg)) { sync_array_signal_object(sync_primary_wait_array, lock); } diff --git a/storage/innobase/include/trx0rseg.ic b/storage/innobase/include/trx0rseg.ic index 35e927f5e79..c9ac50ebf16 100644 --- a/storage/innobase/include/trx0rseg.ic +++ b/storage/innobase/include/trx0rseg.ic @@ -65,7 +65,7 @@ trx_rsegf_get_nth_undo( ulint n, /* in: index of slot */ mtr_t* mtr) /* in: mtr */ { - if (n >= TRX_RSEG_N_SLOTS) { + if (UNIV_UNLIKELY(n >= TRX_RSEG_N_SLOTS)) { fprintf(stderr, "InnoDB: Error: trying to get slot %lu of rseg\n", (unsigned long) n); ut_error; @@ -86,7 +86,7 @@ trx_rsegf_set_nth_undo( ulint page_no,/* in: page number of the undo log segment */ mtr_t* mtr) /* in: mtr */ { - if (n >= TRX_RSEG_N_SLOTS) { + if (UNIV_UNLIKELY(n >= TRX_RSEG_N_SLOTS)) { fprintf(stderr, "InnoDB: Error: trying to set slot %lu of rseg\n", (unsigned long) n); ut_error; diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index d46613c3a68..8df50d6703d 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -312,6 +312,19 @@ trx_print( FILE* f, /* in: output stream */ trx_t* trx); /* in: transaction */ +#ifndef UNIV_HOTBACKUP +/************************************************************************** +Determines if the currently running transaction has been interrupted. */ + +ibool +trx_is_interrupted( +/*===============*/ + /* out: TRUE if interrupted */ + trx_t* trx); /* in: transaction */ +#else /* !UNIV_HOTBACKUP */ +#define trx_is_interrupted(trx) FALSE +#endif /* !UNIV_HOTBACKUP */ + /* Signal to a transaction */ struct trx_sig_struct{ @@ -484,13 +497,6 @@ struct trx_struct{ in the lock list trx_locks */ ibool trx_create_lock;/* this is TRUE if we have created a new lock for a record accessed */ - ulint n_lock_table_exp;/* number of explicit table locks - (LOCK TABLES) reserved by the - transaction, stored in trx_locks */ - ulint n_lock_table_transactional; - /* number of transactional table locks - (LOCK TABLES..WHERE ENGINE) reserved by - the transaction, stored in trx_locks */ UT_LIST_NODE_T(trx_t) trx_list; /* list of transactions */ UT_LIST_NODE_T(trx_t) diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 8158c198e21..132ac9e18c5 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -181,7 +181,7 @@ management to ensure correct alignment for doubles etc. */ /* Another basic type we use is unsigned long integer which should be equal to the word size of the machine, that is on a 32-bit platform 32 bits, and on a 64-bit platform 64 bits. We also give the printf format for the type as a -macro PRULINT. */ +macro ULINTPF. */ #ifdef _WIN64 typedef unsigned __int64 ulint; @@ -243,6 +243,30 @@ contains the sum of the following flag and the locally stored len. */ #define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE) +/* Some macros to improve branch prediction and reduce cache misses */ +#if defined(__GNUC__) && (__GNUC__ > 2) +/* Tell the compiler that 'expr' probably evaluates to 'constant'. */ +# define UNIV_EXPECT(expr,constant) __builtin_expect(expr, constant) +/* Tell the compiler that a pointer is likely to be NULL */ +# define UNIV_LIKELY_NULL(ptr) __builtin_expect((ulint) ptr, 0) +/* Minimize cache-miss latency by moving data at addr into a cache before +it is read. */ +# define UNIV_PREFETCH_R(addr) __builtin_prefetch(addr, 0, 3) +/* Minimize cache-miss latency by moving data at addr into a cache before +it is read or written. */ +# define UNIV_PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 3) +#else +/* Dummy versions of the macros */ +# define UNIV_EXPECT(expr,value) (expr) +# define UNIV_LIKELY_NULL(expr) (expr) +# define UNIV_PREFETCH_R(addr) ((void) 0) +# define UNIV_PREFETCH_RW(addr) ((void) 0) +#endif +/* Tell the compiler that cond is likely to hold */ +#define UNIV_LIKELY(cond) UNIV_EXPECT(cond, TRUE) +/* Tell the compiler that cond is unlikely to hold */ +#define UNIV_UNLIKELY(cond) UNIV_EXPECT(cond, FALSE) + #include <stdio.h> #include "ut0dbg.h" #include "ut0ut.h" diff --git a/storage/innobase/include/ut0dbg.h b/storage/innobase/include/ut0dbg.h index 5f30a894874..bc3f852626a 100644 --- a/storage/innobase/include/ut0dbg.h +++ b/storage/innobase/include/ut0dbg.h @@ -13,74 +13,75 @@ Created 1/30/1994 Heikki Tuuri #include <stdlib.h> #include "os0thread.h" +#if defined(__GNUC__) && (__GNUC__ > 2) +# define UT_DBG_FAIL(EXPR) UNIV_UNLIKELY(!((ulint)(EXPR))) +#else extern ulint ut_dbg_zero; /* This is used to eliminate compiler warnings */ +# define UT_DBG_FAIL(EXPR) !((ulint)(EXPR) + ut_dbg_zero) +#endif + +/***************************************************************** +Report a failed assertion. */ + +void +ut_dbg_assertion_failed( +/*====================*/ + const char* expr, /* in: the failed assertion */ + const char* file, /* in: source file containing the assertion */ + ulint line); /* in: line number of the assertion */ + +#ifdef __NETWARE__ +/* Flag for ignoring further assertion failures. +On NetWare, have a graceful exit rather than a segfault to avoid abends. */ +extern ibool panic_shutdown; +/* Abort the execution. */ +void ut_dbg_panic(void); +# define UT_DBG_PANIC ut_dbg_panic() +/* Stop threads in ut_a(). */ +# define UT_DBG_STOP while (0) /* We do not do this on NetWare */ +#else /* __NETWARE__ */ +/* Flag for indicating that all threads should stop. This will be set +by ut_dbg_assertion_failed(). */ extern ibool ut_dbg_stop_threads; +/* A null pointer that will be dereferenced to trigger a memory trap */ extern ulint* ut_dbg_null_ptr; -extern const char* ut_dbg_msg_assert_fail; -extern const char* ut_dbg_msg_trap; -extern const char* ut_dbg_msg_stop; -/* Have a graceful exit on NetWare rather than a segfault to avoid abends */ -#ifdef __NETWARE__ -extern ibool panic_shutdown; -#define ut_a(EXPR) do {\ - if (!((ulint)(EXPR) + ut_dbg_zero)) {\ - ut_print_timestamp(stderr);\ - fprintf(stderr, ut_dbg_msg_assert_fail,\ - os_thread_pf(os_thread_get_curr_id()), __FILE__,\ - (ulint)__LINE__);\ - fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\ - fputs(ut_dbg_msg_trap, stderr);\ - ut_dbg_stop_threads = TRUE;\ - if (ut_dbg_stop_threads) {\ - fprintf(stderr, ut_dbg_msg_stop,\ - os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\ - }\ - if(!panic_shutdown){\ - panic_shutdown = TRUE;\ - innobase_shutdown_for_mysql();}\ - exit(1);\ - }\ -} while (0) -#define ut_error do {\ - ut_print_timestamp(stderr);\ - fprintf(stderr, ut_dbg_msg_assert_fail,\ - os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\ - fprintf(stderr, ut_dbg_msg_trap);\ - ut_dbg_stop_threads = TRUE;\ - if(!panic_shutdown){panic_shutdown = TRUE;\ - innobase_shutdown_for_mysql();}\ -} while (0) -#else -#define ut_a(EXPR) do {\ - if (!((ulint)(EXPR) + ut_dbg_zero)) {\ - ut_print_timestamp(stderr);\ - fprintf(stderr, ut_dbg_msg_assert_fail,\ - os_thread_pf(os_thread_get_curr_id()), __FILE__,\ - (ulint)__LINE__);\ - fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\ - fputs(ut_dbg_msg_trap, stderr);\ - ut_dbg_stop_threads = TRUE;\ - if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\ - }\ - if (ut_dbg_stop_threads) {\ - fprintf(stderr, ut_dbg_msg_stop,\ - os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\ - os_thread_sleep(1000000000);\ - }\ +/***************************************************************** +Stop a thread after assertion failure. */ + +void +ut_dbg_stop_thread( +/*===============*/ + const char* file, + ulint line); + +/* Abort the execution. */ +# define UT_DBG_PANIC \ + if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL +/* Stop threads in ut_a(). */ +# define UT_DBG_STOP do \ + if (UNIV_UNLIKELY(ut_dbg_stop_threads)) { \ + ut_dbg_stop_thread(__FILE__, (ulint) __LINE__); \ + } while (0) +#endif /* __NETWARE__ */ + +/* Abort execution if EXPR does not evaluate to nonzero. */ +#define ut_a(EXPR) do { \ + if (UT_DBG_FAIL(EXPR)) { \ + ut_dbg_assertion_failed(#EXPR, \ + __FILE__, (ulint) __LINE__); \ + UT_DBG_PANIC; \ + } \ + UT_DBG_STOP; \ } while (0) -#define ut_error do {\ - ut_print_timestamp(stderr);\ - fprintf(stderr, ut_dbg_msg_assert_fail,\ - os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\ - fprintf(stderr, ut_dbg_msg_trap);\ - ut_dbg_stop_threads = TRUE;\ - if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\ +/* Abort execution. */ +#define ut_error do { \ + ut_dbg_assertion_failed(0, __FILE__, (ulint) __LINE__); \ + UT_DBG_PANIC; \ } while (0) -#endif #ifdef UNIV_DEBUG #define ut_ad(EXPR) ut_a(EXPR) diff --git a/storage/innobase/include/ut0rnd.ic b/storage/innobase/include/ut0rnd.ic index 06d7012f60b..d2ab087d491 100644 --- a/storage/innobase/include/ut0rnd.ic +++ b/storage/innobase/include/ut0rnd.ic @@ -207,12 +207,12 @@ ut_fold_binary( const byte* str, /* in: string of bytes */ ulint len) /* in: length */ { - ulint i; - ulint fold = 0; + const byte* str_end = str + len; + ulint fold = 0; ut_ad(str); - for (i = 0; i < len; i++) { + while (str < str_end) { fold = ut_fold_ulint_pair(fold, (ulint)(*str)); str++; diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 73ecc717e0e..48db7ced0cb 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -292,7 +292,25 @@ waiting, in its lock queue. Solution: We can copy the locks as gap type locks, so that also the waiting locks are transformed to granted gap type locks on the inserted record. */ +/* LOCK COMPATIBILITY MATRIX + * IS IX S X AI + * IS + + + - + + * IX + + - - + + * S + - + - - + * X - - - - - + * AI + + - - - + * + * Note that for rows, InnoDB only acquires S or X locks. + * For tables, InnoDB normally acquires IS or IX locks. + * S or X table locks are only acquired for LOCK TABLES. + * Auto-increment (AI) locks are needed because of + * statement-level MySQL binlog. + * See also lock_mode_compatible(). + */ + +#ifdef UNIV_DEBUG ibool lock_print_waits = FALSE; +#endif /* UNIV_DEBUG */ /* The lock system */ lock_sys_t* lock_sys = NULL; @@ -348,17 +366,26 @@ static ibool lock_deadlock_occurs( /*=================*/ - /* out: TRUE if a deadlock was detected */ + /* out: TRUE if a deadlock was detected and we + chose trx as a victim; FALSE if no deadlock, or + there was a deadlock, but we chose other + transaction(s) as victim(s) */ lock_t* lock, /* in: lock the transaction is requesting */ trx_t* trx); /* in: transaction */ /************************************************************************ Looks recursively for a deadlock. */ static -ibool +ulint lock_deadlock_recursive( /*====================*/ - /* out: TRUE if a deadlock was detected - or the calculation took too long */ + /* out: 0 if no deadlock found, + LOCK_VICTIM_IS_START if there was a deadlock + and we chose 'start' as the victim, + LOCK_VICTIM_IS_OTHER if a deadlock + was found and we chose some other trx as a + victim: we must do the search again in this + last case because there may be another + deadlock! */ trx_t* start, /* in: recursion starting point */ trx_t* trx, /* in: a transaction waiting for a lock */ lock_t* wait_lock, /* in: the lock trx is waiting to be granted */ @@ -492,12 +519,7 @@ lock_clust_rec_cons_read_sees( trx_id = row_get_rec_trx_id(rec, index, offsets); - if (read_view_sees_trx_id(view, trx_id)) { - - return(TRUE); - } - - return(FALSE); + return(read_view_sees_trx_id(view, trx_id)); } /************************************************************************* @@ -1261,7 +1283,6 @@ lock_rec_get_next( /*==============*/ /* out: next lock, NULL if none exists */ rec_t* rec, /* in: record on a page */ - ibool comp, /* in: TRUE=compact page format */ lock_t* lock) /* in: lock */ { #ifdef UNIV_SYNC_DEBUG @@ -1269,19 +1290,19 @@ lock_rec_get_next( #endif /* UNIV_SYNC_DEBUG */ ut_ad(lock_get_type(lock) == LOCK_REC); - for (;;) { - lock = lock_rec_get_next_on_page(lock); - - if (lock == NULL) { - - return(NULL); - } - - if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec, comp))) { - - return(lock); - } + if (page_rec_is_comp(rec)) { + do { + lock = lock_rec_get_next_on_page(lock); + } while (lock && !lock_rec_get_nth_bit(lock, + rec_get_heap_no(rec, TRUE))); + } else { + do { + lock = lock_rec_get_next_on_page(lock); + } while (lock && !lock_rec_get_nth_bit(lock, + rec_get_heap_no(rec, FALSE))); } + + return(lock); } /************************************************************************* @@ -1294,22 +1315,18 @@ lock_rec_get_first( rec_t* rec) /* in: record on a page */ { lock_t* lock; - ibool comp; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ lock = lock_rec_get_first_on_page(rec); - comp = page_is_comp(buf_frame_align(rec)); + if (UNIV_LIKELY_NULL(lock)) { + ulint heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); - while (lock) { - if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec, comp))) { - - break; + while (lock && !lock_rec_get_nth_bit(lock, heap_no)) { + lock = lock_rec_get_next_on_page(lock); } - - lock = lock_rec_get_next_on_page(lock); } return(lock); @@ -1471,7 +1488,6 @@ lock_rec_has_expl( for a supremum record we regard this always a gap type request */ rec_t* rec, /* in: record */ - ibool comp, /* in: TRUE=compact page format */ trx_t* trx) /* in: transaction */ { lock_t* lock; @@ -1501,7 +1517,7 @@ lock_rec_has_expl( return(lock); } - lock = lock_rec_get_next(rec, comp, lock); + lock = lock_rec_get_next(rec, lock); } return(NULL); @@ -1520,7 +1536,6 @@ lock_rec_other_has_expl_req( ulint wait, /* in: LOCK_WAIT if also waiting locks are taken into account, or 0 if not */ rec_t* rec, /* in: record to look at */ - ibool comp, /* in: TRUE=compact record format */ trx_t* trx) /* in: transaction, or NULL if requests by all transactions are taken into account */ { @@ -1545,7 +1560,7 @@ lock_rec_other_has_expl_req( return(lock); } - lock = lock_rec_get_next(rec, comp, lock); + lock = lock_rec_get_next(rec, lock); } return(NULL); @@ -1566,13 +1581,11 @@ lock_rec_other_has_conflicting( trx_t* trx) /* in: our transaction */ { lock_t* lock; - ibool comp; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ lock = lock_rec_get_first(rec); - comp = page_is_comp(buf_frame_align(rec)); while (lock) { if (lock_rec_has_to_wait(trx, mode, lock, @@ -1581,7 +1594,7 @@ lock_rec_other_has_conflicting( return(lock); } - lock = lock_rec_get_next(rec, comp, lock); + lock = lock_rec_get_next(rec, lock); } return(NULL); @@ -1607,7 +1620,7 @@ lock_rec_find_similar_on_page( ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - heap_no = rec_get_heap_no(rec, page_is_comp(buf_frame_align(rec))); + heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); lock = lock_rec_get_first_on_page(rec); while (lock != NULL) { @@ -1709,6 +1722,8 @@ lock_rec_create( page_no = buf_frame_get_page_no(page); heap_no = rec_get_heap_no(rec, page_is_comp(page)); + ut_ad(!!page_is_comp(page) == index->table->comp); + /* If rec is the supremum record, then we reset the gap and LOCK_REC_NOT_GAP bits, as all locks on the supremum are automatically of the gap type */ @@ -1725,7 +1740,7 @@ lock_rec_create( lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes); - if (lock == NULL) { + if (UNIV_UNLIKELY(lock == NULL)) { return(NULL); } @@ -1826,7 +1841,7 @@ lock_rec_enqueue_waiting( lock_reset_lock_and_trx_wait(lock); lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec, - page_is_comp(buf_frame_align(rec)))); + page_rec_is_comp(rec))); return(DB_DEADLOCK); } @@ -1845,11 +1860,13 @@ lock_rec_enqueue_waiting( ut_a(que_thr_stop(thr)); +#ifdef UNIV_DEBUG if (lock_print_waits) { fprintf(stderr, "Lock wait for trx %lu in index ", (ulong) ut_dulint_get_low(trx->id)); ut_print_name(stderr, trx, index->name); } +#endif /* UNIV_DEBUG */ return(DB_LOCK_WAIT); } @@ -1876,7 +1893,6 @@ lock_rec_add_to_queue( lock_t* lock; lock_t* similar_lock = NULL; ulint heap_no; - page_t* page = buf_frame_align(rec); ibool somebody_waits = FALSE; #ifdef UNIV_SYNC_DEBUG @@ -1885,11 +1901,11 @@ lock_rec_add_to_queue( ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP)) || ((type_mode & LOCK_MODE_MASK) != LOCK_S) || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT, - rec, page_is_comp(page), trx)); + rec, trx)); ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP)) || ((type_mode & LOCK_MODE_MASK) != LOCK_X) || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT, - rec, page_is_comp(page), trx)); + rec, trx)); type_mode = type_mode | LOCK_REC; @@ -1898,7 +1914,7 @@ lock_rec_add_to_queue( try to avoid unnecessary memory consumption of a new record lock struct for a gap type lock */ - if (rec == page_get_supremum_rec(page)) { + if (page_rec_is_supremum(rec)) { ut_ad(!(type_mode & LOCK_REC_NOT_GAP)); /* There should never be LOCK_REC_NOT_GAP on a supremum @@ -1909,7 +1925,7 @@ lock_rec_add_to_queue( /* Look for a waiting lock request on the same record or on a gap */ - heap_no = rec_get_heap_no(rec, page_is_comp(page)); + heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); lock = lock_rec_get_first_on_page(rec); while (lock != NULL) { @@ -1984,7 +2000,7 @@ lock_rec_lock_fast( || mode - (LOCK_MODE_MASK & mode) == 0 || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); - heap_no = rec_get_heap_no(rec, page_is_comp(buf_frame_align(rec))); + heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); lock = lock_rec_get_first_on_page(rec); @@ -2065,8 +2081,7 @@ lock_rec_lock_slow( trx = thr_get_trx(thr); - if (lock_rec_has_expl(mode, rec, - page_is_comp(buf_frame_align(rec)), trx)) { + if (lock_rec_has_expl(mode, rec, trx)) { /* The trx already has a strong enough lock on rec: do nothing */ @@ -2207,16 +2222,14 @@ lock_grant( release it at the end of the SQL statement */ lock->trx->auto_inc_lock = lock; - } else if (lock_get_type(lock) == LOCK_TABLE_EXP || - lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) { - ut_a(lock_get_mode(lock) == LOCK_S - || lock_get_mode(lock) == LOCK_X); - } + } +#ifdef UNIV_DEBUG if (lock_print_waits) { fprintf(stderr, "Lock wait for trx %lu ends\n", (ulong) ut_dulint_get_low(lock->trx->id)); } +#endif /* UNIV_DEBUG */ /* If we are resolving a deadlock by choosing another transaction as a victim, then our original transaction may not be in the @@ -2383,14 +2396,12 @@ lock_rec_reset_and_release_wait( { lock_t* lock; ulint heap_no; - ibool comp; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - comp = page_is_comp(buf_frame_align(rec)); - heap_no = rec_get_heap_no(rec, comp); + heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); lock = lock_rec_get_first(rec); @@ -2401,7 +2412,7 @@ lock_rec_reset_and_release_wait( lock_rec_reset_nth_bit(lock, heap_no); } - lock = lock_rec_get_next(rec, comp, lock); + lock = lock_rec_get_next(rec, lock); } } @@ -2419,13 +2430,11 @@ lock_rec_inherit_to_gap( the locks on this record */ { lock_t* lock; - ibool comp; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ lock = lock_rec_get_first(rec); - comp = page_is_comp(buf_frame_align(rec)); while (lock != NULL) { if (!lock_rec_get_insert_intention(lock)) { @@ -2435,7 +2444,7 @@ lock_rec_inherit_to_gap( heir, lock->index, lock->trx); } - lock = lock_rec_get_next(rec, comp, lock); + lock = lock_rec_get_next(rec, lock); } } @@ -2452,13 +2461,11 @@ lock_rec_inherit_to_gap_if_gap_lock( the locks on this record */ { lock_t* lock; - ibool comp; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ lock = lock_rec_get_first(rec); - comp = page_is_comp(buf_frame_align(rec)); while (lock != NULL) { if (!lock_rec_get_insert_intention(lock) @@ -2470,7 +2477,7 @@ lock_rec_inherit_to_gap_if_gap_lock( heir, lock->index, lock->trx); } - lock = lock_rec_get_next(rec, comp, lock); + lock = lock_rec_get_next(rec, lock); } } @@ -2484,7 +2491,7 @@ lock_rec_move( rec_t* receiver, /* in: record which gets locks; this record must have no lock requests on it! */ rec_t* donator, /* in: record which gives locks */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { lock_t* lock; ulint heap_no; @@ -2514,7 +2521,7 @@ lock_rec_move( lock_rec_add_to_queue(type_mode, receiver, lock->index, lock->trx); - lock = lock_rec_get_next(donator, comp, lock); + lock = lock_rec_get_next(donator, lock); } ut_ad(lock_rec_get_first(donator) == NULL); @@ -2540,7 +2547,7 @@ lock_move_reorganize_page( UT_LIST_BASE_NODE_T(lock_t) old_locks; mem_heap_t* heap = NULL; rec_t* sup; - ibool comp; + ulint comp; lock_mutex_enter_kernel(); @@ -2659,8 +2666,9 @@ lock_move_rec_list_end( ulint heap_no; rec_t* sup; ulint type_mode; - ibool comp; - + ulint comp; + ut_ad(page == buf_frame_align(rec)); + lock_mutex_enter_kernel(); /* Note: when we move locks from record to record, waiting locks @@ -2745,7 +2753,7 @@ lock_move_rec_list_start( page_cur_t cur2; ulint heap_no; ulint type_mode; - ibool comp; + ulint comp; ut_a(new_page); @@ -2754,6 +2762,7 @@ lock_move_rec_list_start( lock = lock_rec_get_first_on_page(page); comp = page_is_comp(page); ut_ad(comp == page_is_comp(new_page)); + ut_ad(page == buf_frame_align(rec)); while (lock != NULL) { @@ -2812,7 +2821,7 @@ lock_update_split_right( page_t* right_page, /* in: right page */ page_t* left_page) /* in: left page */ { - ibool comp; + ulint comp; lock_mutex_enter_kernel(); comp = page_is_comp(left_page); ut_ad(comp == page_is_comp(right_page)); @@ -2875,7 +2884,7 @@ lock_update_root_raise( page_t* new_page, /* in: index page to which copied */ page_t* root) /* in: root page */ { - ibool comp; + ulint comp; lock_mutex_enter_kernel(); comp = page_is_comp(root); ut_ad(comp == page_is_comp(new_page)); @@ -2898,7 +2907,7 @@ lock_update_copy_and_discard( page_t* new_page, /* in: index page to which copied */ page_t* page) /* in: index page; NOT the root! */ { - ibool comp; + ulint comp; lock_mutex_enter_kernel(); comp = page_is_comp(page); ut_ad(comp == page_is_comp(new_page)); @@ -2945,31 +2954,34 @@ lock_update_merge_left( page_t* right_page) /* in: merged index page which will be discarded */ { - ibool comp; + rec_t* left_next_rec; + rec_t* left_supremum; + ulint comp; lock_mutex_enter_kernel(); comp = page_is_comp(left_page); ut_ad(comp == page_is_comp(right_page)); + ut_ad(left_page == buf_frame_align(orig_pred)); - if (page_rec_get_next(orig_pred) != page_get_supremum_rec(left_page)) { + left_next_rec = page_rec_get_next(orig_pred); + left_supremum = page_get_supremum_rec(left_page); + + if (UNIV_LIKELY(left_next_rec != left_supremum)) { /* Inherit the locks on the supremum of the left page to the first record which was moved from the right page */ - lock_rec_inherit_to_gap(page_rec_get_next(orig_pred), - page_get_supremum_rec(left_page)); + lock_rec_inherit_to_gap(left_next_rec, left_supremum); /* Reset the locks on the supremum of the left page, releasing waiting transactions */ - lock_rec_reset_and_release_wait(page_get_supremum_rec( - left_page)); + lock_rec_reset_and_release_wait(left_supremum); } /* Move the locks from the supremum of right page to the supremum of the left page */ - lock_rec_move(page_get_supremum_rec(left_page), - page_get_supremum_rec(right_page), comp); + lock_rec_move(left_supremum, page_get_supremum_rec(right_page), comp); lock_rec_free_all_from_discard_page(right_page); @@ -3028,7 +3040,7 @@ lock_update_discard( lock_rec_reset_and_release_wait(rec); - if (rec == page_get_supremum_rec(page)) { + if (page_rec_is_supremum(rec)) { break; } @@ -3091,19 +3103,16 @@ actual record is being moved. */ void lock_rec_store_on_page_infimum( /*===========================*/ + page_t* page, /* in: page containing the record */ rec_t* rec) /* in: record whose lock state is stored on the infimum record of the same page; lock bits are reset on the record */ { - page_t* page; - ibool comp; - - page = buf_frame_align(rec); - comp = page_is_comp(page); + ut_ad(page == buf_frame_align(rec)); lock_mutex_enter_kernel(); - lock_rec_move(page_get_infimum_rec(page), rec, comp); + lock_rec_move(page_get_infimum_rec(page), rec, page_is_comp(page)); lock_mutex_exit_kernel(); } @@ -3120,10 +3129,10 @@ lock_rec_restore_from_page_infimum( whose infimum stored the lock state; lock bits are reset on the infimum */ { - ibool comp; + ulint comp; lock_mutex_enter_kernel(); comp = page_is_comp(page); - ut_ad(comp == page_is_comp(buf_frame_align(rec))); + ut_ad(!comp == !page_rec_is_comp(rec)); lock_rec_move(rec, page_get_infimum_rec(page), comp); @@ -3316,11 +3325,11 @@ lock_deadlock_recursive( } else { lock_table_print(ef, start->wait_lock); } - +#ifdef UNIV_DEBUG if (lock_print_waits) { fputs("Deadlock detected\n", stderr); } - +#endif /* UNIV_DEBUG */ if (ut_dulint_cmp(wait_lock->trx->undo_no, start->undo_no) >= 0) { /* Our recursion starting point @@ -3418,14 +3427,6 @@ lock_table_create( lock->type_mode = type_mode | LOCK_TABLE; lock->trx = trx; - if (lock_get_type(lock) == LOCK_TABLE_EXP) { - lock->trx->n_lock_table_exp++; - } - - if (lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) { - lock->trx->n_lock_table_transactional++; - } - lock->un_member.tab_lock.table = table; UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); @@ -3462,14 +3463,6 @@ lock_table_remove_low( trx->auto_inc_lock = NULL; } - if (lock_get_type(lock) == LOCK_TABLE_EXP) { - trx->n_lock_table_exp--; - } - - if (lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) { - trx->n_lock_table_transactional--; - } - UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock); UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock); } @@ -3600,10 +3593,7 @@ lock_table( /* out: DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, - does nothing; - if LOCK_TABLE_EXP|LOCK_TABLE_TRANSACTIONAL - bits are set, - creates an explicit table lock */ + does nothing */ dict_table_t* table, /* in: database table in dictionary cache */ ulint mode, /* in: lock mode */ que_thr_t* thr) /* in: query thread */ @@ -3618,8 +3608,7 @@ lock_table( return(DB_SUCCESS); } - ut_a(flags == 0 || flags == LOCK_TABLE_EXP || - flags == LOCK_TABLE_TRANSACTIONAL); + ut_a(flags == 0); trx = thr_get_trx(thr); @@ -3732,9 +3721,7 @@ lock_table_dequeue( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - ut_a(lock_get_type(in_lock) == LOCK_TABLE || - lock_get_type(in_lock) == LOCK_TABLE_EXP || - lock_get_type(in_lock) == LOCK_TABLE_TRANSACTIONAL); + ut_a(lock_get_type(in_lock) == LOCK_TABLE); lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock); @@ -3838,12 +3825,6 @@ lock_release_off_kernel( } lock_table_dequeue(lock); - - if (lock_get_type(lock) == LOCK_TABLE_EXP || - lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) { - ut_a(lock_get_mode(lock) == LOCK_S - || lock_get_mode(lock) == LOCK_X); - } } if (count == LOCK_RELEASE_KERNEL_INTERVAL) { @@ -3863,74 +3844,6 @@ lock_release_off_kernel( mem_heap_empty(trx->lock_heap); ut_a(trx->auto_inc_lock == NULL); - ut_a(trx->n_lock_table_exp == 0); - ut_a(trx->n_lock_table_transactional == 0); -} - -/************************************************************************* -Releases table locks explicitly requested with LOCK TABLES (indicated by -lock type LOCK_TABLE_EXP), and releases possible other transactions waiting -because of these locks. */ - -void -lock_release_tables_off_kernel( -/*===========================*/ - trx_t* trx) /* in: transaction */ -{ - dict_table_t* table; - ulint count; - lock_t* lock; - -#ifdef UNIV_SYNC_DEBUG - ut_ad(mutex_own(&kernel_mutex)); -#endif /* UNIV_SYNC_DEBUG */ - - lock = UT_LIST_GET_LAST(trx->trx_locks); - - count = 0; - - while (lock != NULL) { - - count++; - - if (lock_get_type(lock) == LOCK_TABLE_EXP) { - ut_a(lock_get_mode(lock) == LOCK_S - || lock_get_mode(lock) == LOCK_X); - if (trx->insert_undo || trx->update_undo) { - - /* The trx may have modified the table. - We block the use of the MySQL query - cache for all currently active - transactions. */ - - table = lock->un_member.tab_lock.table; - - table->query_cache_inv_trx_id = - trx_sys->max_trx_id; - } - - lock_table_dequeue(lock); - - lock = UT_LIST_GET_LAST(trx->trx_locks); - continue; - } - - if (count == LOCK_RELEASE_KERNEL_INTERVAL) { - /* Release the kernel mutex for a while, so that we - do not monopolize it */ - - lock_mutex_exit_kernel(); - - lock_mutex_enter_kernel(); - - count = 0; - } - - lock = UT_LIST_GET_PREV(trx_locks, lock); - } - - ut_a(trx->n_lock_table_exp == 0); - ut_a(trx->n_lock_table_transactional == 0); } /************************************************************************* @@ -4043,15 +3956,7 @@ lock_table_print( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - ut_a(lock_get_type(lock) == LOCK_TABLE || - lock_get_type(lock) == LOCK_TABLE_EXP || - lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL); - - if (lock_get_type(lock) == LOCK_TABLE_EXP) { - fputs("EXPLICIT ", file); - } else if (lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) { - fputs("TRANSACTIONAL ", file); - } + ut_a(lock_get_type(lock) == LOCK_TABLE); fputs("TABLE LOCK table ", file); ut_print_name(file, lock->trx, lock->un_member.tab_lock.table->name); @@ -4187,7 +4092,7 @@ lock_rec_print( } mtr_commit(&mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -4483,15 +4388,14 @@ lock_rec_queue_validate( { trx_t* impl_trx; lock_t* lock; - ibool comp; ut_a(rec); ut_ad(rec_offs_validate(rec, index, offsets)); - comp = page_is_comp(buf_frame_align(rec)); + ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets)); lock_mutex_enter_kernel(); - if (page_rec_is_supremum(rec) || page_rec_is_infimum(rec)) { + if (!page_rec_is_user_rec(rec)) { lock = lock_rec_get_first(rec); @@ -4511,7 +4415,7 @@ lock_rec_queue_validate( ut_a(lock->index == index); } - lock = lock_rec_get_next(rec, comp, lock); + lock = lock_rec_get_next(rec, lock); } lock_mutex_exit_kernel(); @@ -4524,10 +4428,10 @@ lock_rec_queue_validate( impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets); if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0, - LOCK_WAIT, rec, comp, impl_trx)) { + LOCK_WAIT, rec, impl_trx)) { ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec, - comp, impl_trx)); + impl_trx)); } } @@ -4541,10 +4445,10 @@ lock_rec_queue_validate( rec, index, offsets); if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0, - LOCK_WAIT, rec, comp, impl_trx)) { + LOCK_WAIT, rec, impl_trx)) { ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, - rec, comp, impl_trx)); + rec, impl_trx)); } } @@ -4561,21 +4465,23 @@ lock_rec_queue_validate( } if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) { + + ulint mode; if (lock_get_mode(lock) == LOCK_S) { - ut_a(!lock_rec_other_has_expl_req(LOCK_X, - 0, 0, rec, comp, lock->trx)); + mode = LOCK_X; } else { - ut_a(!lock_rec_other_has_expl_req(LOCK_S, - 0, 0, rec, comp, lock->trx)); + mode = LOCK_S; } + ut_a(!lock_rec_other_has_expl_req(mode, + 0, 0, rec, lock->trx)); } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) { ut_a(lock_rec_has_to_wait_in_queue(lock)); } - lock = lock_rec_get_next(rec, comp, lock); + lock = lock_rec_get_next(rec, lock); } lock_mutex_exit_kernel(); @@ -4673,7 +4579,7 @@ function_exit: mtr_commit(&mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(TRUE); @@ -4859,7 +4765,7 @@ lock_rec_insert_check_and_lock( offsets = rec_get_offsets(next_rec, index, offsets_, ULINT_UNDEFINED, &heap); ut_ad(lock_rec_queue_validate(next_rec, index, offsets)); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -4887,7 +4793,7 @@ lock_rec_convert_impl_to_expl( #endif /* UNIV_SYNC_DEBUG */ ut_ad(page_rec_is_user_rec(rec)); ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(page_is_comp(buf_frame_align(rec)) == index->table->comp); + ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets)); if (index->type & DICT_CLUSTERED) { impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets); @@ -4901,7 +4807,7 @@ lock_rec_convert_impl_to_expl( record, set one for it */ if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec, - index->table->comp, impl_trx)) { + impl_trx)) { lock_rec_add_to_queue(LOCK_REC | LOCK_X | LOCK_REC_NOT_GAP, rec, index, @@ -5008,7 +4914,7 @@ lock_sec_rec_modify_check_and_lock( offsets = rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap); ut_ad(lock_rec_queue_validate(rec, index, offsets)); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } diff --git a/storage/innobase/log/log0log.c b/storage/innobase/log/log0log.c index 560f51401ac..5953262ece7 100644 --- a/storage/innobase/log/log0log.c +++ b/storage/innobase/log/log0log.c @@ -57,10 +57,11 @@ ulint log_fsp_current_free_limit = 0; /* Global log system variable */ log_t* log_sys = NULL; +#ifdef UNIV_DEBUG ibool log_do_write = TRUE; ibool log_debug_writes = FALSE; - +#endif /* UNIV_DEBUG */ /* These control how often we print warnings if the last checkpoint is too old */ @@ -974,22 +975,24 @@ log_group_check_flush_completion( #endif /* UNIV_SYNC_DEBUG */ if (!log_sys->one_flushed && group->n_pending_writes == 0) { +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "Log flushed first to group %lu\n", (ulong) group->id); } - +#endif /* UNIV_DEBUG */ log_sys->written_to_some_lsn = log_sys->write_lsn; log_sys->one_flushed = TRUE; return(LOG_UNLOCK_NONE_FLUSHED_LOCK); } +#ifdef UNIV_DEBUG if (log_debug_writes && (group->n_pending_writes == 0)) { fprintf(stderr, "Log flushed to group %lu\n", (ulong) group->id); } - +#endif /* UNIV_DEBUG */ return(0); } @@ -1066,12 +1069,13 @@ log_io_complete( fil_flush(group->space_id); } +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "Checkpoint info written to group %lu\n", group->id); } - +#endif /* UNIV_DEBUG */ log_io_complete_checkpoint(); return; @@ -1133,12 +1137,13 @@ log_group_file_header_flush( dest_offset = nth_file * group->file_size; +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "Writing log file header to group %lu file %lu\n", (ulong) group->id, (ulong) nth_file); } - +#endif /* UNIV_DEBUG */ if (log_do_write) { log_sys->n_log_ios++; @@ -1226,7 +1231,8 @@ loop: } else { write_len = len; } - + +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, @@ -1250,7 +1256,7 @@ loop: + i * OS_FILE_LOG_BLOCK_SIZE)); } } - +#endif /* UNIV_DEBUG */ /* Calculate the checksums for each log block and write them to the trailer fields of the log blocks */ @@ -1384,6 +1390,7 @@ loop: return; } +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "Writing log from %lu %lu up to lsn %lu %lu\n", @@ -1392,7 +1399,7 @@ loop: (ulong) ut_dulint_get_high(log_sys->lsn), (ulong) ut_dulint_get_low(log_sys->lsn)); } - +#endif /* UNIV_DEBUG */ log_sys->n_pending_writes++; group = UT_LIST_GET_FIRST(log_sys->log_groups); @@ -1961,12 +1968,14 @@ log_checkpoint( log_sys->next_checkpoint_lsn = oldest_lsn; +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "Making checkpoint no %lu at lsn %lu %lu\n", (ulong) ut_dulint_get_low(log_sys->next_checkpoint_no), (ulong) ut_dulint_get_high(oldest_lsn), (ulong) ut_dulint_get_low(oldest_lsn)); } +#endif /* UNIV_DEBUG */ log_groups_write_checkpoint_info(); @@ -2029,8 +2038,6 @@ log_checkpoint_margin(void) ulint checkpoint_age; ulint advance; dulint oldest_lsn; - dulint new_oldest; - ibool do_preflush; ibool sync; ibool checkpoint_sync; ibool do_checkpoint; @@ -2038,7 +2045,6 @@ log_checkpoint_margin(void) loop: sync = FALSE; checkpoint_sync = FALSE; - do_preflush = FALSE; do_checkpoint = FALSE; mutex_enter(&(log->mutex)); @@ -2058,21 +2064,13 @@ loop: /* A flush is urgent: we have to do a synchronous preflush */ sync = TRUE; - - advance = 2 * (age - log->max_modified_age_sync); - - new_oldest = ut_dulint_add(oldest_lsn, advance); - - do_preflush = TRUE; - + advance = 2 * (age - log->max_modified_age_async); } else if (age > log->max_modified_age_async) { /* A flush is not urgent: we do an asynchronous preflush */ advance = age - log->max_modified_age_async; - - new_oldest = ut_dulint_add(oldest_lsn, advance); - - do_preflush = TRUE; + } else { + advance = 0; } checkpoint_age = ut_dulint_minus(log->lsn, log->last_checkpoint_lsn); @@ -2096,7 +2094,9 @@ loop: mutex_exit(&(log->mutex)); - if (do_preflush) { + if (advance) { + dulint new_oldest = ut_dulint_add(oldest_lsn, advance); + success = log_preflush_pool_modified_pages(new_oldest, sync); /* If the flush succeeded, this thread has done its part @@ -2347,9 +2347,11 @@ loop: exit(1); } +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "Created archive file %s\n", name); } +#endif /* UNIV_DEBUG */ ret = os_file_close(file_handle); @@ -2375,7 +2377,8 @@ loop: len = group->file_size - (next_offset % group->file_size); } - + +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "Archiving starting at lsn %lu %lu, len %lu to group %lu\n", @@ -2383,6 +2386,7 @@ loop: (ulong) ut_dulint_get_low(start_lsn), (ulong) len, (ulong) group->id); } +#endif /* UNIV_DEBUG */ log_sys->n_pending_archive_ios++; @@ -2473,11 +2477,13 @@ log_archive_write_complete_groups(void) trunc_files = n_files - 1; } +#ifdef UNIV_DEBUG if (log_debug_writes && trunc_files) { fprintf(stderr, "Complete file(s) archived to group %lu\n", (ulong) group->id); } +#endif /* UNIV_DEBUG */ /* Calculate the archive file space start lsn */ start_lsn = ut_dulint_subtract(log_sys->next_archived_lsn, @@ -2500,9 +2506,11 @@ log_archive_write_complete_groups(void) fil_space_truncate_start(group->archive_space_id, trunc_files * group->file_size); +#ifdef UNIV_DEBUG if (log_debug_writes) { fputs("Archiving writes completed\n", stderr); } +#endif /* UNIV_DEBUG */ } /********************************************************** @@ -2519,9 +2527,11 @@ log_archive_check_completion_low(void) if (log_sys->n_pending_archive_ios == 0 && log_sys->archiving_phase == LOG_ARCHIVE_READ) { +#ifdef UNIV_DEBUG if (log_debug_writes) { fputs("Archiving read completed\n", stderr); } +#endif /* UNIV_DEBUG */ /* Archive buffer has now been read in: start archive writes */ @@ -2665,6 +2675,7 @@ loop: log_sys->next_archived_lsn = limit_lsn; +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "Archiving from lsn %lu %lu to lsn %lu %lu\n", @@ -2673,6 +2684,7 @@ loop: (ulong) ut_dulint_get_high(limit_lsn), (ulong) ut_dulint_get_low(limit_lsn)); } +#endif /* UNIV_DEBUG */ /* Read the log segment to the archive buffer */ @@ -2775,12 +2787,14 @@ log_archive_close_groups( group->archived_file_no += 2; } +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "Incrementing arch file no to %lu in log group %lu\n", (ulong) group->archived_file_no + 2, (ulong) group->id); } +#endif /* UNIV_DEBUG */ } } diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c index 6597122f104..0417d01d89a 100644 --- a/storage/innobase/log/log0recv.c +++ b/storage/innobase/log/log0recv.c @@ -489,6 +489,7 @@ recv_find_max_checkpoint( log_group_read_checkpoint_info(group, field); if (!recv_check_cp_is_consistent(buf)) { +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "InnoDB: Checkpoint in group %lu at %lu invalid, %lu\n", @@ -498,7 +499,7 @@ recv_find_max_checkpoint( + LOG_CHECKPOINT_CHECKSUM_1)); } - +#endif /* UNIV_DEBUG */ goto not_consistent; } @@ -511,13 +512,15 @@ recv_find_max_checkpoint( checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO); +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "InnoDB: Checkpoint number %lu found in group %lu\n", (ulong) ut_dulint_get_low(checkpoint_no), (ulong) group->id); } - +#endif /* UNIV_DEBUG */ + if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) { *max_group = group; *max_field = field; @@ -540,7 +543,7 @@ recv_find_max_checkpoint( "InnoDB: to create the InnoDB data files, but log file creation failed.\n" "InnoDB: If that is the case, please refer to\n" "InnoDB: http://dev.mysql.com/doc/mysql/en/Error_creating_InnoDB.html\n"); - + *max_field = 0; return(DB_ERROR); } @@ -765,6 +768,7 @@ recv_parse_or_apply_log_rec_body( case MLOG_REC_INSERT: case MLOG_COMP_REC_INSERT: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_INSERT, &index))) { + ut_a(!page||!!page_is_comp(page)==index->table->comp); ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr, index, page, mtr); } @@ -772,20 +776,27 @@ recv_parse_or_apply_log_rec_body( case MLOG_REC_CLUST_DELETE_MARK: case MLOG_COMP_REC_CLUST_DELETE_MARK: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_CLUST_DELETE_MARK, &index))) { + ut_a(!page||!!page_is_comp(page)==index->table->comp); ptr = btr_cur_parse_del_mark_set_clust_rec(ptr, end_ptr, index, page); } break; - case MLOG_REC_SEC_DELETE_MARK: case MLOG_COMP_REC_SEC_DELETE_MARK: - if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, - type == MLOG_COMP_REC_SEC_DELETE_MARK, &index))) { - ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr, - index, page); + case MLOG_COMP_REC_SEC_DELETE_MARK: + /* This log record type is obsolete, but we process it for + backward compatibility with MySQL 5.0.3 and 5.0.4. */ + ut_a(!page || page_is_comp(page)); + ptr = mlog_parse_index(ptr, end_ptr, TRUE, &index); + if (!ptr) { + break; } + /* Fall through */ + case MLOG_REC_SEC_DELETE_MARK: + ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr, page); break; case MLOG_REC_UPDATE_IN_PLACE: case MLOG_COMP_REC_UPDATE_IN_PLACE: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_UPDATE_IN_PLACE, &index))) { + ut_a(!page||!!page_is_comp(page)==index->table->comp); ptr = btr_cur_parse_update_in_place(ptr, end_ptr, page, index); } @@ -795,6 +806,7 @@ recv_parse_or_apply_log_rec_body( if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_LIST_END_DELETE || type == MLOG_COMP_LIST_START_DELETE, &index))) { + ut_a(!page||!!page_is_comp(page)==index->table->comp); ptr = page_parse_delete_rec_list(type, ptr, end_ptr, index, page, mtr); } @@ -802,6 +814,7 @@ recv_parse_or_apply_log_rec_body( case MLOG_LIST_END_COPY_CREATED: case MLOG_COMP_LIST_END_COPY_CREATED: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_LIST_END_COPY_CREATED, &index))) { + ut_a(!page||!!page_is_comp(page)==index->table->comp); ptr = page_parse_copy_rec_list_to_created_page(ptr, end_ptr, index, page, mtr); } @@ -809,6 +822,7 @@ recv_parse_or_apply_log_rec_body( case MLOG_PAGE_REORGANIZE: case MLOG_COMP_PAGE_REORGANIZE: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_PAGE_REORGANIZE, &index))) { + ut_a(!page||!!page_is_comp(page)==index->table->comp); ptr = btr_parse_page_reorganize(ptr, end_ptr, index, page, mtr); } @@ -841,6 +855,7 @@ recv_parse_or_apply_log_rec_body( case MLOG_REC_DELETE: case MLOG_COMP_REC_DELETE: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_DELETE, &index))) { + ut_a(!page||!!page_is_comp(page)==index->table->comp); ptr = page_cur_parse_delete_rec(ptr, end_ptr, index, page, mtr); } @@ -1186,6 +1201,7 @@ recv_recover_page( start_lsn = recv->start_lsn; } +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "InnoDB: Applying log rec type %lu len %lu to space %lu page no %lu\n", @@ -1193,6 +1209,7 @@ recv_recover_page( (ulong) recv_addr->space, (ulong) recv_addr->page_no); } +#endif /* UNIV_DEBUG */ recv_parse_or_apply_log_rec_body(recv->type, buf, buf + recv->len, page, &mtr); @@ -1801,25 +1818,25 @@ recv_parse_log_rec( new_ptr = mlog_parse_initial_log_record(ptr, end_ptr, type, space, page_no); - if (!new_ptr) { + *body = new_ptr; + + if (UNIV_UNLIKELY(!new_ptr)) { return(0); } /* Check that page_no is sensible */ - if (*page_no > 0x8FFFFFFFUL) { + if (UNIV_UNLIKELY(*page_no > 0x8FFFFFFFUL)) { recv_sys->found_corrupt_log = TRUE; return(0); } - *body = new_ptr; - new_ptr = recv_parse_or_apply_log_rec_body(*type, new_ptr, end_ptr, NULL, NULL); - if (new_ptr == NULL) { + if (UNIV_UNLIKELY(new_ptr == NULL)) { return(0); } @@ -2013,12 +2030,14 @@ loop: recv_sys->recovered_offset += len; recv_sys->recovered_lsn = new_recovered_lsn; +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "InnoDB: Parsed a single log rec type %lu len %lu space %lu page no %lu\n", (ulong) type, (ulong) len, (ulong) space, (ulong) page_no); } +#endif /* UNIV_DEBUG */ if (type == MLOG_DUMMY_RECORD) { /* Do nothing */ @@ -2101,13 +2120,15 @@ loop: body, ptr + len); #endif /* UNIV_LOG_REPLICATE */ } - + +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "InnoDB: Parsed a multi log rec type %lu len %lu space %lu page no %lu\n", (ulong) type, (ulong) len, (ulong) space, (ulong) page_no); } +#endif /* UNIV_DEBUG */ total_len += len; n_recs++; @@ -2514,6 +2535,7 @@ recv_group_scan_log_recs( start_lsn = end_lsn; } +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "InnoDB: Scanned group %lu up to log sequence number %lu %lu\n", @@ -2521,6 +2543,7 @@ recv_group_scan_log_recs( (ulong) ut_dulint_get_high(*group_scanned_lsn), (ulong) ut_dulint_get_low(*group_scanned_lsn)); } +#endif /* UNIV_DEBUG */ } /************************************************************ @@ -2906,10 +2929,12 @@ recv_recovery_from_checkpoint_finish(void) recv_apply_hashed_log_recs(TRUE); } +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "InnoDB: Log records applied to the database\n"); } +#endif /* UNIV_DEBUG */ if (recv_needed_recovery) { trx_sys_print_mysql_master_log_pos(); @@ -3246,6 +3271,7 @@ ask_again: break; } +#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "InnoDB: Archive read starting at lsn %lu %lu, len %lu from file %s\n", @@ -3253,6 +3279,7 @@ ask_again: (ulong) ut_dulint_get_low(start_lsn), (ulong) len, name); } +#endif /* UNIV_DEBUG */ fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, group->archive_space_id, read_offset / UNIV_PAGE_SIZE, diff --git a/storage/innobase/mtr/mtr0log.c b/storage/innobase/mtr/mtr0log.c index 4f826f242e8..0308619073a 100644 --- a/storage/innobase/mtr/mtr0log.c +++ b/storage/innobase/mtr/mtr0log.c @@ -15,6 +15,7 @@ Created 12/7/1995 Heikki Tuuri #include "buf0buf.h" #include "dict0boot.h" #include "log0recv.h" +#include "page0page.h" /************************************************************ Catenates n bytes to the mtr log. */ @@ -22,9 +23,9 @@ Catenates n bytes to the mtr log. */ void mlog_catenate_string( /*=================*/ - mtr_t* mtr, /* in: mtr */ - byte* str, /* in: string to write */ - ulint len) /* in: string length */ + mtr_t* mtr, /* in: mtr */ + const byte* str, /* in: string to write */ + ulint len) /* in: string length */ { dyn_array_t* mlog; @@ -301,14 +302,15 @@ corresponding log record to the mini-transaction log. */ void mlog_write_string( /*==============*/ - byte* ptr, /* in: pointer where to write */ - byte* str, /* in: string to write */ - ulint len, /* in: string length */ - mtr_t* mtr) /* in: mini-transaction handle */ + byte* ptr, /* in: pointer where to write */ + const byte* str, /* in: string to write */ + ulint len, /* in: string length */ + mtr_t* mtr) /* in: mini-transaction handle */ { byte* log_ptr; - if (ptr < buf_pool->frame_zero || ptr >= buf_pool->high_end) { + if (UNIV_UNLIKELY(ptr < buf_pool->frame_zero) + || UNIV_UNLIKELY(ptr >= buf_pool->high_end)) { fprintf(stderr, "InnoDB: Error: trying to write to a stray memory location %p\n", ptr); ut_error; @@ -405,7 +407,9 @@ mlog_open_and_write_index( const byte* log_start; const byte* log_end; - if (!index->table->comp) { + ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + + if (!page_rec_is_comp(rec)) { log_start = log_ptr = mlog_open(mtr, 11 + size); if (!log_ptr) { return(NULL); /* logging is disabled */ @@ -498,6 +502,8 @@ mlog_parse_index( dict_table_t* table; dict_index_t* ind; + ut_ad(comp == FALSE || comp == TRUE); + if (comp) { if (end_ptr < ptr + 4) { return(NULL); diff --git a/storage/innobase/mtr/mtr0mtr.c b/storage/innobase/mtr/mtr0mtr.c index 6e918806eb1..da045be1f62 100644 --- a/storage/innobase/mtr/mtr0mtr.c +++ b/storage/innobase/mtr/mtr0mtr.c @@ -48,16 +48,11 @@ mtr_memo_slot_release( object = slot->object; type = slot->type; - if (object != NULL) { + if (UNIV_LIKELY(object != NULL)) { if (type <= MTR_MEMO_BUF_FIX) { buf_page_release((buf_block_t*)object, type, mtr); } else if (type == MTR_MEMO_S_LOCK) { rw_lock_s_unlock((rw_lock_t*)object); -#ifndef UNIV_DEBUG - } else { - rw_lock_x_unlock((rw_lock_t*)object); - } -#endif #ifdef UNIV_DEBUG } else if (type == MTR_MEMO_X_LOCK) { rw_lock_x_unlock((rw_lock_t*)object); @@ -65,8 +60,11 @@ mtr_memo_slot_release( ut_ad(type == MTR_MEMO_MODIFY); ut_ad(mtr_memo_contains(mtr, object, MTR_MEMO_PAGE_X_FIX)); - } +#else + } else { + rw_lock_x_unlock((rw_lock_t*)object); #endif + } } slot->object = NULL; diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index ac5d1c72c72..8102f24f25a 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -83,7 +83,7 @@ struct os_aio_slot_struct{ made and only the slot message needs to be passed to the caller of os_aio_simulated_handle */ - void* message1; /* message which is given by the */ + fil_node_t* message1; /* message which is given by the */ void* message2; /* the requester of an aio operation and which can be used to identify which pending aio operation was @@ -133,17 +133,17 @@ os_event_t* os_aio_segment_wait_events = NULL; /* The aio arrays for non-ibuf i/o and ibuf i/o, as well as sync aio. These are NULL when the module has not yet been initialized. */ -os_aio_array_t* os_aio_read_array = NULL; -os_aio_array_t* os_aio_write_array = NULL; -os_aio_array_t* os_aio_ibuf_array = NULL; -os_aio_array_t* os_aio_log_array = NULL; -os_aio_array_t* os_aio_sync_array = NULL; +static os_aio_array_t* os_aio_read_array = NULL; +static os_aio_array_t* os_aio_write_array = NULL; +static os_aio_array_t* os_aio_ibuf_array = NULL; +static os_aio_array_t* os_aio_log_array = NULL; +static os_aio_array_t* os_aio_sync_array = NULL; -ulint os_aio_n_segments = ULINT_UNDEFINED; +static ulint os_aio_n_segments = ULINT_UNDEFINED; /* If the following is TRUE, read i/o handler threads try to wait until a batch of new read requests have been posted */ -ibool os_aio_recommend_sleep_for_read_threads = FALSE; +static ibool os_aio_recommend_sleep_for_read_threads = FALSE; ulint os_n_file_reads = 0; ulint os_bytes_read_since_printout = 0; @@ -158,7 +158,7 @@ ibool os_has_said_disk_full = FALSE; /* The mutex protecting the following counts of pending pread and pwrite operations */ -os_mutex_t os_file_count_mutex; +static os_mutex_t os_file_count_mutex; ulint os_file_n_pending_preads = 0; ulint os_file_n_pending_pwrites = 0; @@ -3025,7 +3025,7 @@ os_aio_array_reserve_slot( /* out: pointer to slot */ ulint type, /* in: OS_FILE_READ or OS_FILE_WRITE */ os_aio_array_t* array, /* in: aio array */ - void* message1,/* in: message to be passed along with + fil_node_t* message1,/* in: message to be passed along with the aio operation */ void* message2,/* in: message to be passed along with the aio operation */ @@ -3287,7 +3287,7 @@ os_aio( ulint offset_high, /* in: most significant 32 bits of offset */ ulint n, /* in: number of bytes to read or write */ - void* message1,/* in: messages for the aio handler (these + fil_node_t* message1,/* in: messages for the aio handler (these can be used to identify a completed aio operation); if mode is OS_AIO_SYNC, these are ignored */ @@ -3472,7 +3472,7 @@ os_aio_windows_handle( ignored */ ulint pos, /* this parameter is used only in sync aio: wait for the aio slot at this position */ - void** message1, /* out: the messages passed with the aio + fil_node_t**message1, /* out: the messages passed with the aio request; note that also in the case where the aio operation failed, these output parameters are valid and can be used to @@ -3563,7 +3563,7 @@ os_aio_posix_handle( /*================*/ /* out: TRUE if the aio operation succeeded */ ulint array_no, /* in: array number 0 - 3 */ - void** message1, /* out: the messages passed with the aio + fil_node_t**message1, /* out: the messages passed with the aio request; note that also in the case where the aio operation failed, these output parameters are valid and can be used to @@ -3644,7 +3644,7 @@ os_aio_simulated_handle( i/o thread, segment 1 the log i/o thread, then follow the non-ibuf read threads, and as the last are the non-ibuf write threads */ - void** message1, /* out: the messages passed with the aio + fil_node_t**message1, /* out: the messages passed with the aio request; note that also in the case where the aio operation failed, these output parameters are valid and can be used to @@ -4182,6 +4182,7 @@ os_aio_refresh_stats(void) os_last_printout = time(NULL); } +#ifdef UNIV_DEBUG /************************************************************************** Checks that all slots in the system have been freed, that is, there are no pending io operations. */ @@ -4241,3 +4242,4 @@ os_aio_all_slots_free(void) return(FALSE); } +#endif /* UNIV_DEBUG */ diff --git a/storage/innobase/page/page0cur.c b/storage/innobase/page/page0cur.c index 7738f5a34f0..df6d898d4ac 100644 --- a/storage/innobase/page/page0cur.c +++ b/storage/innobase/page/page0cur.c @@ -129,7 +129,7 @@ page_cur_try_search_shortcut( #endif success = TRUE; exit_func: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(success); @@ -451,7 +451,7 @@ page_cur_search_with_match( *iup_matched_bytes = up_matched_bytes; *ilow_matched_fields = low_matched_fields; *ilow_matched_bytes = low_matched_bytes; - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -515,8 +515,12 @@ page_cur_insert_rec_write_log( byte* log_ptr; byte* log_end; ulint i; + ulint comp; ut_a(rec_size < UNIV_PAGE_SIZE); + ut_ad(buf_frame_align(insert_rec) == buf_frame_align(cursor_rec)); + ut_ad(!page_rec_is_comp(insert_rec) == !index->table->comp); + comp = page_rec_is_comp(insert_rec); { mem_heap_t* heap = NULL; @@ -539,7 +543,7 @@ page_cur_insert_rec_write_log( ut_ad(rec_size == rec_offs_size(ins_offs)); cur_rec_size = rec_offs_size(cur_offs); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -565,7 +569,7 @@ page_cur_insert_rec_write_log( ins_ptr++; cur_ptr++; } else if ((i < extra_size) - && (i >= extra_size - (index->table->comp + && (i >= extra_size - (comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES))) { i = extra_size; @@ -580,7 +584,7 @@ page_cur_insert_rec_write_log( if (mtr_get_log_mode(mtr) != MTR_LOG_SHORT_INSERTS) { log_ptr = mlog_open_and_write_index(mtr, insert_rec, index, - index->table->comp + comp ? MLOG_COMP_REC_INSERT : MLOG_REC_INSERT, 2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN); @@ -605,8 +609,8 @@ page_cur_insert_rec_write_log( log_end = &log_ptr[5 + 1 + 5 + 5 + MLOG_BUF_MARGIN]; } - if ((rec_get_info_and_status_bits(insert_rec, index->table->comp) != - rec_get_info_and_status_bits(cursor_rec, index->table->comp)) + if ((rec_get_info_and_status_bits(insert_rec, comp) != + rec_get_info_and_status_bits(cursor_rec, comp)) || (extra_size != cur_extra_size) || (rec_size != cur_rec_size)) { @@ -622,8 +626,7 @@ page_cur_insert_rec_write_log( if (extra_info_yes) { /* Write the info bits */ mach_write_to_1(log_ptr, - rec_get_info_and_status_bits(insert_rec, - index->table->comp)); + rec_get_info_and_status_bits(insert_rec, comp)); log_ptr++; /* Write the record origin offset */ @@ -757,6 +760,8 @@ page_cur_parse_insert_rec( return(ptr + end_seg_len); } + ut_ad(!!page_is_comp(page) == index->table->comp); + /* Read from the log the inserted index record end segment which differs from the cursor record */ @@ -771,7 +776,7 @@ page_cur_parse_insert_rec( if (extra_info_yes == 0) { info_and_status_bits = rec_get_info_and_status_bits( - cursor_rec, index->table->comp); + cursor_rec, page_is_comp(page)); origin_offset = rec_offs_extra_size(offsets); mismatch_index = rec_offs_size(offsets) - end_seg_len; } @@ -807,7 +812,7 @@ page_cur_parse_insert_rec( ut_memcpy(buf, rec_get_start(cursor_rec, offsets), mismatch_index); ut_memcpy(buf + mismatch_index, ptr, end_seg_len); - rec_set_info_and_status_bits(buf + origin_offset, index->table->comp, + rec_set_info_and_status_bits(buf + origin_offset, page_is_comp(page), info_and_status_bits); page_cur_position(cursor_rec, &cursor); @@ -821,7 +826,7 @@ page_cur_parse_insert_rec( mem_free(buf); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -861,7 +866,7 @@ page_cur_insert_rec_low( rec_t* owner_rec; ulint n_owned; mem_heap_t* heap = NULL; - ibool comp = index->table->comp; + ulint comp; ut_ad(cursor && mtr); ut_ad(tuple || rec); @@ -869,8 +874,8 @@ page_cur_insert_rec_low( ut_ad(rec || dtuple_check_typed(tuple)); page = page_cur_get_page(cursor); - - ut_ad(page_is_comp(page) == comp); + comp = page_is_comp(page); + ut_ad(index->table->comp == !!comp); ut_ad(cursor->rec != page_get_supremum_rec(page)); @@ -890,7 +895,7 @@ page_cur_insert_rec_low( insert_buf = page_mem_alloc(page, rec_size, index, &heap_no); if (insert_buf == NULL) { - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(NULL); @@ -980,7 +985,7 @@ page_cur_insert_rec_low( page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec, index, mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(insert_rec); @@ -1000,8 +1005,10 @@ page_copy_rec_list_to_created_page_write_log( { byte* log_ptr; + ut_ad(!!page_is_comp(page) == index->table->comp); + log_ptr = mlog_open_and_write_index(mtr, page, index, - index->table->comp + page_is_comp(page) ? MLOG_COMP_LIST_END_COPY_CREATED : MLOG_LIST_END_COPY_CREATED, 4); ut_a(log_ptr); @@ -1084,7 +1091,7 @@ page_copy_rec_list_end_to_created_page( ulint log_mode; byte* log_ptr; ulint log_data_len; - ibool comp = page_is_comp(page); + ulint comp = page_is_comp(page); mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; @@ -1186,7 +1193,7 @@ page_copy_rec_list_end_to_created_page( slot_index--; } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -1230,8 +1237,10 @@ page_cur_delete_rec_write_log( { byte* log_ptr; + ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + log_ptr = mlog_open_and_write_index(mtr, rec, index, - index->table->comp + page_rec_is_comp(rec) ? MLOG_COMP_REC_DELETE : MLOG_REC_DELETE, 2); @@ -1242,7 +1251,7 @@ page_cur_delete_rec_write_log( } /* Write the cursor rec offset as a 2-byte ulint */ - mach_write_to_2(log_ptr, rec - buf_frame_align(rec)); + mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE)); mlog_close(mtr, log_ptr + 2); } @@ -1285,7 +1294,7 @@ page_cur_parse_delete_rec( page_cur_delete_rec(&cursor, index, rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap), mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -1320,6 +1329,7 @@ page_cur_delete_rec( page = page_cur_get_page(cursor); current_rec = cursor->rec; ut_ad(rec_offs_validate(current_rec, index, offsets)); + ut_ad(!!page_is_comp(page) == index->table->comp); /* The record must not be the supremum or infimum record. */ ut_ad(current_rec != page_get_supremum_rec(page)); diff --git a/storage/innobase/page/page0page.c b/storage/innobase/page/page0page.c index f3217e91f58..9c957ac8554 100644 --- a/storage/innobase/page/page0page.c +++ b/storage/innobase/page/page0page.c @@ -72,65 +72,70 @@ page_dir_find_owner_slot( /* out: the directory slot number */ rec_t* rec) /* in: the physical record */ { - ulint i; - ulint steps = 0; - page_t* page; - page_dir_slot_t* slot; - rec_t* original_rec = rec; - ibool comp; - + page_t* page; + register uint16 rec_offs_bytes; + register page_dir_slot_t* slot; + register const page_dir_slot_t* first_slot; + register rec_t* r = rec; + ut_ad(page_rec_check(rec)); page = buf_frame_align(rec); - comp = page_is_comp(page); - - while (rec_get_n_owned(rec, comp) == 0) { - steps++; - rec = page_rec_get_next(rec); + first_slot = page_dir_get_nth_slot(page, 0); + slot = page_dir_get_nth_slot(page, page_dir_get_n_slots(page) - 1); + + if (page_is_comp(page)) { + while (rec_get_n_owned(r, TRUE) == 0) { + r = page + rec_get_next_offs(r, TRUE); + ut_ad(r >= page + PAGE_NEW_SUPREMUM); + ut_ad(r < page + (UNIV_PAGE_SIZE - PAGE_DIR)); + } + } else { + while (rec_get_n_owned(r, FALSE) == 0) { + r = page + rec_get_next_offs(r, FALSE); + ut_ad(r >= page + PAGE_OLD_SUPREMUM); + ut_ad(r < page + (UNIV_PAGE_SIZE - PAGE_DIR)); + } } - - page = buf_frame_align(rec); - i = page_dir_get_n_slots(page) - 1; - slot = page_dir_get_nth_slot(page, i); + rec_offs_bytes = mach_encode_2(r - page); - while (page_dir_slot_get_rec(slot) != rec) { + while (UNIV_LIKELY(*(uint16*) slot != rec_offs_bytes)) { - if (i == 0) { + if (UNIV_UNLIKELY(slot == first_slot)) { fprintf(stderr, "InnoDB: Probable data corruption on page %lu\n" "InnoDB: Original record ", (ulong) buf_frame_get_page_no(page)); - if (comp) { + if (page_is_comp(page)) { fputs("(compact record)", stderr); } else { - rec_print_old(stderr, original_rec); + rec_print_old(stderr, rec); } - fprintf(stderr, "\n" - "InnoDB: on that page. Steps %lu.\n", (ulong) steps); - fputs( + fputs("\n" + "InnoDB: on that page.\n" "InnoDB: Cannot find the dir slot for record ", stderr); - if (comp) { + if (page_is_comp(page)) { fputs("(compact record)", stderr); } else { - rec_print_old(stderr, rec); + rec_print_old(stderr, page + + mach_decode_2(rec_offs_bytes)); } fputs("\n" "InnoDB: on that page!\n", stderr); buf_page_print(page); - ut_error; - } + ut_error; + } - i--; - slot = page_dir_get_nth_slot(page, i); + slot += PAGE_DIR_SLOT_SIZE; } - return(i); + return(((ulint) (first_slot - slot)) / PAGE_DIR_SLOT_SIZE); } /****************************************************************** @@ -252,13 +257,13 @@ page_mem_alloc( *heap_no = rec_get_heap_no(rec, page_is_comp(page)); block = rec_get_start(rec, offsets); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(block); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -290,7 +295,7 @@ page_create_write_log( buf_frame_t* frame, /* in: a buffer frame where the page is created */ mtr_t* mtr, /* in: mini-transaction handle */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { mlog_write_initial_log_record(frame, comp ? MLOG_COMP_PAGE_CREATE : MLOG_PAGE_CREATE, mtr); @@ -305,7 +310,7 @@ page_parse_create( /* out: end of log record or NULL */ byte* ptr, /* in: buffer */ byte* end_ptr __attribute__((unused)), /* 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 */ { @@ -330,7 +335,7 @@ page_create( buf_frame_t* frame, /* in: a buffer frame where the page is created */ mtr_t* mtr, /* in: mini-transaction handle */ - ibool comp) /* in: TRUE=compact page format */ + ulint comp) /* in: nonzero=compact page format */ { page_dir_slot_t* slot; mem_heap_t* heap; @@ -396,9 +401,9 @@ page_create( dtuple_set_info_bits(tuple, REC_STATUS_SUPREMUM); field = dtuple_get_nth_field(tuple, 0); - dfield_set_data(field, "supremum", 9 - comp); + dfield_set_data(field, "supremum", comp ? 8 : 9); dtype_set(dfield_get_type(field), - DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, 9 - comp, 0); + DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, comp ? 8 : 9, 0); supremum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple); @@ -478,10 +483,11 @@ page_copy_rec_list_end_no_locks( page_cur_move_to_next(&cur1); } - ut_a(index->table->comp == page_is_comp(page)); - ut_a(index->table->comp == page_is_comp(new_page)); + ut_a(!!page_is_comp(new_page) == index->table->comp); + ut_a(page_is_comp(new_page) == page_is_comp(page)); ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == (ulint) - (index->table->comp ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM)); + (page_is_comp(new_page) + ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM)); page_cur_set_before_first(new_page, &cur2); @@ -489,12 +495,15 @@ page_copy_rec_list_end_no_locks( sup = page_get_supremum_rec(page); - while (sup != page_cur_get_rec(&cur1)) { + for (;;) { rec_t* cur1_rec = page_cur_get_rec(&cur1); + if (cur1_rec == sup) { + break; + } offsets = rec_get_offsets(cur1_rec, index, offsets, ULINT_UNDEFINED, &heap); - if (!page_cur_rec_insert(&cur2, cur1_rec, index, - offsets, mtr)) { + if (UNIV_UNLIKELY(!page_cur_rec_insert(&cur2, cur1_rec, index, + offsets, mtr))) { /* Track an assertion failure reported on the mailing list on June 18th, 2003 */ @@ -514,7 +523,7 @@ page_copy_rec_list_end_no_locks( page_cur_move_to_next(&cur2); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -608,7 +617,7 @@ page_copy_rec_list_start( btr_search_move_or_delete_hash_entries(new_page, page, index); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -619,7 +628,6 @@ UNIV_INLINE void page_delete_rec_list_write_log( /*===========================*/ - page_t* page, /* in: index page */ rec_t* rec, /* in: record on page */ dict_index_t* index, /* in: record descriptor */ byte type, /* in: operation type: @@ -632,10 +640,10 @@ page_delete_rec_list_write_log( || type == MLOG_COMP_LIST_END_DELETE || type == MLOG_COMP_LIST_START_DELETE); - log_ptr = mlog_open_and_write_index(mtr, page, index, type, 2); + log_ptr = mlog_open_and_write_index(mtr, rec, index, type, 2); if (log_ptr) { /* Write the parameter as a 2-byte ulint */ - mach_write_to_2(log_ptr, rec - page); + mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE)); mlog_close(mtr, log_ptr + 2); } } @@ -679,6 +687,8 @@ page_parse_delete_rec_list( return(ptr); } + ut_ad(!!page_is_comp(page) == index->table->comp); + if (type == MLOG_LIST_END_DELETE || type == MLOG_COMP_LIST_END_DELETE) { page_delete_rec_list_end(page, page + offset, index, @@ -716,7 +726,7 @@ page_delete_rec_list_end( ulint count; ulint n_owned; rec_t* sup; - ibool comp; + ulint comp; /* Reset the last insert info in the page header and increment the modify clock for the frame */ @@ -731,12 +741,12 @@ page_delete_rec_list_end( sup = page_get_supremum_rec(page); - if (rec == page_get_infimum_rec(page)) { + comp = page_is_comp(page); + if (page_rec_is_infimum_low(rec - page)) { rec = page_rec_get_next(rec); } - comp = page_is_comp(page); - page_delete_rec_list_write_log(page, rec, index, + page_delete_rec_list_write_log(rec, index, comp ? MLOG_COMP_LIST_END_DELETE : MLOG_LIST_END_DELETE, mtr); if (rec == sup) { @@ -772,7 +782,7 @@ page_delete_rec_list_end( rec2 = page_rec_get_next(rec2); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -841,13 +851,15 @@ page_delete_rec_list_start( byte type; *offsets_ = (sizeof offsets_) / sizeof *offsets_; - if (index->table->comp) { + ut_ad(!!page_is_comp(page) == index->table->comp); + + if (page_is_comp(page)) { type = MLOG_COMP_LIST_START_DELETE; } else { type = MLOG_LIST_START_DELETE; } - page_delete_rec_list_write_log(page, rec, index, type, mtr); + page_delete_rec_list_write_log(rec, index, type, mtr); page_cur_set_before_first(page, &cur1); @@ -868,7 +880,7 @@ page_delete_rec_list_start( page_cur_delete_rec(&cur1, index, offsets, mtr); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -1221,7 +1233,7 @@ page_rec_get_n_recs_before( rec_t* slot_rec; page_t* page; ulint i; - ibool comp; + ulint comp; lint n = 0; ut_ad(page_rec_check(rec)); @@ -1264,9 +1276,9 @@ page_rec_print( rec_t* rec, /* in: physical record */ const ulint* offsets)/* in: record descriptor */ { - ibool comp = page_is_comp(buf_frame_align(rec)); + ulint comp = page_is_comp(buf_frame_align(rec)); - ut_a(comp == rec_offs_comp(offsets)); + ut_a(!comp == !rec_offs_comp(offsets)); rec_print_new(stderr, rec, offsets); fprintf(stderr, " n_owned: %lu; heap_no: %lu; next rec: %lu\n", @@ -1335,7 +1347,7 @@ page_print_list( ulint* offsets = offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_; - ut_a(page_is_comp(page) == index->table->comp); + ut_a(!!page_is_comp(page) == index->table->comp); fprintf(stderr, "--------------------------------\n" @@ -1381,7 +1393,7 @@ page_print_list( "--------------------------------\n", (ulong) (count + 1)); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -1447,11 +1459,11 @@ page_rec_validate( ulint n_owned; ulint heap_no; page_t* page; - ibool comp; + ulint comp; page = buf_frame_align(rec); comp = page_is_comp(page); - ut_a(comp == rec_offs_comp(offsets)); + ut_a(!comp == !rec_offs_comp(offsets)); page_rec_check(rec); rec_validate(rec, offsets); @@ -1528,7 +1540,7 @@ page_simple_validate( ulint count; ulint own_count; ibool ret = FALSE; - ibool comp = page_is_comp(page); + ulint comp = page_is_comp(page); /* Check first that the record heap and the directory do not overlap. */ @@ -1725,11 +1737,11 @@ page_validate( ulint n_slots; ibool ret = FALSE; ulint i; - ibool comp = page_is_comp(page); + ulint comp = page_is_comp(page); ulint* offsets = NULL; ulint* old_offsets = NULL; - if (comp != index->table->comp) { + if (!!comp != index->table->comp) { fputs("InnoDB: 'compact format' flag mismatch\n", stderr); goto func_exit2; } @@ -1810,8 +1822,7 @@ page_validate( } } - if ((rec != page_get_supremum_rec(page)) - && (rec != page_get_infimum_rec(page))) { + if (page_rec_is_user_rec(rec)) { data_size += rec_offs_size(offsets); } diff --git a/storage/innobase/rem/rem0cmp.c b/storage/innobase/rem/rem0cmp.c index 74348b865a8..7c33476fb9e 100644 --- a/storage/innobase/rem/rem0cmp.c +++ b/storage/innobase/rem/rem0cmp.c @@ -320,7 +320,7 @@ cmp_data_data_slow( || (cur_type->mtype == DATA_BLOB && 0 == (cur_type->prtype & DATA_BINARY_TYPE) && dtype_get_charset_coll(cur_type->prtype) != - data_mysql_latin1_swedish_charset_coll)) { + DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) { return(cmp_whole_field(cur_type, data1, (unsigned) len1, @@ -451,6 +451,20 @@ cmp_dtuple_rec_with_match( ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple)); ut_ad(cur_field <= rec_offs_n_fields(offsets)); + if (cur_bytes == 0 && cur_field == 0) { + ulint rec_info = rec_get_info_bits(rec, + rec_offs_comp(offsets)); + ulint tup_info = dtuple_get_info_bits(dtuple); + + if (rec_info & REC_INFO_MIN_REC_FLAG) { + ret = !(tup_info & REC_INFO_MIN_REC_FLAG); + goto order_resolved; + } else if (tup_info & REC_INFO_MIN_REC_FLAG) { + ret = -1; + goto order_resolved; + } + } + /* Match fields in a loop; stop if we run out of fields in dtuple or find an externally stored field */ @@ -469,32 +483,7 @@ cmp_dtuple_rec_with_match( the predefined minimum record, or the field is externally stored */ - if (cur_bytes == 0) { - if (cur_field == 0) { - - if (rec_get_info_bits(rec, - rec_offs_comp(offsets)) - & REC_INFO_MIN_REC_FLAG) { - - if (dtuple_get_info_bits(dtuple) - & REC_INFO_MIN_REC_FLAG) { - - ret = 0; - } else { - ret = 1; - } - - goto order_resolved; - } - - if (dtuple_get_info_bits(dtuple) - & REC_INFO_MIN_REC_FLAG) { - ret = -1; - - goto order_resolved; - } - } - + if (UNIV_LIKELY(cur_bytes == 0)) { if (rec_offs_nth_extern(offsets, cur_field)) { /* We do not compare to an externally stored field */ @@ -504,24 +493,20 @@ cmp_dtuple_rec_with_match( goto order_resolved; } - if (dtuple_f_len == UNIV_SQL_NULL - || rec_f_len == UNIV_SQL_NULL) { - - if (dtuple_f_len == rec_f_len) { + if (dtuple_f_len == UNIV_SQL_NULL) { + if (rec_f_len == UNIV_SQL_NULL) { goto next_field; } - if (rec_f_len == UNIV_SQL_NULL) { - /* We define the SQL null to be the - smallest possible value of a field - in the alphabetical order */ - - ret = 1; - } else { - ret = -1; - } + ret = -1; + goto order_resolved; + } else if (rec_f_len == UNIV_SQL_NULL) { + /* We define the SQL null to be the + smallest possible value of a field + in the alphabetical order */ + ret = 1; goto order_resolved; } } @@ -530,7 +515,7 @@ cmp_dtuple_rec_with_match( || (cur_type->mtype == DATA_BLOB && 0 == (cur_type->prtype & DATA_BINARY_TYPE) && dtype_get_charset_coll(cur_type->prtype) != - data_mysql_latin1_swedish_charset_coll)) { + DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) { ret = cmp_whole_field( cur_type, @@ -555,7 +540,7 @@ cmp_dtuple_rec_with_match( /* Compare then the fields */ for (;;) { - if (rec_f_len <= cur_bytes) { + if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) { if (dtuple_f_len <= cur_bytes) { goto next_field; @@ -572,7 +557,7 @@ cmp_dtuple_rec_with_match( rec_byte = *rec_b_ptr; } - if (dtuple_f_len <= cur_bytes) { + if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) { dtuple_byte = dtype_get_pad_char(cur_type); if (dtuple_byte == ULINT_UNDEFINED) { @@ -600,14 +585,16 @@ cmp_dtuple_rec_with_match( rec_byte = cmp_collate(rec_byte); dtuple_byte = cmp_collate(dtuple_byte); } - - if (dtuple_byte > rec_byte) { - ret = 1; - goto order_resolved; - } else if (dtuple_byte < rec_byte) { - ret = -1; - goto order_resolved; + ret = dtuple_byte - rec_byte; + if (UNIV_UNLIKELY(ret)) { + if (ret < 0) { + ret = -1; + goto order_resolved; + } else { + ret = 1; + goto order_resolved; + } } next_byte: /* Next byte */ @@ -740,7 +727,7 @@ cmp_rec_rec_with_match( ulint cur_bytes; /* number of already matched bytes in current field */ int ret = 3333; /* return value */ - ibool comp; + ulint comp; ut_ad(rec1 && rec2 && index); ut_ad(rec_offs_validate(rec1, index, offsets1)); @@ -832,7 +819,7 @@ cmp_rec_rec_with_match( || (cur_type->mtype == DATA_BLOB && 0 == (cur_type->prtype & DATA_BINARY_TYPE) && dtype_get_charset_coll(cur_type->prtype) != - data_mysql_latin1_swedish_charset_coll)) { + DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) { ret = cmp_whole_field(cur_type, rec1_b_ptr, (unsigned) rec1_f_len, @@ -983,12 +970,8 @@ cmp_debug_dtuple_rec_with_match( if (rec_get_info_bits(rec, rec_offs_comp(offsets)) & REC_INFO_MIN_REC_FLAG) { - if (dtuple_get_info_bits(dtuple) - & REC_INFO_MIN_REC_FLAG) { - ret = 0; - } else { - ret = 1; - } + ret = !(dtuple_get_info_bits(dtuple) + & REC_INFO_MIN_REC_FLAG); goto order_resolved; } diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index 542c746209b..580a7bfe509 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -159,22 +159,20 @@ rec_init_offsets( ulint* offsets)/* in/out: array of offsets; in: n=rec_offs_n_fields(offsets) */ { - ulint n_fields = rec_offs_n_fields(offsets); ulint i = 0; ulint offs; rec_offs_make_valid(rec, index, offsets); - if (index->table->comp) { + if (UNIV_LIKELY(index->table->comp)) { const byte* nulls; const byte* lens; dict_field_t* field; - dtype_t* type; ulint null_mask; ulint status = rec_get_status(rec); ulint n_node_ptr_field = ULINT_UNDEFINED; - switch (status) { + switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) { case REC_STATUS_INFIMUM: case REC_STATUS_SUPREMUM: /* the field is 8 bytes long */ @@ -196,56 +194,69 @@ rec_init_offsets( null_mask = 1; /* read the lengths of fields 0..n */ - for (; i < n_fields; i++) { - ibool is_null = FALSE, is_external = FALSE; + do { ulint len; - if (i == n_node_ptr_field) { - len = 4; + if (UNIV_UNLIKELY(i == n_node_ptr_field)) { + len = offs += 4; goto resolved; } field = dict_index_get_nth_field(index, i); - type = dict_col_get_type(dict_field_get_col(field)); - if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) { + if (!(dtype_get_prtype(dict_col_get_type( + dict_field_get_col(field))) + & DATA_NOT_NULL)) { /* nullable field => read the null flag */ - is_null = (*nulls & null_mask) != 0; - null_mask <<= 1; - if (null_mask == 0x100) { + + if (UNIV_UNLIKELY(!(byte) null_mask)) { nulls--; null_mask = 1; } + + if (*nulls & null_mask) { + null_mask <<= 1; + /* No length is stored for NULL fields. + We do not advance offs, and we set + the length to zero and enable the + SQL NULL flag in offsets[]. */ + len = offs | REC_OFFS_SQL_NULL; + goto resolved; + } + null_mask <<= 1; } - if (is_null) { - /* No length is stored for NULL fields. */ - len = 0; - } else if (!field->fixed_len) { + if (UNIV_UNLIKELY(!field->fixed_len)) { /* Variable-length field: read the length */ + dtype_t* type = dict_col_get_type( + dict_field_get_col(field)); len = *lens--; - if (dtype_get_len(type) > 255 - || dtype_get_mtype(type) == DATA_BLOB) { + if (UNIV_UNLIKELY(dtype_get_len(type) > 255) + || UNIV_UNLIKELY(dtype_get_mtype(type) + == DATA_BLOB)) { if (len & 0x80) { /* 1exxxxxxx xxxxxxxx */ - is_external = !!(len & 0x40); - len &= 0x3f; len <<= 8; len |= *lens--; + + offs += len & 0x3fff; + if (UNIV_UNLIKELY(len + & 0x4000)) { + len = offs + | REC_OFFS_EXTERNAL; + } else { + len = offs; + } + + goto resolved; } } + + len = offs += len; } else { - len = field->fixed_len; + len = offs += field->fixed_len; } resolved: - offs += len; - len = offs; - if (is_external) { - len |= REC_OFFS_EXTERNAL; - } - if (is_null) { - len |= REC_OFFS_SQL_NULL; - } rec_offs_base(offsets)[i + 1] = len; - } + } while (++i < rec_offs_n_fields(offsets)); *rec_offs_base(offsets) = (rec - (lens + 1)) | REC_OFFS_COMPACT; @@ -253,22 +264,22 @@ rec_init_offsets( /* Old-style record: determine extra size and end offsets */ offs = REC_N_OLD_EXTRA_BYTES; if (rec_get_1byte_offs_flag(rec)) { - offs += n_fields; + offs += rec_offs_n_fields(offsets); *rec_offs_base(offsets) = offs; /* Determine offsets to fields */ - for (; i < n_fields; i++) { + do { offs = rec_1_get_field_end_info(rec, i); if (offs & REC_1BYTE_SQL_NULL_MASK) { offs &= ~REC_1BYTE_SQL_NULL_MASK; offs |= REC_OFFS_SQL_NULL; } rec_offs_base(offsets)[1 + i] = offs; - } + } while (++i < rec_offs_n_fields(offsets)); } else { - offs += 2 * n_fields; + offs += 2 * rec_offs_n_fields(offsets); *rec_offs_base(offsets) = offs; /* Determine offsets to fields */ - for (; i < n_fields; i++) { + do { offs = rec_2_get_field_end_info(rec, i); if (offs & REC_2BYTE_SQL_NULL_MASK) { offs &= ~REC_2BYTE_SQL_NULL_MASK; @@ -279,7 +290,7 @@ rec_init_offsets( offs |= REC_OFFS_EXTERNAL; } rec_offs_base(offsets)[1 + i] = offs; - } + } while (++i < rec_offs_n_fields(offsets)); } } } @@ -310,8 +321,9 @@ rec_get_offsets_func( ut_ad(index); ut_ad(heap); - if (index->table->comp) { - switch (rec_get_status(rec)) { + if (UNIV_LIKELY(index->table->comp)) { + switch (UNIV_EXPECT(rec_get_status(rec), + REC_STATUS_ORDINARY)) { case REC_STATUS_ORDINARY: n = dict_index_get_n_fields(index); break; @@ -331,13 +343,14 @@ rec_get_offsets_func( n = rec_get_n_fields_old(rec); } - if (n_fields < n) { + if (UNIV_UNLIKELY(n_fields < n)) { n = n_fields; } size = n + (1 + REC_OFFS_HEADER_SIZE); - if (!offsets || rec_offs_get_n_alloc(offsets) < size) { + if (UNIV_UNLIKELY(!offsets) || + UNIV_UNLIKELY(rec_offs_get_n_alloc(offsets) < size)) { if (!*heap) { *heap = mem_heap_create_func(size * sizeof(ulint), NULL, MEM_HEAP_DYNAMIC, file, line); @@ -652,9 +665,17 @@ rec_set_field_extern_bits( to log about the change */ { ulint i; - - for (i = 0; i < n_fields; i++) { - rec_set_nth_field_extern_bit(rec, index, vec[i], TRUE, mtr); + + if (UNIV_LIKELY(index->table->comp)) { + for (i = 0; i < n_fields; i++) { + rec_set_nth_field_extern_bit_new(rec, index, vec[i], + TRUE, mtr); + } + } else { + for (i = 0; i < n_fields; i++) { + rec_set_nth_field_extern_bit_old(rec, vec[i], + TRUE, mtr); + } } } @@ -949,7 +970,7 @@ rec_convert_dtuple_to_rec( ut_ad(dtuple_validate(dtuple)); ut_ad(dtuple_check_typed(dtuple)); - if (index->table->comp) { + if (UNIV_LIKELY(index->table->comp)) { rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple); } else { rec = rec_convert_dtuple_to_rec_old(buf, dtuple); @@ -965,7 +986,7 @@ rec_convert_dtuple_to_rec( offsets = rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap); ut_ad(rec_validate(rec, offsets)); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -1078,17 +1099,19 @@ rec_copy_prefix_to_buf( for the copied prefix, or NULL */ ulint* buf_size) /* in/out: buffer size */ { - byte* nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); - byte* lens = nulls - (index->n_nullable + 7) / 8; + byte* nulls; + byte* lens; dict_field_t* field; dtype_t* type; ulint i; - ulint prefix_len = 0; + ulint prefix_len; ibool is_null; - ulint null_mask = 1; + ulint null_mask; ulint status; - if (!index->table->comp) { + UNIV_PREFETCH_RW(*buf); + + if (UNIV_UNLIKELY(!index->table->comp)) { ut_ad(rec_validate_old(rec)); return(rec_copy_prefix_to_buf_old(rec, n_fields, rec_get_field_start_offs(rec, n_fields), @@ -1109,10 +1132,16 @@ rec_copy_prefix_to_buf( case REC_STATUS_SUPREMUM: /* infimum or supremum record: no sense to copy anything */ default: - ut_a(0); + ut_error; return(NULL); } + nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); + lens = nulls - (index->n_nullable + 7) / 8; + UNIV_PREFETCH_R(lens); + prefix_len = 0; + null_mask = 1; + /* read the lengths of fields 0..n */ for (i = 0; i < n_fields; i++) { field = dict_index_get_nth_field(index, i); @@ -1122,8 +1151,11 @@ rec_copy_prefix_to_buf( /* nullable field => read the null flag */ is_null = !!(*nulls & null_mask); null_mask <<= 1; - if (null_mask == 0x100) - nulls--, null_mask = 1; + if (null_mask == 0x100) { + --nulls; + UNIV_PREFETCH_R(nulls); + null_mask = 1; + } } if (is_null) { @@ -1138,12 +1170,15 @@ rec_copy_prefix_to_buf( len &= 0x3f; len <<= 8; len |= *lens--; + UNIV_PREFETCH_R(lens); } } prefix_len += len; } } + UNIV_PREFETCH_R(rec + prefix_len); + prefix_len += rec - (lens + 1); if ((*buf == NULL) || (*buf_size < prefix_len)) { @@ -1412,7 +1447,7 @@ rec_print( rec_print_new(file, rec, rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap)); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 303fe5749bc..776094d0de5 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -478,7 +478,7 @@ row_ins_cascade_calc_update_vec( if (parent_ufield->field_no == parent_field_no) { - ulint fixed_size; + ulint min_size; /* A field in the parent index record is updated. Let us make the update vector @@ -508,10 +508,13 @@ row_ins_cascade_calc_update_vec( column, do not allow the update */ if (ufield->new_val.len != UNIV_SQL_NULL - && ufield->new_val.len - > dtype_get_len(type)) { + && dtype_get_at_most_n_mbchars( + type, dtype_get_len(type), + ufield->new_val.len, + ufield->new_val.data) + < ufield->new_val.len) { - return(ULINT_UNDEFINED); + return(ULINT_UNDEFINED); } /* If the parent column type has a different @@ -519,29 +522,46 @@ row_ins_cascade_calc_update_vec( need to pad with spaces the new value of the child column */ - fixed_size = dtype_get_fixed_size(type); - - /* TODO: pad in UCS-2 with 0x0020. - TODO: How does the special truncation of - UTF-8 CHAR cols affect this? */ + min_size = dtype_get_min_size(type); - if (fixed_size + if (min_size && ufield->new_val.len != UNIV_SQL_NULL - && ufield->new_val.len < fixed_size) { + && ufield->new_val.len < min_size) { + char* pad_start; + const char* pad_end; ufield->new_val.data = mem_heap_alloc(heap, - fixed_size); - ufield->new_val.len = fixed_size; - ut_a(dtype_get_pad_char(type) - != ULINT_UNDEFINED); - - memset(ufield->new_val.data, - (byte)dtype_get_pad_char(type), - fixed_size); + min_size); + pad_start = ufield->new_val.data + + ufield->new_val.len; + pad_end = ufield->new_val.data + + min_size; + ufield->new_val.len = min_size; ut_memcpy(ufield->new_val.data, parent_ufield->new_val.data, parent_ufield->new_val.len); + + switch (UNIV_EXPECT( + dtype_get_mbminlen(type), 1)) { + default: + ut_error; + case 1: + /* space=0x20 */ + memset(pad_start, 0x20, + pad_end - pad_start); + break; + case 2: + /* space=0x0020 */ + ut_a(!(ufield->new_val.len + % 2)); + ut_a(!(min_size % 2)); + do { + *pad_start++ = 0x00; + *pad_start++ = 0x20; + } while (pad_start < pad_end); + break; + } } ufield->extern_storage = FALSE; @@ -1255,9 +1275,11 @@ run_again: /* Scan index records and check if there is a matching record */ for (;;) { + page_t* page; rec = btr_pcur_get_rec(&pcur); + page = buf_frame_align(rec); - if (rec == page_get_infimum_rec(buf_frame_align(rec))) { + if (rec == page_get_infimum_rec(page)) { goto next_rec; } @@ -1265,7 +1287,7 @@ run_again: offsets = rec_get_offsets(rec, check_index, offsets, ULINT_UNDEFINED, &heap); - if (rec == page_get_supremum_rec(buf_frame_align(rec))) { + if (rec == page_get_supremum_rec(page)) { err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec, check_index, offsets, thr); @@ -1392,7 +1414,7 @@ do_possible_lock_wait: } exit_func: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); @@ -1529,12 +1551,7 @@ row_ins_dupl_error_with_rec( } } - if (!rec_get_deleted_flag(rec, index->table->comp)) { - - return(TRUE); - } - - return(FALSE); + return(!rec_get_deleted_flag(rec, rec_offs_comp(offsets))); } /******************************************************************* @@ -1629,7 +1646,7 @@ row_ins_scan_sec_index_for_duplicate( break; } - if (rec == page_get_supremum_rec(buf_frame_align(rec))) { + if (page_rec_is_supremum(rec)) { goto next_rec; } @@ -1660,7 +1677,7 @@ next_rec: } } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } mtr_commit(&mtr); @@ -1697,7 +1714,6 @@ row_ins_duplicate_error_in_clust( #ifndef UNIV_HOTBACKUP ulint err; rec_t* rec; - page_t* page; ulint n_unique; trx_t* trx = thr_get_trx(thr); mem_heap_t*heap = NULL; @@ -1728,9 +1744,8 @@ row_ins_duplicate_error_in_clust( if (cursor->low_match >= n_unique) { rec = btr_cur_get_rec(cursor); - page = buf_frame_align(rec); - if (rec != page_get_infimum_rec(page)) { + if (!page_rec_is_infimum(rec)) { offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); @@ -1772,9 +1787,8 @@ row_ins_duplicate_error_in_clust( if (cursor->up_match >= n_unique) { rec = page_rec_get_next(btr_cur_get_rec(cursor)); - page = buf_frame_align(rec); - if (rec != page_get_supremum_rec(page)) { + if (!page_rec_is_supremum(rec)) { offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); @@ -1842,7 +1856,6 @@ row_ins_must_modify( { ulint enough_match; rec_t* rec; - page_t* page; /* NOTE: (compare to the note in row_ins_duplicate_error) Because node pointers on upper levels of the B-tree may match more to entry than @@ -1856,9 +1869,8 @@ row_ins_must_modify( if (cursor->low_match >= enough_match) { rec = btr_cur_get_rec(cursor); - page = buf_frame_align(rec); - if (rec != page_get_infimum_rec(page)) { + if (!page_rec_is_infimum(rec)) { return(ROW_INS_PREV); } @@ -1897,7 +1909,6 @@ row_ins_index_entry_low( ulint modify = 0; /* remove warning */ rec_t* insert_rec; rec_t* rec; - rec_t* first_rec; ulint err; ulint n_unique; big_rec_t* big_rec = NULL; @@ -1932,15 +1943,20 @@ row_ins_index_entry_low( err = DB_SUCCESS; goto function_exit; - } - - first_rec = page_rec_get_next(page_get_infimum_rec( - buf_frame_align(btr_cur_get_rec(&cursor)))); + } + +#ifdef UNIV_DEBUG + { + page_t* page = btr_cur_get_page(&cursor); + rec_t* first_rec = page_rec_get_next( + page_get_infimum_rec(page)); - if (!page_rec_is_supremum(first_rec)) { - ut_a(rec_get_n_fields(first_rec, index) + if (UNIV_LIKELY(first_rec != page_get_supremum_rec(page))) { + ut_a(rec_get_n_fields(first_rec, index) == dtuple_get_n_fields(entry)); + } } +#endif n_unique = dict_index_get_n_unique(index); @@ -2048,7 +2064,7 @@ function_exit: mtr_commit(&mtr); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index fafbef4c999..eb50b83a4d5 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -265,7 +265,7 @@ row_mysql_store_col_in_innobase_format( necessarily the length of the actual payload data; if the column is a true VARCHAR then this is irrelevant */ - ibool comp) /* in: TRUE = compact format */ + ulint comp) /* in: nonzero=compact format */ { byte* ptr = mysql_data; dtype_t* dtype; @@ -971,25 +971,6 @@ run_again: } /************************************************************************* -Unlocks all table locks explicitly requested by trx (with LOCK TABLES, -lock type LOCK_TABLE_EXP). */ - -void -row_unlock_tables_for_mysql( -/*========================*/ - trx_t* trx) /* in: transaction */ -{ - if (!trx->n_lock_table_exp) { - - return; - } - - mutex_enter(&kernel_mutex); - lock_release_tables_off_kernel(trx); - mutex_exit(&kernel_mutex); -} - -/************************************************************************* Sets a table lock on the table mentioned in prebuilt. */ int @@ -1000,9 +981,10 @@ row_lock_table_for_mysql( table handle */ dict_table_t* table, /* in: table to lock, or NULL if prebuilt->table should be - locked or a + locked as prebuilt->select_lock_type */ - ulint mode) /* in: lock mode of table */ + ulint mode) /* in: lock mode of table + (ignored if table==NULL) */ { trx_t* trx = prebuilt->trx; que_thr_t* thr; @@ -1038,14 +1020,8 @@ run_again: if (table) { err = lock_table(0, table, mode, thr); } else { - if (mode == LOCK_TABLE_TRANSACTIONAL) { - err = lock_table(LOCK_TABLE_TRANSACTIONAL, - prebuilt->table, - prebuilt->select_lock_type, thr); - } else { - err = lock_table(LOCK_TABLE_EXP, prebuilt->table, - prebuilt->select_lock_type, thr); - } + err = lock_table(0, prebuilt->table, + prebuilt->select_lock_type, thr); } trx->error_state = err; @@ -3858,7 +3834,7 @@ funct_exit: que_graph_free(graph); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -3893,6 +3869,7 @@ row_scan_and_check_index( int cmp; ibool contains_null; ulint i; + ulint cnt; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; @@ -3915,11 +3892,19 @@ row_scan_and_check_index( dtuple_set_n_fields(prebuilt->search_tuple, 0); prebuilt->select_lock_type = LOCK_NONE; + cnt = 1000; ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0); loop: + /* Check thd->killed every 1,000 scanned rows */ + if (--cnt == 0) { + if (trx_is_interrupted(prebuilt->trx)) { + goto func_exit; + } + cnt = 1000; + } if (ret != DB_SUCCESS) { - + func_exit: mem_free(buf); mem_heap_free(heap); @@ -4046,7 +4031,7 @@ row_check_table_for_mysql( ut_print_name(stderr, index->name); putc('\n', stderr); */ - if (!btr_validate_tree(index->tree)) { + if (!btr_validate_tree(index->tree, prebuilt->trx)) { ret = DB_ERROR; } else { if (!row_scan_and_check_index(prebuilt, @@ -4054,6 +4039,10 @@ row_check_table_for_mysql( ret = DB_ERROR; } + if (trx_is_interrupted(prebuilt->trx)) { + break; + } + /* fprintf(stderr, "%lu entries in index %s\n", n_rows, index->name); */ diff --git a/storage/innobase/row/row0purge.c b/storage/innobase/row/row0purge.c index 5893e016011..abcf97110d9 100644 --- a/storage/innobase/row/row0purge.c +++ b/storage/innobase/row/row0purge.c @@ -126,7 +126,7 @@ row_purge_remove_clust_if_poss_low( if (0 != ut_dulint_cmp(node->roll_ptr, row_get_rec_roll_ptr(rec, index, rec_get_offsets( rec, index, offsets_, ULINT_UNDEFINED, &heap)))) { - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } /* Someone else has modified the record later: do not remove */ @@ -135,7 +135,7 @@ row_purge_remove_clust_if_poss_low( return(TRUE); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } diff --git a/storage/innobase/row/row0row.c b/storage/innobase/row/row0row.c index a6d3f1d5ab0..9a74397dc08 100644 --- a/storage/innobase/row/row0row.c +++ b/storage/innobase/row/row0row.c @@ -535,7 +535,7 @@ row_build_row_ref_in_tuple( } ut_ad(dtuple_check_typed(ref)); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -616,7 +616,6 @@ row_search_on_row_ref( ulint low_match; rec_t* rec; dict_index_t* index; - page_t* page; ut_ad(dtuple_check_typed(ref)); @@ -629,9 +628,8 @@ row_search_on_row_ref( low_match = btr_pcur_get_low_match(pcur); rec = btr_pcur_get_rec(pcur); - page = buf_frame_align(rec); - if (rec == page_get_infimum_rec(page)) { + if (page_rec_is_infimum(rec)) { return(FALSE); } @@ -702,7 +700,6 @@ row_search_index_entry( { ulint n_fields; ulint low_match; - page_t* page; rec_t* rec; ut_ad(dtuple_check_typed(entry)); @@ -711,11 +708,10 @@ row_search_index_entry( low_match = btr_pcur_get_low_match(pcur); rec = btr_pcur_get_rec(pcur); - page = buf_frame_align(rec); n_fields = dtuple_get_n_fields(entry); - if (rec == page_get_infimum_rec(page)) { + if (page_rec_is_infimum(rec)) { return(FALSE); } diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 94cf82d6a3d..c7a548fe448 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -125,7 +125,7 @@ row_sel_sec_rec_is_for_clust_rec( } func_exit: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(is_equal); @@ -630,6 +630,8 @@ row_sel_get_clust_rec( ulint* offsets = offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_; + *out_rec = NULL; + offsets = rec_get_offsets(rec, btr_pcur_get_btr_cur(&plan->pcur)->index, offsets, ULINT_UNDEFINED, &heap); @@ -663,8 +665,6 @@ row_sel_get_clust_rec( clustered index record did not exist in the read view of trx. */ - clust_rec = NULL; - goto func_exit; } @@ -733,7 +733,6 @@ row_sel_get_clust_rec( if ((old_vers || rec_get_deleted_flag(rec, plan->table->comp)) && !row_sel_sec_rec_is_for_clust_rec(rec, plan->index, clust_rec, index)) { - clust_rec = NULL; goto func_exit; } } @@ -742,11 +741,11 @@ row_sel_get_clust_rec( row_sel_fetch_columns(index, clust_rec, offsets, UT_LIST_GET_FIRST(plan->columns)); -func_exit: *out_rec = clust_rec; +func_exit: err = DB_SUCCESS; err_exit: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); @@ -1066,7 +1065,7 @@ row_sel_try_search_shortcut( plan->n_rows_fetched++; func_exit: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(SEL_FOUND); @@ -1261,7 +1260,7 @@ rec_loop: /* PHASE 1: Set a lock if specified */ if (!node->asc && cursor_just_opened - && (rec != page_get_supremum_rec(buf_frame_align(rec)))) { + && !page_rec_is_supremum(rec)) { /* When we open a cursor for a descending search, we must set a next-key lock on the successor record: otherwise it would @@ -1299,7 +1298,7 @@ rec_loop: } } - if (rec == page_get_infimum_rec(buf_frame_align(rec))) { + if (page_rec_is_infimum(rec)) { /* The infimum record on a page cannot be in the result set, and neither can a record lock be placed on it: we skip such @@ -1337,7 +1336,7 @@ rec_loop: } } - if (rec == page_get_supremum_rec(buf_frame_align(rec))) { + if (page_rec_is_supremum(rec)) { /* A page supremum record cannot be in the result set: skip it now when we have placed a possible lock on it */ @@ -1780,7 +1779,7 @@ lock_wait_or_error: ut_ad(sync_thread_levels_empty_gen(TRUE)); func_exit: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); @@ -2416,14 +2415,12 @@ row_sel_store_mysql_rec( mem_heap_t* extern_field_heap = NULL; byte* data; ulint len; - byte* blob_buf; - int pad_char; ulint i; ut_ad(prebuilt->mysql_template); ut_ad(rec_offs_validate(rec, NULL, offsets)); - if (prebuilt->blob_heap != NULL) { + if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) { mem_heap_free(prebuilt->blob_heap); prebuilt->blob_heap = NULL; } @@ -2435,7 +2432,8 @@ row_sel_store_mysql_rec( data = rec_get_nth_field(rec, offsets, templ->rec_field_no, &len); - if (rec_offs_nth_extern(offsets, templ->rec_field_no)) { + if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, + templ->rec_field_no))) { /* Copy an externally stored field to the temporary heap */ @@ -2456,7 +2454,7 @@ row_sel_store_mysql_rec( } if (len != UNIV_SQL_NULL) { - if (templ->type == DATA_BLOB) { + if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) { ut_a(prebuilt->templ_contains_blob); @@ -2465,8 +2463,9 @@ row_sel_store_mysql_rec( of 1000000 bytes. Since the test takes some CPU time, we do not use it for small BLOBs. */ - if (len > 2000000 - && !ut_test_malloc(len + 1000000)) { + if (UNIV_UNLIKELY(len > 2000000) + && UNIV_UNLIKELY(!ut_test_malloc( + len + 1000000))) { ut_print_timestamp(stderr); fprintf(stderr, @@ -2492,11 +2491,9 @@ row_sel_store_mysql_rec( mem_heap_create(len); } - blob_buf = mem_heap_alloc(prebuilt->blob_heap, - len); - ut_memcpy(blob_buf, data, len); - - data = blob_buf; + data = memcpy(mem_heap_alloc( + prebuilt->blob_heap, len), + data, len); } row_sel_field_store_in_mysql_format( @@ -2521,41 +2518,45 @@ row_sel_store_mysql_rec( account caused seg faults with NULL BLOB fields, and bug number 154 in the MySQL bug database: GROUP BY and DISTINCT could treat NULL values inequal. */ + int pad_char; mysql_rec[templ->mysql_null_byte_offset] |= (byte) (templ->mysql_null_bit_mask); - if (templ->type == DATA_VARCHAR - || templ->type == DATA_CHAR - || templ->type == DATA_BINARY - || templ->type == DATA_FIXBINARY - || templ->type == DATA_MYSQL - || templ->type == DATA_VARMYSQL) { + switch (templ->type) { + case DATA_VARCHAR: + case DATA_CHAR: + case DATA_BINARY: + case DATA_FIXBINARY: + case DATA_MYSQL: + case DATA_VARMYSQL: /* MySQL pads all non-BLOB and non-TEXT string types with space ' ' */ - - pad_char = ' '; - } else { - pad_char = '\0'; + if (UNIV_UNLIKELY(templ->mbminlen == 2)) { + /* Treat UCS2 as a special case. */ + data = mysql_rec + + templ->mysql_col_offset; + len = templ->mysql_col_len; + /* There are two UCS2 bytes per char, + so the length has to be even. */ + ut_a(!(len & 1)); + /* Pad with 0x0020. */ + while (len) { + *data++ = 0x00; + *data++ = 0x20; + len -= 2; + } + continue; + } + pad_char = 0x20; + break; + default: + pad_char = 0x00; + break; } - /* Handle UCS2 strings differently. */ - if (pad_char != '\0' && templ->mbminlen == 2) { - /* There are two bytes per char, so the length - has to be an even number. */ - ut_a(!(templ->mysql_col_len & 1)); - data = mysql_rec + templ->mysql_col_offset; - len = templ->mysql_col_len; - /* Pad with 0x0020. */ - while (len >= 2) { - *data++ = 0x00; - *data++ = 0x20; - len -= 2; - } - } else { - ut_ad(!pad_char || templ->mbminlen == 1); - memset(mysql_rec + templ->mysql_col_offset, + ut_ad(!pad_char || templ->mbminlen == 1); + memset(mysql_rec + templ->mysql_col_offset, pad_char, templ->mysql_col_len); - } } } @@ -2849,8 +2850,9 @@ row_sel_pop_cached_row_for_mysql( mysql_row_templ_t* templ; byte* cached_rec; ut_ad(prebuilt->n_fetch_cached > 0); + ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len); - if (prebuilt->keep_other_fields_on_keyread) + if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) { /* Copy cache record field by field, don't touch fields that are not covered by current key */ @@ -2877,7 +2879,7 @@ row_sel_pop_cached_row_for_mysql( else { ut_memcpy(buf, prebuilt->fetch_cache[prebuilt->fetch_cache_first], - prebuilt->mysql_row_len); + prebuilt->mysql_prefix_len); } prebuilt->n_fetch_cached--; prebuilt->fetch_cache_first++; @@ -2925,9 +2927,9 @@ row_sel_push_cache_row_for_mysql( ut_ad(prebuilt->fetch_cache_first == 0); - if (!row_sel_store_mysql_rec( + if (UNIV_UNLIKELY(!row_sel_store_mysql_rec( prebuilt->fetch_cache[prebuilt->n_fetch_cached], - prebuilt, rec, offsets)) { + prebuilt, rec, offsets))) { ut_error; } @@ -3048,11 +3050,7 @@ row_search_for_mysql( rec_t* index_rec; rec_t* clust_rec; rec_t* old_vers; - ulint err = DB_SUCCESS; - ibool moved; - ibool cons_read_requires_clust_rec; - ibool was_lock_wait; - ulint shortcut; + ulint err = DB_SUCCESS; ibool unique_search = FALSE; ibool unique_search_from_clust_index = FALSE; ibool mtr_has_extra_clust_latch = FALSE; @@ -3062,9 +3060,9 @@ row_search_for_mysql( locking SELECT, and the isolation level is <= TRX_ISO_READ_COMMITTED, then this is set to FALSE */ - ibool success; - ibool comp; +#ifdef UNIV_SEARCH_DEBUG ulint cnt = 0; +#endif /* UNIV_SEARCH_DEBUG */ ulint next_offs; mtr_t mtr; mem_heap_t* heap = NULL; @@ -3075,7 +3073,7 @@ row_search_for_mysql( ut_ad(index && pcur && search_tuple); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - if (prebuilt->table->ibd_file_missing) { + if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error:\n" "InnoDB: MySQL is trying to use a table handle but the .ibd file for\n" @@ -3089,7 +3087,7 @@ row_search_for_mysql( return(DB_ERROR); } - if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) { + if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) { fprintf(stderr, "InnoDB: Error: trying to free a corrupt\n" "InnoDB: table handle. Magic n %lu, table name ", @@ -3103,7 +3101,7 @@ row_search_for_mysql( } if (trx->n_mysql_tables_in_use == 0 - && prebuilt->select_lock_type == LOCK_NONE) { + && UNIV_UNLIKELY(prebuilt->select_lock_type == LOCK_NONE)) { /* Note that if MySQL uses an InnoDB temp table that it created inside LOCK TABLES, then n_mysql_tables_in_use can be zero; in that case select_lock_type is set to LOCK_X in @@ -3126,8 +3124,8 @@ row_search_for_mysql( /* PHASE 0: Release a possible s-latch we are holding on the adaptive hash index latch if there is someone waiting behind */ - if (trx->has_search_latch - && btr_search_latch.writer != RW_LOCK_NOT_LOCKED) { + if (UNIV_UNLIKELY(btr_search_latch.writer != RW_LOCK_NOT_LOCKED) + && trx->has_search_latch) { /* There is an x-latch request on the adaptive hash index: release the s-latch to reduce starvation and wait for @@ -3143,7 +3141,7 @@ row_search_for_mysql( /*-------------------------------------------------------------*/ /* PHASE 1: Try to pop the row from the prefetch cache */ - if (direction == 0) { + if (UNIV_UNLIKELY(direction == 0)) { trx->op_info = "starting index read"; prebuilt->n_rows_fetched = 0; @@ -3161,8 +3159,8 @@ row_search_for_mysql( prebuilt->fetch_direction = direction; } - if (direction != prebuilt->fetch_direction) { - if (prebuilt->n_fetch_cached > 0) { + if (UNIV_UNLIKELY(direction != prebuilt->fetch_direction)) { + if (UNIV_UNLIKELY(prebuilt->n_fetch_cached > 0)) { ut_error; /* TODO: scrollable cursor: restore cursor to the place of the latest returned row, @@ -3174,7 +3172,7 @@ row_search_for_mysql( prebuilt->n_fetch_cached = 0; prebuilt->fetch_cache_first = 0; - } else if (prebuilt->n_fetch_cached > 0) { + } else if (UNIV_LIKELY(prebuilt->n_fetch_cached > 0)) { row_sel_pop_cached_row_for_mysql(buf, prebuilt); prebuilt->n_rows_fetched++; @@ -3234,7 +3232,8 @@ row_search_for_mysql( 1 column. Return immediately if this is not a HANDLER command. */ - if (direction != 0 && !prebuilt->used_in_HANDLER) { + if (UNIV_UNLIKELY(direction != 0 && + !prebuilt->used_in_HANDLER)) { err = DB_RECORD_NOT_FOUND; goto func_exit; @@ -3252,9 +3251,9 @@ row_search_for_mysql( cannot use the adaptive hash index in a search in the case the row may be long and there may be externally stored fields */ - if (unique_search + if (UNIV_UNLIKELY(direction == 0) + && unique_search && index->type & DICT_CLUSTERED - && direction == 0 && !prebuilt->templ_contains_blob && !prebuilt->used_in_HANDLER && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) { @@ -3286,9 +3285,9 @@ row_search_for_mysql( trx->has_search_latch = TRUE; } #endif - shortcut = row_sel_try_search_shortcut_for_mysql(&rec, - prebuilt, &offsets, &heap, &mtr); - if (shortcut == SEL_FOUND) { + switch (row_sel_try_search_shortcut_for_mysql(&rec, + prebuilt, &offsets, &heap, &mtr)) { + case SEL_FOUND: #ifdef UNIV_SEARCH_DEBUG ut_a(0 == cmp_dtuple_rec(search_tuple, rec, offsets)); @@ -3322,9 +3321,8 @@ row_search_for_mysql( position */ err = DB_SUCCESS; goto func_exit; - - } else if (shortcut == SEL_EXHAUSTED) { + case SEL_EXHAUSTED: mtr_commit(&mtr); /* ut_print_name(stderr, index->name); @@ -3367,6 +3365,7 @@ shortcut_fails_too_big_rec: /* Scan the MySQL query string; check if SELECT is the first word there */ + ibool success; dict_accept(*trx->mysql_query_str, "SELECT", &success); @@ -3382,7 +3381,7 @@ shortcut_fails_too_big_rec: naturally moves upward (in fetch next) in alphabetical order, otherwise downward */ - if (direction == 0) { + if (UNIV_UNLIKELY(direction == 0)) { if (mode == PAGE_CUR_GE || mode == PAGE_CUR_G) { moves_up = TRUE; } @@ -3396,10 +3395,9 @@ shortcut_fails_too_big_rec: clust_index = dict_table_get_first_index(index->table); - if (direction != 0) { - moved = sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur, - moves_up, &mtr); - if (!moved) { + if (UNIV_LIKELY(direction != 0)) { + if (!sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur, + moves_up, &mtr)) { goto next_rec; } @@ -3440,11 +3438,13 @@ shortcut_fails_too_big_rec: trx_assign_read_view(trx); prebuilt->sql_stat_start = FALSE; } else { + ulint lock_mode; if (prebuilt->select_lock_type == LOCK_S) { - err = lock_table(0, index->table, LOCK_IS, thr); + lock_mode = LOCK_IS; } else { - err = lock_table(0, index->table, LOCK_IX, thr); + lock_mode = LOCK_IX; } + err = lock_table(0, index->table, lock_mode, thr); if (err != DB_SUCCESS) { @@ -3458,8 +3458,8 @@ rec_loop: /* PHASE 4: Look for matching records in a loop */ rec = btr_pcur_get_rec(pcur); - comp = index->table->comp; - ut_ad(comp == page_is_comp(buf_frame_align(rec))); + ut_ad(!!page_rec_is_comp(rec) == index->table->comp); +#ifdef UNIV_SEARCH_DEBUG /* fputs("Using ", stderr); dict_index_name_print(stderr, index); @@ -3467,7 +3467,9 @@ rec_loop: buf_frame_get_page_no(buf_frame_align(rec))); rec_print(rec); */ - if (rec == page_get_infimum_rec(buf_frame_align(rec))) { +#endif /* UNIV_SEARCH_DEBUG */ + + if (page_rec_is_infimum(rec)) { /* The infimum record on a page cannot be in the result set, and neither can a record lock be placed on it: we skip such @@ -3476,10 +3478,11 @@ rec_loop: goto next_rec; } - if (rec == page_get_supremum_rec(buf_frame_align(rec))) { + if (page_rec_is_supremum(rec)) { - if (prebuilt->select_lock_type != LOCK_NONE - && set_also_gap_locks) { + if (set_also_gap_locks + && !srv_locks_unsafe_for_binlog + && prebuilt->select_lock_type != LOCK_NONE) { /* Try to place a lock on the index record */ @@ -3487,18 +3490,16 @@ rec_loop: we do not lock gaps. Supremum record is really a gap and therefore we do not set locks there. */ - if (!srv_locks_unsafe_for_binlog) { - offsets = rec_get_offsets(rec, index, offsets, - ULINT_UNDEFINED, &heap); - err = sel_set_rec_lock(rec, index, offsets, - prebuilt->select_lock_type, - LOCK_ORDINARY, thr); - if (err != DB_SUCCESS) { + offsets = rec_get_offsets(rec, index, offsets, + ULINT_UNDEFINED, &heap); + err = sel_set_rec_lock(rec, index, offsets, + prebuilt->select_lock_type, + LOCK_ORDINARY, thr); - goto lock_wait_or_error; - } - } + if (err != DB_SUCCESS) { + goto lock_wait_or_error; + } } /* A page supremum record cannot be in the result set: skip it now that we have placed a possible lock on it */ @@ -3510,12 +3511,19 @@ rec_loop: /* Do sanity checks in case our cursor has bumped into page corruption */ - next_offs = rec_get_next_offs(rec, comp); - - if (next_offs >= UNIV_PAGE_SIZE - || next_offs < - (ulint) (comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM)) { - + if (page_rec_is_comp(rec)) { + next_offs = rec_get_next_offs(rec, TRUE); + if (UNIV_UNLIKELY(next_offs < PAGE_NEW_SUPREMUM)) { + goto wrong_offs; + } + } else { + next_offs = rec_get_next_offs(rec, FALSE); + if (UNIV_UNLIKELY(next_offs < PAGE_OLD_SUPREMUM)) { + goto wrong_offs; + } + } + if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) { + wrong_offs: if (srv_force_recovery == 0 || moves_up == FALSE) { ut_print_timestamp(stderr); buf_page_print(buf_frame_align(rec)); @@ -3528,7 +3536,7 @@ rec_loop: fprintf(stderr, "InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n" "InnoDB: ", - (ulong) (rec - buf_frame_align(rec)), + (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE), (ulong) next_offs, (ulong) buf_frame_get_page_no(rec)); dict_index_name_print(stderr, trx, index); @@ -3546,7 +3554,7 @@ rec_loop: fprintf(stderr, "InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n" "InnoDB: ", - (ulong) (rec - buf_frame_align(rec)), + (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE), (ulong) next_offs, (ulong) buf_frame_get_page_no(rec)); dict_index_name_print(stderr, trx, index); @@ -3561,13 +3569,13 @@ rec_loop: offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); - if (srv_force_recovery > 0) { + if (UNIV_UNLIKELY(srv_force_recovery > 0)) { if (!rec_validate(rec, offsets) || !btr_index_rec_validate(rec, index, FALSE)) { fprintf(stderr, "InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n" "InnoDB: ", - (ulong) (rec - buf_frame_align(rec)), + (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE), (ulong) next_offs, (ulong) buf_frame_get_page_no(rec)); dict_index_name_print(stderr, trx, index); @@ -3593,25 +3601,22 @@ rec_loop: if (0 != cmp_dtuple_rec(search_tuple, rec, offsets)) { - if (prebuilt->select_lock_type != LOCK_NONE - && set_also_gap_locks) { + if (set_also_gap_locks + && !srv_locks_unsafe_for_binlog + && prebuilt->select_lock_type != LOCK_NONE) { /* Try to place a gap lock on the index record only if innodb_locks_unsafe_for_binlog option is not set */ - if (srv_locks_unsafe_for_binlog == FALSE) { - - err = sel_set_rec_lock(rec, index, - offsets, + err = sel_set_rec_lock(rec, index, offsets, prebuilt->select_lock_type, LOCK_GAP, thr); - if (err != DB_SUCCESS) { - goto lock_wait_or_error; - } - } + if (err != DB_SUCCESS) { + goto lock_wait_or_error; + } } btr_pcur_store_position(pcur, &mtr); @@ -3627,25 +3632,22 @@ rec_loop: if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec, offsets)) { - if (prebuilt->select_lock_type != LOCK_NONE - && set_also_gap_locks) { + if (set_also_gap_locks + && !srv_locks_unsafe_for_binlog + && prebuilt->select_lock_type != LOCK_NONE) { /* Try to place a gap lock on the index record only if innodb_locks_unsafe_for_binlog option is not set */ - if (srv_locks_unsafe_for_binlog == FALSE) { - - err = sel_set_rec_lock(rec, index, - offsets, + err = sel_set_rec_lock(rec, index, offsets, prebuilt->select_lock_type, LOCK_GAP, thr); - if (err != DB_SUCCESS) { - goto lock_wait_or_error; - } - } + if (err != DB_SUCCESS) { + goto lock_wait_or_error; + } } btr_pcur_store_position(pcur, &mtr); @@ -3661,29 +3663,25 @@ rec_loop: /* We are ready to look at a possible new index entry in the result set: the cursor is now placed on a user record */ - cons_read_requires_clust_rec = FALSE; - if (prebuilt->select_lock_type != LOCK_NONE) { /* Try to place a lock on the index record; note that delete marked records are a special case in a unique search. If there is a non-delete marked record, then it is enough to lock its existence with LOCK_REC_NOT_GAP. */ + /* If innodb_locks_unsafe_for_binlog option is used, + we lock only the record, i.e., next-key locking is + not used. */ + ulint lock_type; if (!set_also_gap_locks - || (unique_search && !rec_get_deleted_flag(rec, comp))) { - lock_type = LOCK_REC_NOT_GAP; + || srv_locks_unsafe_for_binlog + || (unique_search && !UNIV_UNLIKELY(rec_get_deleted_flag( + rec, page_rec_is_comp(rec))))) { + goto no_gap_lock; } else { - /* If innodb_locks_unsafe_for_binlog option is used, - we lock only the record, i.e., next-key locking is - not used. */ - - if (srv_locks_unsafe_for_binlog) { - lock_type = LOCK_REC_NOT_GAP; - } else { - lock_type = LOCK_ORDINARY; - } + lock_type = LOCK_ORDINARY; } /* If we are doing a 'greater or equal than a primary key @@ -3703,7 +3701,7 @@ rec_loop: && dtuple_get_n_fields_cmp(search_tuple) == dict_index_get_n_unique(index) && 0 == cmp_dtuple_rec(search_tuple, rec, offsets)) { - + no_gap_lock: lock_type = LOCK_REC_NOT_GAP; } @@ -3731,7 +3729,7 @@ rec_loop: high force recovery level set, we try to avoid crashes by skipping this lookup */ - if (srv_force_recovery < 5 + if (UNIV_LIKELY(srv_force_recovery < 5) && !lock_clust_rec_cons_read_sees(rec, index, offsets, trx->read_view)) { @@ -3762,13 +3760,15 @@ rec_loop: have to look also into the clustered index: this is necessary, because we can only get the undo information via the clustered index record. */ - - cons_read_requires_clust_rec = TRUE; + + /* Get the clustered index record if needed */ + index_rec = rec; + ut_ad(index != clust_index); + goto requires_clust_rec; } } - if (rec_get_deleted_flag(rec, comp) - && !cons_read_requires_clust_rec) { + if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, page_rec_is_comp(rec)))) { /* The record is delete-marked: we can skip it if this is not a consistent read which might see an earlier version @@ -3782,14 +3782,14 @@ rec_loop: index_rec = rec; - /* Before and after the following "if" block, "offsets" will be - related to "rec", which may be in "index", a secondary index or - the clustered index ("clust_index"). However, after this "if" block, - "rec" may be pointing to "clust_rec" of "clust_index". */ - ut_ad(rec_offs_validate(rec, index, offsets)); - - if (index != clust_index && (cons_read_requires_clust_rec - || prebuilt->need_to_access_clustered)) { + if (index != clust_index && prebuilt->need_to_access_clustered) { + requires_clust_rec: + /* Before and after this "if" block, "offsets" will be + related to "rec", which may be in a secondary index "index" or + the clustered index ("clust_index"). However, after this + "if" block, "rec" may be pointing to + "clust_rec" of "clust_index". */ + ut_ad(rec_offs_validate(rec, index, offsets)); /* It was a non-clustered index and we must fetch also the clustered index record */ @@ -3811,7 +3811,8 @@ rec_loop: goto next_rec; } - if (rec_get_deleted_flag(clust_rec, comp)) { + if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, + page_rec_is_comp(clust_rec)))) { /* The record is delete marked: we can skip it */ @@ -3832,7 +3833,8 @@ rec_loop: rec == clust_rec ? clust_index : index, offsets)); - if (prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD + if ((match_mode == ROW_SEL_EXACT + || prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD) && prebuilt->select_lock_type == LOCK_NONE && !prebuilt->templ_contains_blob && !prebuilt->clust_index_was_generated @@ -3907,7 +3909,7 @@ next_rec: /*-------------------------------------------------------------*/ /* PHASE 5: Move the cursor to the next index record */ - if (mtr_has_extra_clust_latch) { + if (UNIV_UNLIKELY(mtr_has_extra_clust_latch)) { /* We must commit mtr if we are moving to the next non-clustered index record, because we could break the latching order if we would access a different clustered @@ -3919,34 +3921,38 @@ next_rec: mtr_has_extra_clust_latch = FALSE; mtr_start(&mtr); - moved = sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur, - moves_up, &mtr); - if (moved) { + if (sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur, + moves_up, &mtr)) { +#ifdef UNIV_SEARCH_DEBUG cnt++; +#endif /* UNIV_SEARCH_DEBUG */ goto rec_loop; } } if (moves_up) { - moved = btr_pcur_move_to_next(pcur, &mtr); - } else { - moved = btr_pcur_move_to_prev(pcur, &mtr); - } + if (UNIV_UNLIKELY(!btr_pcur_move_to_next(pcur, &mtr))) { + not_moved: + btr_pcur_store_position(pcur, &mtr); - if (!moved) { - btr_pcur_store_position(pcur, &mtr); + if (match_mode != 0) { + err = DB_RECORD_NOT_FOUND; + } else { + err = DB_END_OF_INDEX; + } - if (match_mode != 0) { - err = DB_RECORD_NOT_FOUND; - } else { - err = DB_END_OF_INDEX; + goto normal_return; + } + } else { + if (UNIV_UNLIKELY(!btr_pcur_move_to_prev(pcur, &mtr))) { + goto not_moved; } - - goto normal_return; } +#ifdef UNIV_SEARCH_DEBUG cnt++; +#endif /* UNIV_SEARCH_DEBUG */ goto rec_loop; @@ -3964,11 +3970,10 @@ lock_wait_or_error: que_thr_stop_for_mysql(thr); - thr->lock_state= QUE_THR_LOCK_ROW; - was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL); - thr->lock_state= QUE_THR_LOCK_NOLOCK; + thr->lock_state = QUE_THR_LOCK_ROW; - if (was_lock_wait) { + if (row_mysql_handle_errors(&err, trx, thr, NULL)) { + thr->lock_state = QUE_THR_LOCK_NOLOCK; mtr_start(&mtr); sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur, @@ -3978,9 +3983,13 @@ lock_wait_or_error: goto rec_loop; } + thr->lock_state = QUE_THR_LOCK_NOLOCK; + +#ifdef UNIV_SEARCH_DEBUG /* fputs("Using ", stderr); dict_index_name_print(stderr, index); fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */ +#endif /* UNIV_SEARCH_DEBUG */ goto func_exit; normal_return: @@ -3995,16 +4004,18 @@ normal_return: err = DB_SUCCESS; } +#ifdef UNIV_SEARCH_DEBUG /* fputs("Using ", stderr); dict_index_name_print(stderr, index); fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */ +#endif /* UNIV_SEARCH_DEBUG */ if (err == DB_SUCCESS) { srv_n_rows_read++; } func_exit: trx->op_info = ""; - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); diff --git a/storage/innobase/row/row0undo.c b/storage/innobase/row/row0undo.c index abe73cbe705..435c0279dbb 100644 --- a/storage/innobase/row/row0undo.c +++ b/storage/innobase/row/row0undo.c @@ -190,7 +190,7 @@ row_undo_search_clust_to_pcur( btr_pcur_commit_specify_mtr(&(node->pcur), &mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(ret); diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index 3305724a89b..cf2b8db5d32 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -815,9 +815,10 @@ row_upd_build_difference_binary( goto skip_compare; } - extern_bit = rec_offs_nth_extern(offsets, i); + extern_bit = upd_ext_vec_contains(ext_vec, n_ext_vec, i); - if (extern_bit != upd_ext_vec_contains(ext_vec, n_ext_vec, i) + if (UNIV_UNLIKELY(extern_bit == + !rec_offs_nth_extern(offsets, i)) || !dfield_data_is_binary_equal(dfield, len, data)) { upd_field = upd_get_nth_field(update, n_diff); @@ -826,12 +827,8 @@ row_upd_build_difference_binary( upd_field_set_field_no(upd_field, i, index, trx); - if (upd_ext_vec_contains(ext_vec, n_ext_vec, i)) { - upd_field->extern_storage = TRUE; - } else { - upd_field->extern_storage = FALSE; - } - + upd_field->extern_storage = extern_bit; + n_diff++; } skip_compare: @@ -1224,7 +1221,7 @@ row_upd_store_row( node->n_ext_vec = btr_push_update_extern_fields(node->ext_vec, offsets, update); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -1270,7 +1267,7 @@ row_upd_sec_index_entry( rec = btr_cur_get_rec(btr_cur); - if (!found) { + if (UNIV_UNLIKELY(!found)) { fputs("InnoDB: error in sec index entry update in\n" "InnoDB: ", stderr); dict_index_name_print(stderr, trx, index); @@ -1423,7 +1420,7 @@ row_upd_clust_rec_by_insert( index, thr, mtr); if (err != DB_SUCCESS) { mtr_commit(mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); @@ -1549,7 +1546,7 @@ row_upd_clust_rec( rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap), big_rec, mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } mtr_commit(mtr); @@ -1719,7 +1716,7 @@ row_upd_clust_step( node->index = dict_table_get_next_index(index); } exit_func: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); @@ -1736,7 +1733,7 @@ row_upd_clust_step( row_upd_eval_new_vals(node->update); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -2016,7 +2013,7 @@ row_upd_in_place_in_select( btr_pcur_get_rec(pcur), btr_cur->index, offsets_, ULINT_UNDEFINED, &heap), UT_LIST_GET_FIRST(node->columns)); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } row_upd_eval_new_vals(node->update); diff --git a/storage/innobase/row/row0vers.c b/storage/innobase/row/row0vers.c index 36f6c27636d..8e747423047 100644 --- a/storage/innobase/row/row0vers.c +++ b/storage/innobase/row/row0vers.c @@ -57,11 +57,11 @@ row_vers_impl_x_locked_off_kernel( dtuple_t* entry = NULL; /* assignment to eliminate compiler warning */ trx_t* trx; - ibool vers_del; - ibool rec_del; + ulint vers_del; + ulint rec_del; ulint err; mtr_t mtr; - ibool comp; + ulint comp; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); @@ -121,10 +121,10 @@ row_vers_impl_x_locked_off_kernel( goto exit_func; } - comp = index->table->comp; + comp = page_rec_is_comp(rec); ut_ad(index->table == clust_index->table); - ut_ad(comp == page_is_comp(buf_frame_align(rec))); - ut_ad(comp == page_is_comp(buf_frame_align(clust_rec))); + ut_ad(!!comp == index->table->comp); + ut_ad(!comp == !page_rec_is_comp(clust_rec)); /* We look up if some earlier version, which was modified by the trx_id transaction, of the clustered index record would require rec to be in @@ -310,7 +310,7 @@ row_vers_old_has_index_entry( dtuple_t* row; dtuple_t* entry; ulint err; - ibool comp; + ulint comp; ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX) || mtr_memo_contains(mtr, buf_block_align(rec), @@ -322,8 +322,8 @@ row_vers_old_has_index_entry( clust_index = dict_table_get_first_index(index->table); - comp = index->table->comp; - ut_ad(comp == page_is_comp(buf_frame_align(rec))); + comp = page_rec_is_comp(rec); + ut_ad(!index->table->comp == !comp); heap = mem_heap_create(1024); clust_offsets = rec_get_offsets(rec, clust_index, NULL, ULINT_UNDEFINED, &heap); diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c index 541b73b831d..7798e0c8e32 100644 --- a/storage/innobase/srv/srv0start.c +++ b/storage/innobase/srv/srv0start.c @@ -1040,7 +1040,9 @@ innobase_start_or_create_for_mysql(void) srv_start_has_been_called = TRUE; +#ifdef UNIV_DEBUG log_do_write = TRUE; +#endif /* UNIV_DEBUG */ /* yydebug = TRUE; */ srv_is_being_started = TRUE; @@ -1554,8 +1556,9 @@ NetWare. */ os_thread_create(&srv_master_thread, NULL, thread_ids + 1 + SRV_MAX_N_IO_THREADS); +#ifdef UNIV_DEBUG /* buf_debug_prints = TRUE; */ - +#endif /* UNIV_DEBUG */ sum_of_data_file_sizes = 0; for (i = 0; i < srv_n_data_files; i++) { diff --git a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c index e604912e996..f0f0e9a3a2e 100644 --- a/storage/innobase/sync/sync0sync.c +++ b/storage/innobase/sync/sync0sync.c @@ -1136,8 +1136,12 @@ sync_thread_add_level( } else if (level == SYNC_DICT_HEADER) { ut_a(sync_thread_levels_g(array, SYNC_DICT_HEADER)); } else if (level == SYNC_DICT) { +#ifdef UNIV_DEBUG ut_a(buf_debug_prints || sync_thread_levels_g(array, SYNC_DICT)); +#else /* UNIV_DEBUG */ + ut_a(sync_thread_levels_g(array, SYNC_DICT)); +#endif /* UNIV_DEBUG */ } else { ut_error; } diff --git a/storage/innobase/trx/trx0rec.c b/storage/innobase/trx/trx0rec.c index fcb7582ce73..3f3cfd3b000 100644 --- a/storage/innobase/trx/trx0rec.c +++ b/storage/innobase/trx/trx0rec.c @@ -1134,7 +1134,7 @@ trx_undo_report_row_operation( mutex_exit(&(trx->undo_mutex)); mtr_commit(&mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(DB_OUT_OF_FILE_SPACE); @@ -1153,7 +1153,7 @@ trx_undo_report_row_operation( *roll_ptr = trx_undo_build_roll_ptr(is_insert, rseg->id, page_no, offset); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(DB_SUCCESS); diff --git a/storage/innobase/trx/trx0roll.c b/storage/innobase/trx/trx0roll.c index 69f7a99187f..fdfb7428129 100644 --- a/storage/innobase/trx/trx0roll.c +++ b/storage/innobase/trx/trx0roll.c @@ -1237,10 +1237,12 @@ trx_finish_rollback_off_kernel( return; } +#ifdef UNIV_DEBUG if (lock_print_waits) { fprintf(stderr, "Trx %lu rollback finished\n", (ulong) ut_dulint_get_low(trx->id)); } +#endif /* UNIV_DEBUG */ trx_commit_off_kernel(trx); diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index c6d1f953772..9e155ee1de0 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -158,8 +158,6 @@ trx_create( trx->n_tickets_to_enter_innodb = 0; trx->auto_inc_lock = NULL; - trx->n_lock_table_exp = 0; - trx->n_lock_table_transactional = 0; trx->read_view_heap = mem_heap_create(256); trx->read_view = NULL; @@ -309,8 +307,6 @@ trx_free( ut_a(!trx->has_search_latch); ut_a(!trx->auto_inc_lock); - ut_a(!trx->n_lock_table_exp); - ut_a(!trx->n_lock_table_transactional); ut_a(trx->dict_operation_lock_mode == 0); @@ -1711,12 +1707,6 @@ trx_print( (ulong) trx->mysql_n_tables_locked); } - if (trx->n_lock_table_transactional > 0 || trx->n_lock_table_exp > 0) { -fprintf(f, "mysql explicit table locks %lu, transactional table locks %lu\n", - (ulong) trx->n_lock_table_exp, - (ulong) trx->n_lock_table_transactional); - } - newline = TRUE; switch (trx->que_state) { diff --git a/storage/innobase/ut/ut0dbg.c b/storage/innobase/ut/ut0dbg.c index 0f6a27d35d9..e810d8dead7 100644 --- a/storage/innobase/ut/ut0dbg.c +++ b/storage/innobase/ut/ut0dbg.c @@ -8,8 +8,11 @@ Created 1/30/1994 Heikki Tuuri #include "univ.i" +#if defined(__GNUC__) && (__GNUC__ > 2) +#else /* This is used to eliminate compiler warnings */ ulint ut_dbg_zero = 0; +#endif /* If this is set to TRUE all threads will stop into the next assertion and assert */ @@ -19,21 +22,69 @@ ibool panic_shutdown = FALSE; /* This is set to TRUE when on NetWare there happens an InnoDB assertion failure or other fatal error condition that requires an immediate shutdown. */ -#endif +#else /* __NETWARE__ */ /* Null pointer used to generate memory trap */ ulint* ut_dbg_null_ptr = NULL; +#endif /* __NETWARE__ */ + +/***************************************************************** +Report a failed assertion. */ -const char* ut_dbg_msg_assert_fail = -"InnoDB: Assertion failure in thread %lu in file %s line %lu\n"; -const char* ut_dbg_msg_trap = +void +ut_dbg_assertion_failed( +/*====================*/ + const char* expr, /* in: the failed assertion (optional) */ + const char* file, /* in: source file containing the assertion */ + ulint line) /* in: line number of the assertion */ +{ + ut_print_timestamp(stderr); + fprintf(stderr, + "InnoDB: Assertion failure in thread %lu" + " in file %s line %lu\n", + os_thread_pf(os_thread_get_curr_id()), file, line); + if (expr) { + fprintf(stderr, + "InnoDB: Failing assertion: %s\n", expr); + } + + fputs( "InnoDB: We intentionally generate a memory trap.\n" "InnoDB: Submit a detailed bug report to http://bugs.mysql.com.\n" "InnoDB: If you get repeated assertion failures or crashes, even\n" "InnoDB: immediately after the mysqld startup, there may be\n" "InnoDB: corruption in the InnoDB tablespace. Please refer to\n" "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n" -"InnoDB: about forcing recovery.\n"; +"InnoDB: about forcing recovery.\n", stderr); + ut_dbg_stop_threads = TRUE; +} + +#ifdef __NETWARE__ +/***************************************************************** +Shut down MySQL/InnoDB after assertion failure. */ + +void +ut_dbg_panic(void) +/*==============*/ +{ + if (!panic_shutdown) { + panic_shutdown = TRUE; + innobase_shutdown_for_mysql(); + } + exit(1); +} +#else /* __NETWARE__ */ +/***************************************************************** +Stop a thread after assertion failure. */ -const char* ut_dbg_msg_stop = -"InnoDB: Thread %lu stopped in file %s line %lu\n"; +void +ut_dbg_stop_thread( +/*===============*/ + const char* file, + ulint line) +{ + fprintf(stderr, "InnoDB: Thread %lu stopped in file %s line %lu\n", + os_thread_pf(os_thread_get_curr_id()), file, line); + os_thread_sleep(1000000000); +} +#endif /* __NETWARE__ */ |