Commit 769969cc authored by marko's avatar marko

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
parent 33b5eef5
......@@ -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, ... */
......
......@@ -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));
}
/***************************************************************
......
......@@ -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
......
......@@ -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);
......
......@@ -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);
......
......@@ -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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment