📄 fsp0fsp.c
字号:
extent containing a descriptor page is added to the FREE_FRAG list. But we will allocate our page from the the free extent anyway. */ descr = fsp_alloc_free_extent(space, hint, mtr); if (descr == NULL) { /* No free space left */ return(FIL_NULL); } xdes_set_state(descr, XDES_FREE_FRAG, mtr); flst_add_last(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, mtr); } else { descr = xdes_lst_get_descriptor(space, first, mtr); } /* Reset the hint */ hint = 0; } /* Now we have in descr an extent with at least one free page. Look for a free page in the extent. */ free = xdes_find_bit(descr, XDES_FREE_BIT, TRUE, hint % FSP_EXTENT_SIZE, mtr); if (free == ULINT_UNDEFINED) { ut_print_buf(stderr, ((byte*)descr) - 500, 1000); ut_error; } page_no = xdes_get_offset(descr) + free; space_size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); if (space_size <= page_no) { /* It must be that we are extending a single-table tablespace whose size is still < 64 pages */ ut_a(space != 0); if (page_no >= FSP_EXTENT_SIZE) { fprintf(stderr,"InnoDB: Error: trying to extend a single-table tablespace %lu\n""InnoDB: by single page(s) though the space size %lu. Page no %lu.\n", (ulong) space, (ulong) space_size, (ulong) page_no); return(FIL_NULL); } success = fsp_try_extend_data_file_with_pages(space, page_no, header, mtr); if (!success) { /* No disk space left */ return(FIL_NULL); } } xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr); /* Update the FRAG_N_USED field */ frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES, mtr); frag_n_used++; mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES, mtr); if (xdes_is_full(descr, mtr)) { /* The fragment is full: move it to another list */ flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, mtr); xdes_set_state(descr, XDES_FULL_FRAG, mtr); flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE, mtr); mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES, mtr); } /* Initialize the allocated page to the buffer pool, so that it can be obtained immediately with buf_page_get without need for a disk read. */ buf_page_create(space, page_no, mtr); page = buf_page_get(space, page_no, RW_X_LATCH, mtr); #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_FSP_PAGE);#endif /* UNIV_SYNC_DEBUG */ /* Prior contents of the page should be ignored */ fsp_init_file_page(page, mtr); return(page_no);}/**************************************************************************Frees a single page of a space. The page is marked as free and clean. */staticvoidfsp_free_page(/*==========*/ ulint space, /* in: space id */ ulint page, /* in: page offset */ mtr_t* mtr) /* in: mtr handle */{ fsp_header_t* header; xdes_t* descr; ulint state; ulint frag_n_used; ut_ad(mtr);/* fprintf(stderr, "Freeing page %lu in space %lu\n", page, space); */ header = fsp_get_space_header(space, mtr); descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr); state = xdes_get_state(descr, mtr); if (state != XDES_FREE_FRAG && state != XDES_FULL_FRAG) { fprintf(stderr,"InnoDB: Error: File space extent descriptor of page %lu has state %lu\n", (ulong) page, (ulong) state); fputs("InnoDB: Dump of descriptor: ", stderr); ut_print_buf(stderr, ((byte*)descr) - 50, 200); putc('\n', stderr); if (state == XDES_FREE) { /* We put here some fault tolerance: if the page is already free, return without doing anything! */ return; } ut_error; } if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)) { fprintf(stderr,"InnoDB: Error: File space extent descriptor of page %lu says it is free\n""InnoDB: Dump of descriptor: ", (ulong) page); ut_print_buf(stderr, ((byte*)descr) - 50, 200); putc('\n', stderr); /* We put here some fault tolerance: if the page is already free, return without doing anything! */ return; } xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr); xdes_set_bit(descr, XDES_CLEAN_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr); frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES, mtr); if (state == XDES_FULL_FRAG) { /* The fragment was full: move it to another list */ flst_remove(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE, mtr); xdes_set_state(descr, XDES_FREE_FRAG, mtr); flst_add_last(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, mtr); mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used + FSP_EXTENT_SIZE - 1, MLOG_4BYTES, mtr); } else { ut_a(frag_n_used > 0); mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used - 1, MLOG_4BYTES, mtr); } if (xdes_is_free(descr, mtr)) { /* The extent has become free: move it to another list */ flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, mtr); fsp_free_extent(space, page, mtr); } }/**************************************************************************Returns an extent to the free list of a space. */staticvoidfsp_free_extent(/*============*/ ulint space, /* in: space id */ ulint page, /* in: page offset in the extent */ mtr_t* mtr) /* in: mtr */{ fsp_header_t* header; xdes_t* descr; ut_ad(mtr); header = fsp_get_space_header(space, mtr); descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr); if (xdes_get_state(descr, mtr) == XDES_FREE) { ut_print_buf(stderr, (byte*)descr - 500, 1000); ut_error; } xdes_init(descr, mtr); flst_add_last(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);}/**************************************************************************Returns the nth inode slot on an inode page. */UNIV_INLINEfseg_inode_t*fsp_seg_inode_page_get_nth_inode(/*=============================*/ /* out: segment inode */ page_t* page, /* in: segment inode page */ ulint i, /* in: inode index on page */ mtr_t* mtr __attribute__((unused))) /* in: mini-transaction handle */{ ut_ad(i < FSP_SEG_INODES_PER_PAGE); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); return(page + FSEG_ARR_OFFSET + FSEG_INODE_SIZE * i);}/**************************************************************************Looks for a used segment inode on a segment inode page. */ staticulintfsp_seg_inode_page_find_used(/*=========================*/ /* out: segment inode index, or ULINT_UNDEFINED if not found */ page_t* page, /* in: segment inode page */ mtr_t* mtr) /* in: mini-transaction handle */{ ulint i; fseg_inode_t* inode; for (i = 0; i < FSP_SEG_INODES_PER_PAGE; i++) { inode = fsp_seg_inode_page_get_nth_inode(page, i, mtr); if (ut_dulint_cmp(mach_read_from_8(inode + FSEG_ID), ut_dulint_zero) != 0) { /* This is used */ return(i); } } return(ULINT_UNDEFINED);}/**************************************************************************Looks for an unused segment inode on a segment inode page. */ staticulintfsp_seg_inode_page_find_free(/*=========================*/ /* out: segment inode index, or ULINT_UNDEFINED if not found */ page_t* page, /* in: segment inode page */ ulint j, /* in: search forward starting from this index */ mtr_t* mtr) /* in: mini-transaction handle */{ ulint i; fseg_inode_t* inode; for (i = j; i < FSP_SEG_INODES_PER_PAGE; i++) { inode = fsp_seg_inode_page_get_nth_inode(page, i, mtr); if (ut_dulint_cmp(mach_read_from_8(inode + FSEG_ID), ut_dulint_zero) == 0) { /* This is unused */ return(i); } } return(ULINT_UNDEFINED);}/**************************************************************************Allocates a new file segment inode page. */staticiboolfsp_alloc_seg_inode_page(/*=====================*/ /* out: TRUE if could be allocated */ fsp_header_t* space_header, /* in: space header */ mtr_t* mtr) /* in: mini-transaction handle */{ fseg_inode_t* inode; page_t* page; ulint page_no; ulint space; ulint i; space = buf_frame_get_space_id(space_header); page_no = fsp_alloc_free_page(space, 0, mtr); if (page_no == FIL_NULL) { return(FALSE); } page = buf_page_get(space, page_no, RW_X_LATCH, mtr); buf_block_align(page)->check_index_page_at_flush = FALSE; fil_page_set_type(page, FIL_PAGE_INODE);#ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_FSP_PAGE);#endif /* UNIV_SYNC_DEBUG */ for (i = 0; i < FSP_SEG_INODES_PER_PAGE; i++) { inode = fsp_seg_inode_page_get_nth_inode(page, i, mtr); mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr); } flst_add_last(space_header + FSP_SEG_INODES_FREE, page + FSEG_INODE_PAGE_NODE, mtr); return(TRUE);}/**************************************************************************Allocates a new file segment inode. */staticfseg_inode_t*fsp_alloc_seg_inode(/*================*/ /* out: segment inode, or NULL if not enough space */ fsp_header_t* space_header, /* in: space header */ mtr_t* mtr) /* in: mini-transaction handle */{ ulint page_no; page_t* page; fseg_inode_t* inode; ibool success; ulint n; if (flst_get_len(space_header + FSP_SEG_INODES_FREE, mtr) == 0) { /* Allocate a new segment inode page */ success = fsp_alloc_seg_inode_page(space_header, mtr); if (!success) { return(NULL); } } page_no = flst_get_first(space_header + FSP_SEG_INODES_FREE, mtr).page; page = buf_page_get(buf_frame_get_space_id(space_header), page_no, RW_X_LATCH, mtr);#ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(page, SYNC_FSP_PAGE);#endif /* UNIV_SYNC_DEBUG */ n = fsp_seg_inode_page_find_free(page, 0, mtr); ut_a(n != ULINT_UNDEFINED); inode = fsp_seg_inode_page_get_nth_inode(page, n, mtr); if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, n + 1, mtr)) { /* There are no other unused headers left on the page: move it to another list */ flst_remove(space_header + FSP_SEG_INODES_FREE, page + FSEG_INODE_PAGE_NODE, mtr); flst_add_last(space_header + FSP_SEG_INODES_FULL, page + FSEG_INODE_PAGE_NODE, mtr); } return(inode); }/**************************************************************************Frees a file segment inode. */staticvoidfsp_free_seg_inode(/*===============*/ ulint space, /* in: space id */ fseg_inode_t* inode, /* in: segment inode */ mtr_t* mtr) /* in: mini-transaction handle */{ page_t* page; fsp_header_t* space_header; page = buf_frame_align(inode); space_header = fsp_get_space_header(space, mtr); ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, 0, mtr)) { /* Move the page to another list */ flst_remove(space_header + FSP_SEG_INODES_FULL, page + FSEG_INODE_PAGE_NODE, mtr); flst_add_last(space_header + FSP_SEG_INODES_FREE, page + FSEG_INODE_PAGE_NODE, mtr); } mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr); mlog_write_ulint(inode + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr); if (ULINT_UNDEFINED == fsp_seg_inode_page_find_used(page, mtr)) { /* There are no other used headers left on the page: free it */ flst_remove(space_header + FSP_SEG_INODES_FREE, page + FSEG_INODE_PAGE_NODE, mtr); fsp_free_page(space, buf_frame_get_page_no(page), mtr); }}/**************************************************************************Returns the file segment inode, page x-latched. */staticfseg_inode_t*fseg_inode_get(/*===========*/ /* out: segment inode, page x-latched */ fseg_header_t* header, /* in: segment header */ mtr_t* mtr) /* in: mtr handle */{ fil_addr_t inode_addr; fseg_inode_t* inode; inode_addr.page = mach_read_from_4(header + FSEG_HDR_PAGE_NO); inode_addr.boffset = mach_read_from_2(header + FSEG_HDR_OFFSET); inode = fut_get_ptr(mach_read_from_4(header + FSEG_HDR_SPACE), inode_addr, RW_X_LATCH, mtr); ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); return(inode);}/**************************************************************************Gets the page number from the nth fragment page slot. */UNIV_INLINEulint
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -