📄 buf0buf.c
字号:
pool if it is found there. */iboolbuf_page_peek_if_search_hashed(/*===========================*/ /* out: TRUE if page hash index is built in search system */ ulint space, /* in: space id */ ulint offset) /* in: page number */{ buf_block_t* block; ibool is_hashed; mutex_enter_fast(&(buf_pool->mutex)); block = buf_page_hash_get(space, offset); if (!block) { is_hashed = FALSE; } else { is_hashed = block->is_hashed; } mutex_exit(&(buf_pool->mutex)); return(is_hashed);}/************************************************************************Returns TRUE if the page can be found in the buffer pool hash table. NOTEthat it is possible that the page is not yet read from disk, though. */iboolbuf_page_peek(/*==========*/ /* out: TRUE if found from page hash table, NOTE that the page is not necessarily yet read from disk! */ ulint space, /* in: space id */ ulint offset) /* in: page number */{ if (buf_page_peek_block(space, offset)) { return(TRUE); } return(FALSE);}/************************************************************************Sets file_page_was_freed TRUE if the page is found in the buffer pool.This function should be called when we free a file page and want thedebug version to check that it is not accessed any more unlessreallocated. */buf_block_t*buf_page_set_file_page_was_freed(/*=============================*/ /* out: control block if found from page hash table, otherwise NULL */ ulint space, /* in: space id */ ulint offset) /* in: page number */{ buf_block_t* block; mutex_enter_fast(&(buf_pool->mutex)); block = buf_page_hash_get(space, offset); if (block) { block->file_page_was_freed = TRUE; } mutex_exit(&(buf_pool->mutex)); return(block);}/************************************************************************Sets file_page_was_freed FALSE if the page is found in the buffer pool.This function should be called when we free a file page and want thedebug version to check that it is not accessed any more unlessreallocated. */buf_block_t*buf_page_reset_file_page_was_freed(/*===============================*/ /* out: control block if found from page hash table, otherwise NULL */ ulint space, /* in: space id */ ulint offset) /* in: page number */{ buf_block_t* block; mutex_enter_fast(&(buf_pool->mutex)); block = buf_page_hash_get(space, offset); if (block) { block->file_page_was_freed = FALSE; } mutex_exit(&(buf_pool->mutex)); return(block);}/************************************************************************This is the general function used to get access to a database page. */buf_frame_t*buf_page_get_gen(/*=============*/ /* out: pointer to the frame or NULL */ ulint space, /* in: space id */ ulint offset, /* in: page number */ ulint rw_latch,/* in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */ buf_frame_t* guess, /* in: guessed frame or NULL */ ulint mode, /* in: BUF_GET, BUF_GET_IF_IN_POOL, BUF_GET_NO_LATCH, BUF_GET_NOWAIT */ const char* file, /* in: file name */ ulint line, /* in: line where called */ mtr_t* mtr) /* in: mini-transaction */{ buf_block_t* block; ibool accessed; ulint fix_type; ibool success; ibool must_read; ut_ad(mtr); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH) || (rw_latch == RW_NO_LATCH)); ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH)); ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL) || (mode == BUF_GET_NO_LATCH) || (mode == BUF_GET_NOWAIT));#ifndef UNIV_LOG_DEBUG ut_ad(!ibuf_inside() || ibuf_page(space, offset));#endif buf_pool->n_page_gets++;loop: mutex_enter_fast(&(buf_pool->mutex)); block = NULL; if (guess) { block = buf_block_align(guess); if ((offset != block->offset) || (space != block->space) || (block->state != BUF_BLOCK_FILE_PAGE)) { block = NULL; } } if (block == NULL) { block = buf_page_hash_get(space, offset); } if (block == NULL) { /* Page not in buf_pool: needs to be read from file */ mutex_exit(&(buf_pool->mutex)); if (mode == BUF_GET_IF_IN_POOL) { return(NULL); } buf_read_page(space, offset);#ifdef UNIV_DEBUG buf_dbg_counter++; if (buf_dbg_counter % 37 == 0) { ut_ad(buf_validate()); }#endif goto loop; } ut_a(block->state == BUF_BLOCK_FILE_PAGE); must_read = FALSE; if (block->io_fix == BUF_IO_READ) { must_read = TRUE; if (mode == BUF_GET_IF_IN_POOL) { /* The page is only being read to buffer */ mutex_exit(&(buf_pool->mutex)); return(NULL); } } /* If AWE is enabled and the page is not mapped to a frame, then map it */ if (block->frame == NULL) { ut_a(srv_use_awe); /* We set second parameter TRUE because the block is in the LRU list and we must put it to awe_LRU_free_mapped list once mapped to a frame */ buf_awe_map_page_to_frame(block, TRUE); } #ifdef UNIV_SYNC_DEBUG buf_block_buf_fix_inc_debug(block, file, line);#else buf_block_buf_fix_inc(block);#endif buf_block_make_young(block); /* Check if this is the first access to the page */ accessed = block->accessed; block->accessed = TRUE;#ifdef UNIV_DEBUG_FILE_ACCESSES ut_a(block->file_page_was_freed == FALSE);#endif mutex_exit(&(buf_pool->mutex));#ifdef UNIV_DEBUG buf_dbg_counter++; if (buf_dbg_counter % 5771 == 0) { ut_ad(buf_validate()); }#endif ut_ad(block->buf_fix_count > 0); ut_ad(block->state == BUF_BLOCK_FILE_PAGE); if (mode == BUF_GET_NOWAIT) { if (rw_latch == RW_S_LATCH) { success = rw_lock_s_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { ut_ad(rw_latch == RW_X_LATCH); success = rw_lock_x_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } if (!success) { mutex_enter(&(buf_pool->mutex)); block->buf_fix_count--;#ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch));#endif mutex_exit(&(buf_pool->mutex)); return(NULL); } } else if (rw_latch == RW_NO_LATCH) { if (must_read) { /* Let us wait until the read operation completes */ for (;;) { mutex_enter(&(buf_pool->mutex)); if (block->io_fix == BUF_IO_READ) { mutex_exit(&(buf_pool->mutex)); /* Sleep 20 milliseconds */ os_thread_sleep(20000); } else { mutex_exit(&(buf_pool->mutex)); break; } } } fix_type = MTR_MEMO_BUF_FIX; } else if (rw_latch == RW_S_LATCH) { rw_lock_s_lock_func(&(block->lock), 0, file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { rw_lock_x_lock_func(&(block->lock), 0, file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } mtr_memo_push(mtr, block, fix_type); if (!accessed) { /* In the case of a first access, try to apply linear read-ahead */ buf_read_ahead_linear(space, offset); }#ifdef UNIV_IBUF_DEBUG ut_a(ibuf_count_get(block->space, block->offset) == 0);#endif return(block->frame); }/************************************************************************This is the general function used to get optimistic access to a databasepage. */iboolbuf_page_optimistic_get_func(/*=========================*/ /* out: TRUE if success */ ulint rw_latch,/* in: RW_S_LATCH, RW_X_LATCH */ buf_block_t* block, /* in: guessed buffer block */ buf_frame_t* guess, /* in: guessed frame; note that AWE may move frames */ dulint modify_clock,/* in: modify clock value if mode is ..._GUESS_ON_CLOCK */ const char* file, /* in: file name */ ulint line, /* in: line where called */ mtr_t* mtr) /* in: mini-transaction */{ ibool accessed; ibool success; ulint fix_type; ut_ad(mtr && block); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); mutex_enter(&(buf_pool->mutex)); /* If AWE is used, block may have a different frame now, e.g., NULL */ if (UNIV_UNLIKELY(block->state != BUF_BLOCK_FILE_PAGE) || UNIV_UNLIKELY(block->frame != guess)) { exit_func: mutex_exit(&(buf_pool->mutex)); return(FALSE); }#ifdef UNIV_SYNC_DEBUG buf_block_buf_fix_inc_debug(block, file, line);#else buf_block_buf_fix_inc(block);#endif buf_block_make_young(block); /* Check if this is the first access to the page */ accessed = block->accessed; block->accessed = TRUE; mutex_exit(&(buf_pool->mutex)); ut_ad(!ibuf_inside() || ibuf_page(block->space, block->offset)); if (rw_latch == RW_S_LATCH) { success = rw_lock_s_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { success = rw_lock_x_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } if (UNIV_UNLIKELY(!success)) { mutex_enter(&(buf_pool->mutex)); block->buf_fix_count--;#ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch));#endif goto exit_func; } if (UNIV_UNLIKELY(!UT_DULINT_EQ(modify_clock, block->modify_clock))) {#ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(block->frame, SYNC_NO_ORDER_CHECK);#endif /* UNIV_SYNC_DEBUG */ if (rw_latch == RW_S_LATCH) { rw_lock_s_unlock(&(block->lock)); } else { rw_lock_x_unlock(&(block->lock)); } mutex_enter(&(buf_pool->mutex)); block->buf_fix_count--;#ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch));#endif goto exit_func; } mtr_memo_push(mtr, block, fix_type);#ifdef UNIV_DEBUG buf_dbg_counter++; if (buf_dbg_counter % 5771 == 0) { ut_ad(buf_validate()); }#endif ut_ad(block->buf_fix_count > 0); ut_ad(block->state == BUF_BLOCK_FILE_PAGE);#ifdef UNIV_DEBUG_FILE_ACCESSES ut_a(block->file_page_was_freed == FALSE);#endif if (UNIV_UNLIKELY(!accessed)) { /* In the case of a first access, try to apply linear read-ahead */ buf_read_ahead_linear(buf_frame_get_space_id(guess), buf_frame_get_page_no(guess)); }#ifdef UNIV_IBUF_DEBUG ut_a(ibuf_count_get(block->space, block->offset) == 0);#endif buf_pool->n_page_gets++; return(TRUE);}/************************************************************************This is used to get access to a known database page, when no waiting can bedone. For example, if a search in an adaptive hash index leads us to thisframe. */iboolbuf_page_get_known_nowait(/*======================*/ /* out: TRUE if success */ ulint rw_latch,/* in: RW_S_LATCH, RW_X_LATCH */ buf_frame_t* guess, /* in: the known page frame */ ulint mode, /* in: BUF_MAKE_YOUNG or BUF_KEEP_OLD */ const char* file, /* in: file name */ ulint line, /* in: line where called */ mtr_t* mtr) /* in: mini-transaction */{ buf_block_t* block; ibool success; ulint fix_type; ut_ad(mtr); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); mutex_enter(&(buf_pool->mutex)); block = buf_block_align(guess); if (block->state == BUF_BLOCK_REMOVE_HASH) { /* Another thread is just freeing the block from the LRU list of the buffer pool: do not try to access this page; this attempt to access the page can only come through the hash index because when the buffer block state is ..._REMOVE_HASH, we have already removed it from the page address hash table of the buffer pool. */ mutex_exit(&(buf_pool->mutex));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -