📄 buf0lru.c
字号:
} else if (old_len > new_len + BUF_LRU_OLD_TOLERANCE) { (buf_pool->LRU_old)->old = FALSE; buf_pool->LRU_old = UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old); buf_pool->LRU_old_len--; } else { ut_a(buf_pool->LRU_old); /* Check that we did not fall out of the LRU list */ return; } }}/***********************************************************************Initializes the old blocks pointer in the LRU list. This function should becalled when the LRU list grows to BUF_LRU_OLD_MIN_LEN length. */staticvoidbuf_LRU_old_init(void)/*==================*/{ buf_block_t* block; ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN); /* We first initialize all blocks in the LRU list as old and then use the adjust function to move the LRU_old pointer to the right position */ block = UT_LIST_GET_FIRST(buf_pool->LRU); while (block != NULL) { ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->in_LRU_list); block->old = TRUE; block = UT_LIST_GET_NEXT(LRU, block); } buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU); buf_pool->LRU_old_len = UT_LIST_GET_LEN(buf_pool->LRU); buf_LRU_old_adjust_len();} /**********************************************************************Removes a block from the LRU list. */UNIV_INLINEvoidbuf_LRU_remove_block(/*=================*/ buf_block_t* block) /* in: control block */{ ut_ad(buf_pool); ut_ad(block);#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex)));#endif /* UNIV_SYNC_DEBUG */ ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->in_LRU_list); /* If the LRU_old pointer is defined and points to just this block, move it backward one step */ if (block == buf_pool->LRU_old) { /* Below: the previous block is guaranteed to exist, because the LRU_old pointer is only allowed to differ by the tolerance value from strict 3/8 of the LRU list length. */ buf_pool->LRU_old = UT_LIST_GET_PREV(LRU, block); (buf_pool->LRU_old)->old = TRUE; buf_pool->LRU_old_len++; ut_a(buf_pool->LRU_old); } /* Remove the block from the LRU list */ UT_LIST_REMOVE(LRU, buf_pool->LRU, block); block->in_LRU_list = FALSE; if (srv_use_awe && block->frame) { /* Remove from the list of mapped pages */ UT_LIST_REMOVE(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } /* If the LRU list is so short that LRU_old not defined, return */ if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) { buf_pool->LRU_old = NULL; return; } ut_ad(buf_pool->LRU_old); /* Update the LRU_old_len field if necessary */ if (block->old) { buf_pool->LRU_old_len--; } /* Adjust the length of the old block list if necessary */ buf_LRU_old_adjust_len();} /**********************************************************************Adds a block to the LRU list end. */UNIV_INLINEvoidbuf_LRU_add_block_to_end_low(/*=========================*/ buf_block_t* block) /* in: control block */{ buf_block_t* last_block; ut_ad(buf_pool); ut_ad(block);#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex)));#endif /* UNIV_SYNC_DEBUG */ ut_a(block->state == BUF_BLOCK_FILE_PAGE); block->old = TRUE; last_block = UT_LIST_GET_LAST(buf_pool->LRU); if (last_block) { block->LRU_position = last_block->LRU_position; } else { block->LRU_position = buf_pool_clock_tic(); } ut_a(!block->in_LRU_list); UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block); block->in_LRU_list = TRUE; if (srv_use_awe && block->frame) { /* Add to the list of mapped pages */ UT_LIST_ADD_LAST(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) { buf_pool->LRU_old_len++; } if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) { ut_ad(buf_pool->LRU_old); /* Adjust the length of the old block list if necessary */ buf_LRU_old_adjust_len(); } else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) { /* The LRU list is now long enough for LRU_old to become defined: init it */ buf_LRU_old_init(); }} /**********************************************************************Adds a block to the LRU list. */UNIV_INLINEvoidbuf_LRU_add_block_low(/*==================*/ buf_block_t* block, /* in: control block */ ibool old) /* in: TRUE if should be put to the old blocks in the LRU list, else put to the start; if the LRU list is very short, the block is added to the start, regardless of this parameter */{ ulint cl; ut_ad(buf_pool); ut_ad(block);#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex)));#endif /* UNIV_SYNC_DEBUG */ ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(!block->in_LRU_list); block->old = old; cl = buf_pool_clock_tic(); if (srv_use_awe && block->frame) { /* Add to the list of mapped pages; for simplicity we always add to the start, even if the user would have set 'old' TRUE */ UT_LIST_ADD_FIRST(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } if (!old || (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN)) { UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, block); block->LRU_position = cl; block->freed_page_clock = buf_pool->freed_page_clock; } else { UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU, buf_pool->LRU_old, block); buf_pool->LRU_old_len++; /* We copy the LRU position field of the previous block to the new block */ block->LRU_position = (buf_pool->LRU_old)->LRU_position; } block->in_LRU_list = TRUE; if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) { ut_ad(buf_pool->LRU_old); /* Adjust the length of the old block list if necessary */ buf_LRU_old_adjust_len(); } else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) { /* The LRU list is now long enough for LRU_old to become defined: init it */ buf_LRU_old_init(); } } /**********************************************************************Adds a block to the LRU list. */voidbuf_LRU_add_block(/*==============*/ buf_block_t* block, /* in: control block */ ibool old) /* in: TRUE if should be put to the old blocks in the LRU list, else put to the start; if the LRU list is very short, the block is added to the start, regardless of this parameter */{ buf_LRU_add_block_low(block, old);}/**********************************************************************Moves a block to the start of the LRU list. */voidbuf_LRU_make_block_young(/*=====================*/ buf_block_t* block) /* in: control block */{ buf_LRU_remove_block(block); buf_LRU_add_block_low(block, FALSE);}/**********************************************************************Moves a block to the end of the LRU list. */voidbuf_LRU_make_block_old(/*===================*/ buf_block_t* block) /* in: control block */{ buf_LRU_remove_block(block); buf_LRU_add_block_to_end_low(block);}/**********************************************************************Puts a block back to the free list. */voidbuf_LRU_block_free_non_file_page(/*=============================*/ buf_block_t* block) /* in: block, must not contain a file page */{#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex)));#endif /* UNIV_SYNC_DEBUG */ ut_ad(block); ut_a((block->state == BUF_BLOCK_MEMORY) || (block->state == BUF_BLOCK_READY_FOR_USE)); ut_a(block->n_pointers == 0); ut_a(!block->in_free_list); block->state = BUF_BLOCK_NOT_USED;#ifdef UNIV_DEBUG /* Wipe contents of page to reveal possible stale pointers to it */ memset(block->frame, '\0', UNIV_PAGE_SIZE);#endif UT_LIST_ADD_FIRST(free, buf_pool->free, block); block->in_free_list = TRUE; if (srv_use_awe && block->frame) { /* Add to the list of mapped pages */ UT_LIST_ADD_FIRST(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); }}/**********************************************************************Takes a block out of the LRU list and page hash table and sets the blockstate to BUF_BLOCK_REMOVE_HASH. */staticvoidbuf_LRU_block_remove_hashed_page(/*=============================*/ buf_block_t* block) /* 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 */{#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex)));#endif /* UNIV_SYNC_DEBUG */ ut_ad(block); ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->io_fix == 0); ut_a(block->buf_fix_count == 0); ut_a(ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) == 0); buf_LRU_remove_block(block); buf_pool->freed_page_clock += 1; /* Note that if AWE is enabled the block may not have a frame at all */ buf_block_modify_clock_inc(block); if (block != buf_page_hash_get(block->space, block->offset)) { fprintf(stderr,"InnoDB: Error: page %lu %lu not found from the hash table\n", (ulong) block->space, (ulong) block->offset); if (buf_page_hash_get(block->space, block->offset)) { fprintf(stderr,"InnoDB: From hash table we find block %p of %lu %lu which is not %p\n", buf_page_hash_get(block->space, block->offset), (ulong) buf_page_hash_get(block->space, block->offset)->space, (ulong) buf_page_hash_get(block->space, block->offset)->offset, block); }#ifdef UNIV_DEBUG buf_print(); buf_LRU_print(); buf_validate(); buf_LRU_validate();#endif ut_a(0); } HASH_DELETE(buf_block_t, hash, buf_pool->page_hash, buf_page_address_fold(block->space, block->offset), block); block->state = BUF_BLOCK_REMOVE_HASH;}/**********************************************************************Puts a file page whose has no hash index to the free list. */staticvoidbuf_LRU_block_free_hashed_page(/*===========================*/ buf_block_t* block) /* in: block, must contain a file page and be in a state where it can be freed */{#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex)));#endif /* UNIV_SYNC_DEBUG */ ut_a(block->state == BUF_BLOCK_REMOVE_HASH); block->state = BUF_BLOCK_MEMORY; buf_LRU_block_free_non_file_page(block);}#ifdef UNIV_DEBUG/**************************************************************************Validates the LRU list. */iboolbuf_LRU_validate(void)/*==================*/{ buf_block_t* block; ulint old_len; ulint new_len; ulint LRU_pos; ut_ad(buf_pool); mutex_enter(&(buf_pool->mutex)); if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) { ut_a(buf_pool->LRU_old); old_len = buf_pool->LRU_old_len; new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8); ut_a(old_len >= new_len - BUF_LRU_OLD_TOLERANCE); ut_a(old_len <= new_len + BUF_LRU_OLD_TOLERANCE); } UT_LIST_VALIDATE(LRU, buf_block_t, buf_pool->LRU); block = UT_LIST_GET_FIRST(buf_pool->LRU); old_len = 0; while (block != NULL) { ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (block->old) { old_len++; } if (buf_pool->LRU_old && (old_len == 1)) { ut_a(buf_pool->LRU_old == block); } LRU_pos = block->LRU_position; block = UT_LIST_GET_NEXT(LRU, block); if (block) { /* If the following assert fails, it may not be an error: just the buf_pool clock has wrapped around */ ut_a(LRU_pos >= block->LRU_position); } } if (buf_pool->LRU_old) { ut_a(buf_pool->LRU_old_len == old_len); } UT_LIST_VALIDATE(free, buf_block_t, buf_pool->free); block = UT_LIST_GET_FIRST(buf_pool->free); while (block != NULL) { ut_a(block->state == BUF_BLOCK_NOT_USED); block = UT_LIST_GET_NEXT(free, block); } mutex_exit(&(buf_pool->mutex)); return(TRUE);}/**************************************************************************Prints the LRU list. */voidbuf_LRU_print(void)/*===============*/{ buf_block_t* block; buf_frame_t* frame; ulint len; ut_ad(buf_pool); mutex_enter(&(buf_pool->mutex)); fprintf(stderr, "Pool ulint clock %lu\n", (ulong) buf_pool->ulint_clock); block = UT_LIST_GET_FIRST(buf_pool->LRU); len = 0; while (block != NULL) { fprintf(stderr, "BLOCK %lu ", (ulong) block->offset); if (block->old) { fputs("old ", stderr); } if (block->buf_fix_count) { fprintf(stderr, "buffix count %lu ", (ulong) block->buf_fix_count); } if (block->io_fix) { fprintf(stderr, "io_fix %lu ", (ulong) block->io_fix); } if (ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0) { fputs("modif. ", stderr); } frame = buf_block_get_frame(block); fprintf(stderr, "LRU pos %lu type %lu index id %lu ", (ulong) block->LRU_position, (ulong) fil_page_get_type(frame), (ulong) ut_dulint_get_low(btr_page_get_index_id(frame))); block = UT_LIST_GET_NEXT(LRU, block); if (++len == 10) { len = 0; putc('\n', stderr); } } mutex_exit(&(buf_pool->mutex));}#endif /* UNIV_DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -