From 8e8f02e521e4c21a7cae188fc5075b59f0f1e8b8 Mon Sep 17 00:00:00 2001 From: marko <> Date: Tue, 30 Sep 2008 18:06:38 +0000 Subject: [PATCH] branches/innodb+: row_search_index_entry(): Clean up the call interface and add assertions to callers. Remove the added ibool* parameter and return enum row_search_result instead of ibool, to reflect the four different outcomes: record found, not found, buffered, and status unknown (record not in the buffer pool). rb://6 --- include/row0row.h | 22 +++++-- row/row0purge.c | 150 ++++++++++++++++++++++++++-------------------- row/row0row.c | 32 ++++------ row/row0uins.c | 49 ++++++++------- row/row0umod.c | 83 ++++++++++++++++--------- row/row0upd.c | 43 +++++++------ 6 files changed, 217 insertions(+), 162 deletions(-) diff --git a/include/row0row.h b/include/row0row.h index 9d2f08dde4e..310c1aaaffe 100644 --- a/include/row0row.h +++ b/include/row0row.h @@ -261,16 +261,28 @@ row_get_clust_rec( dict_index_t* index, /* in: secondary index */ dict_index_t** clust_index,/* out: clustered index */ mtr_t* mtr); /* in: mtr */ + +/* Result of row_search_index_entry */ +enum row_search_result { + ROW_FOUND = 0, /* the record was found */ + ROW_NOT_FOUND, /* record not found */ + ROW_BUFFERED, /* one of BTR_INSERT, BTR_DELETE, or + BTR_DELETE_MARK was specified, the + secondary index leaf page was not in + the buffer pool, and the operation was + enqueued in the insert/delete buffer */ + ROW_NOT_IN_POOL /* BTR_WATCH_LEAF was specified and the + record was not in the buffer pool */ +}; + /******************************************************************* Searches an index record. */ UNIV_INTERN -ibool +enum row_search_result row_search_index_entry( /*===================*/ - /* out: TRUE if found */ - ibool* was_buffered, - /* out: TRUE if the operation was buffered - in the insert/delete buffer. Can be NULL. */ + /* out: whether the record was found + or buffered */ dict_index_t* index, /* in: index */ const dtuple_t* entry, /* in: index entry */ ulint mode, /* in: BTR_MODIFY_LEAF, ... */ diff --git a/row/row0purge.c b/row/row0purge.c index 468855b994e..703ea904ffa 100644 --- a/row/row0purge.c +++ b/row/row0purge.c @@ -211,30 +211,41 @@ row_purge_remove_sec_if_poss_low_nonbuffered( ulint mode) /* in: latch mode BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { - btr_pcur_t pcur; - btr_cur_t* btr_cur; - ibool success; - ibool old_has = FALSE; /* remove warning */ - ibool found; - ulint err; - mtr_t mtr; - mtr_t* mtr_vers; + btr_pcur_t pcur; + btr_cur_t* btr_cur; + ibool success; + ibool old_has = FALSE; + ulint err; + mtr_t mtr; + mtr_t* mtr_vers; + enum row_search_result search_result; log_free_check(); mtr_start(&mtr); - found = row_search_index_entry(NULL, index, entry, mode, &pcur, &mtr); + ut_ad(mode == BTR_MODIFY_TREE || mode == BTR_MODIFY_LEAF); - if (!found) { + search_result = row_search_index_entry(index, entry, mode, + &pcur, &mtr); + + switch (search_result) { + case ROW_NOT_FOUND: /* Not found */ /* fputs("PURGE:........sec entry not found\n", stderr); */ - /* dtuple_print(entry); */ - - btr_pcur_close(&pcur); - mtr_commit(&mtr); - - return(TRUE); + /* dtuple_print(stderr, entry); */ + + success = TRUE; + goto func_exit; + case ROW_FOUND: + break; + case ROW_BUFFERED: + case ROW_NOT_IN_POOL: + /* These are invalid outcomes, because the mode passed + to row_search_index_entry() did not include any of the + flags BTR_INSERT, BTR_DELETE, BTR_DELETE_MARK, or + BTR_WATCH_LEAF. */ + ut_error; } btr_cur = btr_pcur_get_btr_cur(&pcur); @@ -259,7 +270,7 @@ row_purge_remove_sec_if_poss_low_nonbuffered( mem_free(mtr_vers); - if (!success || !old_has) { + if (!old_has) { /* Remove the index record */ if (mode == BTR_MODIFY_LEAF) { @@ -273,6 +284,7 @@ row_purge_remove_sec_if_poss_low_nonbuffered( } } +func_exit: btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -292,65 +304,64 @@ row_purge_remove_sec_if_poss_low( ulint mode) /* in: latch mode BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { - mtr_t mtr; - btr_pcur_t pcur; - btr_cur_t* btr_cur; - ibool found; - ibool success; - ibool was_buffered; - ibool old_has = FALSE; - ibool leaf_in_buf_pool; - - ut_a((mode == BTR_MODIFY_TREE) || (mode == BTR_MODIFY_LEAF)); + mtr_t mtr; + btr_pcur_t pcur; +#ifdef UNIV_DEBUG + ibool leaf_in_buf_pool; +#endif /* UNIV_DEBUG */ + ibool old_has = FALSE; + enum row_search_result search_result; if (mode == BTR_MODIFY_TREE) { /* Can't use the insert/delete buffer if we potentially need to split pages. */ - - return(row_purge_remove_sec_if_poss_low_nonbuffered( - node, index, entry, mode)); + goto unbuffered; } + ut_ad(mode == BTR_MODIFY_LEAF); + log_free_check(); mtr_start(&mtr); - found = row_search_index_entry( - NULL, index, entry, - BTR_SEARCH_LEAF | BTR_WATCH_LEAF, &pcur, &mtr); + search_result = row_search_index_entry( + index, entry, BTR_SEARCH_LEAF | BTR_WATCH_LEAF, &pcur, &mtr); - btr_cur = btr_pcur_get_btr_cur(&pcur); - leaf_in_buf_pool = btr_cur->leaf_in_buf_pool; - - ut_a(!found || leaf_in_buf_pool); + ut_d(leaf_in_buf_pool = btr_pcur_get_btr_cur(&pcur)->leaf_in_buf_pool); btr_pcur_close(&pcur); mtr_commit(&mtr); - if (leaf_in_buf_pool) { - - if (found) { - /* Index entry exists and is in the buffer pool, no - need to use the insert/delete buffer. */ - - return(row_purge_remove_sec_if_poss_low_nonbuffered( - node, index, entry, BTR_MODIFY_LEAF)); - } else { - /* Index entry does not exist, nothing to do. */ + switch (search_result) { + case ROW_NOT_FOUND: + /* Index entry does not exist, nothing to do. */ + ut_ad(leaf_in_buf_pool); + return(TRUE); - return(TRUE); - } + case ROW_FOUND: + /* The index entry exists and is in the buffer pool; + no need to use the insert/delete buffer. */ + ut_ad(leaf_in_buf_pool); + goto unbuffered; + + case ROW_BUFFERED: + /* We did not pass any BTR_INSERT, BTR_DELETE, or + BTR_DELETE_MARK flag. Therefore, the operation must + not have been buffered yet. */ + ut_error; + + case ROW_NOT_IN_POOL: + ut_ad(!leaf_in_buf_pool); + break; } - /* We should remove the index record if no later version of the row, - which cannot be purged yet, requires its existence. If some - requires, we should do nothing. */ + /* We should remove the index record if no later version of + the row, which cannot be purged yet, requires its existence. + If some requires, we should do nothing. */ mtr_start(&mtr); - success = row_purge_reposition_pcur(BTR_SEARCH_LEAF, node, &mtr); - - if (success) { + if (row_purge_reposition_pcur(BTR_SEARCH_LEAF, node, &mtr)) { old_has = row_vers_old_has_index_entry( TRUE, btr_pcur_get_rec(&node->pcur), &mtr, index, entry); @@ -358,7 +369,7 @@ row_purge_remove_sec_if_poss_low( btr_pcur_commit_specify_mtr(&node->pcur, &mtr); - if (success && old_has) { + if (old_has) { /* Can't remove the index record yet. */ buf_pool_watch_clear(); @@ -370,26 +381,35 @@ row_purge_remove_sec_if_poss_low( /* Set the query thread, so that ibuf_insert_low() will be able to invoke thd_get_trx(). */ - btr_cur->thr = que_node_get_parent(node); + btr_pcur_get_btr_cur(&pcur)->thr = que_node_get_parent(node); - row_search_index_entry(&was_buffered, index, entry, - BTR_MODIFY_LEAF | BTR_DELETE, &pcur, - &mtr); + search_result = row_search_index_entry( + index, entry, BTR_MODIFY_LEAF | BTR_DELETE, &pcur, &mtr); btr_pcur_close(&pcur); mtr_commit(&mtr); buf_pool_watch_clear(); - if (!was_buffered) { - /* Page read into buffer pool or delete-buffering failed. */ + switch (search_result) { + case ROW_NOT_FOUND: + case ROW_FOUND: + break; - return(row_purge_remove_sec_if_poss_low_nonbuffered( - node, index, entry, BTR_MODIFY_LEAF)); + case ROW_BUFFERED: + return(TRUE); + + case ROW_NOT_IN_POOL: + /* BTR_WATCH_LEAF was not specified, + so this should not occur! */ + ut_error; } - return(TRUE); + /* Page read into buffer pool or delete-buffering failed. */ +unbuffered: + return(row_purge_remove_sec_if_poss_low_nonbuffered(node, index, + entry, mode)); } /*************************************************************** diff --git a/row/row0row.c b/row/row0row.c index b0b010f45a2..cb72262ca80 100644 --- a/row/row0row.c +++ b/row/row0row.c @@ -781,13 +781,11 @@ row_get_clust_rec( /******************************************************************* Searches an index record. */ UNIV_INTERN -ibool +enum row_search_result row_search_index_entry( /*===================*/ - /* out: TRUE if found */ - ibool* was_buffered, - /* out: TRUE if the operation was buffered - in the insert/delete buffer. Can be NULL. */ + /* out: whether the record was found + or buffered */ dict_index_t* index, /* in: index */ const dtuple_t* entry, /* in: index entry */ ulint mode, /* in: BTR_MODIFY_LEAF, ... */ @@ -798,30 +796,23 @@ row_search_index_entry( ulint n_fields; ulint low_match; rec_t* rec; - ibool ret; ut_ad(dtuple_check_typed(entry)); btr_pcur_open(index, entry, PAGE_CUR_LE, mode, pcur, mtr); - ret = btr_pcur_was_buffered(pcur); + if (btr_pcur_was_buffered(pcur)) { - if (was_buffered) { - *was_buffered = ret; + return(ROW_BUFFERED); } - if (ret) { - /* Operation was buffered in the insert/delete buffer; - pretend that we found the record. */ - - return(TRUE); - } else if ((mode & BTR_WATCH_LEAF) - && !btr_pcur_get_btr_cur(pcur)->leaf_in_buf_pool) { + if ((mode & BTR_WATCH_LEAF) + && !btr_pcur_get_btr_cur(pcur)->leaf_in_buf_pool) { /* We did not read in the leaf page, thus we can't have found anything. */ - return(FALSE); + return(ROW_NOT_IN_POOL); } low_match = btr_pcur_get_low_match(pcur); @@ -832,14 +823,13 @@ row_search_index_entry( if (page_rec_is_infimum(rec)) { - return(FALSE); + return(ROW_NOT_FOUND); } else if (low_match != n_fields) { - /* Not found */ - return(FALSE); + return(ROW_NOT_FOUND); } - return(TRUE); + return(ROW_FOUND); } #ifndef UNIV_HOTBACKUP diff --git a/row/row0uins.c b/row/row0uins.c index 6dfb81a9ee8..a642c58e277 100644 --- a/row/row0uins.c +++ b/row/row0uins.c @@ -129,37 +129,40 @@ row_undo_ins_remove_sec_low( dict_index_t* index, /* in: index */ dtuple_t* entry) /* in: index entry to remove */ { - btr_pcur_t pcur; - btr_cur_t* btr_cur; - ibool found; - ibool success; - ulint err; - mtr_t mtr; + btr_pcur_t pcur; + btr_cur_t* btr_cur; + ulint err; + mtr_t mtr; + enum row_search_result search_result; log_free_check(); mtr_start(&mtr); - found = row_search_index_entry(NULL, index, entry, mode, &pcur, &mtr); - btr_cur = btr_pcur_get_btr_cur(&pcur); - if (!found) { - /* Not found */ - - btr_pcur_close(&pcur); - mtr_commit(&mtr); - - return(DB_SUCCESS); + ut_ad(mode == BTR_MODIFY_TREE || mode == BTR_MODIFY_LEAF); + + search_result = row_search_index_entry(index, entry, mode, + &pcur, &mtr); + + switch (search_result) { + case ROW_NOT_FOUND: + err = DB_SUCCESS; + goto func_exit; + case ROW_FOUND: + break; + case ROW_BUFFERED: + case ROW_NOT_IN_POOL: + /* These are invalid outcomes, because the mode passed + to row_search_index_entry() did not include any of the + flags BTR_INSERT, BTR_DELETE, BTR_DELETE_MARK, or + BTR_WATCH_LEAF. */ + ut_error; } if (mode == BTR_MODIFY_LEAF) { - success = btr_cur_optimistic_delete(btr_cur, &mtr); - - if (success) { - err = DB_SUCCESS; - } else { - err = DB_FAIL; - } + err = btr_cur_optimistic_delete(btr_cur, &mtr) + ? DB_SUCCESS : DB_FAIL; } else { ut_ad(mode == BTR_MODIFY_TREE); @@ -172,7 +175,7 @@ row_undo_ins_remove_sec_low( btr_cur_pessimistic_delete(&err, FALSE, btr_cur, RB_NORMAL, &mtr); } - +func_exit: btr_pcur_close(&pcur); mtr_commit(&mtr); diff --git a/row/row0umod.c b/row/row0umod.c index 85986699e51..65e72bc01a0 100644 --- a/row/row0umod.c +++ b/row/row0umod.c @@ -295,29 +295,38 @@ row_undo_mod_del_mark_or_remove_sec_low( ulint mode) /* in: latch mode BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { - ibool found; - btr_pcur_t pcur; - btr_cur_t* btr_cur; - ibool success; - ibool old_has; - ulint err; - mtr_t mtr; - mtr_t mtr_vers; + btr_pcur_t pcur; + btr_cur_t* btr_cur; + ibool success; + ibool old_has; + ulint err; + mtr_t mtr; + mtr_t mtr_vers; + enum row_search_result search_result; log_free_check(); mtr_start(&mtr); - found = row_search_index_entry(NULL, index, entry, mode, &pcur, &mtr); - btr_cur = btr_pcur_get_btr_cur(&pcur); - if (!found) { - /* Not found */ - - btr_pcur_close(&pcur); - mtr_commit(&mtr); - - return(DB_SUCCESS); + ut_ad(mode == BTR_MODIFY_TREE || mode == BTR_MODIFY_LEAF); + + search_result = row_search_index_entry(index, entry, mode, + &pcur, &mtr); + + switch (search_result) { + case ROW_NOT_FOUND: + err = DB_SUCCESS; + goto func_exit; + case ROW_FOUND: + break; + case ROW_BUFFERED: + case ROW_NOT_IN_POOL: + /* These are invalid outcomes, because the mode passed + to row_search_index_entry() did not include any of the + flags BTR_INSERT, BTR_DELETE, BTR_DELETE_MARK, or + BTR_WATCH_LEAF. */ + ut_error; } /* We should remove the index record if no prior version of the row, @@ -366,6 +375,8 @@ row_undo_mod_del_mark_or_remove_sec_low( } btr_pcur_commit_specify_mtr(&(node->pcur), &mtr_vers); + +func_exit: btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -421,13 +432,15 @@ row_undo_mod_del_unmark_sec_and_undo_update( dict_index_t* index, /* in: index */ dtuple_t* entry) /* in: index entry */ { - mem_heap_t* heap; - btr_pcur_t pcur; - upd_t* update; - ulint err = DB_SUCCESS; - big_rec_t* dummy_big_rec; - mtr_t mtr; - trx_t* trx = thr_get_trx(thr); + mem_heap_t* heap; + btr_pcur_t pcur; + btr_cur_t* btr_cur; + upd_t* update; + ulint err = DB_SUCCESS; + big_rec_t* dummy_big_rec; + mtr_t mtr; + trx_t* trx = thr_get_trx(thr); + enum row_search_result search_result; /* Ignore indexes that are being created. */ if (UNIV_UNLIKELY(*index->name == TEMP_INDEX_PREFIX)) { @@ -438,8 +451,20 @@ row_undo_mod_del_unmark_sec_and_undo_update( log_free_check(); mtr_start(&mtr); - if (UNIV_UNLIKELY(!row_search_index_entry(NULL, index, entry, - mode, &pcur, &mtr))) { + ut_ad(mode == BTR_MODIFY_TREE || mode == BTR_MODIFY_LEAF); + + search_result = row_search_index_entry(index, entry, mode, + &pcur, &mtr); + + switch (search_result) { + case ROW_BUFFERED: + case ROW_NOT_IN_POOL: + /* These are invalid outcomes, because the mode passed + to row_search_index_entry() did not include any of the + flags BTR_INSERT, BTR_DELETE, BTR_DELETE_MARK, or + BTR_WATCH_LEAF. */ + ut_error; + case ROW_NOT_FOUND: fputs("InnoDB: error in sec index entry del undo in\n" "InnoDB: ", stderr); dict_index_name_print(stderr, trx, index); @@ -454,9 +479,9 @@ row_undo_mod_del_unmark_sec_and_undo_update( fputs("\n" "InnoDB: Submit a detailed bug report" " to http://bugs.mysql.com\n", stderr); - } else { - btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur); - + break; + case ROW_FOUND: + btr_cur = btr_pcur_get_btr_cur(&pcur); err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG, btr_cur, FALSE, thr, &mtr); ut_a(err == DB_SUCCESS); diff --git a/row/row0upd.c b/row/row0upd.c index 891506a7986..8b4c54c8959 100644 --- a/row/row0upd.c +++ b/row/row0upd.c @@ -1407,19 +1407,18 @@ row_upd_sec_index_entry( upd_node_t* node, /* in: row update node */ que_thr_t* thr) /* in: query thread */ { - mtr_t mtr; - rec_t* rec; - btr_pcur_t pcur; - mem_heap_t* heap; - dtuple_t* entry; - dict_index_t* index; - ibool found; - btr_cur_t* btr_cur; - ibool referenced; - ibool was_buffered; - ulint err = DB_SUCCESS; - trx_t* trx = thr_get_trx(thr); - ulint mode = BTR_MODIFY_LEAF; + mtr_t mtr; + const rec_t* rec; + btr_pcur_t pcur; + mem_heap_t* heap; + dtuple_t* entry; + dict_index_t* index; + btr_cur_t* btr_cur; + ibool referenced; + ulint err = DB_SUCCESS; + trx_t* trx = thr_get_trx(thr); + ulint mode = BTR_MODIFY_LEAF; + enum row_search_result search_result; index = node->index; @@ -1445,10 +1444,9 @@ row_upd_sec_index_entry( mode |= BTR_DELETE_MARK; } - found = row_search_index_entry( - &was_buffered, index, entry, mode, &pcur, &mtr); - - if (was_buffered) { + search_result = row_search_index_entry(index, entry, mode, + &pcur, &mtr); + if (search_result == ROW_BUFFERED) { /* Entry was delete marked already. */ goto close_cur; @@ -1458,7 +1456,12 @@ row_upd_sec_index_entry( rec = btr_cur_get_rec(btr_cur); - if (UNIV_UNLIKELY(!found)) { + switch (search_result) { + case ROW_BUFFERED: /* already handled above */ + case ROW_NOT_IN_POOL: /* should only occur for BTR_WATCH_LEAF */ + ut_error; + break; + case ROW_NOT_FOUND: fputs("InnoDB: error in sec index entry update in\n" "InnoDB: ", stderr); dict_index_name_print(stderr, trx, index); @@ -1475,7 +1478,8 @@ row_upd_sec_index_entry( fputs("\n" "InnoDB: Submit a detailed bug report" " to http://bugs.mysql.com\n", stderr); - } else { + break; + case ROW_FOUND: /* Delete mark the old index record; it can already be delete marked if we return after a lock wait in row_ins_index_entry below */ @@ -1501,6 +1505,7 @@ row_upd_sec_index_entry( index, offsets, thr, &mtr); } } + break; } close_cur: