summaryrefslogtreecommitdiff
path: root/innobase/page
diff options
context:
space:
mode:
authorheikki@hundin.mysql.fi <>2002-10-29 23:16:46 +0200
committerheikki@hundin.mysql.fi <>2002-10-29 23:16:46 +0200
commit9153d88c6bfbb7b1d9fd5fd1633aade67b48e774 (patch)
treee57bf300e559932ce45e0f749d7349577e7e0479 /innobase/page
parent245218284495701846f49d986bc91997b97563d6 (diff)
downloadmariadb-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')
-rw-r--r--innobase/page/page0cur.c52
-rw-r--r--innobase/page/page0page.c196
2 files changed, 238 insertions, 10 deletions
diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c
index 2909573b14b..bb49e9080ce 100644
--- a/innobase/page/page0cur.c
+++ b/innobase/page/page0cur.c
@@ -169,7 +169,7 @@ page_cur_search_with_match(
ut_ad(dtuple_check_typed(tuple));
ut_ad((mode == PAGE_CUR_L) || (mode == PAGE_CUR_LE)
|| (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)
- || (mode == PAGE_CUR_DBG));
+ || (mode == PAGE_CUR_LE_OR_EXTENDS) || (mode == PAGE_CUR_DBG));
#ifdef PAGE_CUR_ADAPT
if ((page_header_get_field(page, PAGE_LEVEL) == 0)
@@ -232,9 +232,26 @@ page_cur_search_with_match(
low_matched_bytes = cur_matched_bytes;
} else if (cmp == -1) {
- up = mid;
- up_matched_fields = cur_matched_fields;
- up_matched_bytes = cur_matched_bytes;
+
+ if (mode == PAGE_CUR_LE_OR_EXTENDS
+ && dfield_get_len(dtuple_get_nth_field(tuple,
+ cur_matched_fields))
+ == cur_matched_bytes
+ && rec_get_nth_field_len(mid_rec,
+ cur_matched_fields)
+ != UNIV_SQL_NULL) {
+
+ /* This means current dfield is not SQL
+ NULL, and the current rec field extends it */
+
+ low = mid;
+ low_matched_fields = cur_matched_fields;
+ low_matched_bytes = cur_matched_bytes;
+ } else {
+ up = mid;
+ up_matched_fields = cur_matched_fields;
+ up_matched_bytes = cur_matched_bytes;
+ }
} else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) {
low = mid;
@@ -252,8 +269,8 @@ page_cur_search_with_match(
slot = page_dir_get_nth_slot(page, up);
up_rec = page_dir_slot_get_rec(slot);
- /* Perform linear search until the upper and lower records
- come to distance 1 of each other. */
+ /* Perform linear search until the upper and lower records come to
+ distance 1 of each other. */
while (page_rec_get_next(low_rec) != up_rec) {
@@ -272,10 +289,25 @@ page_cur_search_with_match(
low_matched_bytes = cur_matched_bytes;
} else if (cmp == -1) {
- up_rec = mid_rec;
- up_matched_fields = cur_matched_fields;
- up_matched_bytes = cur_matched_bytes;
-
+ if (mode == PAGE_CUR_LE_OR_EXTENDS
+ && dfield_get_len(dtuple_get_nth_field(tuple,
+ cur_matched_fields))
+ == cur_matched_bytes
+ && rec_get_nth_field_len(mid_rec,
+ cur_matched_fields)
+ != UNIV_SQL_NULL) {
+
+ /* This means current dfield is not SQL
+ NULL, and the current rec field extends it */
+
+ low = mid;
+ low_matched_fields = cur_matched_fields;
+ low_matched_bytes = cur_matched_bytes;
+ } else {
+ up_rec = mid_rec;
+ up_matched_fields = cur_matched_fields;
+ up_matched_bytes = cur_matched_bytes;
+ }
} else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) {
low_rec = mid_rec;
low_matched_fields = cur_matched_fields;
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