/******************************************************************//** Takes a block out of the LRU list and page hash table. If the block is compressed-only (BUF_BLOCK_ZIP_PAGE), the object will be freed and buf_pool->zip_mutex will be released. If a compressed page or a compressed-only block descriptor is freed, other compressed pages or compressed-only block descriptors may be relocated. @return the new state of the block (BUF_BLOCK_ZIP_FREE if the state was BUF_BLOCK_ZIP_PAGE, or BUF_BLOCK_REMOVE_HASH otherwise) */ static enum buf_page_state buf_LRU_block_remove_hashed_page( /*=============================*/ buf_page_t* bpage, /*!< in: block, must contain a file page and be in a state where it can be freed; there may or may not be a hash index to the page */ ibool zip) /*!< in: TRUE if should remove also the compressed page of an uncompressed page */ { ulint fold; const buf_page_t* hashed_bpage; buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); ut_ad(bpage); ut_ad(buf_pool_mutex_own(buf_pool)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE); ut_a(bpage->buf_fix_count == 0); #if UNIV_WORD_SIZE == 4 /* On 32-bit systems, there is no padding in buf_page_t. On other systems, Valgrind could complain about uninitialized pad bytes. */ UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage); #endif buf_LRU_remove_block(bpage); buf_pool->freed_page_clock += 1; switch (buf_page_get_state(bpage)) { case BUF_BLOCK_FILE_PAGE: UNIV_MEM_ASSERT_W(bpage, sizeof(buf_block_t)); UNIV_MEM_ASSERT_W(((buf_block_t*) bpage)->frame, UNIV_PAGE_SIZE); buf_block_modify_clock_inc((buf_block_t*) bpage); if (bpage->zip.data) { const page_t* page = ((buf_block_t*) bpage)->frame; const ulint zip_size = page_zip_get_size(&bpage->zip); ut_a(!zip || bpage->oldest_modification == 0); switch (UNIV_EXPECT(fil_page_get_type(page), FIL_PAGE_INDEX)) { case FIL_PAGE_TYPE_ALLOCATED: case FIL_PAGE_INODE: case FIL_PAGE_IBUF_BITMAP: case FIL_PAGE_TYPE_FSP_HDR: case FIL_PAGE_TYPE_XDES: /* These are essentially uncompressed pages. */ if (!zip) { /* InnoDB writes the data to the uncompressed page frame. Copy it to the compressed page, which will be preserved. */ memcpy(bpage->zip.data, page, zip_size); } break; case FIL_PAGE_TYPE_ZBLOB: case FIL_PAGE_TYPE_ZBLOB2: break; case FIL_PAGE_INDEX: #ifdef UNIV_ZIP_DEBUG ut_a(page_zip_validate( &bpage->zip, page, ((buf_block_t*) bpage)->index)); #endif /* UNIV_ZIP_DEBUG */ break; default: ut_print_timestamp(stderr); fputs(" InnoDB: ERROR: The compressed page" " to be evicted seems corrupt:", stderr); ut_print_buf(stderr, page, zip_size); fputs("\nInnoDB: Possibly older version" " of the page:", stderr); ut_print_buf(stderr, bpage->zip.data, zip_size); putc(‘\n‘, stderr); ut_error; } break; } /* fall through */ case BUF_BLOCK_ZIP_PAGE: ut_a(bpage->oldest_modification == 0); UNIV_MEM_ASSERT_W(bpage->zip.data, page_zip_get_size(&bpage->zip)); break; case BUF_BLOCK_ZIP_FREE: case BUF_BLOCK_ZIP_DIRTY: case BUF_BLOCK_NOT_USED: case BUF_BLOCK_READY_FOR_USE: case BUF_BLOCK_MEMORY: case BUF_BLOCK_REMOVE_HASH: ut_error; break; } fold = buf_page_address_fold(bpage->space, bpage->offset); hashed_bpage = buf_page_hash_get_low( buf_pool, bpage->space, bpage->offset, fold); if (UNIV_UNLIKELY(bpage != hashed_bpage)) { fprintf(stderr, "InnoDB: Error: page %lu %lu not found" " in the hash table\n", (ulong) bpage->space, (ulong) bpage->offset); if (hashed_bpage) { fprintf(stderr, "InnoDB: In hash table we find block" " %p of %lu %lu which is not %p\n", (const void*) hashed_bpage, (ulong) hashed_bpage->space, (ulong) hashed_bpage->offset, (const void*) bpage); } #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG mutex_exit(buf_page_get_mutex(bpage)); buf_pool_mutex_exit(buf_pool); buf_print(); buf_LRU_print(); buf_validate(); buf_LRU_validate(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ ut_error; } ut_ad(!bpage->in_zip_hash); ut_ad(bpage->in_page_hash); ut_d(bpage->in_page_hash = FALSE); HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage); //这里 switch (buf_page_get_state(bpage)) { case BUF_BLOCK_ZIP_PAGE: ut_ad(!bpage->in_free_list); ut_ad(!bpage->in_flush_list); ut_ad(!bpage->in_LRU_list); ut_a(bpage->zip.data); ut_a(buf_page_get_zip_size(bpage)); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ mutex_exit(&buf_pool->zip_mutex); buf_pool_mutex_exit_forbid(buf_pool); buf_buddy_free( buf_pool, bpage->zip.data, page_zip_get_size(&bpage->zip)); buf_pool_mutex_exit_allow(buf_pool); buf_page_free_descriptor(bpage); return(BUF_BLOCK_ZIP_FREE); case BUF_BLOCK_FILE_PAGE: memset(((buf_block_t*) bpage)->frame + FIL_PAGE_OFFSET, 0xff, 4); memset(((buf_block_t*) bpage)->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xff, 4); UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame, UNIV_PAGE_SIZE); buf_page_set_state(bpage, BUF_BLOCK_REMOVE_HASH); if (zip && bpage->zip.data) { /* Free the compressed page. */ void* data = bpage->zip.data; bpage->zip.data = NULL; ut_ad(!bpage->in_free_list); ut_ad(!bpage->in_flush_list); ut_ad(!bpage->in_LRU_list); mutex_exit(&((buf_block_t*) bpage)->mutex); buf_pool_mutex_exit_forbid(buf_pool); buf_buddy_free( buf_pool, data, page_zip_get_size(&bpage->zip)); buf_pool_mutex_exit_allow(buf_pool); mutex_enter(&((buf_block_t*) bpage)->mutex); page_zip_set_size(&bpage->zip, 0); } return(BUF_BLOCK_REMOVE_HASH); case BUF_BLOCK_ZIP_FREE: case BUF_BLOCK_ZIP_DIRTY: case BUF_BLOCK_NOT_USED: case BUF_BLOCK_READY_FOR_USE: case BUF_BLOCK_MEMORY: case BUF_BLOCK_REMOVE_HASH: break; } ut_error; return(BUF_BLOCK_ZIP_FREE); }
时间: 2024-11-03 21:38:15