Commit 0303bc42 authored by Marko Mäkelä's avatar Marko Mäkelä

Bug#14554000 CRASH IN PAGE_REC_GET_NTH_CONST(NTH=0) DURING COMPRESSED

PAGE SPLIT

page_rec_get_nth_const(): Map nth==0 to the page infimum.

btr_compress(adjust=TRUE): Add a debug assertion for nth>0. The cursor
should never be positioned on the page infimum.

btr_index_page_validate(): Add test instrumentation for checking the
return values of page_rec_get_nth_const() during CHECK TABLE, and for
checking that the page directory slot 0 always contains only one
record, the predefined page infimum record.

page_cur_delete_rec(), page_delete_rec_list_end(): Add debug
assertions guarding against accessing the page slot 0.

page_copy_rec_list_start(): Clarify a comment about ret_pos==0.

rb:1248 approved by Jimmy Yang
parent 22f264f3
2012-08-29 The InnoDB Team
* btr/btr0btr.c, page/page0cur.c, page/page0page.c:
Fix Bug#14554000 CRASH IN PAGE_REC_GET_NTH_CONST(NTH=0)
DURING COMPRESSED PAGE SPLIT
2012-08-16 The InnoDB Team
* btr/btr0cur.c:
......
......@@ -3241,6 +3241,7 @@ btr_compress(
if (adjust) {
nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
ut_ad(nth_rec > 0);
}
/* Decide the page to which we try to merge and which will inherit
......@@ -3476,6 +3477,7 @@ func_exit:
mem_heap_free(heap);
if (adjust) {
ut_ad(nth_rec > 0);
btr_cur_position(
index,
page_rec_get_nth(merge_block->frame, nth_rec),
......@@ -3988,8 +3990,22 @@ btr_index_page_validate(
{
page_cur_t cur;
ibool ret = TRUE;
#ifndef DBUG_OFF
ulint nth = 1;
#endif /* !DBUG_OFF */
page_cur_set_before_first(block, &cur);
/* Directory slot 0 should only contain the infimum record. */
DBUG_EXECUTE_IF("check_table_rec_next",
ut_a(page_rec_get_nth_const(
page_cur_get_page(&cur), 0)
== cur.rec);
ut_a(page_dir_slot_get_n_owned(
page_dir_get_nth_slot(
page_cur_get_page(&cur), 0))
== 1););
page_cur_move_to_next(&cur);
for (;;) {
......@@ -4003,6 +4019,16 @@ btr_index_page_validate(
return(FALSE);
}
/* Verify that page_rec_get_nth_const() is correctly
retrieving each record. */
DBUG_EXECUTE_IF("check_table_rec_next",
ut_a(cur.rec == page_rec_get_nth_const(
page_cur_get_page(&cur),
page_rec_get_n_recs_before(
cur.rec)));
ut_a(nth++ == page_rec_get_n_recs_before(
cur.rec)););
page_cur_move_to_next(&cur);
}
......
......@@ -1902,6 +1902,7 @@ page_cur_delete_rec(
/* Save to local variables some data associated with current_rec */
cur_slot_no = page_dir_find_owner_slot(current_rec);
ut_ad(cur_slot_no > 0);
cur_dir_slot = page_dir_get_nth_slot(page, cur_slot_no);
cur_n_owned = page_dir_slot_get_n_owned(cur_dir_slot);
......
......@@ -795,8 +795,8 @@ zip_reorganize:
/* Before copying, "ret" was the predecessor
of the predefined supremum record. If it was
the predefined infimum record, then it would
still be the infimum. Thus, the assertion
ut_a(ret_pos > 0) would fail here. */
still be the infimum, and we would have
ret_pos == 0. */
if (UNIV_UNLIKELY
(!page_zip_reorganize(new_block, index, mtr))) {
......@@ -1051,6 +1051,7 @@ page_delete_rec_list_end(
n_owned = rec_get_n_owned_new(rec2) - count;
slot_index = page_dir_find_owner_slot(rec2);
ut_ad(slot_index > 0);
slot = page_dir_get_nth_slot(page, slot_index);
} else {
rec_t* rec2 = rec;
......@@ -1066,6 +1067,7 @@ page_delete_rec_list_end(
n_owned = rec_get_n_owned_old(rec2) - count;
slot_index = page_dir_find_owner_slot(rec2);
ut_ad(slot_index > 0);
slot = page_dir_get_nth_slot(page, slot_index);
}
......@@ -1492,6 +1494,10 @@ page_rec_get_nth_const(
ulint n_owned;
const rec_t* rec;
if (nth == 0) {
return(page_get_infimum_rec(page));
}
ut_ad(nth < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
for (i = 0;; i++) {
......
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