📄 page0cur.c
字号:
are no user records, sets the cursor on the infimum record. */voidpage_cur_open_on_rnd_user_rec(/*==========================*/ page_t* page, /* in: page */ page_cur_t* cursor) /* in/out: page cursor */{ ulint rnd; rec_t* rec; if (page_get_n_recs(page) == 0) { page_cur_position(page_get_infimum_rec(page), cursor); return; } page_rnd += 87584577; rnd = page_rnd % page_get_n_recs(page); rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); while (rnd > 0) { rec = page_rec_get_next(rec); rnd--; } page_cur_position(rec, cursor);} /***************************************************************Writes the log record of a record insert on a page. */staticvoidpage_cur_insert_rec_write_log(/*==========================*/ rec_t* insert_rec, /* in: inserted physical record */ ulint rec_size, /* in: insert_rec size */ rec_t* cursor_rec, /* in: record the cursor is pointing to */ dict_index_t* index, /* in: record descriptor */ mtr_t* mtr) /* in: mini-transaction handle */{ ulint cur_rec_size; ulint extra_size; ulint cur_extra_size; ulint min_rec_size; byte* ins_ptr; byte* cur_ptr; ulint extra_info_yes; byte* log_ptr; byte* log_end; ulint i; ulint comp; ut_a(rec_size < UNIV_PAGE_SIZE); ut_ad(buf_frame_align(insert_rec) == buf_frame_align(cursor_rec)); ut_ad(!page_rec_is_comp(insert_rec) == !index->table->comp); comp = page_rec_is_comp(insert_rec); { mem_heap_t* heap = NULL; ulint cur_offs_[REC_OFFS_NORMAL_SIZE]; ulint ins_offs_[REC_OFFS_NORMAL_SIZE]; ulint* cur_offs; ulint* ins_offs; *cur_offs_ = (sizeof cur_offs_) / sizeof *cur_offs_; *ins_offs_ = (sizeof ins_offs_) / sizeof *ins_offs_; cur_offs = rec_get_offsets(cursor_rec, index, cur_offs_, ULINT_UNDEFINED, &heap); ins_offs = rec_get_offsets(insert_rec, index, ins_offs_, ULINT_UNDEFINED, &heap); extra_size = rec_offs_extra_size(ins_offs); cur_extra_size = rec_offs_extra_size(cur_offs); ut_ad(rec_size == rec_offs_size(ins_offs)); cur_rec_size = rec_offs_size(cur_offs); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } } ins_ptr = insert_rec - extra_size; i = 0; if (cur_extra_size == extra_size) { min_rec_size = ut_min(cur_rec_size, rec_size); cur_ptr = cursor_rec - cur_extra_size; /* Find out the first byte in insert_rec which differs from cursor_rec; skip the bytes in the record info */ for (;;) { if (i >= min_rec_size) { break; } else if (*ins_ptr == *cur_ptr) { i++; ins_ptr++; cur_ptr++; } else if ((i < extra_size) && (i >= extra_size - (comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES))) { i = extra_size; ins_ptr = insert_rec; cur_ptr = cursor_rec; } else { break; } } } if (mtr_get_log_mode(mtr) != MTR_LOG_SHORT_INSERTS) { log_ptr = mlog_open_and_write_index(mtr, insert_rec, index, comp ? MLOG_COMP_REC_INSERT : MLOG_REC_INSERT, 2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN); if (!log_ptr) { /* Logging in mtr is switched off during crash recovery: in that case mlog_open returns NULL */ return; } log_end = &log_ptr[2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN]; /* Write the cursor rec offset as a 2-byte ulint */ mach_write_to_2(log_ptr, cursor_rec - buf_frame_align(cursor_rec)); log_ptr += 2; } else { log_ptr = mlog_open(mtr, 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN); if (!log_ptr) { /* Logging in mtr is switched off during crash recovery: in that case mlog_open returns NULL */ return; } log_end = &log_ptr[5 + 1 + 5 + 5 + MLOG_BUF_MARGIN]; } if ((rec_get_info_and_status_bits(insert_rec, comp) != rec_get_info_and_status_bits(cursor_rec, comp)) || (extra_size != cur_extra_size) || (rec_size != cur_rec_size)) { extra_info_yes = 1; } else { extra_info_yes = 0; } /* Write the record end segment length and the extra info storage flag */ log_ptr += mach_write_compressed(log_ptr, 2 * (rec_size - i) + extra_info_yes); if (extra_info_yes) { /* Write the info bits */ mach_write_to_1(log_ptr, rec_get_info_and_status_bits(insert_rec, comp)); log_ptr++; /* Write the record origin offset */ log_ptr += mach_write_compressed(log_ptr, extra_size); /* Write the mismatch index */ log_ptr += mach_write_compressed(log_ptr, i); ut_a(i < UNIV_PAGE_SIZE); ut_a(extra_size < UNIV_PAGE_SIZE); } /* Write to the log the inserted index record end segment which differs from the cursor record */ rec_size -= i; if (log_ptr + rec_size <= log_end) { memcpy(log_ptr, ins_ptr, rec_size); mlog_close(mtr, log_ptr + rec_size); } else { mlog_close(mtr, log_ptr); ut_a(rec_size < UNIV_PAGE_SIZE); mlog_catenate_string(mtr, ins_ptr, rec_size); }} /***************************************************************Parses a log record of a record insert on a page. */byte*page_cur_parse_insert_rec(/*======================*/ /* out: end of log record or NULL */ ibool is_short,/* in: TRUE if short inserts */ 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 extra_info_yes; ulint offset = 0; /* remove warning */ ulint origin_offset; ulint end_seg_len; ulint mismatch_index; rec_t* cursor_rec; byte buf1[1024]; byte* buf; byte* ptr2 = ptr; ulint info_and_status_bits = 0; /* remove warning */ page_cur_t cursor; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_; if (!is_short) { /* Read the cursor rec offset as a 2-byte ulint */ if (end_ptr < ptr + 2) { return(NULL); } offset = mach_read_from_2(ptr); if (offset >= UNIV_PAGE_SIZE) { recv_sys->found_corrupt_log = TRUE; return(NULL); } ptr += 2; } ptr = mach_parse_compressed(ptr, end_ptr, &end_seg_len); if (ptr == NULL) { return(NULL); } extra_info_yes = end_seg_len & 0x1UL; end_seg_len >>= 1; if (end_seg_len >= UNIV_PAGE_SIZE) { recv_sys->found_corrupt_log = TRUE; return(NULL); } if (extra_info_yes) { /* Read the info bits */ if (end_ptr < ptr + 1) { return(NULL); } info_and_status_bits = mach_read_from_1(ptr); ptr++; ptr = mach_parse_compressed(ptr, end_ptr, &origin_offset); if (ptr == NULL) { return(NULL); } ut_a(origin_offset < UNIV_PAGE_SIZE); ptr = mach_parse_compressed(ptr, end_ptr, &mismatch_index); if (ptr == NULL) { return(NULL); } ut_a(mismatch_index < UNIV_PAGE_SIZE); } if (end_ptr < ptr + end_seg_len) { return(NULL); } if (page == NULL) { return(ptr + end_seg_len); } ut_ad(!!page_is_comp(page) == index->table->comp); /* Read from the log the inserted index record end segment which differs from the cursor record */ if (is_short) { cursor_rec = page_rec_get_prev(page_get_supremum_rec(page)); } else { cursor_rec = page + offset; } offsets = rec_get_offsets(cursor_rec, index, offsets, ULINT_UNDEFINED, &heap); if (extra_info_yes == 0) { info_and_status_bits = rec_get_info_and_status_bits( cursor_rec, page_is_comp(page)); origin_offset = rec_offs_extra_size(offsets); mismatch_index = rec_offs_size(offsets) - end_seg_len; } if (mismatch_index + end_seg_len < sizeof buf1) { buf = buf1; } else { buf = mem_alloc(mismatch_index + end_seg_len); } /* Build the inserted record to buf */ if (mismatch_index >= UNIV_PAGE_SIZE) { fprintf(stderr, "Is short %lu, info_and_status_bits %lu, offset %lu, " "o_offset %lu\n" "mismatch index %lu, end_seg_len %lu\n" "parsed len %lu\n", (ulong) is_short, (ulong) info_and_status_bits, (ulong) offset, (ulong) origin_offset, (ulong) mismatch_index, (ulong) end_seg_len, (ulong) (ptr - ptr2)); fputs("Dump of 300 bytes of log:\n", stderr); ut_print_buf(stderr, ptr2, 300); buf_page_print(page); ut_error; } ut_memcpy(buf, rec_get_start(cursor_rec, offsets), mismatch_index); ut_memcpy(buf + mismatch_index, ptr, end_seg_len); rec_set_info_and_status_bits(buf + origin_offset, page_is_comp(page), info_and_status_bits); page_cur_position(cursor_rec, &cursor); offsets = rec_get_offsets(buf + origin_offset, index, offsets, ULINT_UNDEFINED, &heap); page_cur_rec_insert(&cursor, buf + origin_offset, index, offsets, mtr); if (buf != buf1) { mem_free(buf); } if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(ptr + end_seg_len);} /***************************************************************Inserts a record next to page cursor. Returns pointer to inserted record ifsucceed, i.e., enough space available, NULL otherwise. The record to beinserted can be in a data tuple or as a physical record. The other parametermust then be NULL. The cursor stays at the same position. */rec_t*page_cur_insert_rec_low(/*====================*/ /* out: pointer to record if succeed, NULL otherwise */ page_cur_t* cursor, /* in: a page cursor */ dtuple_t* tuple, /* in: pointer to a data tuple or NULL */ dict_index_t* index, /* in: record descriptor */ rec_t* rec, /* in: pointer to a physical record or NULL */ ulint* offsets,/* in: rec_get_offsets(rec, index) or NULL */ mtr_t* mtr) /* in: mini-transaction handle */{ byte* insert_buf = NULL; ulint rec_size; byte* page; /* the relevant page */ rec_t* last_insert; /* cursor position at previous insert */ rec_t* insert_rec; /* inserted record */ ulint heap_no; /* heap number of the inserted record */ rec_t* current_rec; /* current record after which the new record is inserted */ rec_t* next_rec; /* next record after current before the insertion */ ulint owner_slot; /* the slot which owns the inserted record */ rec_t* owner_rec; ulint n_owned; mem_heap_t* heap = NULL; ulint comp; ut_ad(cursor && mtr); ut_ad(tuple || rec); ut_ad(!(tuple && rec)); ut_ad(rec || dtuple_check_typed(tuple)); page = page_cur_get_page(cursor); comp = page_is_comp(page); ut_ad(index->table->comp == !!comp); ut_ad(cursor->rec != page_get_supremum_rec(page)); /* 1. Get the size of the physical record in the page */ if (tuple != NULL) { rec_size = rec_get_converted_size(index, tuple); } else { if (!offsets) { offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); } ut_ad(rec_offs_validate(rec, index, offsets)); rec_size = rec_offs_size(offsets); } /* 2. Try to find suitable space from page memory management */ insert_buf = page_mem_alloc(page, rec_size, index, &heap_no); if (insert_buf == NULL) { if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return(NULL); } /* 3. Create the record */ if (tuple != NULL) { insert_rec = rec_convert_dtuple_to_rec(insert_buf, index, tuple); offsets = rec_get_offsets(insert_rec, index, offsets, ULINT_UNDEFINED, &heap); } else { insert_rec = rec_copy(insert_buf, rec, offsets); ut_ad(rec_offs_validate(rec, index, offsets)); rec_offs_make_valid(insert_rec, index, offsets); } ut_ad(insert_rec); ut_ad(rec_size == rec_offs_size(offsets)); /* 4. Insert the record in the linked list of records */ current_rec = cursor->rec; ut_ad(!comp || rec_get_status(current_rec) <= REC_STATUS_INFIMUM); ut_ad(!comp || rec_get_status(insert_rec) < REC_STATUS_INFIMUM); next_rec = page_rec_get_next(current_rec); ut_ad(!comp || rec_get_status(next_rec) != REC_STATUS_INFIMUM); page_rec_set_next(insert_rec, next_rec); page_rec_set_next(current_rec, insert_rec); page_header_set_field(page, PAGE_N_RECS, 1 + page_get_n_recs(page)); /* 5. Set the n_owned field in the inserted record to zero, and set the heap_no field */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -