📄 page0page.c
字号:
{ ulint n_slots; n_slots = page_dir_get_n_slots(page); if (page_dir_slot_get_rec(page_dir_get_nth_slot(page, 0)) != page_get_infimum_rec(page)) { fprintf(stderr,"InnoDB: Page directory corruption: supremum not pointed to\n"); buf_page_print(page); } if (page_dir_slot_get_rec(page_dir_get_nth_slot(page, n_slots - 1)) != page_get_supremum_rec(page)) { fprintf(stderr,"InnoDB: Page directory corruption: supremum not pointed to\n"); buf_page_print(page); }} /*******************************************************************This function checks the consistency of an index page when we do notknow the index. This is also resilient so that this should never crasheven if the page is total garbage. */iboolpage_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; ulint comp = page_is_comp(page); /* 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, "InnoDB: Nonsensical number %lu of page dir slots\n", (ulong) 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, "InnoDB: Record heap and dir overlap on a page, heap top %lu, dir %lu\n", (ulong)(page_header_get_ptr(page, PAGE_HEAP_TOP) - page), (ulong)(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, "InnoDB: Record %lu is above rec heap top %lu\n", (ulong)(rec - page), (ulong)(rec_heap_top - page)); goto func_exit; } if (rec_get_n_owned(rec, comp) != 0) { /* This is a record pointed to by a dir slot */ if (rec_get_n_owned(rec, comp) != own_count) { fprintf(stderr, "InnoDB: Wrong owned count %lu, %lu, rec %lu\n", (ulong) rec_get_n_owned(rec, comp), (ulong) own_count, (ulong)(rec - page)); goto func_exit; } if (page_dir_slot_get_rec(slot) != rec) { fprintf(stderr, "InnoDB: Dir slot does not point to right rec %lu\n", (ulong)(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, comp) < FIL_PAGE_DATA || rec_get_next_offs(rec, comp) >= UNIV_PAGE_SIZE) { fprintf(stderr, "InnoDB: Next record offset nonsensical %lu for rec %lu\n", (ulong) rec_get_next_offs(rec, comp), (ulong)(rec - page)); goto func_exit; } count++; if (count > UNIV_PAGE_SIZE) { fprintf(stderr, "InnoDB: Page record list appears to be circular %lu\n", (ulong) count); goto func_exit; } page_cur_move_to_next(&cur); own_count++; } if (rec_get_n_owned(rec, comp) == 0) { fprintf(stderr, "InnoDB: n owned is zero in a supremum rec\n"); goto func_exit; } if (slot_no != n_slots - 1) { fprintf(stderr, "InnoDB: n slots wrong %lu, %lu\n", (ulong) slot_no, (ulong) (n_slots - 1)); goto func_exit; } if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) { fprintf(stderr, "InnoDB: n recs wrong %lu %lu\n", (ulong) page_header_get_field(page, PAGE_N_RECS) + 2, (ulong) (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, "InnoDB: Free list record has a nonsensical offset %lu\n", (ulong)(rec - page)); goto func_exit; } if (rec > rec_heap_top) { fprintf(stderr, "InnoDB: Free list record %lu is above rec heap top %lu\n", (ulong)(rec - page), (ulong)(rec_heap_top - page)); goto func_exit; } count++; if (count > UNIV_PAGE_SIZE) { fprintf(stderr, "InnoDB: Page free list appears to be circular %lu\n", (ulong) count); goto func_exit; } rec = page_rec_get_next(rec); } if (page_dir_get_n_heap(page) != count + 1) { fprintf(stderr, "InnoDB: N heap is wrong %lu, %lu\n", (ulong) page_dir_get_n_heap(page), (ulong) (count + 1)); goto func_exit; } ret = TRUE; func_exit: return(ret); }/*******************************************************************This function checks the consistency of an index page. */iboolpage_validate(/*==========*/ /* out: TRUE if ok */ page_t* page, /* in: index page */ dict_index_t* index) /* in: data dictionary index containing the page record type definition */{ page_dir_slot_t* slot; mem_heap_t* heap; page_cur_t cur; byte* buf; ulint count; ulint own_count; ulint slot_no; ulint data_size; rec_t* rec; rec_t* old_rec = NULL; ulint offs; ulint n_slots; ibool ret = FALSE; ulint i; ulint comp = page_is_comp(page); ulint* offsets = NULL; ulint* old_offsets = NULL; if ((ibool)!!comp != index->table->comp) { fputs("InnoDB: 'compact format' flag mismatch\n", stderr); goto func_exit2; } if (!page_simple_validate(page)) { goto func_exit2; } heap = mem_heap_create(UNIV_PAGE_SIZE + 200); /* The following buffer is used to check that the records in the page record heap do not overlap */ buf = mem_heap_alloc(heap, UNIV_PAGE_SIZE); memset(buf, 0, UNIV_PAGE_SIZE); /* Check first that the record heap and the directory do not overlap. */ n_slots = page_dir_get_n_slots(page); if (!(page_header_get_ptr(page, PAGE_HEAP_TOP) <= page_dir_get_nth_slot(page, n_slots - 1))) { fputs("InnoDB: Record heap and dir overlap on a page ", stderr); dict_index_name_print(stderr, NULL, index); fprintf(stderr, ", %p, %p\n", page_header_get_ptr(page, PAGE_HEAP_TOP), page_dir_get_nth_slot(page, n_slots - 1)); goto func_exit; } /* Validate the record list in a loop checking also that it is consistent with the directory. */ count = 0; data_size = 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; offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); if (comp && page_rec_is_user_rec(rec) && rec_get_node_ptr_flag(rec) != (ibool) (btr_page_get_level_low(page) != 0)) { fputs("InnoDB: node_ptr flag mismatch\n", stderr); goto func_exit; } if (!page_rec_validate(rec, offsets)) { goto func_exit; } /* Check that the records are in the ascending order */ if ((count >= 2) && (!page_cur_is_after_last(&cur))) { if (!(1 == cmp_rec_rec(rec, old_rec, offsets, old_offsets, index))) { fprintf(stderr, "InnoDB: Records in wrong order on page %lu", (ulong) buf_frame_get_page_no(page)); dict_index_name_print(stderr, NULL, index); fputs("\nInnoDB: previous record ", stderr); rec_print_new(stderr, old_rec, old_offsets); fputs("\nInnoDB: record ", stderr); rec_print_new(stderr, rec, offsets); putc('\n', stderr); goto func_exit; } } if (page_rec_is_user_rec(rec)) { data_size += rec_offs_size(offsets); } offs = rec_get_start(rec, offsets) - page; for (i = 0; i < rec_offs_size(offsets); i++) { if (!buf[offs + i] == 0) { /* No other record may overlap this */ fputs("InnoDB: Record overlaps another\n", stderr); goto func_exit; } buf[offs + i] = 1; } if (rec_get_n_owned(rec, comp) != 0) { /* This is a record pointed to by a dir slot */ if (rec_get_n_owned(rec, comp) != own_count) { fprintf(stderr, "InnoDB: Wrong owned count %lu, %lu\n", (ulong) rec_get_n_owned(rec, comp), (ulong) own_count); goto func_exit; } if (page_dir_slot_get_rec(slot) != rec) { fputs( "InnoDB: Dir slot does not point to right rec\n", stderr); goto func_exit; } page_dir_slot_check(slot); 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, comp) < FIL_PAGE_DATA || rec_get_next_offs(rec, comp) >= UNIV_PAGE_SIZE) { fprintf(stderr, "InnoDB: Next record offset wrong %lu\n", (ulong) rec_get_next_offs(rec, comp)); goto func_exit; } count++; page_cur_move_to_next(&cur); own_count++; old_rec = rec; /* set old_offsets to offsets; recycle offsets */ { ulint* offs = old_offsets; old_offsets = offsets; offsets = offs; } } if (rec_get_n_owned(rec, comp) == 0) { fputs("InnoDB: n owned is zero\n", stderr); goto func_exit; } if (slot_no != n_slots - 1) { fprintf(stderr, "InnoDB: n slots wrong %lu %lu\n", (ulong) slot_no, (ulong) (n_slots - 1)); goto func_exit; } if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) { fprintf(stderr, "InnoDB: n recs wrong %lu %lu\n", (ulong) page_header_get_field(page, PAGE_N_RECS) + 2, (ulong) (count + 1)); goto func_exit; } if (data_size != page_get_data_size(page)) { fprintf(stderr, "InnoDB: Summed data size %lu, returned by func %lu\n", (ulong) data_size, (ulong) page_get_data_size(page)); goto func_exit; } /* Check then the free list */ rec = page_header_get_ptr(page, PAGE_FREE); while (rec != NULL) { offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); if (!page_rec_validate(rec, offsets)) { goto func_exit; } count++; offs = rec_get_start(rec, offsets) - page; for (i = 0; i < rec_offs_size(offsets); i++) { if (buf[offs + i] != 0) { fputs( "InnoDB: Record overlaps another in free list\n", stderr); goto func_exit; } buf[offs + i] = 1; } rec = page_rec_get_next(rec); } if (page_dir_get_n_heap(page) != count + 1) { fprintf(stderr, "InnoDB: N heap is wrong %lu %lu\n", (ulong) page_dir_get_n_heap(page), (ulong) count + 1); goto func_exit; } ret = TRUE; func_exit: mem_heap_free(heap); if (ret == FALSE) { func_exit2: fprintf(stderr, "InnoDB: Apparent corruption in page %lu in ", (ulong) buf_frame_get_page_no(page)); dict_index_name_print(stderr, NULL, index); putc('\n', stderr); buf_page_print(page); } return(ret); }/*******************************************************************Looks in the page record list for a record with the given heap number. */rec_t*page_find_rec_with_heap_no(/*=======================*/ /* out: record, NULL if not found */ page_t* page, /* in: index page */ ulint heap_no)/* in: heap number */{ page_cur_t cur; page_cur_set_before_first(page, &cur); for (;;) { if (rec_get_heap_no(cur.rec, page_is_comp(page)) == heap_no) { return(cur.rec); } if (page_cur_is_after_last(&cur)) { return(NULL); } page_cur_move_to_next(&cur); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -