diff options
author | heikki@hundin.mysql.fi <> | 2002-10-29 23:16:46 +0200 |
---|---|---|
committer | heikki@hundin.mysql.fi <> | 2002-10-29 23:16:46 +0200 |
commit | 9153d88c6bfbb7b1d9fd5fd1633aade67b48e774 (patch) | |
tree | e57bf300e559932ce45e0f749d7349577e7e0479 /innobase/page/page0page.c | |
parent | 245218284495701846f49d986bc91997b97563d6 (diff) | |
download | mariadb-git-9153d88c6bfbb7b1d9fd5fd1633aade67b48e774.tar.gz |
Many files:
Merge InnoDB-4.0.5: new isolation levels READ COMMITTED and READ UNCOMMITTED now supported, selective deadlock resolution
mysqld.cc:
Change MySQL default isolation level to REPEATABLE READ; note that InnoDB has always had that default, and BDB and MyISAM always run at SERIALIZABLE level anyway
Diffstat (limited to 'innobase/page/page0page.c')
-rw-r--r-- | innobase/page/page0page.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c index ed74736c8da..7d0d88c6afc 100644 --- a/innobase/page/page0page.c +++ b/innobase/page/page0page.c @@ -1313,6 +1313,194 @@ page_rec_validate( } /******************************************************************* +This function checks the consistency of an index page when we do not +know the index. This is also resilient so that this should never crash +even if the page is total garbage. */ + +ibool +page_simple_validate( +/*=================*/ + /* out: TRUE if ok */ + page_t* page) /* in: index page */ +{ + page_cur_t cur; + page_dir_slot_t* slot; + ulint slot_no; + ulint n_slots; + rec_t* rec; + byte* rec_heap_top; + ulint count; + ulint own_count; + ibool ret = FALSE; + + /* Check first that the record heap and the directory do not + overlap. */ + + n_slots = page_dir_get_n_slots(page); + + if (n_slots > UNIV_PAGE_SIZE / 4) { + fprintf(stderr, + "Nonsensical number %lu of page dir slots\n", n_slots); + + goto func_exit; + } + + rec_heap_top = page_header_get_ptr(page, PAGE_HEAP_TOP); + + if (rec_heap_top > page_dir_get_nth_slot(page, n_slots - 1)) { + + fprintf(stderr, + "Record heap and dir overlap on a page, heap top %lu, dir %lu\n", + (ulint)(page_header_get_ptr(page, PAGE_HEAP_TOP) - page), + (ulint)(page_dir_get_nth_slot(page, n_slots - 1) - page)); + + goto func_exit; + } + + /* Validate the record list in a loop checking also that it is + consistent with the page record directory. */ + + count = 0; + own_count = 1; + slot_no = 0; + slot = page_dir_get_nth_slot(page, slot_no); + + page_cur_set_before_first(page, &cur); + + for (;;) { + rec = (&cur)->rec; + + if (rec > rec_heap_top) { + fprintf(stderr, + "Record %lu is above rec heap top %lu\n", + (ulint)(rec - page), (ulint)(rec_heap_top - page)); + + goto func_exit; + } + + if (rec_get_n_owned(rec) != 0) { + /* This is a record pointed to by a dir slot */ + if (rec_get_n_owned(rec) != own_count) { + + fprintf(stderr, + "Wrong owned count %lu, %lu, rec %lu\n", + rec_get_n_owned(rec), own_count, + (ulint)(rec - page)); + + goto func_exit; + } + + if (page_dir_slot_get_rec(slot) != rec) { + fprintf(stderr, + "Dir slot does not point to right rec %lu\n", + (ulint)(rec - page)); + + goto func_exit; + } + + own_count = 0; + + if (!page_cur_is_after_last(&cur)) { + slot_no++; + slot = page_dir_get_nth_slot(page, slot_no); + } + } + + if (page_cur_is_after_last(&cur)) { + + break; + } + + if (rec_get_next_offs(rec) < FIL_PAGE_DATA + || rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) { + fprintf(stderr, + "Next record offset nonsensical %lu for rec %lu\n", + rec_get_next_offs(rec), + (ulint)(rec - page)); + + goto func_exit; + } + + count++; + + if (count > UNIV_PAGE_SIZE) { + fprintf(stderr, + "Page record list appears to be circular %lu\n", + count); + goto func_exit; + } + + page_cur_move_to_next(&cur); + own_count++; + } + + if (rec_get_n_owned(rec) == 0) { + fprintf(stderr, "n owned is zero in a supremum rec\n"); + + goto func_exit; + } + + if (slot_no != n_slots - 1) { + fprintf(stderr, "n slots wrong %lu, %lu\n", + slot_no, n_slots - 1); + goto func_exit; + } + + if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) { + fprintf(stderr, "n recs wrong %lu %lu\n", + page_header_get_field(page, PAGE_N_RECS) + 2, count + 1); + + goto func_exit; + } + + /* Check then the free list */ + rec = page_header_get_ptr(page, PAGE_FREE); + + while (rec != NULL) { + if (rec < page + FIL_PAGE_DATA + || rec >= page + UNIV_PAGE_SIZE) { + fprintf(stderr, + "Free list record has a nonsensical offset %lu\n", + (ulint)(rec - page)); + + goto func_exit; + } + + if (rec > rec_heap_top) { + fprintf(stderr, + "Free list record %lu is above rec heap top %lu\n", + (ulint)(rec - page), (ulint)(rec_heap_top - page)); + + goto func_exit; + } + + count++; + + if (count > UNIV_PAGE_SIZE) { + fprintf(stderr, + "Page free list appears to be circular %lu\n", + count); + goto func_exit; + } + + rec = page_rec_get_next(rec); + } + + if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) { + + fprintf(stderr, "N heap is wrong %lu, %lu\n", + page_header_get_field(page, PAGE_N_HEAP), count + 1); + + goto func_exit; + } + + ret = TRUE; + +func_exit: + return(ret); +} + +/******************************************************************* This function checks the consistency of an index page. */ ibool @@ -1339,6 +1527,14 @@ page_validate( ulint i; char err_buf[1000]; + if (!page_simple_validate(page)) { + buf_page_print(page); + + fprintf(stderr, "Apparent corruption in a page in index %s\n", + index->name); + return(FALSE); + } + heap = mem_heap_create(UNIV_PAGE_SIZE); /* The following buffer is used to check that the |