/********************************************************************//** Initializes a page to the buffer buf_pool. The page is usually not read from a file even if it cannot be found in the buffer buf_pool. This is one of the functions which perform to a block a state transition NOT_USED => FILE_PAGE (the other is buf_page_get_gen). @return pointer to the block, page bufferfixed */ UNIV_INTERN buf_block_t* buf_page_create( /*============*/ ulint space, /*!< in: space id */ ulint offset, /*!< in: offset of the page within space in units of a page */ ulint zip_size,/*!< in: compressed page size, or 0 */ mtr_t* mtr) /*!< in: mini-transaction handle */ { buf_frame_t* frame; buf_block_t* block; ulint fold; buf_block_t* free_block = NULL; buf_pool_t* buf_pool = buf_pool_get(space, offset); ut_ad(mtr); ut_ad(mtr->state == MTR_ACTIVE); ut_ad(space || !zip_size); free_block = buf_LRU_get_free_block(buf_pool); //这里 fold = buf_page_address_fold(space, offset); buf_pool_mutex_enter(buf_pool); block = (buf_block_t*) buf_page_hash_get_low( buf_pool, space, offset, fold); if (block && buf_page_in_file(&block->page) && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) { #ifdef UNIV_IBUF_COUNT_DEBUG ut_a(ibuf_count_get(space, offset) == 0); #endif #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG block->page.file_page_was_freed = FALSE; #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ /* Page can be found in buf_pool */ buf_pool_mutex_exit(buf_pool); buf_block_free(free_block); return(buf_page_get_with_no_latch(space, zip_size, offset, mtr)); } /* If we get here, the page was not in buf_pool: init it there */ #ifdef UNIV_DEBUG if (buf_debug_prints) { fprintf(stderr, "Creating space %lu page %lu to buffer\n", (ulong) space, (ulong) offset); } #endif /* UNIV_DEBUG */ block = free_block; mutex_enter(&block->mutex); buf_page_init(buf_pool, space, offset, fold, zip_size, block); /* The block must be put to the LRU list */ buf_LRU_add_block(&block->page, FALSE); buf_block_buf_fix_inc(block, __FILE__, __LINE__); buf_pool->stat.n_pages_created++; if (zip_size) { void* data; ibool lru; /* Prevent race conditions during buf_buddy_alloc(), which may release and reacquire buf_pool->mutex, by IO-fixing and X-latching the block. */ buf_page_set_io_fix(&block->page, BUF_IO_READ); rw_lock_x_lock(&block->lock); mutex_exit(&block->mutex); /* buf_pool->mutex may be released and reacquired by buf_buddy_alloc(). Thus, we must release block->mutex in order not to break the latching order in the reacquisition of buf_pool->mutex. We also must defer this operation until after the block descriptor has been added to buf_pool->LRU and buf_pool->page_hash. */ data = buf_buddy_alloc(buf_pool, zip_size, &lru); mutex_enter(&block->mutex); block->page.zip.data = data; /* To maintain the invariant block->in_unzip_LRU_list == buf_page_belongs_to_unzip_LRU(&block->page) we have to add this block to unzip_LRU after block->page.zip.data is set. */ ut_ad(buf_page_belongs_to_unzip_LRU(&block->page)); buf_unzip_LRU_add_block(block, FALSE); buf_page_set_io_fix(&block->page, BUF_IO_NONE); rw_lock_x_unlock(&block->lock); } buf_pool_mutex_exit(buf_pool); mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX); buf_page_set_accessed(&block->page); mutex_exit(&block->mutex); /* Delete possible entries for the page from the insert buffer: such can exist if the page belonged to an index which was dropped */ ibuf_merge_or_delete_for_page(NULL, space, offset, zip_size, TRUE); /* Flush pages from the end of the LRU list if necessary */ buf_flush_free_margin(buf_pool); frame = block->frame; memset(frame + FIL_PAGE_PREV, 0xff, 4); memset(frame + FIL_PAGE_NEXT, 0xff, 4); mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED); /* Reset to zero the file flush lsn field in the page; if the first page of an ibdata file is ‘created‘ in this function into the buffer pool then we lose the original contents of the file flush lsn stamp. Then InnoDB could in a crash recovery print a big, false, corruption warning if the stamp contains an lsn bigger than the ib_logfile lsn. */ memset(frame + FIL_PAGE_FILE_FLUSH_LSN, 0, 8); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG ut_a(++buf_dbg_counter % 5771 || buf_validate()); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #ifdef UNIV_IBUF_COUNT_DEBUG ut_a(ibuf_count_get(buf_block_get_space(block), buf_block_get_page_no(block)) == 0); #endif return(block); }
时间: 2024-10-05 04:00:27