📄 fsp0fsp.c
字号:
id = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); if (id != fsp_id) { fprintf(stderr,"InnoDB: Error: space id in fsp header %lu, but in the page header %lu\n", (ulong) fsp_id, (ulong) id); return(ULINT_UNDEFINED); } return(id);}/**************************************************************************Increases the space size field of a space. */voidfsp_header_inc_size(/*================*/ ulint space, /* in: space id */ ulint size_inc,/* in: size increment in pages */ mtr_t* mtr) /* in: mini-transaction handle */ { fsp_header_t* header; ulint size; ut_ad(mtr); mtr_x_lock(fil_space_get_latch(space), mtr); header = fsp_get_space_header(space, mtr); size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); mlog_write_ulint(header + FSP_SIZE, size + size_inc, MLOG_4BYTES, mtr); }/**************************************************************************Gets the current free limit of a tablespace. The free limit means theplace of the first page which has never been put to the the free listfor allocation. The space above that address is initialized to zero.Sets also the global variable log_fsp_current_free_limit. */ulintfsp_header_get_free_limit(/*======================*/ /* out: free limit in megabytes */ ulint space) /* in: space id, must be 0 */{ fsp_header_t* header; ulint limit; mtr_t mtr; ut_a(space == 0); /* We have only one log_fsp_current_... variable */ mtr_start(&mtr); mtr_x_lock(fil_space_get_latch(space), &mtr); header = fsp_get_space_header(space, &mtr); limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, &mtr); limit = limit / ((1024 * 1024) / UNIV_PAGE_SIZE); log_fsp_current_free_limit_set_and_checkpoint(limit); mtr_commit(&mtr); return(limit);}/**************************************************************************Gets the size of the tablespace from the tablespace header. If we do nothave an auto-extending data file, this should be equal to the size of thedata files. If there is an auto-extending data file, this can be smaller. */ulintfsp_header_get_tablespace_size(/*===========================*/ /* out: size in pages */ ulint space) /* in: space id, must be 0 */{ fsp_header_t* header; ulint size; mtr_t mtr; ut_a(space == 0); /* We have only one log_fsp_current_... variable */ mtr_start(&mtr); mtr_x_lock(fil_space_get_latch(space), &mtr); header = fsp_get_space_header(space, &mtr); size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr); mtr_commit(&mtr); return(size);}/***************************************************************************Tries to extend a single-table tablespace so that a page would fit in thedata file. */staticiboolfsp_try_extend_data_file_with_pages(/*================================*/ /* out: TRUE if success */ ulint space, /* in: space */ ulint page_no, /* in: page number */ fsp_header_t* header, /* in: space header */ mtr_t* mtr) /* in: mtr */{ ibool success; ulint actual_size; ulint size; ut_a(space != 0); size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); ut_a(page_no >= size); success = fil_extend_space_to_desired_size(&actual_size, space, page_no + 1); /* actual_size now has the space size in pages; it may be less than we wanted if we ran out of disk space */ mlog_write_ulint(header + FSP_SIZE, actual_size, MLOG_4BYTES, mtr); return(success);}/***************************************************************************Tries to extend the last data file of a tablespace if it is auto-extending. */staticiboolfsp_try_extend_data_file(/*=====================*/ /* out: FALSE if not auto-extending */ ulint* actual_increase,/* out: actual increase in pages, where we measure the tablespace size from what the header field says; it may be the actual file size rounded down to megabyte */ ulint space, /* in: space */ fsp_header_t* header, /* in: space header */ mtr_t* mtr) /* in: mtr */{ ulint size; ulint new_size; ulint old_size; ulint size_increase; ulint actual_size; ibool success; *actual_increase = 0; if (space == 0 && !srv_auto_extend_last_data_file) { return(FALSE); } size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); old_size = size; if (space == 0 && srv_last_file_size_max != 0) { if (srv_last_file_size_max < srv_data_file_sizes[srv_n_data_files - 1]) { fprintf(stderr,"InnoDB: Error: Last data file size is %lu, max size allowed %lu\n", (ulong) srv_data_file_sizes[srv_n_data_files - 1], (ulong) srv_last_file_size_max); } size_increase = srv_last_file_size_max - srv_data_file_sizes[srv_n_data_files - 1]; if (size_increase > SRV_AUTO_EXTEND_INCREMENT) { size_increase = SRV_AUTO_EXTEND_INCREMENT; } } else { if (space == 0) { size_increase = SRV_AUTO_EXTEND_INCREMENT; } else { /* We extend single-table tablespaces first one extent at a time, but for bigger tablespaces more. It is not enough to extend always by one extent, because some extents are frag page extents. */ if (size < FSP_EXTENT_SIZE) { /* Let us first extend the file to 64 pages */ success = fsp_try_extend_data_file_with_pages( space, FSP_EXTENT_SIZE - 1, header, mtr); if (!success) { new_size = mtr_read_ulint( header + FSP_SIZE, MLOG_4BYTES, mtr); *actual_increase = new_size - old_size; return(FALSE); } size = FSP_EXTENT_SIZE; } if (size < 32 * FSP_EXTENT_SIZE) { size_increase = FSP_EXTENT_SIZE; } else { /* Below in fsp_fill_free_list() we assume that we add at most FSP_FREE_ADD extents at a time */ size_increase = FSP_FREE_ADD * FSP_EXTENT_SIZE; } } } if (size_increase == 0) { return(TRUE); } success = fil_extend_space_to_desired_size(&actual_size, space, size + size_increase); /* We ignore any fragments of a full megabyte when storing the size to the space header */ mlog_write_ulint(header + FSP_SIZE, ut_calc_align_down(actual_size, (1024 * 1024) / UNIV_PAGE_SIZE), MLOG_4BYTES, mtr); new_size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); *actual_increase = new_size - old_size; return(TRUE);}/**************************************************************************Puts new extents to the free list if there are free extents above the freelimit. If an extent happens to contain an extent descriptor page, the extentis put to the FSP_FREE_FRAG list with the page marked as used. */staticvoidfsp_fill_free_list(/*===============*/ ibool init_space, /* in: TRUE if this is a single-table tablespace and we are only initing the tablespace's first extent descriptor page and ibuf bitmap page; then we do not allocate more extents */ ulint space, /* in: space */ fsp_header_t* header, /* in: space header */ mtr_t* mtr) /* in: mtr */{ ulint limit; ulint size; xdes_t* descr; ulint count = 0; ulint frag_n_used; page_t* descr_page; page_t* ibuf_page; ulint actual_increase; ulint i; mtr_t ibuf_mtr; ut_ad(header && mtr); /* Check if we can fill free list from above the free list limit */ size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr); if (space == 0 && srv_auto_extend_last_data_file && size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) { /* Try to increase the last data file size */ fsp_try_extend_data_file(&actual_increase, space, header, mtr); size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); } if (space != 0 && !init_space && size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) { /* Try to increase the .ibd file size */ fsp_try_extend_data_file(&actual_increase, space, header, mtr); size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); } i = limit; while ((init_space && i < 1) || ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) { mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE, MLOG_4BYTES, mtr); /* Update the free limit info in the log system and make a checkpoint */ if (space == 0) { log_fsp_current_free_limit_set_and_checkpoint( (i + FSP_EXTENT_SIZE) / ((1024 * 1024) / UNIV_PAGE_SIZE)); } if (0 == i % XDES_DESCRIBED_PER_PAGE) { /* We are going to initialize a new descriptor page and a new ibuf bitmap page: the prior contents of the pages should be ignored. */ if (i > 0) { descr_page = buf_page_create(space, i, mtr); buf_page_get(space, i, RW_X_LATCH, mtr);#ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(descr_page, SYNC_FSP_PAGE);#endif /* UNIV_SYNC_DEBUG */ fsp_init_file_page(descr_page, mtr); } /* Initialize the ibuf bitmap page in a separate mini-transaction because it is low in the latching order, and we must be able to release its latch before returning from the fsp routine */ mtr_start(&ibuf_mtr); ibuf_page = buf_page_create(space, i + FSP_IBUF_BITMAP_OFFSET, &ibuf_mtr); buf_page_get(space, i + FSP_IBUF_BITMAP_OFFSET, RW_X_LATCH, &ibuf_mtr);#ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(ibuf_page, SYNC_FSP_PAGE);#endif /* UNIV_SYNC_DEBUG */ fsp_init_file_page(ibuf_page, &ibuf_mtr); ibuf_bitmap_page_init(ibuf_page, &ibuf_mtr); mtr_commit(&ibuf_mtr); } descr = xdes_get_descriptor_with_space_hdr(header, space, i, mtr); xdes_init(descr, mtr); ut_ad(XDES_DESCRIBED_PER_PAGE % FSP_EXTENT_SIZE == 0); if (0 == i % XDES_DESCRIBED_PER_PAGE) { /* The first page in the extent is a descriptor page and the second is an ibuf bitmap page: mark them used */ xdes_set_bit(descr, XDES_FREE_BIT, 0, FALSE, mtr); xdes_set_bit(descr, XDES_FREE_BIT, FSP_IBUF_BITMAP_OFFSET, FALSE, mtr); xdes_set_state(descr, XDES_FREE_FRAG, mtr); flst_add_last(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, mtr); frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES, mtr); mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used + 2, MLOG_4BYTES, mtr); } else { flst_add_last(header + FSP_FREE, descr + XDES_FLST_NODE, mtr); count++; } i += FSP_EXTENT_SIZE; }} /**************************************************************************Allocates a new free extent. */staticxdes_t*fsp_alloc_free_extent(/*==================*/ /* out: extent descriptor, NULL if cannot be allocated */ ulint space, /* in: space id */ ulint hint, /* in: hint of which extent would be desirable: any page offset in the extent goes; the hint must not be > FSP_FREE_LIMIT */ mtr_t* mtr) /* in: mtr */{ fsp_header_t* header; fil_addr_t first; xdes_t* descr; ut_ad(mtr); header = fsp_get_space_header(space, mtr); descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr); if (descr && (xdes_get_state(descr, mtr) == XDES_FREE)) { /* Ok, we can take this extent */ } else { /* Take the first extent in the free list */ first = flst_get_first(header + FSP_FREE, mtr); if (fil_addr_is_null(first)) { fsp_fill_free_list(FALSE, space, header, mtr); first = flst_get_first(header + FSP_FREE, mtr); } if (fil_addr_is_null(first)) { return(NULL); /* No free extents left */ } descr = xdes_lst_get_descriptor(space, first, mtr); } flst_remove(header + FSP_FREE, descr + XDES_FLST_NODE, mtr); return(descr);}/**************************************************************************Allocates a single free page from a space. The page is marked as used. */staticulintfsp_alloc_free_page(/*================*/ /* out: the page offset, FIL_NULL if no page could be allocated */ ulint space, /* in: space id */ ulint hint, /* in: hint of which page would be desirable */ mtr_t* mtr) /* in: mtr handle */{ fsp_header_t* header; fil_addr_t first; xdes_t* descr; page_t* page; ulint free; ulint frag_n_used; ulint page_no; ulint space_size; ibool success; ut_ad(mtr); header = fsp_get_space_header(space, mtr); /* Get the hinted descriptor */ descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr); if (descr && (xdes_get_state(descr, mtr) == XDES_FREE_FRAG)) { /* Ok, we can take this extent */ } else { /* Else take the first extent in free_frag list */ first = flst_get_first(header + FSP_FREE_FRAG, mtr); if (fil_addr_is_null(first)) { /* There are no partially full fragments: allocate a free extent and add it to the FREE_FRAG list. NOTE that the allocation may have as a side-effect that an
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -