📄 page0page.c
字号:
break; } offsets = rec_get_offsets(cur1_rec, index, offsets, ULINT_UNDEFINED, &heap); if (UNIV_UNLIKELY(!page_cur_rec_insert(&cur2, cur1_rec, index, offsets, mtr))) { /* Track an assertion failure reported on the mailing list on June 18th, 2003 */ buf_page_print(new_page); buf_page_print(page); ut_print_timestamp(stderr); fprintf(stderr,"InnoDB: rec offset %lu, cur1 offset %lu, cur2 offset %lu\n", (ulong)(rec - page), (ulong)(page_cur_get_rec(&cur1) - page), (ulong)(page_cur_get_rec(&cur2) - new_page)); ut_error; } page_cur_move_to_next(&cur1); page_cur_move_to_next(&cur2); } if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); }}/*****************************************************************Copies records from page to new_page, from a given record onward,including that record. Infimum and supremum records are not copied.The records are copied to the start of the record list on new_page. */voidpage_copy_rec_list_end(/*===================*/ page_t* new_page, /* in: index page to copy to */ page_t* page, /* in: index page */ rec_t* rec, /* in: record on page */ dict_index_t* index, /* in: record descriptor */ mtr_t* mtr) /* in: mtr */{ if (page_dir_get_n_heap(new_page) == 2) { page_copy_rec_list_end_to_created_page(new_page, page, rec, index, mtr); } else { page_copy_rec_list_end_no_locks(new_page, page, rec, index, mtr); } /* Update the lock table, MAX_TRX_ID, and possible hash index */ lock_move_rec_list_end(new_page, page, rec); page_update_max_trx_id(new_page, page_get_max_trx_id(page)); btr_search_move_or_delete_hash_entries(new_page, page, index);} /*****************************************************************Copies records from page to new_page, up to the given record,NOT including that record. Infimum and supremum records are not copied.The records are copied to the end of the record list on new_page. */voidpage_copy_rec_list_start(/*=====================*/ page_t* new_page, /* in: index page to copy to */ page_t* page, /* in: index page */ rec_t* rec, /* in: record on page */ dict_index_t* index, /* in: record descriptor */ mtr_t* mtr) /* in: mtr */{ page_cur_t cur1; page_cur_t cur2; rec_t* old_end; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_; page_cur_set_before_first(page, &cur1); if (rec == page_cur_get_rec(&cur1)) { return; } page_cur_move_to_next(&cur1); page_cur_set_after_last(new_page, &cur2); page_cur_move_to_prev(&cur2); old_end = page_cur_get_rec(&cur2); /* Copy records from the original page to the new page */ while (page_cur_get_rec(&cur1) != rec) { rec_t* ins_rec; rec_t* cur1_rec = page_cur_get_rec(&cur1); offsets = rec_get_offsets(cur1_rec, index, offsets, ULINT_UNDEFINED, &heap); ins_rec = page_cur_rec_insert(&cur2, cur1_rec, index, offsets, mtr); ut_a(ins_rec); page_cur_move_to_next(&cur1); page_cur_move_to_next(&cur2); } /* Update the lock table, MAX_TRX_ID, and possible hash index */ lock_move_rec_list_start(new_page, page, rec, old_end); page_update_max_trx_id(new_page, page_get_max_trx_id(page)); btr_search_move_or_delete_hash_entries(new_page, page, index); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); }}/**************************************************************Writes a log record of a record list end or start deletion. */UNIV_INLINEvoidpage_delete_rec_list_write_log(/*===========================*/ rec_t* rec, /* in: record on page */ dict_index_t* index, /* in: record descriptor */ byte type, /* in: operation type: MLOG_LIST_END_DELETE, ... */ mtr_t* mtr) /* in: mtr */{ byte* log_ptr; ut_ad(type == MLOG_LIST_END_DELETE || type == MLOG_LIST_START_DELETE || type == MLOG_COMP_LIST_END_DELETE || type == MLOG_COMP_LIST_START_DELETE); log_ptr = mlog_open_and_write_index(mtr, rec, index, type, 2); if (log_ptr) { /* Write the parameter as a 2-byte ulint */ mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE)); mlog_close(mtr, log_ptr + 2); }}/**************************************************************Parses a log record of a record list end or start deletion. */byte*page_parse_delete_rec_list(/*=======================*/ /* out: end of log record or NULL */ byte type, /* in: MLOG_LIST_END_DELETE, MLOG_LIST_START_DELETE, MLOG_COMP_LIST_END_DELETE or MLOG_COMP_LIST_START_DELETE */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ dict_index_t* index, /* in: record descriptor */ page_t* page, /* in: page or NULL */ mtr_t* mtr) /* in: mtr or NULL */{ ulint offset; ut_ad(type == MLOG_LIST_END_DELETE || type == MLOG_LIST_START_DELETE || type == MLOG_COMP_LIST_END_DELETE || type == MLOG_COMP_LIST_START_DELETE); /* Read the record offset as a 2-byte ulint */ if (end_ptr < ptr + 2) { return(NULL); } offset = mach_read_from_2(ptr); ptr += 2; if (!page) { return(ptr); } ut_ad(!!page_is_comp(page) == index->table->comp); if (type == MLOG_LIST_END_DELETE || type == MLOG_COMP_LIST_END_DELETE) { page_delete_rec_list_end(page, page + offset, index, ULINT_UNDEFINED, ULINT_UNDEFINED, mtr); } else { page_delete_rec_list_start(page, page + offset, index, mtr); } return(ptr);}/*****************************************************************Deletes records from a page from a given record onward, including that record.The infimum and supremum records are not deleted. */voidpage_delete_rec_list_end(/*=====================*/ page_t* page, /* in: index page */ rec_t* rec, /* in: record on page */ dict_index_t* index, /* in: record descriptor */ ulint n_recs, /* in: number of records to delete, or ULINT_UNDEFINED if not known */ ulint size, /* in: the sum of the sizes of the records in the end of the chain to delete, or ULINT_UNDEFINED if not known */ mtr_t* mtr) /* in: mtr */{ page_dir_slot_t* slot; ulint slot_index; rec_t* last_rec; rec_t* prev_rec; rec_t* free; rec_t* rec2; ulint count; ulint n_owned; rec_t* sup; ulint comp; /* Reset the last insert info in the page header and increment the modify clock for the frame */ ut_ad(size == ULINT_UNDEFINED || size < UNIV_PAGE_SIZE); page_header_set_ptr(page, PAGE_LAST_INSERT, NULL); /* The page gets invalid for optimistic searches: increment the frame modify clock */ buf_frame_modify_clock_inc(page); sup = page_get_supremum_rec(page); comp = page_is_comp(page); if (page_rec_is_infimum_low(rec - page)) { rec = page_rec_get_next(rec); } page_delete_rec_list_write_log(rec, index, comp ? MLOG_COMP_LIST_END_DELETE : MLOG_LIST_END_DELETE, mtr); if (rec == sup) { return; } prev_rec = page_rec_get_prev(rec); last_rec = page_rec_get_prev(sup); if ((size == ULINT_UNDEFINED) || (n_recs == ULINT_UNDEFINED)) { mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_; /* Calculate the sum of sizes and the number of records */ size = 0; n_recs = 0; rec2 = rec; while (rec2 != sup) { ulint s; offsets = rec_get_offsets(rec2, index, offsets, ULINT_UNDEFINED, &heap); s = rec_offs_size(offsets); ut_ad(rec2 - page + s - rec_offs_extra_size(offsets) < UNIV_PAGE_SIZE); ut_ad(size + s < UNIV_PAGE_SIZE); size += s; n_recs++; rec2 = page_rec_get_next(rec2); } if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } ut_ad(size < UNIV_PAGE_SIZE); /* Update the page directory; there is no need to balance the number of the records owned by the supremum record, as it is allowed to be less than PAGE_DIR_SLOT_MIN_N_OWNED */ rec2 = rec; count = 0; while (rec_get_n_owned(rec2, comp) == 0) { count++; rec2 = page_rec_get_next(rec2); } ut_ad(rec_get_n_owned(rec2, comp) - count > 0); n_owned = rec_get_n_owned(rec2, comp) - count; slot_index = page_dir_find_owner_slot(rec2); slot = page_dir_get_nth_slot(page, slot_index); page_dir_slot_set_rec(slot, sup); page_dir_slot_set_n_owned(slot, n_owned); page_dir_set_n_slots(page, slot_index + 1); /* Remove the record chain segment from the record chain */ page_rec_set_next(prev_rec, page_get_supremum_rec(page)); /* Catenate the deleted chain segment to the page free list */ free = page_header_get_ptr(page, PAGE_FREE); page_rec_set_next(last_rec, free); page_header_set_ptr(page, PAGE_FREE, rec); page_header_set_field(page, PAGE_GARBAGE, size + page_header_get_field(page, PAGE_GARBAGE)); page_header_set_field(page, PAGE_N_RECS, (ulint)(page_get_n_recs(page) - n_recs));} /*****************************************************************Deletes records from page, up to the given record, NOT includingthat record. Infimum and supremum records are not deleted. */voidpage_delete_rec_list_start(/*=======================*/ page_t* page, /* in: index page */ rec_t* rec, /* in: record on page */ dict_index_t* index, /* in: record descriptor */ mtr_t* mtr) /* in: mtr */{ page_cur_t cur1; ulint log_mode; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; mem_heap_t* heap = NULL; byte type; *offsets_ = (sizeof offsets_) / sizeof *offsets_; ut_ad(!!page_is_comp(page) == index->table->comp); if (page_is_comp(page)) { type = MLOG_COMP_LIST_START_DELETE; } else { type = MLOG_LIST_START_DELETE; } page_delete_rec_list_write_log(rec, index, type, mtr); page_cur_set_before_first(page, &cur1); if (rec == page_cur_get_rec(&cur1)) { return; } page_cur_move_to_next(&cur1); /* Individual deletes are not logged */ log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); while (page_cur_get_rec(&cur1) != rec) { offsets = rec_get_offsets(page_cur_get_rec(&cur1), index, offsets, ULINT_UNDEFINED, &heap); page_cur_delete_rec(&cur1, index, offsets, mtr); } if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } /* Restore log mode */ mtr_set_log_mode(mtr, log_mode);} /*****************************************************************Moves record list end to another page. Moved records includesplit_rec. */voidpage_move_rec_list_end(/*===================*/ page_t* new_page, /* in: index page where to move */ page_t* page, /* in: index page */ rec_t* split_rec, /* in: first record to move */ dict_index_t* index, /* in: record descriptor */ mtr_t* mtr) /* in: mtr */{ ulint old_data_size; ulint new_data_size; ulint old_n_recs; ulint new_n_recs; old_data_size = page_get_data_size(new_page); old_n_recs = page_get_n_recs(new_page); page_copy_rec_list_end(new_page, page, split_rec, index, mtr); new_data_size = page_get_data_size(new_page); new_n_recs = page_get_n_recs(new_page); ut_ad(new_data_size >= old_data_size); page_delete_rec_list_end(page, split_rec, index, new_n_recs - old_n_recs, new_data_size - old_data_size, mtr);}/*****************************************************************Moves record list start to another page. Moved records do not includesplit_rec. */voidpage_move_rec_list_start(/*=====================*/ page_t* new_page, /* in: index page where to move */ page_t* page, /* in: index page */ rec_t* split_rec, /* in: first record not to move */ dict_index_t* index, /* in: record descriptor */ mtr_t* mtr) /* in: mtr */{ page_copy_rec_list_start(new_page, page, split_rec, index, mtr); page_delete_rec_list_start(page, split_rec, index, mtr);}/***************************************************************************This is a low-level operation which is used in a database index creationto update the page number of a created B-tree to a data dictionary record. */voidpage_rec_write_index_page_no(/*=========================*/ rec_t* rec, /* in: record to update */ ulint i, /* in: index of the field to update */ ulint page_no,/* in: value to write */ mtr_t* mtr) /* in: mtr */{ byte* data; ulint len; data = rec_get_nth_field_old(rec, i, &len); ut_ad(len == 4); mlog_write_ulint(data, page_no, MLOG_4BYTES, mtr);}/******************************************************************Used to delete n slots from the directory. This function updatesalso n_owned fields in the records, so that the first slot afterthe deleted ones inherits the records of the deleted slots. */UNIV_INLINEvoidpage_dir_delete_slots(/*==================*/ page_t* page, /* in: the index page */ ulint start, /* in: first slot to be deleted */ ulint n) /* in: number of slots to delete (currently only n == 1 allowed) */{ page_dir_slot_t* slot; ulint i; ulint sum_owned = 0; ulint n_slots; rec_t* rec; ut_ad(n == 1); ut_ad(start > 0); ut_ad(start + n < page_dir_get_n_slots(page)); n_slots = page_dir_get_n_slots(page); /* 1. Reset the n_owned fields of the slots to be deleted */ for (i = start; i < start + n; i++) { slot = page_dir_get_nth_slot(page, i); sum_owned += page_dir_slot_get_n_owned(slot); page_dir_slot_set_n_owned(slot, 0); } /* 2. Update the n_owned value of the first non-deleted slot */ slot = page_dir_get_nth_slot(page, start + n); page_dir_slot_set_n_owned(slot,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -