From dfa485b47dd768304a5324f619af3da374c6165d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Apr 2005 15:12:30 +0300 Subject: [PATCH 01/38] InnoDB: Replace the redo log entry type MLOG_COMP_REC_SEC_DELETE_MARK with MLOG_REC_SEC_DELETE_MARK in order to reduce the space occupied by the redo log. innobase/btr/btr0cur.c: Replace MLOG_COMP_REC_SEC_DELETE_MARK with MLOG_REC_SEC_DELETE_MARK and eliminate redundant dict_index_t* parameters. innobase/ibuf/ibuf0ibuf.c: Remove unnecessary parameter to btr_cur_del_unmark_for_ibuf() innobase/include/btr0cur.h: Remove unnecessary dict_index_t* parameters innobase/include/mtr0mtr.h: Note that MLOG_COMP_REC_SEC_DELETE_MARK is obsolete innobase/log/log0recv.c: recv_parse_or_apply_log_rec_body(): Ignore the index information in MLOG_COMP_REC_SEC_DELETE_MARK. Add assertions about page_is_comp(). --- innobase/btr/btr0cur.c | 25 ++++++++++++------------- innobase/ibuf/ibuf0ibuf.c | 2 +- innobase/include/btr0cur.h | 2 -- innobase/include/mtr0mtr.h | 6 +++++- innobase/log/log0recv.c | 22 +++++++++++++++++----- 5 files changed, 35 insertions(+), 22 deletions(-) diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index e093c911f22..d7342c8bff5 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -2189,17 +2189,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 +2203,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,7 +2224,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: record descriptor */ page_t* page) /* in: page or NULL */ { ibool val; @@ -2253,7 +2250,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); @@ -2293,18 +2290,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 +2317,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 =========================*/ diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index 5ad61e2590f..caa2ac013d7 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/innobase/ibuf/ibuf0ibuf.c @@ -2848,7 +2848,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); diff --git a/innobase/include/btr0cur.h b/innobase/include/btr0cur.h index 0a8d8ceaeb7..352d1739b6a 100644 --- a/innobase/include/btr0cur.h +++ b/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/innobase/include/mtr0mtr.h b/innobase/include/mtr0mtr.h index 071279d5259..f44e813cf6b 100644 --- a/innobase/include/mtr0mtr.h +++ b/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/innobase/log/log0recv.c b/innobase/log/log0recv.c index 6597122f104..fd136e96668 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -765,6 +765,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 +773,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 +803,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 +811,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 +819,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 +852,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); } From ea5c2a148a6b704265324a2adcd7ae779a0df0b0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Apr 2005 17:39:05 +0300 Subject: [PATCH 02/38] InnoDB: Make CHECK TABLE killable. (Bug #9730) innobase/btr/btr0btr.c: Enclose btr_print_size() and btr_print_tree() in #ifdef UNIV_BTR_PRINT Add trx_t* parameter to btr_validate_tree() and btr_validate_level(). btr_validate_level(): Call trx_is_interrupted() on each page. innobase/ibuf/ibuf0ibuf.c: Add trx_t* parameter to btr_validate_tree(). innobase/include/btr0btr.h: Enclose btr_print_size() and btr_print_tree() in #ifdef UNIV_BTR_PRINT Add trx_t* parameter to btr_validate_tree(). innobase/include/trx0trx.h: Declare trx_is_interrupted(). innobase/row/row0mysql.c: row_scan_and_check_index(): Check trx_is_interrupted() every 1,000 scanned rows. row_check_table_for_mysql(): Check trx_is_interrupted() for each index after btr_validate_tree(). sql/ha_innodb.cc: Define trx_is_interrupted(). --- innobase/btr/btr0btr.c | 19 ++++++++++++++----- innobase/ibuf/ibuf0ibuf.c | 4 +++- innobase/include/btr0btr.h | 5 ++++- innobase/include/trx0trx.h | 13 +++++++++++++ innobase/row/row0mysql.c | 17 +++++++++++++++-- sql/ha_innodb.cc | 17 +++++++++++++++++ 6 files changed, 66 insertions(+), 9 deletions(-) diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 1744fc36f4d..fe6220b860d 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -20,6 +20,7 @@ Created 6/2/1994 Heikki Tuuri #include "rem0cmp.h" #include "lock0lock.h" #include "ibuf0ibuf.h" +#include "trx0trx.h" /* Latching strategy of the InnoDB B-tree @@ -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. */ @@ -2407,8 +2409,9 @@ btr_print_tree( 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. */ @@ -2649,6 +2652,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 +2700,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); @@ -2941,7 +2950,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 +2964,8 @@ btr_validate_tree( root = btr_root_get(tree, &mtr); n = btr_page_get_level(root, &mtr); - for (i = 0; i <= n; i++) { - - if (!btr_validate_level(tree, n - i)) { + for (i = 0; i <= n && !trx_is_interrupted(trx); i++) { + if (!btr_validate_level(tree, trx, n - i)) { mtr_commit(&mtr); diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index caa2ac013d7..c72bb2b1b65 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/innobase/ibuf/ibuf0ibuf.c @@ -2969,7 +2969,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/innobase/include/btr0btr.h b/innobase/include/btr0btr.h index 0b19e64d4e0..23116d24288 100644 --- a/innobase/include/btr0btr.h +++ b/innobase/include/btr0btr.h @@ -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/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index d46613c3a68..6ca9c778aeb 100644 --- a/innobase/include/trx0trx.h +++ b/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{ diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 7f78a5b723b..a201368f3d5 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -3880,6 +3880,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_; @@ -3902,11 +3903,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); @@ -4033,7 +4042,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, @@ -4041,6 +4050,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/sql/ha_innodb.cc b/sql/ha_innodb.cc index a26c706bb08..4834dd24fa8 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -996,6 +996,23 @@ mysql_get_identifier_quote_char( name, namelen)); } +/************************************************************************** +Determines if the currently running transaction has been interrupted. */ +extern "C" +ibool +trx_is_interrupted( +/*===============*/ + /* out: TRUE if interrupted */ + trx_t* trx) /* in: transaction */ +{ + fprintf(stderr, + "trx_is_interrupted: %p %p %d\n", + trx, trx ? trx->mysql_thd : 0, + trx && trx->mysql_thd ? ((THD*) trx->mysql_thd)->killed : -1); + + return(trx && trx->mysql_thd && ((THD*) trx->mysql_thd)->killed); +} + /************************************************************************** Obtain a pointer to the MySQL THD object, as in current_thd(). This definition must match the one in sql/ha_innodb.cc! */ From 4e0e9a3bae62ea2a153052f96f4c0e7833e44c86 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Apr 2005 14:23:26 +0300 Subject: [PATCH 03/38] InnoDB: Define some macros around GCC's __builtin_expect() and __builtin_prefetch(). Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/btr/btr0btr.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/btr/btr0cur.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/btr/btr0sea.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/include/univ.i: Define UNIV_EXPECT(), UNIV_LIKELY(), UNIV_UNLIKELY(), UNIV_LIKELY_NULL(), UNIV_PREFETCH_R() and UNIV_PREFETCH_RW(). innobase/lock/lock0lock.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/page/page0cur.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/page/page0page.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/rem/rem0rec.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/row/row0ins.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/row/row0mysql.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/row/row0purge.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/row/row0row.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/row/row0sel.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/row/row0undo.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/row/row0upd.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. innobase/trx/trx0rec.c: Add UNIV_LIKELY_NULL to if (heap) mem_free_heap(heap) tests. --- innobase/btr/btr0btr.c | 12 ++++++------ innobase/btr/btr0cur.c | 26 +++++++++++++------------- innobase/btr/btr0sea.c | 14 +++++++------- innobase/include/univ.i | 14 ++++++++++++++ innobase/lock/lock0lock.c | 8 ++++---- innobase/page/page0cur.c | 16 ++++++++-------- innobase/page/page0page.c | 14 +++++++------- innobase/rem/rem0rec.c | 4 ++-- innobase/row/row0ins.c | 6 +++--- innobase/row/row0mysql.c | 2 +- innobase/row/row0purge.c | 4 ++-- innobase/row/row0row.c | 2 +- innobase/row/row0sel.c | 10 +++++----- innobase/row/row0undo.c | 2 +- innobase/row/row0upd.c | 12 ++++++------ innobase/trx/trx0rec.c | 4 ++-- 16 files changed, 82 insertions(+), 68 deletions(-) diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index fe6220b860d..961b9eb696d 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -1284,14 +1284,14 @@ btr_page_get_sure_split_rec( next_rec = page_rec_get_next(rec); } if (next_rec != page_get_supremum_rec(page)) { - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(next_rec); } } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(rec); @@ -2109,7 +2109,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); @@ -2403,7 +2403,7 @@ 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); } @@ -2557,14 +2557,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); diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index d7342c8bff5..80a2600c7f9 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -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; @@ -525,7 +525,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 +681,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 +762,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); } } @@ -1261,7 +1261,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) { @@ -1451,7 +1451,7 @@ btr_cur_update_in_place( thr, &roll_ptr); if (err != DB_SUCCESS) { - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); @@ -1498,7 +1498,7 @@ btr_cur_update_in_place( btr_cur_unmark_extern_fields(rec, mtr, offsets); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(DB_SUCCESS); @@ -2078,7 +2078,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); } } @@ -2138,7 +2138,7 @@ btr_cur_del_mark_set_clust_rec( if (err != DB_SUCCESS) { - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); @@ -2149,7 +2149,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); @@ -2175,7 +2175,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); @@ -2443,7 +2443,7 @@ btr_cur_optimistic_delete( mtr); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -2943,7 +2943,7 @@ btr_estimate_number_of_different_key_vals( } mem_free(n_diff); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 97fdce2df75..cb43876e303 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -435,7 +435,7 @@ btr_search_update_hash_ref( offsets_, ULINT_UNDEFINED, &heap), block->curr_n_fields, block->curr_n_bytes, tree_id); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } #ifdef UNIV_SYNC_DEBUG @@ -659,7 +659,7 @@ btr_search_check_guess( success = cmp != 1; } exit_func: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(success); @@ -1010,7 +1010,7 @@ next_rec: prev_fold = fold; } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -1252,7 +1252,7 @@ exit_func: mem_free(folds); mem_free(recs); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -1370,7 +1370,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); @@ -1573,7 +1573,7 @@ check_next_rec: } function_exit: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } if (locked) { @@ -1662,7 +1662,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/innobase/include/univ.i b/innobase/include/univ.i index 8158c198e21..4bd16dc4a40 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -243,6 +243,20 @@ contains the sum of the following flag and the locally stored len. */ #define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE) +#if defined(__GNUC__) && (__GNUC__ > 2) +# define UNIV_EXPECT(expr,value) __builtin_expect(expr, value) +# define UNIV_LIKELY_NULL(expr) __builtin_expect((ulint) expr, 0) +# define UNIV_PREFETCH_R(addr) __builtin_prefetch(addr, 0, 3) +# define UNIV_PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 3) +#else +# 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 +#define UNIV_LIKELY(expr) UNIV_EXPECT(expr, TRUE) +#define UNIV_UNLIKELY(expr) UNIV_EXPECT(expr, FALSE) + #include #include "ut0dbg.h" #include "ut0ut.h" diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index 512f487b3f5..4a69c718abb 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -4187,7 +4187,7 @@ lock_rec_print( } mtr_commit(&mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -4664,7 +4664,7 @@ function_exit: mtr_commit(&mtr); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(TRUE); @@ -4850,7 +4850,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); } } @@ -4999,7 +4999,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/innobase/page/page0cur.c b/innobase/page/page0cur.c index 7738f5a34f0..aade42c3a45 100644 --- a/innobase/page/page0cur.c +++ b/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); } } @@ -539,7 +539,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); } } @@ -821,7 +821,7 @@ page_cur_parse_insert_rec( mem_free(buf); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -890,7 +890,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 +980,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); @@ -1186,7 +1186,7 @@ page_copy_rec_list_end_to_created_page( slot_index--; } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -1285,7 +1285,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); } } diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c index f3217e91f58..768444008b8 100644 --- a/innobase/page/page0page.c +++ b/innobase/page/page0page.c @@ -252,13 +252,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); } } @@ -514,7 +514,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 +608,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); } } @@ -772,7 +772,7 @@ page_delete_rec_list_end( rec2 = page_rec_get_next(rec2); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } @@ -868,7 +868,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); } @@ -1381,7 +1381,7 @@ page_print_list( "--------------------------------\n", (ulong) (count + 1)); - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c index 542c746209b..a8f75072e65 100644 --- a/innobase/rem/rem0rec.c +++ b/innobase/rem/rem0rec.c @@ -965,7 +965,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); } } @@ -1412,7 +1412,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/innobase/row/row0ins.c b/innobase/row/row0ins.c index 303fe5749bc..e2cb64a9742 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -1392,7 +1392,7 @@ do_possible_lock_wait: } exit_func: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); @@ -1660,7 +1660,7 @@ next_rec: } } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } mtr_commit(&mtr); @@ -2048,7 +2048,7 @@ function_exit: mtr_commit(&mtr); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index a201368f3d5..1b0888e535b 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -3845,7 +3845,7 @@ funct_exit: que_graph_free(graph); } - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c index 5893e016011..abcf97110d9 100644 --- a/innobase/row/row0purge.c +++ b/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/innobase/row/row0row.c b/innobase/row/row0row.c index a6d3f1d5ab0..46bd51d4694 100644 --- a/innobase/row/row0row.c +++ b/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); } } diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 94cf82d6a3d..d8c8fa5c2e4 100644 --- a/innobase/row/row0sel.c +++ b/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); @@ -746,7 +746,7 @@ func_exit: *out_rec = clust_rec; err = DB_SUCCESS; err_exit: - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); @@ -1066,7 +1066,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); @@ -1780,7 +1780,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); @@ -4004,7 +4004,7 @@ normal_return: func_exit: trx->op_info = ""; - if (heap) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(err); diff --git a/innobase/row/row0undo.c b/innobase/row/row0undo.c index abe73cbe705..435c0279dbb 100644 --- a/innobase/row/row0undo.c +++ b/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/innobase/row/row0upd.c b/innobase/row/row0upd.c index 3305724a89b..a595ad00247 100644 --- a/innobase/row/row0upd.c +++ b/innobase/row/row0upd.c @@ -1224,7 +1224,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); } } @@ -1423,7 +1423,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 +1549,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 +1719,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 +1736,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 +2016,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/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c index fcb7582ce73..3f3cfd3b000 100644 --- a/innobase/trx/trx0rec.c +++ b/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); From 7b07e3329a8fac0728ff8d2fa405eac206fe134a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Apr 2005 15:02:54 +0300 Subject: [PATCH 04/38] InnoDB: Reduce memcpy() load in row_sel_pop_cached_row_for_mysql() by copying only a prefix of the row that covers the requested columns. innobase/include/row0mysql.h: row_prebuilt_struct: Add field mysql_prefix_len in order to reduce memcpy() time in row_sel_pop_cached_row_for_mysql(). innobase/row/row0sel.c: row_sel_pop_cached_row_for_mysql(): memcpy() only mysql_prefix_len bytes instead of mysql_row_len. sql/ha_innodb.cc: build_template(): Initialize prebuilt->mysql_prefix_len. --- innobase/include/row0mysql.h | 2 ++ innobase/row/row0sel.c | 5 +++-- sql/ha_innodb.cc | 8 ++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index e44d689b88b..277089430d4 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -599,6 +599,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/innobase/row/row0sel.c b/innobase/row/row0sel.c index d8c8fa5c2e4..c6171789b8b 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2849,8 +2849,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 +2878,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++; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 4834dd24fa8..53061c6f3a6 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2618,6 +2618,8 @@ build_template( ibool fetch_all_in_key = FALSE; ibool fetch_primary_key_cols = FALSE; ulint i; + /* byte offset of the end of last requested column */ + ulint mysql_prefix_len = 0; if (prebuilt->select_lock_type == LOCK_X) { /* We always retrieve the whole clustered index record if we @@ -2738,6 +2740,11 @@ build_template( get_field_offset(table, field); templ->mysql_col_len = (ulint) field->pack_length(); + if (mysql_prefix_len < templ->mysql_col_offset + + templ->mysql_col_len) { + mysql_prefix_len = templ->mysql_col_offset + + templ->mysql_col_len; + } templ->type = index->table->cols[i].type.mtype; templ->mysql_type = (ulint)field->type(); @@ -2760,6 +2767,7 @@ skip_field: } prebuilt->n_template = n_requested_fields; + prebuilt->mysql_prefix_len = mysql_prefix_len; if (index != clust_index && prebuilt->need_to_access_clustered) { /* Change rec_field_no's to correspond to the clustered index From fea290807c89790b62ea41a6f457287a5d2ef1e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Apr 2005 15:09:10 +0300 Subject: [PATCH 05/38] InnoDB: Speed up comparison functions by making DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL a constant. innobase/data/data0type.c: Remove data_mysql_latin1_swedish_charset_coll. innobase/include/data0type.h: Replace variable data_mysql_latin1_swedish_charset_coll with constant DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL. innobase/rem/rem0cmp.c: Replace variable data_mysql_latin1_swedish_charset_coll with constant DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL. sql/ha_innodb.cc: Eliminate variable data_mysql_latin1_swedish_charset_coll. Add an assertion about DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL. --- innobase/data/data0type.c | 1 - innobase/include/data0type.h | 2 +- innobase/rem/rem0cmp.c | 6 +++--- sql/ha_innodb.cc | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/innobase/data/data0type.c b/innobase/data/data0type.c index 3fcd666b5a5..36b0f9603e5 100644 --- a/innobase/data/data0type.c +++ b/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; diff --git a/innobase/include/data0type.h b/innobase/include/data0type.h index a4d2c1a2e1d..7e9692eca5a 100644 --- a/innobase/include/data0type.h +++ b/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/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c index 74348b865a8..f8aed202586 100644 --- a/innobase/rem/rem0cmp.c +++ b/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, @@ -530,7 +530,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, @@ -832,7 +832,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, diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 53061c6f3a6..2a4c9159618 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1271,8 +1271,8 @@ innobase_init(void) data_mysql_default_charset_coll = (ulint)default_charset_info->number; - data_mysql_latin1_swedish_charset_coll = - (ulint)my_charset_latin1.number; + ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL == + my_charset_latin1.number); /* Store the latin1_swedish_ci character ordering table to InnoDB. For non-latin1_swedish_ci charsets we use the MySQL comparison functions, From 87c4f37a5009bc1b0889c7a3dfc316d47e9fb9f8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Apr 2005 15:16:16 +0300 Subject: [PATCH 06/38] ha_innodb.cc: trx_is_interrupted(): Remove debug output. sql/ha_innodb.cc: trx_is_interrupted(): Remove debug output. --- sql/ha_innodb.cc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 2a4c9159618..025fc184fc9 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1005,11 +1005,6 @@ trx_is_interrupted( /* out: TRUE if interrupted */ trx_t* trx) /* in: transaction */ { - fprintf(stderr, - "trx_is_interrupted: %p %p %d\n", - trx, trx ? trx->mysql_thd : 0, - trx && trx->mysql_thd ? ((THD*) trx->mysql_thd)->killed : -1); - return(trx && trx->mysql_thd && ((THD*) trx->mysql_thd)->killed); } From c546b5f3b566d3e2b0e970c0313244823cb8c9a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Apr 2005 15:27:18 +0300 Subject: [PATCH 07/38] InnoDB: Make branch prediction assume that assertions do not fail. innobase/include/ut0dbg.h: Remove ut_dbg_zero. Use the UNIV_UNLIKELY() macro in assertions in order to assist branch prediction. innobase/ut/ut0dbg.c: Remove ut_dbg_zero. --- innobase/include/ut0dbg.h | 6 ++---- innobase/ut/ut0dbg.c | 3 --- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h index 5f30a894874..a0af0e2f0ad 100644 --- a/innobase/include/ut0dbg.h +++ b/innobase/include/ut0dbg.h @@ -13,8 +13,6 @@ Created 1/30/1994 Heikki Tuuri #include #include "os0thread.h" -extern ulint ut_dbg_zero; /* This is used to eliminate - compiler warnings */ extern ibool ut_dbg_stop_threads; extern ulint* ut_dbg_null_ptr; @@ -26,7 +24,7 @@ extern const char* ut_dbg_msg_stop; #ifdef __NETWARE__ extern ibool panic_shutdown; #define ut_a(EXPR) do {\ - if (!((ulint)(EXPR) + ut_dbg_zero)) {\ + if (UNIV_UNLIKELY(!((ulint)(EXPR)))) {\ ut_print_timestamp(stderr);\ fprintf(stderr, ut_dbg_msg_assert_fail,\ os_thread_pf(os_thread_get_curr_id()), __FILE__,\ @@ -55,7 +53,7 @@ extern ibool panic_shutdown; } while (0) #else #define ut_a(EXPR) do {\ - if (!((ulint)(EXPR) + ut_dbg_zero)) {\ + if (UNIV_UNLIKELY(!((ulint)(EXPR)))) {\ ut_print_timestamp(stderr);\ fprintf(stderr, ut_dbg_msg_assert_fail,\ os_thread_pf(os_thread_get_curr_id()), __FILE__,\ diff --git a/innobase/ut/ut0dbg.c b/innobase/ut/ut0dbg.c index 0f6a27d35d9..ea3b48b6e9e 100644 --- a/innobase/ut/ut0dbg.c +++ b/innobase/ut/ut0dbg.c @@ -8,9 +8,6 @@ Created 1/30/1994 Heikki Tuuri #include "univ.i" -/* This is used to eliminate compiler warnings */ -ulint ut_dbg_zero = 0; - /* If this is set to TRUE all threads will stop into the next assertion and assert */ ibool ut_dbg_stop_threads = FALSE; From f2c13c3f4fa493e4054e9d6c34a82d80af2bbafc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Apr 2005 13:43:49 +0300 Subject: [PATCH 08/38] dict0dict.c: Add some UNIV_LIKELY and UNIV_UNLIKELY hints. dict_tree_copy_rec_order_prefix(): Add a UNIV_PREFETCH_R hint on rec. innobase/dict/dict0dict.c: Add some UNIV_LIKELY and UNIV_UNLIKELY hints. dict_tree_copy_rec_order_prefix(): Add a UNIV_PREFETCH_R hint on rec. --- innobase/dict/dict0dict.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 8c9724da079..4df2bb21e03 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -1443,7 +1443,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); @@ -1472,7 +1472,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, @@ -1673,7 +1673,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; @@ -1769,7 +1769,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; @@ -3672,7 +3672,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); @@ -3828,7 +3828,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 @@ -3893,9 +3893,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 { @@ -3947,7 +3948,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++) { @@ -4267,9 +4268,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 */ } /************************************************************************** From 98dc4142b206ea3fcf1d7b4bd127baef1aeac2d4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Apr 2005 14:04:18 +0300 Subject: [PATCH 09/38] InnoDB: Some low-level optimizations made based on OProfile results. innobase/dict/dict0mem.c: dict_mem_table_create(): Add a debug assertion. innobase/include/btr0btr.ic: btr_node_ptr_get_child_page_no(): Add a UNIV_UNLIKELY hint. Remove a buf_frame_align() call. innobase/include/btr0cur.ic: btr_cur_get_page(): Add a debug assertion. innobase/include/buf0buf.ic: buf_block_peek_if_too_old(): Replace if() with return(). buf_block_align(), buf_frame_align(): Add UNIV_UNLIKELY hints. innobase/include/data0type.ic: dtype_get_fixed_size(): Add UNIV_UNLIKELY hints. innobase/include/mem0mem.ic: Remove signedness warning in debug assertion. innobase/include/read0read.ic: read_view_sees_trx_id(): Eliminate a comparison inside loop. innobase/include/row0sel.ic: open_step(): Add UNIV_EXPECT hint. innobase/include/row0upd.ic: upd_field_set_field_no(): Add a UNIV_UNLIKELY hint. innobase/include/sync0rw.ic: Add UNIV_LIKELY and UNIV_UNLIKELY hints. rw_lock_x_lock_func_nowait(): Eliminate a function call. Replace ut_a() assertions with ut_ad(). innobase/include/trx0rseg.ic: Add UNIV_UNLIKELY hints. innobase/include/ut0rnd.ic: ut_fold_binary(): Eliminate a loop variable to avoid register spilling on x86. --- innobase/dict/dict0mem.c | 1 + innobase/include/btr0btr.ic | 4 ++-- innobase/include/btr0cur.ic | 4 +++- innobase/include/buf0buf.ic | 16 ++++++-------- innobase/include/data0type.ic | 4 ++-- innobase/include/mem0mem.ic | 2 +- innobase/include/read0read.ic | 9 ++------ innobase/include/row0sel.ic | 2 +- innobase/include/row0upd.ic | 2 +- innobase/include/sync0rw.ic | 39 +++++++++++++++++++---------------- innobase/include/trx0rseg.ic | 4 ++-- innobase/include/ut0rnd.ic | 6 +++--- 12 files changed, 45 insertions(+), 48 deletions(-) diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c index 48b9f28d292..eec35310039 100644 --- a/innobase/dict/dict0mem.c +++ b/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/innobase/include/btr0btr.ic b/innobase/include/btr0btr.ic index 1d1f97d3668..a0860b1c3a7 100644 --- a/innobase/include/btr0btr.ic +++ b/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/innobase/include/btr0cur.ic b/innobase/include/btr0cur.ic index dcad3e9e14d..bf8a6efb68d 100644 --- a/innobase/include/btr0cur.ic +++ b/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/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic index 681a0ef000a..803b20560bf 100644 --- a/innobase/include/buf0buf.ic +++ b/innobase/include/buf0buf.ic @@ -26,12 +26,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 +206,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 +242,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, diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic index a87a08ca582..06d45dd5501 100644 --- a/innobase/include/data0type.ic +++ b/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/innobase/include/mem0mem.ic b/innobase/include/mem0mem.ic index 82d88099c3f..8c87c884d78 100644 --- a/innobase/include/mem0mem.ic +++ b/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/innobase/include/read0read.ic b/innobase/include/read0read.ic index 03d84ee0c51..ec9ef5814bb 100644 --- a/innobase/include/read0read.ic +++ b/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/innobase/include/row0sel.ic b/innobase/include/row0sel.ic index 595cea1138b..600c6204571 100644 --- a/innobase/include/row0sel.ic +++ b/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/innobase/include/row0upd.ic b/innobase/include/row0upd.ic index e2d81a39cfa..acbb11aa1c7 100644 --- a/innobase/include/row0upd.ic +++ b/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/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic index 3a92100ba01..b1ae636010a 100644 --- a/innobase/include/sync0rw.ic +++ b/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/innobase/include/trx0rseg.ic b/innobase/include/trx0rseg.ic index 35e927f5e79..c9ac50ebf16 100644 --- a/innobase/include/trx0rseg.ic +++ b/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/innobase/include/ut0rnd.ic b/innobase/include/ut0rnd.ic index 06d7012f60b..d2ab087d491 100644 --- a/innobase/include/ut0rnd.ic +++ b/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++; From 33d5b13bbebcfc3657a7b8cc10eec10f73d44d71 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Apr 2005 15:15:18 +0300 Subject: [PATCH 10/38] row0upd.c: Add UNIV_UNLIKELY hint. lock0lock.c: Correct the prototypes of lock_deadlock_recursive() and lock_deadlock_occurs(). data0data.c: dtuple_convert_big_rec(): Add UNIV_UNLIKELY hint. ha_innodb.cc: ha_innobase::write_row(): Correct the type of 'mode'. sql/ha_innodb.cc: ha_innobase::write_row(): Correct the type of 'mode'. innobase/data/data0data.c: dtuple_convert_big_rec(): Add UNIV_UNLIKELY hint. innobase/lock/lock0lock.c: Correct the prototypes of lock_deadlock_recursive() and lock_deadlock_occurs(). innobase/row/row0upd.c: Add UNIV_UNLIKELY hint. --- innobase/data/data0data.c | 2 +- innobase/lock/lock0lock.c | 17 +++++++++++++---- innobase/row/row0upd.c | 2 +- sql/ha_innodb.cc | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/innobase/data/data0data.c b/innobase/data/data0data.c index 5f74dde8710..194213a04e1 100644 --- a/innobase/data/data0data.c +++ b/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/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index 4a69c718abb..650552be366 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -348,17 +348,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 */ diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c index a595ad00247..c0aa285d7e5 100644 --- a/innobase/row/row0upd.c +++ b/innobase/row/row0upd.c @@ -1270,7 +1270,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); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 025fc184fc9..3dd82960958 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2834,7 +2834,7 @@ ha_innobase::write_row( being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */ dict_table_t* src_table; - ibool mode; + ulint mode; num_write_row = 0; From 1c8f5500963814507754e878e092fdc76ebce6a7 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Apr 2005 15:27:11 +0300 Subject: [PATCH 11/38] InnoDB: Optimize rec_get_offsets(), rec_copy_prefix_to_buf() and other rec_ functions based on OProfile measurements on GNU/Linux x86. innobase/include/rem0rec.h: Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp. Remove rec_set_node_ptr_flag(). innobase/include/rem0rec.ic: Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp. Remove rec_set_node_ptr_flag(). Add UNIV_LIKELY and UNIV_UNLIKELY hints. Correct a spelling error in comment. Simplify rec_get_deleted_flag(). innobase/rem/rem0rec.c: Add UNIV_LIKELY and UNIV_UNLIKELY hints. rec_init_offsets(), rec_get_offsets_func(): Optimize for x86. rec_set_field_extern_bits(): Move "comp" flag outside the loop. rec_copy_prefix_to_buf(): Add UNIV_PREFETCH hints. --- innobase/include/rem0rec.h | 34 ++++----- innobase/include/rem0rec.ic | 80 ++++++++------------ innobase/rem/rem0rec.c | 146 +++++++++++++++++++++++------------- 3 files changed, 136 insertions(+), 124 deletions(-) diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h index 134c37c8030..3c150d6601d 100644 --- a/innobase/include/rem0rec.h +++ b/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,7 +156,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 */ /********************************************************** @@ -167,7 +167,7 @@ rec_get_deleted_flag( /*=================*/ /* out: TRUE 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,7 +175,7 @@ void rec_set_deleted_flag( /*=================*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ibool flag); /* in: TRUE if delete marked */ /********************************************************** The following function tells if a new-style record is a node pointer. */ @@ -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,7 +297,7 @@ 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 */ diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index 2593fb8edeb..cd742aef6a6 100644 --- a/innobase/include/rem0rec.ic +++ b/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) \ @@ -583,14 +583,15 @@ rec_get_deleted_flag( /*=================*/ /* out: TRUE 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(0 != rec_get_bit_field_1(rec, REC_NEW_INFO_BITS, + REC_INFO_DELETED_FLAG, REC_INFO_BITS_SHIFT)); + } else { + return(0 != rec_get_bit_field_1(rec, REC_OLD_INFO_BITS, + REC_INFO_DELETED_FLAG, REC_INFO_BITS_SHIFT)); } - - return(FALSE); } /********************************************************** @@ -600,24 +601,23 @@ void rec_set_deleted_flag( /*=================*/ rec_t* rec, /* in: physical record */ - ibool comp, /* in: TRUE=compact page format */ + ulint comp, /* in: nonzero=compact page format */ ibool flag) /* in: TRUE if delete marked */ { - ulint old_val; - ulint new_val; + ulint val; ut_ad(TRUE == 1); ut_ad(flag <= TRUE); - 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); } /********************************************************** @@ -632,26 +632,6 @@ rec_get_node_ptr_flag( return(REC_STATUS_NODE_PTR == rec_get_status(rec)); } -/********************************************************** -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. */ @@ -661,7 +641,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 +662,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 +823,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 +906,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); @@ -1037,7 +1017,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 +1028,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 +1432,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/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c index a8f75072e65..a1e7e348781 100644 --- a/innobase/rem/rem0rec.c +++ b/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,74 @@ 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 = REC_OFFS_SQL_NULL; + goto resolved; + } + null_mask <<= 1; + + ut_ad(!field->fixed_len); + goto variable_length; } - if (is_null) { - /* No length is stored for NULL fields. */ - len = 0; - } else if (!field->fixed_len) { + if (UNIV_UNLIKELY(!field->fixed_len)) { + dtype_t* type; + variable_length: /* Variable-length field: read the length */ + 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 +269,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 +295,7 @@ rec_init_offsets( offs |= REC_OFFS_EXTERNAL; } rec_offs_base(offsets)[1 + i] = offs; - } + } while (++i < rec_offs_n_fields(offsets)); } } } @@ -310,8 +326,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 +348,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 +670,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 +975,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); @@ -1078,17 +1104,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 +1137,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 +1156,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 +1175,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)) { From f51eb30b5a9f769ebe1af8cbd56fc6f3183d4bb3 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Apr 2005 15:47:46 +0300 Subject: [PATCH 12/38] rem0cmp.c: Add UNIV_LIKELY and UNIV_UNLIKELY hints. cmp_dtuple_rec_with_match(): Move condition outside loop. Reduce the number of comparisons per iteration. mtr0mtr.c: mtr_memo_slot_release(): Add a UNIV_LIKELY hint. Simplify the preprocessor magic. buf0buf.c: buf_page_optimistic_get_func(): Add UNIV_UNLIKELY hints. Introduce an exit_func label to remove duplicated error exits. innobase/buf/buf0buf.c: buf_page_optimistic_get_func(): Add UNIV_UNLIKELY hints. Introduce an exit_func label to remove duplicated error exits. innobase/mtr/mtr0mtr.c: mtr_memo_slot_release(): Add a UNIV_LIKELY hint. Simplify the preprocessor magic. innobase/rem/rem0cmp.c: Add UNIV_LIKELY and UNIV_UNLIKELY hints. cmp_dtuple_rec_with_match(): Move condition outside loop. Reduce the number of comparisons per iteration. --- innobase/buf/buf0buf.c | 23 +++++------ innobase/mtr/mtr0mtr.c | 12 +++--- innobase/rem/rem0cmp.c | 91 +++++++++++++++++------------------------- 3 files changed, 52 insertions(+), 74 deletions(-) diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 89f851709db..fca0b9f85f8 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -1286,8 +1286,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 +1321,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 +1346,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 +1365,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 */ diff --git a/innobase/mtr/mtr0mtr.c b/innobase/mtr/mtr0mtr.c index 6e918806eb1..da045be1f62 100644 --- a/innobase/mtr/mtr0mtr.c +++ b/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/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c index f8aed202586..0a918d0e470 100644 --- a/innobase/rem/rem0cmp.c +++ b/innobase/rem/rem0cmp.c @@ -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; } } @@ -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 */ @@ -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; } From 4a3a46af13ae0703f590ac058fc1df61aeb946b6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Apr 2005 10:14:35 +0300 Subject: [PATCH 13/38] InnoDB: Performance optimizations based on OProfile analysis innobase/btr/btr0btr.c: Eliminate some buf_frame_align() calls. Make use of the page_rec_is_infimum(), page_rec_is_supremum() and page_rec_is_user_rec() functions. Replace some index->table->comp with page_is_comp(). Eliminate some variables to reduce register spilling on x86. Note that page_is_comp() may return nonzero instead of TRUE. Note that rec_offs_comp() may return nonzero instead of TRUE. innobase/btr/btr0cur.c: Eliminate some buf_frame_align() calls. Replace some index->table->comp with page_is_comp() or rec_offs_comp(). Eliminate some variables to reduce register spilling on x86. Note that page_is_comp() may return nonzero instead of TRUE. Note that rec_offs_comp() may return nonzero instead of TRUE. Remove an extra mem_heap_create() call from btr_cur_update_in_place(). Add "page" parameter to lock_rec_store_on_page_infimum(). Add some UNIV_LIKELY() and UNIV_UNLIKELY() hints. btr_estimate_number_of_different_key_vals(): Rename the offsets_* variables to be more descriptive and eliminate one rec_get_offsets() and one page_rec_get_next() call in the loop. innobase/btr/btr0pcur.c: Eliminate some buf_frame_align() calls. Make use of the page_rec_is_infimum(), page_rec_is_supremum() and page_rec_is_user_rec() functions. Replace some index->table->comp with page_is_comp(). Eliminate some variables to reduce register spilling on x86. Note that page_is_comp() may return nonzero instead of TRUE. Make some ut_a() assertions ut_ad() ones to improve performance. Add some UNIV_LIKELY() and UNIV_UNLIKELY() hints. innobase/btr/btr0sea.c: Make use of page_rec_is_infimum() and page_rec_is_supremum(). Eliminate some buf_frame_align() calls. Add some UNIV_UNLIKELY and UNIV_LIKELY hints. Turn some assertions into debug assertions. innobase/dict/dict0crea.c: Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp innobase/ibuf/ibuf0ibuf.c: Make use of page_rec_is_infimum() and page_rec_is_supremum(). Add some UNIV_UNLIKELY and UNIV_LIKELY hints. ibuf_get_merge_page_nos(): Rename parameter "first_rec" to "rec" and eliminate local variable "rec". innobase/include/btr0btr.h: Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp innobase/include/buf0buf.h: Rename buf_frame_get_modify_clock() to buf_block_get_modify_clock(). innobase/include/buf0buf.ic: Rename buf_frame_get_modify_clock() to buf_block_get_modify_clock() and remove the buf_block_align() call. innobase/include/lock0lock.h: lock_rec_store_on_page_infimum(): Add parameter "page" innobase/include/mach0data.h: Add mach_encode_2() and mach_decode_2(). innobase/include/mach0data.ic: Add mach_encode_2() and mach_decode_2(). innobase/include/page0cur.h: Add const qualifier to page_cur_is_before_first() and page_cur_is_after_last(). innobase/include/page0cur.ic: Make use of page_rec_is_infimum() and page_rec_is_supremum(). innobase/include/page0page.h: Remove page_rec_is_first_user_rec() and page_rec_is_last_user_rec(). Add page_rec_is_infimum() and page_rec_is_supremum(). Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp. innobase/include/page0page.ic: Remove page_rec_is_first_user_rec() and page_rec_is_last_user_rec(). Add page_rec_is_infimum() and page_rec_is_supremum(). Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp. Add UNIV_UNLIKELY, UNIV_LIKELY and UNIV_EXPECT hints. Reduce the number of buf_frame_align() calls. innobase/include/rem0rec.ic: rec_offs_comp(): Return zero or nonzero instead of FALSE or TRUE. innobase/include/row0mysql.h: Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp. innobase/lock/lock0lock.c: Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp. Remove parameter "comp" from lock_rec_get_next(), lock_rec_has_expl() and lock_rec_other_has_expl_req(). Add parameter "page" to lock_rec_store_on_page_infimum(). Add UNIV_UNLIKELY hints. Reduce the number of buf_frame_align() calls. Make use of page_rec_is_infimum(), page_rec_is_supremum() and page_rec_is_user_rec(). Move the "comp" flag outside some loops. innobase/mtr/mtr0log.c: Replace index->table->comp with page_rec_is_comp(). innobase/page/page0cur.c: Replace index->table->comp with page_is_comp() or page_rec_is_comp(). Eliminate some buf_frame_align() calls. Add some debug assertions. innobase/page/page0page.c: Optimize page_dir_find_owner_slot(). Compare the record offset 16 bits at a time, because that seems to be the only way to avoid register spilling on x86. Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp. Remove parameter "page" of page_delete_rec_list_write_log(). Make use of page_rec_is_infimum(). innobase/rem/rem0cmp.c: Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp. innobase/row/row0ins.c: Make use of page_rec_is_infimum() and page_rec_is_supremum(). Reduce the amount of buf_frame_align() calls. row_ins_index_entry_low(): Disable assertion about column count unless #ifdef UNIV_DEBUG. innobase/row/row0mysql.c: Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp. innobase/row/row0row.c: Eliminate some buf_frame_align() calls. Make use of page_rec_is_infimum(). innobase/row/row0sel.c: Make use of page_rec_is_supremum() and page_rec_is_infimum(). Turn some assertions into debug assertions. Add UNIV_LIKELY and UNIV_UNLIKELY hints. row_search_for_mysql(): Eliminate local variables "moved", "cons_read_requires_clust_rec", "was_lock_wait", "shortcut", "success" and "comp". Replace some of them with goto's. Disable variable "cnt" unless #ifdef UNIV_SEARCH_DEBUG. innobase/row/row0vers.c: Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp. Replace index->table->comp with page_rec_is_comp(). Eliminate some buf_frame_align() calls. --- innobase/btr/btr0btr.c | 138 ++++++------- innobase/btr/btr0cur.c | 161 +++++++++------- innobase/btr/btr0pcur.c | 66 +++---- innobase/btr/btr0sea.c | 139 ++++++-------- innobase/dict/dict0crea.c | 2 +- innobase/ibuf/ibuf0ibuf.c | 48 +++-- innobase/include/btr0btr.h | 6 +- innobase/include/buf0buf.h | 4 +- innobase/include/buf0buf.ic | 10 +- innobase/include/lock0lock.h | 1 + innobase/include/mach0data.h | 21 ++ innobase/include/mach0data.ic | 31 +++ innobase/include/page0cur.h | 8 +- innobase/include/page0cur.ic | 22 +-- innobase/include/page0page.h | 72 ++++--- innobase/include/page0page.ic | 296 ++++++++++++++-------------- innobase/include/rem0rec.ic | 6 +- innobase/include/row0mysql.h | 2 +- innobase/lock/lock0lock.c | 183 +++++++++--------- innobase/mtr/mtr0log.c | 7 +- innobase/page/page0cur.c | 40 ++-- innobase/page/page0page.c | 141 +++++++------- innobase/rem/rem0cmp.c | 2 +- innobase/row/row0ins.c | 48 +++-- innobase/row/row0mysql.c | 2 +- innobase/row/row0row.c | 8 +- innobase/row/row0sel.c | 351 ++++++++++++++++++---------------- innobase/row/row0vers.c | 14 +- 28 files changed, 951 insertions(+), 878 deletions(-) diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 961b9eb696d..75c99e04f7b 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -138,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); } @@ -164,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); @@ -193,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); @@ -216,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); @@ -245,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); @@ -574,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)); @@ -599,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); @@ -613,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); @@ -664,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; @@ -855,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); @@ -878,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; @@ -1071,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); @@ -1152,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); @@ -1161,13 +1152,22 @@ 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)) { - 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) { + rec_t* next_rec; + + next_rec = page_rec_get_next(insert_point); + + 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 @@ -1176,12 +1176,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); } @@ -1221,7 +1217,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 */ @@ -1283,11 +1279,8 @@ btr_page_get_sure_split_rec( } else { next_rec = page_rec_get_next(rec); } - if (next_rec != page_get_supremum_rec(page)) { - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } - return(next_rec); + if (!page_rec_is_supremum(next_rec))) { + rec = next_rec; } } @@ -1330,13 +1323,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 */ @@ -1833,14 +1825,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); } /******************************************************************** @@ -1853,7 +1846,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 */ { @@ -1865,6 +1858,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); @@ -1880,7 +1875,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; @@ -2009,11 +2004,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)); @@ -2056,7 +2052,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); @@ -2251,10 +2247,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); @@ -2499,8 +2494,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 */ @@ -2508,9 +2503,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); @@ -2774,7 +2778,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)) { @@ -2930,7 +2934,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); diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 80a2600c7f9..4a68ef1d42e 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -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); } @@ -961,7 +962,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 +1028,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 +1040,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 +1167,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 @@ -1293,9 +1294,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 +1320,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 +1377,11 @@ 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 (!ptr || !page) { + goto func_exit; } - if (!page) { - mem_heap_free(heap); - - return(ptr); - } - + 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 +1396,7 @@ btr_cur_parse_update_in_place( row_upd_rec_in_place(rec, offsets, update); +func_exit: mem_heap_free(heap); return(ptr); @@ -1438,7 +1435,6 @@ btr_cur_update_in_place( rec = btr_cur_get_rec(cursor); index = cursor->index; trx = thr_get_trx(thr); - heap = mem_heap_create(100); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); if (btr_cur_print_record_ops && thr) { @@ -1449,7 +1445,7 @@ btr_cur_update_in_place( /* 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 (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -1458,6 +1454,8 @@ btr_cur_update_in_place( } 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 +1479,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,7 +1490,8 @@ 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 */ @@ -1597,7 +1597,7 @@ btr_cur_optimistic_update( new_rec_size = rec_get_converted_size(index, new_entry); if (new_rec_size >= - page_get_free_space_of_empty(index->table->comp) / 2) { + page_get_free_space_of_empty(page_is_comp(page)) / 2) { mem_heap_free(heap); @@ -1644,7 +1644,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 +1665,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 +1814,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 +1858,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 +1887,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 +1965,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 +1994,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 +2014,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); @@ -2039,6 +2041,8 @@ btr_cur_parse_del_mark_set_clust_rec( ulint offset; rec_t* rec; + ut_ad(!!page_is_comp(page) == index->table->comp); + if (end_ptr < ptr + 2) { return(NULL); @@ -2087,7 +2091,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); @@ -2161,7 +2165,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); @@ -2486,6 +2490,7 @@ btr_cur_pessimistic_delete( ulint n_reserved; ibool success; ibool ret = FALSE; + ulint level; mem_heap_t* heap; ulint* offsets; @@ -2522,15 +2527,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 @@ -2545,9 +2550,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) { @@ -2555,8 +2564,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 @@ -2566,13 +2575,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); } } @@ -2812,12 +2820,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); @@ -2830,6 +2839,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); @@ -2842,26 +2852,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); @@ -2874,9 +2887,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; + } } @@ -2898,11 +2919,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); } @@ -3598,7 +3619,7 @@ btr_rec_free_externally_stored_fields( MTR_MEMO_PAGE_X_FIX)); /* Free possible externally stored fields in the record */ - ut_ad(index->table->comp == rec_offs_comp(offsets)); + ut_ad(index->table->comp == !!rec_offs_comp(offsets)); n_fields = rec_offs_n_fields(offsets); for (i = 0; i < n_fields; i++) { diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c index 74feff8653c..7cc883a6696 100644 --- a/innobase/btr/btr0pcur.c +++ b/innobase/btr/btr0pcur.c @@ -78,6 +78,7 @@ btr_pcur_store_position( rec_t* rec; dict_tree_t* tree; page_t* page; + ulint offs; ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); @@ -87,7 +88,8 @@ btr_pcur_store_position( page_cursor = btr_pcur_get_page_cur(cursor); rec = page_cur_get_rec(page_cursor); - page = buf_frame_align(rec); + page = ut_align_down(rec, UNIV_PAGE_SIZE); + offs = ut_align_offset(rec, UNIV_PAGE_SIZE); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_S_FIX) @@ -95,35 +97,33 @@ btr_pcur_store_position( MTR_MEMO_PAGE_X_FIX)); ut_a(cursor->latch_mode != BTR_NO_LATCHES); - if (page_get_n_recs(page) == 0) { + if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) { /* It must be an empty index tree; NOTE that in this case we do not store the modify_clock, but always do a search if we restore the cursor position */ - ut_a(btr_page_get_next(page, mtr) == FIL_NULL - && btr_page_get_prev(page, mtr) == FIL_NULL); + ut_a(btr_page_get_next(page, mtr) == FIL_NULL); + ut_a(btr_page_get_prev(page, mtr) == FIL_NULL); - if (rec == page_get_supremum_rec(page)) { + cursor->old_stored = BTR_PCUR_OLD_STORED; + + if (page_rec_is_supremum_low(offs)) { cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE; - cursor->old_stored = BTR_PCUR_OLD_STORED; - - return; + } 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,12 +203,11 @@ 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 + ut_ad(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)) { ut_print_buf(stderr, (const byte*)cursor, sizeof(btr_pcur_t)); if (cursor->trx_if_known) { trx_print(stderr, cursor->trx_if_known); @@ -216,19 +216,14 @@ btr_pcur_restore_position( ut_a(0); } - 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); @@ -238,17 +233,18 @@ btr_pcur_restore_position( return(FALSE); } - ut_a(cursor->old_rec); - ut_a(cursor->old_n_fields); + ut_ad(cursor->old_rec); + ut_ad(cursor->old_n_fields); page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor)); - if (latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF) { + if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF) + || UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) { /* Try optimistic restoration */ - if (buf_page_optimistic_get(latch_mode, + if (UNIV_LIKELY(buf_page_optimistic_get(latch_mode, cursor->block_when_stored, page, - cursor->modify_clock, mtr)) { + cursor->modify_clock, mtr))) { cursor->pos_state = BTR_PCUR_IS_POSITIONED; #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_TREE_NODE); @@ -297,7 +293,7 @@ btr_pcur_restore_position( /* Save the old search mode of the cursor */ old_mode = cursor->search_mode; - if (cursor->rel_pos == BTR_PCUR_ON) { + if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) { mode = PAGE_CUR_LE; } else if (cursor->rel_pos == BTR_PCUR_AFTER) { mode = PAGE_CUR_G; @@ -323,12 +319,10 @@ btr_pcur_restore_position( the cursor can now be on a different page! But we can retain the value of old_rec */ - cursor->modify_clock = - buf_frame_get_modify_clock(btr_pcur_get_page(cursor)); - cursor->block_when_stored = buf_block_align(btr_pcur_get_page(cursor)); - + cursor->modify_clock = + buf_block_get_modify_clock(cursor->block_when_stored); cursor->old_stored = BTR_PCUR_OLD_STORED; mem_heap_free(heap); diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index cb43876e303..742a02b1de4 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -544,7 +544,6 @@ 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; @@ -561,7 +560,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)); @@ -612,12 +610,13 @@ btr_search_check_guess( if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)) { - 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; } @@ -634,12 +633,13 @@ btr_search_check_guess( goto exit_func; } - ut_ad(rec != page_get_supremum_rec(page)); + ut_ad(!page_rec_is_supremum(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; @@ -694,7 +694,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 +709,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 +719,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 +740,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 +774,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 +783,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 +817,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 +834,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 +862,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 +894,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 +944,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 +962,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, @@ -1090,7 +1064,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 +1131,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 +1159,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) { @@ -1443,7 +1414,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 +1458,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 +1503,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) { diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c index 1f12386e413..c7d6ffd2c22 100644 --- a/innobase/dict/dict0crea.c +++ b/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/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index c72bb2b1b65..712d43f916c 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/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); @@ -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); diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h index 23116d24288..1f3a32fa70c 100644 --- a/innobase/include/btr0btr.h +++ b/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 */ /*************************************************************** diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index 5ee323f1b1e..7b8e1b7bb09 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -382,10 +382,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 diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic index 803b20560bf..9044c3251a4 100644 --- a/innobase/include/buf0buf.ic +++ b/innobase/include/buf0buf.ic @@ -481,17 +481,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/innobase/include/lock0lock.h b/innobase/include/lock0lock.h index 710c945375c..9830c8abfc6 100644 --- a/innobase/include/lock0lock.h +++ b/innobase/include/lock0lock.h @@ -216,6 +216,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 */ diff --git a/innobase/include/mach0data.h b/innobase/include/mach0data.h index 7ad760cd60f..f9a3ff521d5 100644 --- a/innobase/include/mach0data.h +++ b/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/innobase/include/mach0data.ic b/innobase/include/mach0data.ic index 3ffb9baa344..888f3f743e4 100644 --- a/innobase/include/mach0data.ic +++ b/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/innobase/include/page0cur.h b/innobase/include/page0cur.h index 4fc62f37db7..e89e740e775 100644 --- a/innobase/include/page0cur.h +++ b/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/innobase/include/page0cur.ic b/innobase/include/page0cur.ic index e99d799b372..f8346819e84 100644 --- a/innobase/include/page0cur.ic +++ b/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/innobase/include/page0page.h b/innobase/include/page0page.h index 144c297b811..c4ffa39d3ac 100644 --- a/innobase/include/page0page.h +++ b/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,6 +415,30 @@ 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_low( +/*=====================*/ + /* out: TRUE if a user 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_low( +/*=====================*/ + /* out: TRUE if the supremum 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_low( +/*=====================*/ + /* out: TRUE if the infimum record */ + ulint offset);/* in: record offset on page */ /**************************************************************** TRUE if the record is a user record on the page. */ @@ -414,40 +446,24 @@ UNIV_INLINE ibool page_rec_is_user_rec( /*=================*/ - /* out: TRUE if a user record */ - rec_t* rec); /* in: record */ + /* out: TRUE if a user record */ + const rec_t* rec); /* in: record */ /**************************************************************** TRUE if the record is the supremum record on a page. */ UNIV_INLINE ibool page_rec_is_supremum( /*=================*/ - /* out: TRUE if the supremum record */ - rec_t* rec); /* in: record */ + /* 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 */ - rec_t* rec); /* in: record */ -/**************************************************************** -TRUE if the record is the first 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 */ -/**************************************************************** -TRUE if the record is the last user record on the page. */ -UNIV_INLINE -ibool -page_rec_is_last_user_rec( -/*======================*/ - /* out: TRUE if last user record */ - rec_t* rec); /* in: record */ + /* 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/innobase/include/page0page.ic b/innobase/include/page0page.ic index bc0805ca30c..8299d160b28 100644 --- a/innobase/include/page0page.ic +++ b/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(!!(page_header_get_field(page, PAGE_N_HEAP) & 0x8000)); + 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_is_comp(ut_align_down((rec_t*) rec, UNIV_PAGE_SIZE))); } /**************************************************************** @@ -201,28 +214,85 @@ page_get_supremum_rec( } } +/**************************************************************** +TRUE if the record is a user record on the page. */ +UNIV_INLINE +ibool +page_rec_is_user_rec_low( +/*=====================*/ + /* out: TRUE if a user record */ + ulint offset) /* in: record offset on page */ +{ + 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(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_low( +/*=====================*/ + /* out: TRUE if the supremum record */ + ulint offset) /* in: record offset on page */ +{ + ut_ad(offset >= PAGE_NEW_INFIMUM); + ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START); + + 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_low( +/*=====================*/ + /* out: TRUE if the infimum record */ + ulint offset) /* in: record offset on page */ +{ + ut_ad(offset >= PAGE_NEW_INFIMUM); + ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START); + + return(UNIV_UNLIKELY(offset == PAGE_NEW_INFIMUM) + || UNIV_UNLIKELY(offset == PAGE_OLD_INFIMUM)); +} + /**************************************************************** TRUE if the record is a user record on the page. */ UNIV_INLINE ibool page_rec_is_user_rec( /*=================*/ - /* out: TRUE if a user record */ - rec_t* rec) /* in: record */ + /* 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_get_infimum_rec(buf_frame_align(rec))) { - - return(FALSE); - } - - return(TRUE); + return(page_rec_is_user_rec_low( + ut_align_offset(rec, UNIV_PAGE_SIZE))); } /**************************************************************** @@ -231,17 +301,11 @@ UNIV_INLINE ibool page_rec_is_supremum( /*=================*/ - /* out: TRUE if the supremum record */ - rec_t* rec) /* in: record */ + /* 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(TRUE); - } - - return(FALSE); + return(page_rec_is_supremum_low( + ut_align_offset(rec, UNIV_PAGE_SIZE))); } /**************************************************************** @@ -250,67 +314,11 @@ UNIV_INLINE ibool page_rec_is_infimum( /*================*/ - /* out: TRUE if the infimum record */ - rec_t* rec) /* in: record */ + /* out: TRUE if the infimum record */ + const rec_t* rec) /* in: record */ { - ut_ad(rec); - - if (rec == page_get_infimum_rec(buf_frame_align(rec))) { - - return(TRUE); - } - - return(FALSE); -} - -/**************************************************************** -TRUE if the record is the first 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 */ -{ - 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); -} - -/**************************************************************** -TRUE if the record is the last user record on the page. */ -UNIV_INLINE -ibool -page_rec_is_last_user_rec( -/*======================*/ - /* out: TRUE if last user record */ - 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(FALSE); + 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) { + if (UNIV_UNLIKELY(offs >= UNIV_PAGE_SIZE)) { fprintf(stderr, -"InnoDB: Next record offset is nonsensical %lu in record at offset %lu\n", - (ulong)offs, (ulong)(rec - page)); - 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)); + ut_ad(!page_rec_is_infimum(next)); + page = ut_align_down(rec, UNIV_PAGE_SIZE); if (next) { + ut_a(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); - 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); - - occupied = page_header_get_field(page, PAGE_HEAP_TOP) - - (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END) - + page_dir_calc_reserved_space( + 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); - free_space = page_get_free_space_of_empty(comp); - + 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(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/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index cd742aef6a6..85e196bbcf8 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -929,14 +929,14 @@ 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); } /********************************************************** diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 277089430d4..28e94fad68f 100644 --- a/innobase/include/row0mysql.h +++ b/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. */ diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index 650552be366..bde3eb0c16f 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -501,12 +501,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)); } /************************************************************************* @@ -1270,7 +1265,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 @@ -1278,19 +1272,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); } /************************************************************************* @@ -1303,22 +1297,24 @@ 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)); - - while (lock) { - if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec, comp))) { - - break; + if (UNIV_LIKELY_NULL(lock)) { + if (page_rec_is_comp(rec)) { + while (lock && !lock_rec_get_nth_bit(lock, + rec_get_heap_no(rec, TRUE))) { + lock = lock_rec_get_next_on_page(lock); + } + } else { + while (lock && !lock_rec_get_nth_bit(lock, + rec_get_heap_no(rec, FALSE))) { + lock = lock_rec_get_next_on_page(lock); + } } - - lock = lock_rec_get_next_on_page(lock); } return(lock); @@ -1480,7 +1476,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; @@ -1510,7 +1505,7 @@ lock_rec_has_expl( return(lock); } - lock = lock_rec_get_next(rec, comp, lock); + lock = lock_rec_get_next(rec, lock); } return(NULL); @@ -1529,7 +1524,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 */ { @@ -1554,7 +1548,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); @@ -1575,13 +1569,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, @@ -1590,7 +1582,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); @@ -1616,7 +1608,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) { @@ -1718,6 +1710,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 */ @@ -1734,7 +1728,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); } @@ -1835,7 +1829,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); } @@ -1885,7 +1879,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 @@ -1894,11 +1887,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; @@ -1907,7 +1900,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 @@ -1918,7 +1911,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) { @@ -1993,7 +1986,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); @@ -2074,8 +2067,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 */ @@ -2392,14 +2384,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); @@ -2410,7 +2400,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); } } @@ -2428,13 +2418,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)) { @@ -2444,7 +2432,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); } } @@ -2461,13 +2449,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) @@ -2479,7 +2465,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); } } @@ -2493,7 +2479,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; @@ -2523,7 +2509,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); @@ -2549,7 +2535,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(); @@ -2668,8 +2654,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 @@ -2754,7 +2741,7 @@ lock_move_rec_list_start( page_cur_t cur2; ulint heap_no; ulint type_mode; - ibool comp; + ulint comp; ut_a(new_page); @@ -2763,6 +2750,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) { @@ -2821,7 +2809,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)); @@ -2884,7 +2872,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)); @@ -2907,7 +2895,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)); @@ -2954,31 +2942,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); @@ -3037,7 +3028,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; } @@ -3100,19 +3091,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(); } @@ -3129,10 +3117,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); @@ -4483,15 +4471,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 +4498,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 +4511,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 +4528,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 +4548,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(); @@ -4887,7 +4876,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 +4890,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, diff --git a/innobase/mtr/mtr0log.c b/innobase/mtr/mtr0log.c index 4f826f242e8..d80f22fd2f3 100644 --- a/innobase/mtr/mtr0log.c +++ b/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. */ @@ -405,7 +406,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 +501,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/innobase/page/page0cur.c b/innobase/page/page0cur.c index aade42c3a45..df6d898d4ac 100644 --- a/innobase/page/page0cur.c +++ b/innobase/page/page0cur.c @@ -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; @@ -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); @@ -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)); @@ -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_; @@ -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); } @@ -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/innobase/page/page0page.c b/innobase/page/page0page.c index 768444008b8..9c957ac8554 100644 --- a/innobase/page/page0page.c +++ b/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); + first_slot = page_dir_get_nth_slot(page, 0); + slot = page_dir_get_nth_slot(page, page_dir_get_n_slots(page) - 1); - while (rec_get_n_owned(rec, comp) == 0) { - steps++; - rec = page_rec_get_next(rec); + 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) { - fputs("(compact record)", stderr); - } else { - rec_print_old(stderr, original_rec); - } - - fprintf(stderr, "\n" - "InnoDB: on that page. Steps %lu.\n", (ulong) steps); - fputs( - "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); } + + fputs("\n" + "InnoDB: on that page.\n" + "InnoDB: Cannot find the dir slot for record ", + stderr); + if (page_is_comp(page)) { + fputs("(compact record)", stderr); + } else { + 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); } /****************************************************************** @@ -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 */ @@ -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) { @@ -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); @@ -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" @@ -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/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c index 0a918d0e470..7c33476fb9e 100644 --- a/innobase/rem/rem0cmp.c +++ b/innobase/rem/rem0cmp.c @@ -727,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)); diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index e2cb64a9742..f1a43868ba5 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -1255,9 +1255,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 +1267,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); @@ -1529,12 +1531,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 +1626,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; } @@ -1697,7 +1694,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 +1724,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 +1767,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 +1836,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 +1849,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 +1889,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,16 +1923,21 @@ 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)))); - - if (!page_rec_is_supremum(first_rec)) { - ut_a(rec_get_n_fields(first_rec, index) - == dtuple_get_n_fields(entry)); } +#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 (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); if (index->type & DICT_UNIQUE && (cursor.up_match >= n_unique diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 1b0888e535b..fcb3831b5fc 100644 --- a/innobase/row/row0mysql.c +++ b/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; diff --git a/innobase/row/row0row.c b/innobase/row/row0row.c index 46bd51d4694..9a74397dc08 100644 --- a/innobase/row/row0row.c +++ b/innobase/row/row0row.c @@ -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/innobase/row/row0sel.c b/innobase/row/row0sel.c index c6171789b8b..c2f9e79ca65 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -1261,7 +1261,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 +1299,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 +1337,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 */ @@ -2416,14 +2416,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 +2433,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 +2455,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 +2464,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 +2492,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 +2519,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); - } } } @@ -2926,9 +2928,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; } @@ -3049,11 +3051,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; @@ -3063,9 +3061,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; @@ -3076,7 +3074,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" @@ -3090,7 +3088,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 ", @@ -3104,7 +3102,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 @@ -3127,8 +3125,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 @@ -3144,7 +3142,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; @@ -3162,8 +3160,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, @@ -3175,7 +3173,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++; @@ -3235,7 +3233,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; @@ -3253,9 +3252,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)) { @@ -3287,9 +3286,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)); @@ -3323,9 +3322,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); @@ -3368,6 +3366,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); @@ -3383,7 +3382,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; } @@ -3397,10 +3396,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; } @@ -3441,11 +3439,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) { @@ -3459,8 +3459,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); @@ -3468,7 +3468,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 @@ -3477,10 +3479,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 */ @@ -3488,18 +3491,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 */ @@ -3511,12 +3512,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)); @@ -3529,7 +3537,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); @@ -3547,7 +3555,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); @@ -3562,13 +3570,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); @@ -3594,25 +3602,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); @@ -3628,25 +3633,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); @@ -3662,29 +3664,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 @@ -3704,7 +3702,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; } @@ -3732,7 +3730,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)) { @@ -3763,13 +3761,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 @@ -3783,14 +3783,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 */ @@ -3812,7 +3812,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 */ @@ -3833,7 +3834,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 @@ -3908,7 +3910,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 @@ -3920,34 +3922,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; @@ -3965,11 +3971,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, @@ -3979,9 +3984,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: @@ -3996,9 +4005,11 @@ 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++; } diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c index 36f6c27636d..68231f6eade 100644 --- a/innobase/row/row0vers.c +++ b/innobase/row/row0vers.c @@ -61,7 +61,7 @@ row_vers_impl_x_locked_off_kernel( ibool 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); From 949112c12a2a74555c5049aa8b82cee87660cbb5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Apr 2005 12:28:44 +0300 Subject: [PATCH 14/38] Fix bugs found in previous optimizations. Make rec_get_deleted_flag() return zero/nonzero instead of FALSE/TRUE. innobase/btr/btr0btr.c: btr_page_get_sure_split_rec(): Fix bug caused by optimization (dereferencing null pointer in page_rec_is_supremum()) btr_page_insert_fits(): Correct a debug assertion. innobase/btr/btr0cur.c: Add debug assertions about page_rec_is_comp(). Add UNIV_LIKELY and UNIV_UNLIKELY hints. Note that rec_get_deleted_flag() returns zero/nonzero ulint instead of FALSE/TRUE ibool. innobase/include/page0page.ic: Move debug assertion to proper place. innobase/include/rem0rec.h: rec_get_deleted_flag(), rec_set_deleted_flag(): Make the flag zero/nonzero in order to avoid FALSE/TRUE normalization in every rec_get_deleted_flag() call. innobase/include/rem0rec.ic: rec_get_deleted_flag(), rec_set_deleted_flag(): Make the flag zero/nonzero in order to avoid FALSE/TRUE normalization in every rec_get_deleted_flag() call. innobase/rem/rem0rec.c: rec_init_offsets(): Fix bugs introduced in optimization. innobase/row/row0sel.c: Make debug assertion stricter. innobase/row/row0vers.c: Note that rec_get_deleted_flag() returns zero/nonzero ulint instead of FALSE/TRUE ibool. --- innobase/btr/btr0btr.c | 9 ++++++--- innobase/btr/btr0cur.c | 22 +++++++++++++--------- innobase/include/page0page.ic | 2 +- innobase/include/rem0rec.h | 6 +++--- innobase/include/rem0rec.ic | 19 +++++++++---------- innobase/rem/rem0rec.c | 9 ++------- innobase/row/row0sel.c | 2 +- innobase/row/row0vers.c | 4 ++-- 8 files changed, 37 insertions(+), 36 deletions(-) diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 75c99e04f7b..6ca0077523f 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -1273,17 +1273,20 @@ 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 (!page_rec_is_supremum(next_rec))) { + ut_ad(next_rec); + if (!page_rec_is_supremum(next_rec)) { rec = next_rec; } } + func_exit: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -1323,7 +1326,7 @@ btr_page_insert_fits( ut_ad(!split_rec == !offsets); ut_ad(!offsets - || page_is_comp(page) == !!rec_offs_comp(offsets)); + || !page_is_comp(page) == !rec_offs_comp(offsets)); ut_ad(!offsets || rec_offs_validate(split_rec, cursor->index, offsets)); diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 4a68ef1d42e..a3f071c7729 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -1426,7 +1426,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_; @@ -1434,6 +1434,7 @@ btr_cur_update_in_place( rec = btr_cur_get_rec(cursor); index = cursor->index; + ut_ad(!!page_rec_is_comp(rec) == index->table->comp); trx = thr_get_trx(thr); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); @@ -1547,6 +1548,7 @@ 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); @@ -1596,8 +1598,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(page_is_comp(page)) / 2) { + if (UNIV_UNLIKELY(new_rec_size >= page_get_free_space_of_empty( + page_is_comp(page)) / 2)) { mem_heap_free(heap); @@ -1607,8 +1609,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 */ @@ -2034,14 +2037,14 @@ 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_is_comp(page) == index->table->comp); + ut_ad(!page || !!page_is_comp(page) == index->table->comp); if (end_ptr < ptr + 2) { @@ -2127,6 +2130,7 @@ btr_cur_del_mark_set_clust_rec( rec = btr_cur_get_rec(cursor); index = cursor->index; + ut_ad(!!page_rec_is_comp(rec) == index->table->comp); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); if (btr_cur_print_record_ops && thr) { @@ -2135,7 +2139,7 @@ btr_cur_del_mark_set_clust_rec( } 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); @@ -2230,7 +2234,7 @@ btr_cur_parse_del_mark_set_sec_rec( byte* end_ptr,/* in: buffer end */ page_t* page) /* in: page or NULL */ { - ibool val; + ulint val; ulint offset; rec_t* rec; diff --git a/innobase/include/page0page.ic b/innobase/include/page0page.ic index 8299d160b28..cef8f6a1b80 100644 --- a/innobase/include/page0page.ic +++ b/innobase/include/page0page.ic @@ -593,10 +593,10 @@ page_rec_set_next( ut_ad(page_rec_check(rec)); ut_ad(!page_rec_is_supremum(rec)); - ut_ad(!page_rec_is_infimum(next)); page = ut_align_down(rec, UNIV_PAGE_SIZE); if (next) { + ut_ad(!page_rec_is_infimum(next)); ut_a(page == ut_align_down(next, UNIV_PAGE_SIZE)); offs = (ulint) (next - page); } else { diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h index 3c150d6601d..bfb43847e39 100644 --- a/innobase/include/rem0rec.h +++ b/innobase/include/rem0rec.h @@ -162,10 +162,10 @@ 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 */ ulint comp); /* in: nonzero=compact page format */ /********************************************************** @@ -176,7 +176,7 @@ rec_set_deleted_flag( /*=================*/ rec_t* rec, /* in: physical record */ ulint comp, /* in: nonzero=compact page format */ - ibool flag); /* in: TRUE if delete marked */ + ulint flag); /* in: nonzero if delete marked */ /********************************************************** The following function tells if a new-style record is a node pointer. */ UNIV_INLINE diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index 85e196bbcf8..3ada4100bd0 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -578,19 +578,21 @@ 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 */ ulint comp) /* in: nonzero=compact page format */ { if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) { - return(0 != rec_get_bit_field_1(rec, REC_NEW_INFO_BITS, - REC_INFO_DELETED_FLAG, REC_INFO_BITS_SHIFT)); + return(UNIV_UNLIKELY(rec_get_bit_field_1(rec, + REC_NEW_INFO_BITS, REC_INFO_DELETED_FLAG, + REC_INFO_BITS_SHIFT))); } else { - return(0 != rec_get_bit_field_1(rec, REC_OLD_INFO_BITS, - REC_INFO_DELETED_FLAG, REC_INFO_BITS_SHIFT)); + return(UNIV_UNLIKELY(rec_get_bit_field_1(rec, + REC_OLD_INFO_BITS, REC_INFO_DELETED_FLAG, + REC_INFO_BITS_SHIFT))); } } @@ -602,13 +604,10 @@ rec_set_deleted_flag( /*=================*/ rec_t* rec, /* in: physical record */ ulint comp, /* in: nonzero=compact page format */ - ibool flag) /* in: TRUE if delete marked */ + ulint flag) /* in: nonzero if delete marked */ { ulint val; - ut_ad(TRUE == 1); - ut_ad(flag <= TRUE); - val = rec_get_info_bits(rec, comp); if (flag) { diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c index a1e7e348781..580a7bfe509 100644 --- a/innobase/rem/rem0rec.c +++ b/innobase/rem/rem0rec.c @@ -218,20 +218,15 @@ rec_init_offsets( We do not advance offs, and we set the length to zero and enable the SQL NULL flag in offsets[]. */ - len = REC_OFFS_SQL_NULL; + len = offs | REC_OFFS_SQL_NULL; goto resolved; } null_mask <<= 1; - - ut_ad(!field->fixed_len); - goto variable_length; } if (UNIV_UNLIKELY(!field->fixed_len)) { - dtype_t* type; - variable_length: /* Variable-length field: read the length */ - type = dict_col_get_type( + dtype_t* type = dict_col_get_type( dict_field_get_col(field)); len = *lens--; if (UNIV_UNLIKELY(dtype_get_len(type) > 255) diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index c2f9e79ca65..a2257e0b72e 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -3459,7 +3459,7 @@ rec_loop: /* PHASE 4: Look for matching records in a loop */ rec = btr_pcur_get_rec(pcur); - ut_ad(!page_rec_is_comp(rec) == !index->table->comp); + ut_ad(!!page_rec_is_comp(rec) == index->table->comp); #ifdef UNIV_SEARCH_DEBUG /* fputs("Using ", stderr); diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c index 68231f6eade..8e747423047 100644 --- a/innobase/row/row0vers.c +++ b/innobase/row/row0vers.c @@ -57,8 +57,8 @@ 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; ulint comp; From bcd031271fbfc22e662337386e529185fd434fc5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Apr 2005 13:35:57 +0300 Subject: [PATCH 15/38] Remove unused function rec_offs_nth_null(). rec_offs_nth_extern(): Return zero/nonzero instead of FALSE/TRUE. innobase/row/row0upd.c: Normalize the return value of rec_offs_nth_extern() to FALSE/TRUE. Avoid a repeated call to upd_ext_vec_contains(). --- innobase/include/rem0rec.h | 15 +++------------ innobase/include/rem0rec.ic | 23 +++++------------------ innobase/row/row0upd.c | 13 +++++-------- 3 files changed, 13 insertions(+), 38 deletions(-) diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h index bfb43847e39..0e9ab49f363 100644 --- a/innobase/include/rem0rec.h +++ b/innobase/include/rem0rec.h @@ -303,21 +303,12 @@ rec_offs_comp( /* out: TRUE 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/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index 3ada4100bd0..d60fb3b9eda 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -939,32 +939,19 @@ rec_offs_comp( } /********************************************************** -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 */ -{ - 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. */ -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)); } /********************************************************** diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c index c0aa285d7e5..cf2b8db5d32 100644 --- a/innobase/row/row0upd.c +++ b/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: From 807a543b8b795adb1b9c6546d1e2a044ecf1950e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 May 2005 15:55:53 +0300 Subject: [PATCH 16/38] InnoDB: Disable throttling against thread thrashing by default. sql/ha_innodb.cc: Remove unused variable innobase_thread_concurrency. Add UNIV_LIKELY hints to srv_thread_concurrency tests and lower the limit from 500 to 20. sql/ha_innodb.h: Remove unused variable innobase_thread_concurrency. sql/mysqld.cc: Make innodb_thread_concurrency=20 by default (it was 8). --- sql/ha_innodb.cc | 7 +++---- sql/ha_innodb.h | 2 +- sql/mysqld.cc | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 3dd82960958..91c1dab44f1 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -98,8 +98,7 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group, innobase_buffer_pool_awe_mem_mb, innobase_buffer_pool_size, innobase_additional_mem_pool_size, innobase_file_io_threads, innobase_lock_wait_timeout, - innobase_thread_concurrency, innobase_force_recovery, - innobase_open_files; + innobase_force_recovery, innobase_open_files; /* The default values for the following char* start-up parameters are determined in innobase_init below: */ @@ -279,7 +278,7 @@ innodb_srv_conc_enter_innodb( /*=========================*/ trx_t* trx) /* in: transaction handle */ { - if (srv_thread_concurrency >= 500) { + if (UNIV_LIKELY(srv_thread_concurrency >= 20)) { return; } @@ -296,7 +295,7 @@ innodb_srv_conc_exit_innodb( /*========================*/ trx_t* trx) /* in: transaction handle */ { - if (srv_thread_concurrency >= 500) { + if (UNIV_LIKELY(srv_thread_concurrency >= 20)) { return; } diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 35f95ead757..26d827f3efe 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -219,7 +219,7 @@ extern long innobase_log_file_size, innobase_log_buffer_size; extern long innobase_buffer_pool_size, innobase_additional_mem_pool_size; extern long innobase_buffer_pool_awe_mem_mb; extern long innobase_file_io_threads, innobase_lock_wait_timeout; -extern long innobase_force_recovery, innobase_thread_concurrency; +extern long innobase_force_recovery; extern long innobase_open_files; extern char *innobase_data_home_dir, *innobase_data_file_path; extern char *innobase_log_group_home_dir, *innobase_log_arch_dir; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9c592d068ee..845a4450bef 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5170,7 +5170,7 @@ log and this option does nothing anymore.", {"innodb_thread_concurrency", OPT_INNODB_THREAD_CONCURRENCY, "Helps in performance tuning in heavily concurrent environments.", (gptr*) &srv_thread_concurrency, (gptr*) &srv_thread_concurrency, - 0, GET_LONG, REQUIRED_ARG, 8, 1, 1000, 0, 1, 0}, + 0, GET_LONG, REQUIRED_ARG, 20, 1, 1000, 0, 1, 0}, {"innodb_thread_sleep_delay", OPT_INNODB_THREAD_SLEEP_DELAY, "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0" " disable a sleep", From 67d0502bcf05ee19edf0710ef153ca6b68244b26 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 12:55:59 +0300 Subject: [PATCH 17/38] InnoDB ON UPDATE CASCADE fixes: Enforce maximum char_length of UTF-8 data (Bug #10409). Pad UTF-8 variable-length CHAR columns with 0x20. Pad UCS2 CHAR columns with 0x0020 (Bug #10511). innobase/data/data0type.c: dtype_get_at_most_n_mbchars(): Avoid division by zero in assertion when this function is called with dtype->mbmaxlen==0 innobase/row/row0ins.c: row_ins_cascade_calc_update_vec(): Enforce maximum char_length of UTF-8 data (Bug #10409). Pad UTF-8 CHAR columns with 0x20. Pad UCS2 CHAR columns with 0x0020 (Bug #10511). --- innobase/data/data0type.c | 3 +- innobase/row/row0ins.c | 58 ++++++++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/innobase/data/data0type.c b/innobase/data/data0type.c index 36b0f9603e5..d4264ad2926 100644 --- a/innobase/data/data0type.c +++ b/innobase/data/data0type.c @@ -63,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/innobase/row/row0ins.c b/innobase/row/row0ins.c index f1a43868ba5..776094d0de5 100644 --- a/innobase/row/row0ins.c +++ b/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); + min_size = dtype_get_min_size(type); - /* TODO: pad in UCS-2 with 0x0020. - TODO: How does the special truncation of - UTF-8 CHAR cols affect this? */ - - 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; From 9a67ecc3e4c080aeb53eb947a70531e035805d25 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Jun 2005 01:25:06 +0200 Subject: [PATCH 18/38] Fix Windows build warning and file missing from projects. VC++Files/libmysql/libmysql.dsp: Add missing file VC++Files/client/mysqlclient.dsp: Add missing file vio/viosocket.c: Add missing parameter --- VC++Files/client/mysqlclient.dsp | 4 ++++ VC++Files/libmysql/libmysql.dsp | 4 ++++ vio/viosocket.c | 1 + 3 files changed, 9 insertions(+) diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp index 599bad92d7f..9a6fd933041 100644 --- a/VC++Files/client/mysqlclient.dsp +++ b/VC++Files/client/mysqlclient.dsp @@ -322,6 +322,10 @@ SOURCE=..\mysys\mulalloc.c # End Source File # Begin Source File +SOURCE=..\mysys\my_access.c +# End Source File +# Begin Source File + SOURCE=..\mysys\my_alloc.c # End Source File # Begin Source File diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp index 21e393f137d..9bc7dfb8a1d 100644 --- a/VC++Files/libmysql/libmysql.dsp +++ b/VC++Files/libmysql/libmysql.dsp @@ -295,6 +295,10 @@ SOURCE=..\mysys\mulalloc.c # End Source File # Begin Source File +SOURCE=..\mysys\my_access.c +# End Source File +# Begin Source File + SOURCE=..\mysys\my_alloc.c # End Source File # Begin Source File diff --git a/vio/viosocket.c b/vio/viosocket.c index 172d9127dc2..904b75583a9 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -379,6 +379,7 @@ int vio_close_pipe(Vio * vio) void vio_ignore_timeout(Vio *vio __attribute__((unused)), + uint which __attribute__((unused)), uint timeout __attribute__((unused))) { } From 2e2a4e4f3e4086186b0e6cfba5bfaf0019aeb88a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Jun 2005 15:45:56 +0300 Subject: [PATCH 19/38] InnoDB: Do not distinguish explicitly requested table locks. Since UNLOCK TABLES will commit the transaction (and thus release all InnoDB locks held by it), it is unnecessary to release the user-requested table locks separately. innobase/include/lock0lock.h: Remove references to LOCK_TABLE_EXP and LOCK_TABLE_TRANSACTIONAL. Remove lock_release_tables_off_kernel(). innobase/include/row0mysql.h: Remove row_unlock_tables_for_mysql(). innobase/include/trx0trx.h: Remove n_lock_table_exp and n_lock_table_transactional. innobase/lock/lock0lock.c: Remove references to LOCK_TABLE_EXP and LOCK_TABLE_TRANSACTIONAL. Remove lock_release_tables_off_kernel(). Remove references to trx->n_lock_table_exp and trx->n_lock_table_transactional. innobase/row/row0mysql.c: Remove row_unlock_tables_for_mysql(). Remove references to LOCK_TABLE_TRANSACTIONAL and LOCK_TABLE_EXP. innobase/trx/trx0trx.c: Remove n_lock_table_exp and n_lock_table_transactional. sql/ha_innodb.cc: Remove references to LOCK_TABLE_EXP and LOCK_TABLE_TRANSACTIONAL and row_unlock_tables_for_mysql(). --- innobase/include/lock0lock.h | 16 +---- innobase/include/row0mysql.h | 13 +--- innobase/include/trx0trx.h | 7 --- innobase/lock/lock0lock.c | 118 ++--------------------------------- innobase/row/row0mysql.c | 34 ++-------- innobase/trx/trx0trx.c | 10 --- sql/ha_innodb.cc | 10 +-- 7 files changed, 17 insertions(+), 191 deletions(-) diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h index 9830c8abfc6..3f39a0b40c7 100644 --- a/innobase/include/lock0lock.h +++ b/innobase/include/lock0lock.h @@ -413,9 +413,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 */ @@ -452,15 +450,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. */ @@ -612,9 +601,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/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 28e94fad68f..4bb9fa63cd1 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -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. */ diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 6ca9c778aeb..8df50d6703d 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -497,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/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index bde3eb0c16f..f2d5d035ab1 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -2208,11 +2208,7 @@ 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); - } + } if (lock_print_waits) { fprintf(stderr, "Lock wait for trx %lu ends\n", @@ -3415,14 +3411,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); @@ -3459,14 +3447,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); } @@ -3597,10 +3577,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 */ @@ -3615,8 +3592,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); @@ -3729,9 +3705,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); @@ -3835,12 +3809,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) { @@ -3860,74 +3828,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); } /************************************************************************* @@ -4040,15 +3940,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); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index fcb3831b5fc..0b010096002 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -970,25 +970,6 @@ run_again: return((int) err); } -/************************************************************************* -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. */ @@ -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; diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index cdda1dd4dee..c3b12468523 100644 --- a/innobase/trx/trx0trx.c +++ b/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/sql/ha_innodb.cc b/sql/ha_innodb.cc index 91c1dab44f1..2675ccdbfbb 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5719,7 +5719,7 @@ ha_innobase::external_lock( ulint error; error = row_lock_table_for_mysql(prebuilt, - NULL, LOCK_TABLE_EXP); + NULL, 0); if (error != DB_SUCCESS) { error = convert_error_code_to_mysql( @@ -5739,9 +5739,6 @@ ha_innobase::external_lock( trx->n_mysql_tables_in_use--; prebuilt->mysql_has_locked = FALSE; auto_inc_counter_for_this_stat = 0; - if (trx->n_lock_table_exp) { - row_unlock_tables_for_mysql(trx); - } /* If the MySQL lock count drops to zero we know that the current SQL statement has ended */ @@ -5783,7 +5780,7 @@ user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */ int ha_innobase::transactional_table_lock( /*==================================*/ - /* out: 0 */ + /* out: error code */ THD* thd, /* in: handle to the user thread */ int lock_type) /* in: lock type */ { @@ -5847,8 +5844,7 @@ ha_innobase::transactional_table_lock( if (thd->in_lock_tables && thd->variables.innodb_table_locks) { ulint error = DB_SUCCESS; - error = row_lock_table_for_mysql(prebuilt,NULL, - LOCK_TABLE_TRANSACTIONAL); + error = row_lock_table_for_mysql(prebuilt, NULL, 0); if (error != DB_SUCCESS) { error = convert_error_code_to_mysql(error, user_thd); From 9db57192c178695e1dc86b58fca408038cfd96b4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Jun 2005 11:40:20 +0300 Subject: [PATCH 20/38] btr0cur.c: Move the flag btr_cur_print_record_ops behind #ifdef UNIV_DEBUG. Remove unused variable btr_cur_rnd. innobase/btr/btr0cur.c: Move the flag btr_cur_print_record_ops behind #ifdef UNIV_DEBUG. Remove unused variable btr_cur_rnd. --- innobase/btr/btr0cur.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index a3f071c7729..85d6194055f 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -36,11 +36,11 @@ Created 10/16/1994 Heikki Tuuri #include "ibuf0ibuf.h" #include "lock0lock.h" +#ifdef UNIV_DEBUG /* If the following is set to TRUE, this module prints a lot of trace information of individual record operations */ ibool btr_cur_print_record_ops = FALSE; - -ulint btr_cur_rnd = 0; +#endif /* UNIV_DEBUG */ ulint btr_cur_n_non_sea = 0; ulint btr_cur_n_sea = 0; @@ -880,6 +880,7 @@ btr_cur_ins_lock_and_undo( return(DB_SUCCESS); } +#ifdef UNIV_DEBUG /***************************************************************** Report information about a transaction. */ static @@ -897,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. @@ -946,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); @@ -1437,11 +1440,12 @@ btr_cur_update_in_place( ut_ad(!!page_rec_is_comp(rec) == index->table->comp); trx = thr_get_trx(thr); 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, @@ -1553,10 +1557,12 @@ btr_cur_optimistic_update( 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)); @@ -2133,10 +2139,12 @@ btr_cur_del_mark_set_clust_rec( 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, rec_offs_comp(offsets))); @@ -2284,11 +2292,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); From 7256cdaa563a8248527978acfedd806252cb98be Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Jun 2005 12:22:23 +0300 Subject: [PATCH 21/38] InnoDB: Improved the handling of assertions. innobase/include/ut0dbg.h: Write help macros to use in ut_a() and ut_error. Moved some ut_a() and ut_error code to non-inlined functions. Fixed ut_error on NetWare. Reintroduced ut_dbg_zero on non-GCC platforms. innobase/ut/ut0dbg.c: Reintroduced ut_dbg_zero on non-GCC platforms. Removed ut_dbg_null_ptr on NetWare. Add helpers ut_dbg_assertion_failed() and ut_dbg_stop_thread(). --- innobase/include/ut0dbg.h | 125 ++++++++++++++++++++------------------ innobase/ut/ut0dbg.c | 54 +++++++++++++--- 2 files changed, 113 insertions(+), 66 deletions(-) diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h index a0af0e2f0ad..7e614343f5b 100644 --- a/innobase/include/ut0dbg.h +++ b/innobase/include/ut0dbg.h @@ -13,72 +13,79 @@ Created 1/30/1994 Heikki Tuuri #include #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. */ +# define UT_DBG_PANIC \ + if (!panic_shutdown){ \ + panic_shutdown = TRUE; \ + innobase_shutdown_for_mysql(); \ + } \ + exit(1) +/* 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 (UNIV_UNLIKELY(!((ulint)(EXPR)))) {\ - 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 (UNIV_UNLIKELY(!((ulint)(EXPR)))) {\ - 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/innobase/ut/ut0dbg.c b/innobase/ut/ut0dbg.c index ea3b48b6e9e..c4d738ffb83 100644 --- a/innobase/ut/ut0dbg.c +++ b/innobase/ut/ut0dbg.c @@ -8,6 +8,12 @@ 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 */ ibool ut_dbg_stop_threads = FALSE; @@ -16,21 +22,55 @@ 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__ */ -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 = +/***************************************************************** +Report a failed assertion. */ + +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; +} -const char* ut_dbg_msg_stop = -"InnoDB: Thread %lu stopped in file %s line %lu\n"; +#ifndef __NETWARE__ +/***************************************************************** +Stop a thread after assertion failure. */ + +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__ */ From 5900f0cd5cae72f5480697ac83601cd9115fae7e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Jun 2005 12:29:35 +0300 Subject: [PATCH 22/38] innobase/include/univ.i: Added some comments. innobase/include/univ.i: Replace PRULINT with ULINTPF in a comment. Document the macros based on __builtin_expect() and __builtin_prefetch(). --- innobase/include/univ.i | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/innobase/include/univ.i b/innobase/include/univ.i index 4bd16dc4a40..132ac9e18c5 100644 --- a/innobase/include/univ.i +++ b/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,19 +243,29 @@ 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) -# define UNIV_EXPECT(expr,value) __builtin_expect(expr, value) -# define UNIV_LIKELY_NULL(expr) __builtin_expect((ulint) expr, 0) +/* 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 -#define UNIV_LIKELY(expr) UNIV_EXPECT(expr, TRUE) -#define UNIV_UNLIKELY(expr) UNIV_EXPECT(expr, FALSE) +/* 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 #include "ut0dbg.h" From 2ebdd2d90a512812f366732e32dc4d42c323e004 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Jun 2005 14:00:53 +0300 Subject: [PATCH 23/38] InnoDB: minor clean-up in os0file innobase/include/os0file.h: Remove unused function os_aio_all_slots_free() from non-debug builds. innobase/os/os0file.c: Remove unused function os_aio_all_slots_free() from non-debug builds. Add static qualifiers to module-global variables. --- innobase/include/os0file.h | 3 +++ innobase/os/os0file.c | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index f55c345537e..729ad81da9c 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -688,6 +688,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 +697,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/innobase/os/os0file.c b/innobase/os/os0file.c index 9df26150160..01cddcd19a5 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -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; @@ -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 */ From f6da55d8ceb1ca731c7d5aeba11f7b858f253b30 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Jun 2005 15:55:00 +0300 Subject: [PATCH 24/38] InnoDB: Remove compiler warning innobase/fil/fil0fil.c: Move the declaration of fil_node_t to os0file.h. Remove type casting from address-of operation (which would break strict aliasing rules) innobase/include/os0file.h: Declare fil_node_t as an opaque structure. Replace void* message1 with fil_node_t* message1. innobase/os/os0file.c: Replace void* message1 with fil_node_t* message1. --- innobase/fil/fil0fil.c | 3 +-- innobase/include/os0file.h | 10 ++++++---- innobase/os/os0file.c | 12 ++++++------ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index e8efdcfbce0..211ad1d01ed 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -98,7 +98,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 */ @@ -4037,7 +4036,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/innobase/include/os0file.h b/innobase/include/os0file.h index 729ad81da9c..e75281dd93c 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -17,6 +17,8 @@ Created 10/21/1995 Heikki Tuuri #include #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 diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 01cddcd19a5..caa1fe0aa10 100644 --- a/innobase/os/os0file.c +++ b/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 @@ -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 From 59332c86c005227b0e85423a5dcfb594a2738dcf Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 13 Jun 2005 11:39:31 +0300 Subject: [PATCH 25/38] InnoDB: Remove unreferenced debug functions from non-debug builds. innobase/buf/buf0buf.c: Remove buf_print() and buf_validate() unless #ifdef UNIV_DEBUG innobase/buf/buf0lru.c: Remove buf_LRU_print() and buf_LRU_validate() unless #ifdef UNIV_DEBUG innobase/include/buf0buf.h: Remove buf_print() and buf_validate() unless #ifdef UNIV_DEBUG innobase/include/buf0lru.h: Remove buf_LRU_print() and buf_LRU_validate() unless #ifdef UNIV_DEBUG innobase/include/rem0rec.h: rec_offs_comp(): Correct the comment about return value. --- innobase/buf/buf0buf.c | 2 ++ innobase/buf/buf0lru.c | 4 +++- innobase/include/buf0buf.h | 14 ++++++++------ innobase/include/buf0lru.h | 2 ++ innobase/include/rem0rec.h | 2 +- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index fca0b9f85f8..84d1510581c 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -1947,6 +1947,7 @@ buf_pool_invalidate(void) mutex_exit(&(buf_pool->mutex)); } +#ifdef UNIV_DEBUG /************************************************************************* Validates the buffer buf_pool data structure. */ @@ -2146,6 +2147,7 @@ buf_print(void) ut_a(buf_validate()); } +#endif /* UNIV_DEBUG */ /************************************************************************* Returns the number of latched pages in the buffer pool. */ diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c index 18c4f8c10fb..0a195b6162f 100644 --- a/innobase/buf/buf0lru.c +++ b/innobase/buf/buf0lru.c @@ -919,7 +919,8 @@ buf_LRU_block_free_hashed_page( buf_LRU_block_free_non_file_page(block); } - + +#ifdef UNIV_DEBUG /************************************************************************** Validates the LRU list. */ @@ -1050,3 +1051,4 @@ buf_LRU_print(void) mutex_exit(&(buf_pool->mutex)); } +#endif /* UNIV_DEBUG */ diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index 7b8e1b7bb09..81170226171 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -480,12 +480,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 +502,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/innobase/include/buf0lru.h b/innobase/include/buf0lru.h index 45164dd561e..fb29b44ba98 100644 --- a/innobase/include/buf0lru.h +++ b/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/innobase/include/rem0rec.h b/innobase/include/rem0rec.h index 0e9ab49f363..c068f4cb73c 100644 --- a/innobase/include/rem0rec.h +++ b/innobase/include/rem0rec.h @@ -300,7 +300,7 @@ UNIV_INLINE 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 nonzero if the extern bit is set in nth field of rec. */ From 113c6278516f56f5f4a9356b8ffb234d618e782b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 14 Jun 2005 12:21:40 +0300 Subject: [PATCH 26/38] InnoDB: Cleanup and after review fixes. innobase/btr/btr0btr.c: Code formatting: add blank line before "goto", do not indent labels innobase/btr/btr0cur.c: Code formatting: add blank line before "goto" innobase/btr/btr0pcur.c: btr_pcur_restore_position(): Replace assertion on cursor->pos_state with if condition, to provide better diagnostics. Restore ut_a() assertions on cursor->old_rec and cursor->old_n_fields. innobase/btr/btr0sea.c: btr_search_check_guess(): Declare prev_rec and next_rec closer to usage. Add blank lines before goto statements. --- innobase/btr/btr0btr.c | 6 ++++-- innobase/btr/btr0cur.c | 1 + innobase/btr/btr0pcur.c | 12 +++++------ innobase/btr/btr0sea.c | 46 +++++++++++++++++++++-------------------- 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 6ca0077523f..2d84586216a 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -1160,12 +1160,13 @@ btr_page_get_split_rec_to_right( next_rec = page_rec_get_next(insert_point); if (page_rec_is_supremum(next_rec)) { - split_at_new: +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; } @@ -1274,6 +1275,7 @@ btr_page_get_sure_split_rec( if (rec == ins_rec) { rec = NULL; + goto func_exit; } else if (rec == NULL) { next_rec = page_rec_get_next(ins_rec); @@ -1286,7 +1288,7 @@ btr_page_get_sure_split_rec( } } - func_exit: +func_exit: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 85d6194055f..98d90ecf18a 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -1381,6 +1381,7 @@ btr_cur_parse_update_in_place( ptr = row_upd_index_parse(ptr, end_ptr, heap, &update); if (!ptr || !page) { + goto func_exit; } diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c index 7cc883a6696..cb398b4afab 100644 --- a/innobase/btr/btr0pcur.c +++ b/innobase/btr/btr0pcur.c @@ -205,15 +205,15 @@ btr_pcur_restore_position( ulint old_mode; mem_heap_t* heap; - ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED - || cursor->pos_state == BTR_PCUR_IS_POSITIONED); - if (UNIV_UNLIKELY(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 (UNIV_UNLIKELY(cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE @@ -233,8 +233,8 @@ btr_pcur_restore_position( return(FALSE); } - ut_ad(cursor->old_rec); - ut_ad(cursor->old_n_fields); + ut_a(cursor->old_rec); + ut_a(cursor->old_n_fields); page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor)); diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 742a02b1de4..f705fee4275 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -545,8 +545,6 @@ btr_search_check_guess( mtr_t* mtr) /* in: mtr */ { rec_t* rec; - rec_t* prev_rec; - rec_t* next_rec; ulint n_unique; ulint match; ulint bytes; @@ -609,6 +607,7 @@ btr_search_check_guess( bytes = 0; if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)) { + rec_t* prev_rec; ut_ad(!page_rec_is_infimum(rec)); @@ -617,6 +616,7 @@ btr_search_check_guess( if (page_rec_is_infimum(prev_rec)) { success = btr_page_get_prev( buf_frame_align(prev_rec), mtr) == FIL_NULL; + goto exit_func; } @@ -631,32 +631,34 @@ btr_search_check_guess( } goto exit_func; - } - - ut_ad(!page_rec_is_supremum(rec)); + } 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 (page_rec_is_supremum(next_rec)) { - if (btr_page_get_next(buf_frame_align(next_rec), 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 (UNIV_LIKELY_NULL(heap)) { From 5fed4f3a5026b6fa1b6da28d463b9f43839041a0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 15 Jun 2005 12:50:27 +0300 Subject: [PATCH 27/38] InnoDB: Remove unreachable debug code from non-debug builds. innobase/buf/buf0buf.c: Remove buf_dbg_counter unless #ifdef UNIV_DEBUG Remove buf_debug_prints unless #ifdef UNIV_DEBUG innobase/buf/buf0flu.c: Remove buf_debug_prints unless #ifdef UNIV_DEBUG innobase/buf/buf0lru.c: Remove buf_debug_prints unless #ifdef UNIV_DEBUG innobase/buf/buf0rea.c: Remove buf_debug_prints unless #ifdef UNIV_DEBUG innobase/include/buf0buf.h: Remove buf_debug_prints unless #ifdef UNIV_DEBUG innobase/include/buf0buf.ic: Remove buf_dbg_counter unless #ifdef UNIV_DEBUG innobase/include/log0log.h: Remove log_do_write and log_debug_writes unless #ifdef UNIV_DEBUG innobase/log/log0log.c: Remove log_do_write and log_debug_writes unless #ifdef UNIV_DEBUG innobase/log/log0recv.c: Remove log_debug_writes unless #ifdef UNIV_DEBUG innobase/srv/srv0start.c: Remove log_do_write and buf_debug_prints unless #ifdef UNIV_DEBUG innobase/sync/sync0sync.c: Remove buf_debug_prints unless #ifdef UNIV_DEBUG --- innobase/buf/buf0buf.c | 11 +++++++++- innobase/buf/buf0flu.c | 6 ++++++ innobase/buf/buf0lru.c | 2 ++ innobase/buf/buf0rea.c | 8 ++++++++ innobase/include/buf0buf.h | 2 ++ innobase/include/buf0buf.ic | 3 ++- innobase/include/log0log.h | 4 ++++ innobase/log/log0log.c | 41 +++++++++++++++++++++++++++++-------- innobase/log/log0recv.c | 21 ++++++++++++++++--- innobase/srv/srv0start.c | 5 ++++- innobase/sync/sync0sync.c | 4 ++++ 11 files changed, 92 insertions(+), 15 deletions(-) diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 84d1510581c..78189617aab 100644 --- a/innobase/buf/buf0buf.c +++ b/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 @@ -1739,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; @@ -1893,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); @@ -1908,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 */ } /************************************************************************* diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index 592ed972376..ffb16790b2d 100644 --- a/innobase/buf/buf0flu.c +++ b/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/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c index 0a195b6162f..a0157da2d42 100644 --- a/innobase/buf/buf0lru.c +++ b/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); diff --git a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c index d9dc2ca93f5..813ca589907 100644 --- a/innobase/buf/buf0rea.c +++ b/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/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index 81170226171..ae8d0411c12 100644 --- a/innobase/include/buf0buf.h +++ b/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 */ diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic index 9044c3251a4..d949254d47d 100644 --- a/innobase/include/buf0buf.ic +++ b/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 diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h index d14a116072d..7f3f10438b4 100644 --- a/innobase/include/log0log.h +++ b/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/innobase/log/log0log.c b/innobase/log/log0log.c index 560f51401ac..1ff6799e5fb 100644 --- a/innobase/log/log0log.c +++ b/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(); @@ -2347,9 +2356,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 +2386,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 +2395,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 +2486,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 +2515,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 +2536,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 +2684,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 +2693,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 +2796,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/innobase/log/log0recv.c b/innobase/log/log0recv.c index fd136e96668..99379589519 100644 --- a/innobase/log/log0recv.c +++ b/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; @@ -1198,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", @@ -1205,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); @@ -2025,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 */ @@ -2113,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++; @@ -2526,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", @@ -2533,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 */ } /************************************************************ @@ -2918,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(); @@ -3258,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", @@ -3265,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/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index e136aee43e8..cf63ae7acc3 100644 --- a/innobase/srv/srv0start.c +++ b/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/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index e604912e996..f0f0e9a3a2e 100644 --- a/innobase/sync/sync0sync.c +++ b/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; } From 76a11195b8f6af78ca7c90d5fea0ed751cdb3751 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Jun 2005 15:00:25 +0300 Subject: [PATCH 28/38] InnoDB: Fix ut0dbg compilation errors on NetWare innobase/dict/dict0boot.c: Remove dummy code to work around bug in the pgcc compiler. innobase/include/ut0dbg.h: UT_DBG_PANIC: Avoid exit(), as lexyy.c re-#defines exit(). Move the code to the function ut_dbg_panic() instead. innobase/ut/ut0dbg.c: [__NETWARE__] Add function ut_dbg_panic() --- innobase/dict/dict0boot.c | 9 --------- innobase/include/ut0dbg.h | 8 ++------ innobase/ut/ut0dbg.c | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/innobase/dict/dict0boot.c b/innobase/dict/dict0boot.c index 0f6d55c9341..18a707a1b93 100644 --- a/innobase/dict/dict0boot.c +++ b/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/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h index 7e614343f5b..bc3f852626a 100644 --- a/innobase/include/ut0dbg.h +++ b/innobase/include/ut0dbg.h @@ -36,12 +36,8 @@ ut_dbg_assertion_failed( On NetWare, have a graceful exit rather than a segfault to avoid abends. */ extern ibool panic_shutdown; /* Abort the execution. */ -# define UT_DBG_PANIC \ - if (!panic_shutdown){ \ - panic_shutdown = TRUE; \ - innobase_shutdown_for_mysql(); \ - } \ - exit(1) +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__ */ diff --git a/innobase/ut/ut0dbg.c b/innobase/ut/ut0dbg.c index c4d738ffb83..e810d8dead7 100644 --- a/innobase/ut/ut0dbg.c +++ b/innobase/ut/ut0dbg.c @@ -59,7 +59,21 @@ ut_dbg_assertion_failed( ut_dbg_stop_threads = TRUE; } -#ifndef __NETWARE__ +#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. */ From ca25e99b16c85679b57baaed2807143c034c8598 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Jun 2005 16:59:49 +0300 Subject: [PATCH 29/38] InnoDB: After review fixes innobase/include/page0page.ic: page_rec_set_next(): s/ut_a()/ut_ad()/ page_rec_get_prev(): Eliminate a buf_frame_align() call innobase/lock/lock0lock.c: lock_rec_get_first(): Determine heap_no before the loop --- innobase/include/page0page.ic | 4 ++-- innobase/lock/lock0lock.c | 14 ++++---------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/innobase/include/page0page.ic b/innobase/include/page0page.ic index cef8f6a1b80..fd5281fdbec 100644 --- a/innobase/include/page0page.ic +++ b/innobase/include/page0page.ic @@ -597,7 +597,7 @@ page_rec_set_next( if (next) { ut_ad(!page_rec_is_infimum(next)); - ut_a(page == ut_align_down(next, UNIV_PAGE_SIZE)); + ut_ad(page == ut_align_down(next, UNIV_PAGE_SIZE)); offs = (ulint) (next - page); } else { offs = 0; @@ -624,7 +624,7 @@ page_rec_get_prev( ut_ad(page_rec_check(rec)); - page = buf_frame_align(rec); + page = ut_align_down(rec, UNIV_PAGE_SIZE); ut_ad(!page_rec_is_infimum(rec)); diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index f2d5d035ab1..d28cc99ac38 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -1304,16 +1304,10 @@ lock_rec_get_first( lock = lock_rec_get_first_on_page(rec); if (UNIV_LIKELY_NULL(lock)) { - if (page_rec_is_comp(rec)) { - while (lock && !lock_rec_get_nth_bit(lock, - rec_get_heap_no(rec, TRUE))) { - lock = lock_rec_get_next_on_page(lock); - } - } else { - while (lock && !lock_rec_get_nth_bit(lock, - rec_get_heap_no(rec, FALSE))) { - lock = lock_rec_get_next_on_page(lock); - } + ulint heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); + + while (lock && !lock_rec_get_nth_bit(lock, heap_no)) { + lock = lock_rec_get_next_on_page(lock); } } From 1eec421fec74a09303744f5216ea571f4fa8f4ae Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jun 2005 15:29:03 +0300 Subject: [PATCH 30/38] InnoDB: remove flag lock_print_waits from non-debug builds. innobase/include/lock0lock.h: Remove flag lock_print_waits from non-debug builds. innobase/lock/lock0lock.c: Remove flag lock_print_waits from non-debug builds. Add InnoDB lock compatibility matrix for easy reference. innobase/trx/trx0roll.c: Remove flag lock_print_waits from non-debug builds. --- innobase/include/lock0lock.h | 2 ++ innobase/lock/lock0lock.c | 26 ++++++++++++++++++++++++-- innobase/trx/trx0roll.c | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h index 3f39a0b40c7..ce308e50651 100644 --- a/innobase/include/lock0lock.h +++ b/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; diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index d28cc99ac38..cdb4f1ee73e 100644 --- a/innobase/lock/lock0lock.c +++ b/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; @@ -1842,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); } @@ -2204,10 +2224,12 @@ lock_grant( lock->trx->auto_inc_lock = lock; } +#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 @@ -3303,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 diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c index 69f7a99187f..fdfb7428129 100644 --- a/innobase/trx/trx0roll.c +++ b/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); From 61b2a6b08312555eb2800a27d982edc13d5f0e86 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jun 2005 21:44:17 +0200 Subject: [PATCH 31/38] Fix hang/crash with Boolean full-text search against an unindexed field for which the query contained more words than we allocated space. (Bug #7858) myisam/ft_boolean_search.c: Fix calculation of max number of elements -- "words" may not have spaces between them. mysql-test/t/fulltext.test: Modify test to be specific to reported bug (fix for old bug wasn't quite enough) mysql-test/r/fulltext.result: Update results --- myisam/ft_boolean_search.c | 2 +- mysql-test/r/fulltext.result | 2 +- mysql-test/t/fulltext.test | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index 62c68322595..8045ddd4657 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -398,7 +398,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, Hack: instead of init_queue, we'll use reinit queue to be able to alloc queue with alloc_root() */ - res=ftb->queue.max_elements=1+query_len/(min(ft_min_word_len,2)+1); + res=ftb->queue.max_elements=1+query_len/2; if (!(ftb->queue.root= (byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*)))) goto err; diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index dd5b0407eb3..7ac7e1ca72b 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -338,7 +338,7 @@ insert into t2 values (3, 1, 'xxbuz'); select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('xxfoo' in boolean mode); t1_id name t2_id t1_id name 1 data1 1 1 xxfoo -select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode); +select * from t2 where match name against ('*a*b*c*d*e*f*' in boolean mode); t2_id t1_id name drop table t1,t2; create table t1 (a text, fulltext key (a)); diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 4809f6f0357..d5493daf63e 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -253,9 +253,9 @@ insert into t2 values (3, 1, 'xxbuz'); select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('xxfoo' in boolean mode); # -# bug with many short (< ft_min_word_len) words in boolean search +# Bug #7858: bug with many short (< ft_min_word_len) words in boolean search # -select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode); +select * from t2 where match name against ('*a*b*c*d*e*f*' in boolean mode); drop table t1,t2; # From 3236060592757ec84b4abcd9e617009dd68555e1 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jun 2005 11:06:20 +0300 Subject: [PATCH 32/38] InnoDB: Remove warnings detected by GCC 4.0.0 innobase/fsp/fsp0fsp.c: Declare "first" in the scope where it is used, and add dummy return statement after ut_error to silence compiler warning. innobase/include/dyn0dyn.h: Add const qualifier to dyn_push_string(). innobase/include/dyn0dyn.ic: dyn_push_string(): Add const qualifier to str; remove intermediate assignment. innobase/include/mtr0log.h: mlog_write_string(), mlog_catenate_string(): Add const to str innobase/log/log0log.c: Eliminate variables new_oldest and do_preflush in order to avoid warnings about possibly uninitialized variables. (new_oldest will now be declared in the scope of usage, and do_preflush == (advance != 0).) innobase/log/log0recv.c: Remove warnings about uninitialized variables. Add UNIV_UNLIKELY() hints. innobase/mtr/mtr0log.c: mlog_write_string(), mlog_catenate_string(): Add const to str mlog_write_string(): Add UNIV_UNLIKELY hints to assertion-like tests innobase/row/row0sel.c: Remove warning about possibly uninitialized variable. (Always initialize *out_rec.) --- innobase/fsp/fsp0fsp.c | 4 +++- innobase/include/dyn0dyn.h | 2 +- innobase/include/dyn0dyn.ic | 7 ++----- innobase/include/mtr0log.h | 14 +++++++------- innobase/log/log0log.c | 21 ++++++--------------- innobase/log/log0recv.c | 12 ++++++------ innobase/mtr/mtr0log.c | 17 +++++++++-------- innobase/row/row0sel.c | 7 +++---- 8 files changed, 37 insertions(+), 47 deletions(-) diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c index ef8e70646c6..ad4228f6797 100644 --- a/innobase/fsp/fsp0fsp.c +++ b/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/innobase/include/dyn0dyn.h b/innobase/include/dyn0dyn.h index abee62300e3..1df976a5301 100644 --- a/innobase/include/dyn0dyn.h +++ b/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/innobase/include/dyn0dyn.ic b/innobase/include/dyn0dyn.ic index b6c4808398b..c1b8f2cb8ce 100644 --- a/innobase/include/dyn0dyn.ic +++ b/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/innobase/include/mtr0log.h b/innobase/include/mtr0log.h index c0636ea1e1e..6a3920aa8a1 100644 --- a/innobase/include/mtr0log.h +++ b/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/innobase/log/log0log.c b/innobase/log/log0log.c index 1ff6799e5fb..5953262ece7 100644 --- a/innobase/log/log0log.c +++ b/innobase/log/log0log.c @@ -2038,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; @@ -2047,7 +2045,6 @@ log_checkpoint_margin(void) loop: sync = FALSE; checkpoint_sync = FALSE; - do_preflush = FALSE; do_checkpoint = FALSE; mutex_enter(&(log->mutex)); @@ -2067,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); @@ -2105,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 diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index 99379589519..0417d01d89a 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -543,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); } @@ -1818,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); } diff --git a/innobase/mtr/mtr0log.c b/innobase/mtr/mtr0log.c index d80f22fd2f3..0308619073a 100644 --- a/innobase/mtr/mtr0log.c +++ b/innobase/mtr/mtr0log.c @@ -23,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; @@ -302,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; diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index a2257e0b72e..c7a548fe448 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -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,8 +741,8 @@ 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 (UNIV_LIKELY_NULL(heap)) { From 0f5b946ccf3aa2e9bc030b674a85acbfda41cee4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jun 2005 18:03:30 +0200 Subject: [PATCH 33/38] Makefile.am: Corrected dependency for "lex_hash.h", to avoid occasional make failure sql/Makefile.am: Corrected dependency for "lex_hash.h", to avoid occasional make failure --- sql/Makefile.am | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/sql/Makefile.am b/sql/Makefile.am index f812bbe72af..a76adbd0d57 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -104,8 +104,8 @@ DEFS = -DMYSQL_SERVER \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \ @DEFS@ -# Don't put lex_hash.h in BUILT_SOURCES as this will give infinite recursion -BUILT_SOURCES = sql_yacc.cc sql_yacc.h + +BUILT_SOURCES = sql_yacc.cc sql_yacc.h lex_hash.h EXTRA_DIST = udf_example.cc $(BUILT_SOURCES) AM_YFLAGS = -d @@ -123,9 +123,6 @@ link_sources: mysql_tzinfo_to_sql.cc rm -f my_time.c @LN_CP_F@ ../sql-common/my_time.c my_time.c -gen_lex_hash.o: gen_lex_hash.cc lex.h - $(CXXCOMPILE) -c $(INCLUDES) $< - mysql_tzinfo_to_sql.o: $(mysql_tzinfo_to_sql_SOURCES) $(CXXCOMPILE) -c $(INCLUDES) -DTZINFO2SQL $< @@ -140,13 +137,9 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS) @echo "If it fails, re-run configure with --with-low-memory" $(CXXCOMPILE) $(LM_CFLAGS) -c $< -lex_hash.h: lex.h gen_lex_hash.cc sql_yacc.h - $(MAKE) gen_lex_hash$(EXEEXT) +lex_hash.h: gen_lex_hash$(EXEEXT) ./gen_lex_hash$(EXEEXT) > $@ -# Hack to ensure that lex_hash.h is built early -sql_lex.o: lex_hash.h - # For testing of udf_example.so; Works on platforms with gcc # (This is not part of our build process but only provided as an example) udf_example.so: udf_example.cc From 7b24dad470ad5cd3526ad081672adc25f1e1a672 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jun 2005 18:54:45 +0200 Subject: [PATCH 34/38] Fix handling of command-line on Windows, missed as part of earlier commit. (Bug #10840) client/mysql.cc: Add cast of unsigned value stored in signed char --- client/mysql.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/mysql.cc b/client/mysql.cc index b9b9b938da0..5454c76e720 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -989,7 +989,8 @@ static int read_lines(bool execute_commands) a nil, it still needs the space in the linebuffer for it. This is, naturally, undocumented. */ - } while (linebuffer[0] <= linebuffer[1] + 1); + } while ((unsigned char)linebuffer[0] <= + (unsigned char)linebuffer[1] + 1); line= buffer.c_ptr(); #endif /* __NETWARE__ */ #else From 15b113e186939e091af4c93759dfc1ca66a37fda Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jun 2005 10:49:04 -0700 Subject: [PATCH 35/38] group_by.result: Added a test case for bug #11385. group_by.test: Added a test case for bug #11385. field.h: Fixed bug #11385. The bug was due to not defined method decimals for the class Field_datetime. sql/field.h: Fixed bug #11385. The bug was due to not defined method decimals for the class Field_datetime. mysql-test/t/group_by.test: Added atest case for bug #11385. mysql-test/r/group_by.result: Added a test case for bug #11385. --- mysql-test/r/group_by.result | 9 +++++++++ mysql-test/t/group_by.test | 15 ++++++++++++++- sql/field.h | 2 ++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index ee4b6a31f2f..e279fca2a9d 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -732,3 +732,12 @@ SELECT DISTINCT a, b FROM t1 GROUP BY 'const'; a b 1 2 DROP TABLE t1; +CREATE TABLE t1 (id INT, dt DATETIME); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +SELECT dt DIV 1 AS f, id FROM t1 GROUP BY f; +f id +20050501123000 1 +DROP TABLE t1; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index f9d113a9c50..382580cbd4e 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -543,7 +543,7 @@ SELECT hostname, COUNT(DISTINCT user_id) as no FROM t1 DROP TABLE t1; # -# Test for bug #8614: GROUP BY 'const with DISTINCT +# Test for bug #8614: GROUP BY 'const' with DISTINCT # CREATE TABLE t1 (a int, b int); @@ -552,3 +552,16 @@ SELECT a, b FROM t1 GROUP BY 'const'; SELECT DISTINCT a, b FROM t1 GROUP BY 'const'; DROP TABLE t1; + +# +# Test for bug #11385: GROUP BY for datetime converted to decimals +# + +CREATE TABLE t1 (id INT, dt DATETIME); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +SELECT dt DIV 1 AS f, id FROM t1 GROUP BY f; + +DROP TABLE t1; diff --git a/sql/field.h b/sql/field.h index 1d7669d540d..ba963418c7a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -25,6 +25,7 @@ #endif #define NOT_FIXED_DEC 31 +#define DATETIME_DEC 6 class Send_field; class Protocol; @@ -861,6 +862,7 @@ public: enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; } #endif enum Item_result cmp_type () const { return INT_RESULT; } + uint decimals() const { return DATETIME_DEC; } int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); int store(longlong nr); From d73327e1996d172640d063b6ac22a0d21be26562 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jun 2005 21:37:39 +0200 Subject: [PATCH 36/38] mtr_cases.pl: Bug#11466: Script can now get test case name from test case file path on command line mysql-test-run.pl: Bug#11466: Added --skip-ndbcluster/--skip-ndb option mtr_cases.pl: Don't set --default-time-zone if opt file sets it Restart the server if time zone is given in opt file mysql-test-run.pl: Don't remove symlink to "var" directory in cleanup Removed duplicate/unessesary options to mysqld mysql-test/mysql-test-run.pl: Bug#11466: Added --skip-ndbcluster/--skip-ndb option mysql-test/lib/mtr_cases.pl: Bug#11466: Script can now get test case name from test case file path on command line --- mysql-test/lib/mtr_cases.pl | 75 +++++++++++++++++++++++------------- mysql-test/mysql-test-run.pl | 29 +++++++------- 2 files changed, 63 insertions(+), 41 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index c07f10c3bf7..72cbe72bc0a 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -4,6 +4,7 @@ # and is part of the translation of the Bourne shell script with the # same name. +use File::Basename; use strict; sub collect_test_cases ($); @@ -39,6 +40,7 @@ sub collect_test_cases ($) { if ( @::opt_cases ) { foreach my $tname ( @::opt_cases ) { # Run in specified order, no sort + $tname= basename($tname, ".test"); my $elem= "$tname.test"; if ( ! -f "$testdir/$elem") { @@ -161,52 +163,73 @@ sub collect_one_test_case($$$$$) { my $slave_sh= "$testdir/$tname-slave.sh"; my $disabled= "$testdir/$tname.disabled"; - $tinfo->{'master_opt'}= ["--default-time-zone=+3:00"]; - $tinfo->{'slave_opt'}= ["--default-time-zone=+3:00"]; + $tinfo->{'master_opt'}= $::glob_win32 ? ["--default-time-zone=+3:00"] : []; + $tinfo->{'slave_opt'}= $::glob_win32 ? ["--default-time-zone=+3:00"] : []; $tinfo->{'slave_mi'}= []; if ( -f $master_opt_file ) { $tinfo->{'master_restart'}= 1; # We think so for now - # This is a dirty hack from old mysql-test-run, we use the opt file - # to flag other things as well, it is not a opt list at all - $tinfo->{'master_opt'}= mtr_get_opts_from_file($master_opt_file); - foreach my $opt (@{$tinfo->{'master_opt'}}) + MASTER_OPT: { - my $value; + my $master_opt= mtr_get_opts_from_file($master_opt_file); - $value= mtr_match_prefix($opt, "--timezone="); - - if ( defined $value ) + foreach my $opt ( @$master_opt ) { - $tinfo->{'timezone'}= $value; - $tinfo->{'master_opt'}= []; - $tinfo->{'master_restart'}= 0; - last; - } + my $value; - $value= mtr_match_prefix($opt, "--result-file="); + # This is a dirty hack from old mysql-test-run, we use the opt + # file to flag other things as well, it is not a opt list at + # all - if ( defined $value ) - { - $tinfo->{'result_file'}= "r/$value.result"; - if ( $::opt_result_ext and $::opt_record or - -f "$tinfo->{'result_file'}$::opt_result_ext") + $value= mtr_match_prefix($opt, "--timezone="); + if ( defined $value ) { - $tinfo->{'result_file'}.= $::opt_result_ext; + $tinfo->{'timezone'}= $value; + $tinfo->{'skip'}= 1 if $::glob_win32; # FIXME server unsets TZ + last MASTER_OPT; } - $tinfo->{'master_opt'}= []; - $tinfo->{'master_restart'}= 0; - last; + + $value= mtr_match_prefix($opt, "--result-file="); + if ( defined $value ) + { + $tinfo->{'result_file'}= "r/$value.result"; + if ( $::opt_result_ext and $::opt_record or + -f "$tinfo->{'result_file'}$::opt_result_ext") + { + $tinfo->{'result_file'}.= $::opt_result_ext; + } + $tinfo->{'master_restart'}= 0; + last MASTER_OPT; + } + + # If we set default time zone, remove the one we have + $value= mtr_match_prefix($opt, "--default-time-zone="); + if ( defined $value ) + { + $tinfo->{'master_opt'}= []; + } + } + + # Ok, this was a real option list, add it + push(@{$tinfo->{'master_opt'}}, @$master_opt); } } if ( -f $slave_opt_file ) { - $tinfo->{'slave_opt'}= mtr_get_opts_from_file($slave_opt_file); $tinfo->{'slave_restart'}= 1; + my $slave_opt= mtr_get_opts_from_file($slave_opt_file); + + foreach my $opt ( @$slave_opt ) + { + # If we set default time zone, remove the one we have + my $value= mtr_match_prefix($opt, "--default-time-zone="); + $tinfo->{'slave_opt'}= [] if defined $value; + } + push(@{$tinfo->{'slave_opt'}}, @$slave_opt); } if ( -f $slave_mi_file ) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 6151dd68160..060d8f7207a 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -264,6 +264,7 @@ our $opt_warnings; our $opt_udiff; +our $opt_skip_ndbcluster; our $opt_with_ndbcluster; our $opt_with_openssl; @@ -463,6 +464,7 @@ sub command_line_setup () { # Control what test suites or cases to run 'force' => \$opt_force, 'with-ndbcluster' => \$opt_with_ndbcluster, + 'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster, 'do-test=s' => \$opt_do_test, 'suite=s' => \$opt_suite, 'skip-rpl' => \$opt_skip_rpl, @@ -662,6 +664,11 @@ sub command_line_setup () { $opt_ndbconnectstring= "host=localhost:$opt_ndbcluster_port"; } + if ( $opt_skip_ndbcluster ) + { + $opt_with_ndbcluster= 0; + } + # FIXME #if ( $opt_valgrind or $opt_valgrind_all ) @@ -1020,11 +1027,6 @@ sub kill_and_cleanup () { mtr_report("Removing Stale Files"); - if ( -l $opt_vardir and ! unlink($opt_vardir) ) - { - mtr_error("Can't remove soft link \"$opt_vardir\""); - } - rmtree("$opt_vardir/log"); rmtree("$opt_vardir/ndbcluster-$opt_ndbcluster_port"); rmtree("$opt_vardir/run"); @@ -1722,6 +1724,11 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--local-infile", $prefix); mtr_add_arg($args, "%s--datadir=%s", $prefix, $master->[$idx]->{'path_myddir'}); + + if ( $opt_skip_ndbcluster ) + { + mtr_add_arg($args, "%s--skip-ndbcluster", $prefix); + } } if ( $type eq 'slave' ) @@ -1862,19 +1869,11 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--rpl-recovery-rank=1", $prefix); mtr_add_arg($args, "%s--init-rpl-role=master", $prefix); } - else + elsif ( $type eq 'master' ) { mtr_add_arg($args, "%s--exit-info=256", $prefix); mtr_add_arg($args, "%s--open-files-limit=1024", $prefix); - - if ( $type eq 'master' ) - { - mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'}); - } - if ( $type eq 'slave' ) - { - mtr_add_arg($args, "%s--log=%s", $prefix, $slave->[0]->{'path_mylog'}); - } + mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'}); } return $args; From e74d5313738d853dd7108aeab12db96bfc26b489 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 02:21:52 +0200 Subject: [PATCH 37/38] mysql-test-run.pl: More compact and safe handling of path names. Support for running in Windows source tree. Use libtool wrapper, instead of messing with library path names, and objects in .libs dir. mtr_misc.pl: Utility function that search aand check path names mtr_report.pl: Patch by Carsten, set correct reject/result/eval if not main suite mysql-test/lib/mtr_report.pl: Patch by Carsten, set correct reject/result/eval if not main suite mysql-test/lib/mtr_misc.pl: Utility function that search aand check path names mysql-test/mysql-test-run.pl: More compact and safe handling of path names. Support for running in Windows source tree. Use libtool wrapper, instead of messing with library path names, and objects in .libs dir. --- mysql-test/lib/mtr_misc.pl | 52 ++++++++++ mysql-test/lib/mtr_report.pl | 7 ++ mysql-test/mysql-test-run.pl | 187 ++++++++++++----------------------- 3 files changed, 123 insertions(+), 123 deletions(-) diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl index efa1b3bec21..aba6f78c9de 100644 --- a/mysql-test/lib/mtr_misc.pl +++ b/mysql-test/lib/mtr_misc.pl @@ -9,6 +9,9 @@ use strict; sub mtr_full_hostname (); sub mtr_init_args ($); sub mtr_add_arg ($$); +sub mtr_path_exists(@); +sub mtr_script_exists(@); +sub mtr_exe_exists(@); ############################################################################## # @@ -47,4 +50,53 @@ sub mtr_add_arg ($$) { push(@$args, sprintf($format, @fargs)); } +############################################################################## + +sub mtr_path_exists (@) { + foreach my $path ( @_ ) + { + return $path if -e $path; + } + if ( @_ == 1 ) + { + mtr_error("Could not find $_[0]"); + } + else + { + mtr_error("Could not find any of " . join(" ", @_)); + } +} + +sub mtr_script_exists (@) { + foreach my $path ( @_ ) + { + return $path if -x $path; + } + if ( @_ == 1 ) + { + mtr_error("Could not find $_[0]"); + } + else + { + mtr_error("Could not find any of " . join(" ", @_)); + } +} + +sub mtr_exe_exists (@) { + foreach my $path ( @_ ) + { + $path.= ".exe" if $::opt_win32; + return $path if -x $path; + } + if ( @_ == 1 ) + { + mtr_error("Could not find $_[0]"); + } + else + { + mtr_error("Could not find any of " . join(" ", @_)); + } +} + + 1; diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index a258d139bb1..0af34d11a3f 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -38,6 +38,13 @@ sub mtr_show_failed_diff ($) { my $result_file= "r/$tname.result"; my $eval_file= "r/$tname.eval"; + if ( $::opt_suite ne "main" ) + { + $reject_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$reject_file"; + $result_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$result_file"; + $eval_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$eval_file"; + } + if ( -f $eval_file ) { $result_file= $eval_file; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 060d8f7207a..0ecc7bc6c52 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -770,146 +770,83 @@ sub executable_setup () { if ( $opt_source_dist ) { + if ( $glob_win32 ) + { + $path_client_bindir= mtr_path_exists("$glob_basedir/client_release"); + $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-nt"); + $path_language= mtr_path_exists("$glob_basedir/share/english/"); + $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets"); + } + else + { + $path_client_bindir= mtr_path_exists("$glob_basedir/client"); + $exe_mysqld= mtr_exe_exists ("$glob_basedir/sql/mysqld"); + $path_language= mtr_path_exists("$glob_basedir/sql/share/english/"); + $path_charsetsdir= mtr_path_exists("$glob_basedir/sql/share/charsets"); + } + if ( $glob_use_embedded_server ) { - if ( -f "$glob_basedir/libmysqld/examples/mysqltest" ) - { - $exe_mysqltest= "$glob_basedir/libmysqld/examples/mysqltest"; - } - else - { - mtr_error("Can't find embedded server 'mysqltest'"); - } + my $path_examples= "$glob_basedir/libmysqld/examples"; + $exe_mysqltest= mtr_exe_exists("$path_examples/mysqltest"); $exe_mysql_client_test= - "$glob_basedir/libmysqld/examples/mysql_client_test_embedded"; + mtr_exe_exists("$path_examples/mysql_client_test_embedded"); } else { - if ( -f "$glob_basedir/client/.libs/lt-mysqltest" ) - { - $exe_mysqltest= "$glob_basedir/client/.libs/lt-mysqltest"; - } - elsif ( -f "$glob_basedir/client/.libs/mysqltest" ) - { - $exe_mysqltest= "$glob_basedir/client/.libs/mysqltest"; - } - else - { - $exe_mysqltest= "$glob_basedir/client/mysqltest"; - } + $exe_mysqltest= mtr_exe_exists("$glob_basedir/client/mysqltest"); $exe_mysql_client_test= - "$glob_basedir/tests/mysql_client_test"; + mtr_exe_exists("$glob_basedir/tests/mysql_client_test"); } - if ( -f "$glob_basedir/client/.libs/mysqldump" ) - { - $exe_mysqldump= "$glob_basedir/client/.libs/mysqldump"; - } - else - { - $exe_mysqldump= "$glob_basedir/client/mysqldump"; - } - if ( -f "$glob_basedir/client/.libs/mysqlshow" ) - { - $exe_mysqlshow= "$glob_basedir/client/.libs/mysqlshow"; - } - else - { - $exe_mysqlshow= "$glob_basedir/client/mysqlshow"; - } - if ( -f "$glob_basedir/client/.libs/mysqlbinlog" ) - { - $exe_mysqlbinlog= "$glob_basedir/client/.libs/mysqlbinlog"; - } - else - { - $exe_mysqlbinlog= "$glob_basedir/client/mysqlbinlog"; - } - - $path_client_bindir= "$glob_basedir/client"; - $exe_mysqld= "$glob_basedir/sql/mysqld"; - $exe_mysqladmin= "$path_client_bindir/mysqladmin"; - $exe_mysql= "$path_client_bindir/mysql"; - $exe_mysql_fix_system_tables= "$glob_basedir/scripts/mysql_fix_privilege_tables"; - $path_language= "$glob_basedir/sql/share/english/"; - $path_charsetsdir= "$glob_basedir/sql/share/charsets"; - - $path_ndb_tools_dir= "$glob_basedir/ndb/tools"; - $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm"; + $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump"); + $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow"); + $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog"); + $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin"); + $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql"); + $exe_mysql_fix_system_tables= + mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables"); + $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools"); + $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm"; } else { - my $path_tests_bindir= "$glob_basedir/tests"; + $path_client_bindir= mtr_path_exists("$glob_basedir/bin"); + $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest"); + $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump"); + $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow"); + $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog"); + $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin"); + $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql"); + $exe_mysql_fix_system_tables= + mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables"); - $path_client_bindir= "$glob_basedir/bin"; - $exe_mysqltest= "$path_client_bindir/mysqltest"; - $exe_mysqldump= "$path_client_bindir/mysqldump"; - $exe_mysqlshow= "$path_client_bindir/mysqlshow"; - $exe_mysqlbinlog= "$path_client_bindir/mysqlbinlog"; - $exe_mysqladmin= "$path_client_bindir/mysqladmin"; - $exe_mysql= "$path_client_bindir/mysql"; - $exe_mysql_fix_system_tables= "$path_client_bindir/mysql_fix_privilege_tables"; - - if ( -d "$glob_basedir/share/mysql/english" ) - { - $path_language ="$glob_basedir/share/mysql/english/"; - $path_charsetsdir ="$glob_basedir/share/mysql/charsets"; - } - else - { - $path_language ="$glob_basedir/share/english/"; - $path_charsetsdir ="$glob_basedir/share/charsets"; - } - - if ( -x "$glob_basedir/libexec/mysqld" ) - { - $exe_mysqld= "$glob_basedir/libexec/mysqld"; - } - else - { - $exe_mysqld= "$glob_basedir/bin/mysqld"; - } + $path_language= mtr_path_exists("$glob_basedir/share/mysql/english/", + "$glob_basedir/share/english/"); + $path_charsetsdir= mtr_path_exists("$glob_basedir/share/mysql/charsets", + "$glob_basedir/share/charsets"); + $exe_mysqld= mtr_exe_exists ("$glob_basedir/libexec/mysqld", + "$glob_basedir/bin/mysqld"); if ( $glob_use_embedded_server ) { - if ( -f "$path_client_bindir/mysqltest_embedded" ) - { - # FIXME valgrind? - $exe_mysqltest="$path_client_bindir/mysqltest_embedded"; - } - else - { - mtr_error("Cannot find embedded server 'mysqltest_embedded'"); - } - if ( -d "$path_tests_bindir/mysql_client_test_embedded" ) - { - $exe_mysql_client_test= - "$path_tests_bindir/mysql_client_test_embedded"; - } - else - { - $exe_mysql_client_test= - "$path_client_bindir/mysql_client_test_embedded"; - } + $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest_embedded"); + $exe_mysql_client_test= + mtr_exe_exists("$glob_basedir/tests/mysql_client_test_embedded", + "$path_client_bindir/mysql_client_test_embedded"); } else { - $exe_mysqltest="$path_client_bindir/mysqltest"; - $exe_mysql_client_test="$path_client_bindir/mysql_client_test"; + $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest"); + $exe_mysql_client_test= + mtr_exe_exists("$path_client_bindir/mysql_client_test"); } $path_ndb_tools_dir= "$glob_basedir/bin"; $exe_ndb_mgm= "$glob_basedir/bin/ndb_mgm"; } - if ( ! $exe_master_mysqld ) - { - $exe_master_mysqld= $exe_mysqld; - } - - if ( ! $exe_slave_mysqld ) - { - $exe_slave_mysqld= $exe_mysqld; - } + $exe_master_mysqld= $exe_master_mysqld || $exe_mysqld; + $exe_slave_mysqld= $exe_slave_mysqld || $exe_mysqld; $path_ndb_backup_dir= "$opt_vardir/ndbcluster-$opt_ndbcluster_port"; @@ -928,15 +865,19 @@ sub executable_setup () { sub environment_setup () { # -------------------------------------------------------------------------- - # Set LD_LIBRARY_PATH if we are using shared libraries + # We might not use a standard installation directory, like /usr/lib. + # Set LD_LIBRARY_PATH to make sure we find our installed libraries. # -------------------------------------------------------------------------- - $ENV{'LD_LIBRARY_PATH'}= - "$glob_basedir/lib:$glob_basedir/libmysql/.libs" . - ($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : ""); - $ENV{'DYLD_LIBRARY_PATH'}= - "$glob_basedir/lib:$glob_basedir/libmysql/.libs" . - ($ENV{'DYLD_LIBRARY_PATH'} ? ":$ENV{'DYLD_LIBRARY_PATH'}" : ""); + unless ( $opt_source_dist ) + { + $ENV{'LD_LIBRARY_PATH'}= + "$glob_basedir/lib" . + ($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : ""); + $ENV{'DYLD_LIBRARY_PATH'}= + "$glob_basedir/lib" . + ($ENV{'DYLD_LIBRARY_PATH'} ? ":$ENV{'DYLD_LIBRARY_PATH'}" : ""); + } # -------------------------------------------------------------------------- # Also command lines in .opt files may contain env vars From bf6a86afcafc559aed642d10da692c94584d258b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 08:16:36 +0300 Subject: [PATCH 38/38] InnoDB: adjust test result mysql-test/r/innodb.result: Current default is innodb_thread_concurrency=20 --- mysql-test/r/innodb.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 24ba58e0b68..b07a6b03c8a 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1779,7 +1779,7 @@ Variable_name Value innodb_sync_spin_loops 20 show variables like "innodb_thread_concurrency"; Variable_name Value -innodb_thread_concurrency 8 +innodb_thread_concurrency 20 set global innodb_thread_concurrency=1000; show variables like "innodb_thread_concurrency"; Variable_name Value