Commit a0030fcf authored by marko's avatar marko

branches/innodb+: Clean up the buffering of purges. Instead of

traversing the index B-tree twice (first in BTR_WATCH_LEAF mode and
then in BTR_DELETE mode), let BTR_DELETE take care of checking that
the record can be purged, and either buffering or performing the
purge.

row_purge_poss_sec(): New function, to check if it is possible to
purge a secondary index record.  Refactored from
row_purge_remove_sec_if_poss_low().

row_purge_remove_sec_if_poss_nonbuffered(): Rename to
row_purge_remove_sec_if_poss_tree().  Remove the parameter mode
(always use BTR_MODIFY_TREE).  Use row_purge_poss_sec().

row_purge_remove_sec_if_poss_low(): Rename to
row_purge_remove_sec_if_poss_leaf().  Remove the parameter mode
(always use BTR_MODIFY_LEAF). Let row_search_index_entry() do all the
hard work.

btr_cur_t: Add purge_node, which will be needed by
btr_cur_search_to_nth_level() for BTR_DELETE.  Replace the flag value
BTR_CUR_ABORTED with BTR_CUR_DELETE_REF and BTR_CUR_DELETE_FAILED.

enum row_search_result, row_search_index_entry(): Replace
ROW_NOT_IN_POOL with ROW_NOT_DELETED_REF and ROW_NOT_DELETED.

btr_cur_search_to_nth_level(): Remove BTR_WATCH_LEAF.  As a side
effect, the adaptive hash index can be used in purge as well.  If
BTR_DELETE cannot be buffered, attempt btr_cur_optimistic_delete().
Either way, check row_purge_poss_sec().  Move the code to set
cursor->ibuf_count to get rid of another if (height == 0)
check. Eliminate the label loop_end.  Do not call ibuf_should_try()
twice.

ibuf_should_try(): Now that the successful calls to this function will
be halved, halve the magic constant that ibuf_flush_count will be
compared to, accordingly.

The changes regarding ibuf_should_try() were merged from branches/zip
r3515.

rb://60 approved by Heikki over IM
parent f784ab22
......@@ -30,6 +30,7 @@ Created 10/16/1994 Heikki Tuuri
#include "buf0lru.h"
#include "btr0btr.h"
#include "btr0sea.h"
#include "row0purge.h"
#include "row0upd.h"
#include "trx0rec.h"
#include "trx0roll.h" /* trx_is_recv() */
......@@ -331,7 +332,6 @@ btr_cur_search_to_nth_level(
ulint buf_mode;
ulint estimate;
ulint zip_size;
ulint watch_leaf;
page_cur_t* page_cursor;
ulint ignore_sec_unique;
btr_op_t btr_op = BTR_NO_OP;
......@@ -370,6 +370,7 @@ btr_cur_search_to_nth_level(
break;
case BTR_DELETE:
btr_op = BTR_DELETE_OP;
ut_a(cursor->purge_node);
break;
case BTR_DELETE_MARK:
btr_op = BTR_DELMARK_OP;
......@@ -385,19 +386,15 @@ btr_cur_search_to_nth_level(
/* Operations on the clustered index cannot be buffered. */
ut_ad(btr_op == BTR_NO_OP || !dict_index_is_clust(index));
watch_leaf = latch_mode & BTR_WATCH_LEAF;
estimate = latch_mode & BTR_ESTIMATE;
ignore_sec_unique = latch_mode & BTR_IGNORE_SEC_UNIQUE;
/* Turn the flags unrelated to the latch mode off. */
latch_mode &= ~(
BTR_INSERT
| BTR_DELETE_MARK
| BTR_DELETE
| BTR_ESTIMATE
| BTR_IGNORE_SEC_UNIQUE
| BTR_WATCH_LEAF);
latch_mode &= ~(BTR_INSERT
| BTR_DELETE_MARK
| BTR_DELETE
| BTR_ESTIMATE
| BTR_IGNORE_SEC_UNIQUE);
cursor->flag = BTR_CUR_BINARY;
cursor->index = index;
......@@ -417,16 +414,12 @@ btr_cur_search_to_nth_level(
info->n_searches++;
#endif
/* TODO: investigate if there is any real reason for forbidding
adaptive hash usage when watch_leaf is true.*/
/* Ibuf does not use adaptive hash; this is prevented by the
latch_mode check below. */
if (btr_search_latch.writer == RW_LOCK_NOT_LOCKED
&& latch_mode <= BTR_MODIFY_LEAF
&& info->last_hash_succ
&& !estimate
&& !watch_leaf
#ifdef PAGE_CUR_LE_OR_EXTENDS
&& mode != PAGE_CUR_LE_OR_EXTENDS
#endif /* PAGE_CUR_LE_OR_EXTENDS */
......@@ -486,8 +479,6 @@ btr_cur_search_to_nth_level(
low_bytes = 0;
height = ULINT_UNDEFINED;
rw_latch = RW_NO_LATCH;
buf_mode = BUF_GET;
/* We use these modified search modes on non-leaf levels of the
B-tree. These let us end up in the right B-tree leaf. In that leaf
......@@ -514,94 +505,111 @@ btr_cur_search_to_nth_level(
/* Loop and search until we arrive at the desired level */
search_loop:
buf_mode = BUF_GET;
rw_latch = RW_NO_LATCH;
if (height == 0) {
if (height != 0) {
/* We are about to fetch the root or a non-leaf page. */
} else if (dict_index_is_ibuf(index)) {
/* We're doing a search on an ibuf tree and we're one
level above the leaf page. */
if (watch_leaf) {
buf_mode = BUF_GET_IF_IN_POOL;
ulint is_min_rec;
} else if (latch_mode <= BTR_MODIFY_LEAF) {
rw_latch = latch_mode;
ut_ad(level == 0);
if (btr_op != BTR_NO_OP
&& ibuf_should_try(index, ignore_sec_unique)) {
is_min_rec = rec_get_info_bits(node_ptr, 0)
& REC_INFO_MIN_REC_FLAG;
/* Try insert/delete mark/delete to the
insert/delete buffer if the page is not in
the buffer pool */
if (!is_min_rec) {
cursor->ibuf_cnt = ibuf_rec_get_counter(node_ptr);
buf_mode = BUF_GET_IF_IN_POOL;
}
ut_a(cursor->ibuf_cnt <= 0xFFFF
|| cursor->ibuf_cnt == ULINT_UNDEFINED);
}
}
} else if (latch_mode <= BTR_MODIFY_LEAF) {
rw_latch = latch_mode;
retry_page_get:
zip_size = dict_table_zip_size(index->table);
if (btr_op != BTR_NO_OP
&& ibuf_should_try(index, ignore_sec_unique)) {
if (watch_leaf && height == 0) {
ut_a(buf_mode == BUF_GET_IF_IN_POOL);
/* Try to buffer the operation if the leaf
page is not in the buffer pool. */
buf_mode = BUF_GET_IF_IN_POOL_OR_WATCH;
buf_mode = btr_op == BTR_DELETE_OP
? BUF_GET_IF_IN_POOL_OR_WATCH
: BUF_GET_IF_IN_POOL;
}
}
zip_size = dict_table_zip_size(index->table);
retry_page_get:
block = buf_page_get_gen(
space, zip_size, page_no, rw_latch, guess, buf_mode,
__FILE__, __LINE__, mtr);
if (block == NULL) {
if (watch_leaf && height == 0) {
/* We didn't find a page but we set a watch on it. */
cursor->flag = BTR_CUR_ABORTED;
goto func_exit;
}
/* This must be a search to perform an insert/delete
mark/ delete; try using the insert/delete buffer */
ut_ad(buf_mode == BUF_GET_IF_IN_POOL);
ut_ad(height == 0);
ut_ad(cursor->thr);
if (ibuf_should_try(index, ignore_sec_unique)) {
switch (btr_op) {
case BTR_INSERT_OP:
ut_ad(buf_mode == BUF_GET_IF_IN_POOL);
switch (btr_op) {
case BTR_INSERT_OP:
if (ibuf_insert(IBUF_OP_INSERT, tuple, index,
space, zip_size, page_no,
cursor->thr)) {
if (ibuf_insert(IBUF_OP_INSERT, tuple, index,
space, zip_size, page_no,
cursor->thr)) {
cursor->flag = BTR_CUR_INSERT_TO_IBUF;
cursor->flag = BTR_CUR_INSERT_TO_IBUF;
goto func_exit;
}
break;
goto func_exit;
}
break;
case BTR_DELMARK_OP:
if (ibuf_insert(IBUF_OP_DELETE_MARK, tuple,
index, space, zip_size,
page_no, cursor->thr)) {
case BTR_DELMARK_OP:
ut_ad(buf_mode == BUF_GET_IF_IN_POOL);
cursor->flag = BTR_CUR_DEL_MARK_IBUF;
if (ibuf_insert(IBUF_OP_DELETE_MARK, tuple,
index, space, zip_size,
page_no, cursor->thr)) {
goto func_exit;
}
cursor->flag = BTR_CUR_DEL_MARK_IBUF;
break;
goto func_exit;
}
case BTR_DELETE_OP:
if (ibuf_insert(IBUF_OP_DELETE, tuple, index,
space, zip_size, page_no,
cursor->thr)) {
break;
cursor->flag = BTR_CUR_DELETE_IBUF;
case BTR_DELETE_OP:
ut_ad(buf_mode == BUF_GET_IF_IN_POOL_OR_WATCH);
goto func_exit;
}
if (!row_purge_poss_sec(cursor->purge_node,
index, tuple)) {
/* The record cannot be purged yet. */
cursor->flag = BTR_CUR_DELETE_REF;
} else if (ibuf_insert(IBUF_OP_DELETE, tuple,
index, space, zip_size,
page_no,
cursor->thr)) {
/* The purge was buffered. */
cursor->flag = BTR_CUR_DELETE_IBUF;
} else {
/* The purge could not be buffered. */
buf_pool_watch_clear();
break;
default:
ut_error;
}
buf_pool_watch_clear();
goto func_exit;
default:
ut_error;
}
/* Insert to the insert/delete buffer did not succeed, we
......@@ -678,46 +686,24 @@ btr_cur_search_to_nth_level(
ut_ad(height == btr_page_get_level(page_cur_get_page(page_cursor),
mtr));
if (level == height) {
goto loop_end;
}
if (level != height) {
ut_ad(height > 0);
height--;
guess = NULL;
node_ptr = page_cur_get_rec(page_cursor);
if (height == 0 && dict_index_is_ibuf(index)) {
/* We're doing a search on an ibuf tree and we're one level
above the leaf page. */
ut_ad(height > 0);
ulint is_min_rec;
height--;
guess = NULL;
ut_ad(level == 0);
node_ptr = page_cur_get_rec(page_cursor);
is_min_rec = rec_get_info_bits(node_ptr, 0)
& REC_INFO_MIN_REC_FLAG;
offsets = rec_get_offsets(
node_ptr, index, offsets, ULINT_UNDEFINED, &heap);
if (!is_min_rec) {
cursor->ibuf_cnt = ibuf_rec_get_counter(node_ptr);
/* Go to the child node */
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
ut_a(cursor->ibuf_cnt <= 0xFFFF
|| cursor->ibuf_cnt == ULINT_UNDEFINED);
}
goto search_loop;
}
offsets = rec_get_offsets(
node_ptr, index, offsets, ULINT_UNDEFINED, &heap);
/* Go to the child node */
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
goto search_loop;
loop_end:
if (level != 0) {
/* x-latch the page */
page = btr_page_get(
......@@ -743,6 +729,35 @@ btr_cur_search_to_nth_level(
|| mode != PAGE_CUR_LE);
ut_ad(cursor->low_match != ULINT_UNDEFINED
|| mode != PAGE_CUR_LE);
/* If this was a delete operation, the leaf page was
in the buffer pool, and a matching record was found in
the leaf page, attempt to delete it. If the deletion
fails, set the cursor flag accordingly. */
if (UNIV_UNLIKELY(btr_op == BTR_DELETE_OP)
&& low_match == dtuple_get_n_fields(tuple)
&& !page_cur_is_before_first(page_cursor)) {
/* Before attempting to purge a record, check
if it is safe to do so. */
if (!row_purge_poss_sec(cursor->purge_node,
index, tuple)) {
cursor->flag = BTR_CUR_DELETE_REF;
} else {
/* Only delete-marked records should
be purged. */
ut_ad(REC_INFO_DELETED_FLAG
& rec_get_info_bits(
btr_cur_get_rec(cursor),
page_is_comp(page)));
if (!btr_cur_optimistic_delete(cursor, mtr)) {
cursor->flag = BTR_CUR_DELETE_FAILED;
}
}
}
}
func_exit:
......
......@@ -65,11 +65,6 @@ insert/delete buffer. */
buffer. */
#define BTR_DELETE 8192
/* If the leaf page is not in the buffer pool: don't read it in, set
cursor->flag = BTR_CUR_ABORTED, and set buf_pool_t::watch_* that
watches for the page to get read in. */
#define BTR_WATCH_LEAF 16384
/******************************************************************
Gets the root node of a tree and x-latches it. */
UNIV_INTERN
......
......@@ -601,6 +601,7 @@ to know struct size! */
struct btr_cur_struct {
dict_index_t* index; /* index where positioned */
page_cur_t page_cur; /* page cursor */
purge_node_t* purge_node; /* purge node, for BTR_DELETE */
buf_block_t* left_block; /* this field is used to store
a pointer to the left neighbor
page, in the cases
......@@ -696,9 +697,9 @@ struct btr_cur_struct {
mark in the insert/delete buffer */
#define BTR_CUR_DELETE_IBUF 6 /* performed the intended delete in
the insert/delete buffer */
#define BTR_CUR_ABORTED 7 /* search with BTR_CHECK_LEAF
aborted due to leaf page not being
in buffer pool */
#define BTR_CUR_DELETE_REF 7 /* row_purge_poss_sec() failed */
#define BTR_CUR_DELETE_FAILED 8 /* an optimistic delete could not
be performed */
/* If pessimistic delete fails because of lack of file space,
there is still a good change of success a little later: try this many times,
......
......@@ -89,7 +89,7 @@ ibuf_should_try(
ibuf_flush_count++;
if (ibuf_flush_count % 8 == 0) {
if (ibuf_flush_count % 4 == 0) {
buf_LRU_try_free_flushed_blocks();
}
......
......@@ -28,6 +28,29 @@ row_purge_node_create(
que_thr_t* parent, /* in: parent node, i.e., a thr node */
mem_heap_t* heap); /* in: memory heap where created */
/***************************************************************
Determines if it is possible to remove a secondary index entry.
Removal is possible if the secondary index entry does not refer to any
not delete marked version of a clustered index record where DB_TRX_ID
is newer than the purge view.
NOTE: This function should only be called by the purge thread, only
while holding a latch on the leaf page of the secondary index entry
(or keeping the buffer pool watch on the page). It is possible that
this function first returns TRUE and then FALSE, if a user transaction
inserts a record that the secondary index entry would refer to.
However, in that case, the user transaction would also re-insert the
secondary index entry after purge has removed it and released the leaf
page latch. */
UNIV_INTERN
ibool
row_purge_poss_sec(
/*===============*/
/* out: TRUE if the secondary index
record can be purged */
purge_node_t* node, /* in/out: row purge node */
dict_index_t* index, /* in: secondary index */
const dtuple_t* entry); /* in: secondary index entry */
/***************************************************************
Does the purge operation for a single undo log record. This is a high-level
function used in an SQL execution graph. */
UNIV_INTERN
......
......@@ -271,8 +271,10 @@ enum row_search_result {
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 */
ROW_NOT_DELETED_REF, /* BTR_DELETE was specified, and
row_purge_poss_sec() failed */
ROW_NOT_DELETED, /* BTR_DELETE was specified, and the
optimistic delete failed */
};
/*******************************************************************
......
......@@ -198,34 +198,68 @@ row_purge_remove_clust_if_poss(
}
/***************************************************************
Removes a secondary index entry if possible, without trying to use the
insert/delete buffer. */
Determines if it is possible to remove a secondary index entry.
Removal is possible if the secondary index entry does not refer to any
not delete marked version of a clustered index record where DB_TRX_ID
is newer than the purge view.
NOTE: This function should only be called by the purge thread, only
while holding a latch on the leaf page of the secondary index entry
(or keeping the buffer pool watch on the page). It is possible that
this function first returns TRUE and then FALSE, if a user transaction
inserts a record that the secondary index entry would refer to.
However, in that case, the user transaction would also re-insert the
secondary index entry after purge has removed it and released the leaf
page latch. */
UNIV_INTERN
ibool
row_purge_poss_sec(
/*===============*/
/* out: TRUE if the secondary index
record can be purged */
purge_node_t* node, /* in/out: row purge node */
dict_index_t* index, /* in: secondary index */
const dtuple_t* entry) /* in: secondary index entry */
{
ibool can_delete;
mtr_t mtr;
ut_ad(!dict_index_is_clust(index));
mtr_start(&mtr);
can_delete = !row_purge_reposition_pcur(BTR_SEARCH_LEAF, node, &mtr)
|| !row_vers_old_has_index_entry(TRUE,
btr_pcur_get_rec(&node->pcur),
&mtr, index, entry);
btr_pcur_commit_specify_mtr(&node->pcur, &mtr);
return(can_delete);
}
/***************************************************************
Removes a secondary index entry if possible, by modifying the
index tree. Does not try to buffer the delete. */
static
ibool
row_purge_remove_sec_if_poss_low_nonbuffered(
/*=========================================*/
row_purge_remove_sec_if_poss_tree(
/*==============================*/
/* out: TRUE if success or if not found */
purge_node_t* node, /* in: row purge node */
dict_index_t* index, /* in: index */
const dtuple_t* entry, /* in: index entry */
ulint mode) /* in: latch mode BTR_MODIFY_LEAF or
BTR_MODIFY_TREE */
const dtuple_t* entry) /* in: index entry */
{
btr_pcur_t pcur;
btr_cur_t* btr_cur;
ibool success;
ibool old_has = FALSE;
ibool success = TRUE;
ulint err;
mtr_t mtr;
mtr_t mtr_vers;
enum row_search_result search_result;
log_free_check();
mtr_start(&mtr);
ut_ad(mode == BTR_MODIFY_TREE || mode == BTR_MODIFY_LEAF);
search_result = row_search_index_entry(index, entry, mode,
search_result = row_search_index_entry(index, entry, BTR_MODIFY_TREE,
&pcur, &mtr);
switch (search_result) {
......@@ -242,17 +276,15 @@ row_purge_remove_sec_if_poss_low_nonbuffered(
/* fputs("PURGE:........sec entry not found\n", stderr); */
/* dtuple_print(stderr, entry); */
success = TRUE;
goto func_exit;
case ROW_FOUND:
break;
case ROW_BUFFERED:
case ROW_NOT_IN_POOL:
case ROW_NOT_DELETED_REF:
case ROW_NOT_DELETED:
/* 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. */
flags BTR_INSERT, BTR_DELETE, or BTR_DELETE_MARK. */
ut_error;
}
......@@ -262,33 +294,23 @@ row_purge_remove_sec_if_poss_low_nonbuffered(
which cannot be purged yet, requires its existence. If some requires,
we should do nothing. */
mtr_start(&mtr_vers);
success = row_purge_reposition_pcur(BTR_SEARCH_LEAF, node, &mtr_vers);
if (success) {
old_has = row_vers_old_has_index_entry(
TRUE, btr_pcur_get_rec(&(node->pcur)),
&mtr_vers, index, entry);
}
btr_pcur_commit_specify_mtr(&(node->pcur), &mtr_vers);
if (!old_has) {
if (row_purge_poss_sec(node, index, entry)) {
/* Remove the index record, which should have been
marked for deletion. */
ut_ad(REC_INFO_DELETED_FLAG
& rec_get_info_bits(btr_cur_get_rec(btr_cur),
dict_table_is_comp(index->table)));
if (mode == BTR_MODIFY_LEAF) {
success = btr_cur_optimistic_delete(btr_cur, &mtr);
} else {
ut_ad(mode == BTR_MODIFY_TREE);
btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
RB_NONE, &mtr);
success = err == DB_SUCCESS;
ut_a(success || err == DB_OUT_OF_FILE_SPACE);
btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
RB_NONE, &mtr);
switch (UNIV_EXPECT(err, DB_SUCCESS)) {
case DB_SUCCESS:
break;
case DB_OUT_OF_FILE_SPACE:
success = FALSE;
break;
default:
ut_error;
}
}
......@@ -300,88 +322,30 @@ row_purge_remove_sec_if_poss_low_nonbuffered(
}
/***************************************************************
Removes a secondary index entry if possible. */
Removes a secondary index entry without modifying the index tree,
if possible. */
static
ibool
row_purge_remove_sec_if_poss_low(
/*=============================*/
row_purge_remove_sec_if_poss_leaf(
/*==============================*/
/* out: TRUE if success or if not found */
purge_node_t* node, /* in: row purge node */
dict_index_t* index, /* in: index */
const dtuple_t* entry, /* in: index entry */
ulint mode) /* in: latch mode BTR_MODIFY_LEAF or
BTR_MODIFY_TREE */
const dtuple_t* entry) /* in: index entry */
{
mtr_t mtr;
btr_pcur_t pcur;
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. */
goto unbuffered;
}
ut_ad(mode == BTR_MODIFY_LEAF);
log_free_check();
mtr_start(&mtr);
search_result = row_search_index_entry(
index, entry, BTR_SEARCH_LEAF | BTR_WATCH_LEAF, &pcur, &mtr);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
switch (search_result) {
case ROW_NOT_FOUND:
/* Index entry does not exist, nothing to do. */
return(TRUE);
case ROW_FOUND:
/* The index entry exists and is in the buffer pool;
no need to use the insert/delete buffer. */
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:
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. */
mtr_start(&mtr);
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);
}
btr_pcur_commit_specify_mtr(&node->pcur, &mtr);
if (old_has) {
/* Can't remove the index record yet. */
buf_pool_watch_clear();
return(TRUE);
}
mtr_start(&mtr);
/* Set the purge node for the call to row_purge_poss_sec(). */
pcur.btr_cur.purge_node = node;
/* Set the query thread, so that ibuf_insert_low() will be
able to invoke thd_get_trx(). */
btr_pcur_get_btr_cur(&pcur)->thr = que_node_get_parent(node);
pcur.btr_cur.thr = que_node_get_parent(node);
search_result = row_search_index_entry(
index, entry, BTR_MODIFY_LEAF | BTR_DELETE, &pcur, &mtr);
......@@ -389,31 +353,25 @@ row_purge_remove_sec_if_poss_low(
btr_pcur_close(&pcur);
mtr_commit(&mtr);
buf_pool_watch_clear();
switch (search_result) {
case ROW_NOT_DELETED:
/* The index entry could not be deleted. */
return(FALSE);
case ROW_NOT_DELETED_REF:
/* The index entry is still needed. */
case ROW_NOT_FOUND:
/* Index entry does not exist, nothing to do. */
return(TRUE);
/* The index entry does not exist, nothing to do. */
case ROW_FOUND:
/* The index entry exists and is in the buffer pool;
no need to use the insert/delete buffer. */
break;
/* The index entry existed in the buffer pool
and was deleted because of the BTR_DELETE. */
case ROW_BUFFERED:
/* The deletion was buffered. */
return(TRUE);
case ROW_NOT_IN_POOL:
/* BTR_WATCH_LEAF was not specified,
so this should not occur! */
ut_error;
}
/* Page read into buffer pool or delete-buffering failed. */
unbuffered:
return(row_purge_remove_sec_if_poss_low_nonbuffered(node, index,
entry, mode));
ut_error;
return(FALSE);
}
/***************************************************************
......@@ -431,15 +389,12 @@ row_purge_remove_sec_if_poss(
/* fputs("Purge: Removing secondary record\n", stderr); */
success = row_purge_remove_sec_if_poss_low(node, index, entry,
BTR_MODIFY_LEAF);
if (success) {
if (row_purge_remove_sec_if_poss_leaf(node, index, entry)) {
return;
}
retry:
success = row_purge_remove_sec_if_poss_low(node, index, entry,
BTR_MODIFY_TREE);
success = row_purge_remove_sec_if_poss_tree(node, index, entry);
/* The delete operation may fail if we have little
file space left: TODO: easiest to crash the database
and restart with more file space */
......
......@@ -802,11 +802,13 @@ row_search_index_entry(
btr_pcur_open(index, entry, PAGE_CUR_LE, mode, pcur, mtr);
switch (btr_pcur_get_btr_cur(pcur)->flag) {
case BTR_CUR_ABORTED:
/* We did not read in the leaf page, thus we can't have
found anything. */
ut_a(mode & BTR_WATCH_LEAF);
return(ROW_NOT_IN_POOL);
case BTR_CUR_DELETE_REF:
ut_a(mode & BTR_DELETE);
return(ROW_NOT_DELETED_REF);
case BTR_CUR_DELETE_FAILED:
ut_a(mode & BTR_DELETE);
return(ROW_NOT_DELETED);
case BTR_CUR_DEL_MARK_IBUF:
case BTR_CUR_DELETE_IBUF:
......
......@@ -152,11 +152,11 @@ row_undo_ins_remove_sec_low(
case ROW_FOUND:
break;
case ROW_BUFFERED:
case ROW_NOT_IN_POOL:
case ROW_NOT_DELETED:
case ROW_NOT_DELETED_REF:
/* 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. */
flags BTR_INSERT, BTR_DELETE, or BTR_DELETE_MARK. */
ut_error;
}
......
......@@ -331,11 +331,11 @@ row_undo_mod_del_mark_or_remove_sec_low(
case ROW_FOUND:
break;
case ROW_BUFFERED:
case ROW_NOT_IN_POOL:
case ROW_NOT_DELETED:
case ROW_NOT_DELETED_REF:
/* 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. */
flags BTR_INSERT, BTR_DELETE, or BTR_DELETE_MARK. */
ut_error;
}
......@@ -468,11 +468,11 @@ row_undo_mod_del_unmark_sec_and_undo_update(
switch (search_result) {
case ROW_BUFFERED:
case ROW_NOT_IN_POOL:
case ROW_NOT_DELETED:
case ROW_NOT_DELETED_REF:
/* 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. */
flags BTR_INSERT, BTR_DELETE, or BTR_DELETE_MARK. */
ut_error;
case ROW_NOT_FOUND:
fputs("InnoDB: error in sec index entry del undo in\n"
......
......@@ -1454,8 +1454,8 @@ row_upd_sec_index_entry(
rec = btr_cur_get_rec(btr_cur);
switch (search_result) {
case ROW_NOT_IN_POOL:
/* This should only occur for BTR_WATCH_LEAF. */
case ROW_NOT_DELETED: /* should only occur for BTR_DELETE */
case ROW_NOT_DELETED_REF: /* should only occur for BTR_DELETE */
ut_error;
break;
case ROW_BUFFERED:
......
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