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