📄 buf0buf.c
字号:
block->modify_clock = ut_dulint_zero; block->file_page_was_freed = FALSE; block->check_index_page_at_flush = FALSE; block->index = NULL; block->in_free_list = FALSE; block->in_LRU_list = FALSE; block->n_pointers = 0; rw_lock_create(&(block->lock)); ut_ad(rw_lock_validate(&(block->lock)));#ifdef UNIV_SYNC_DEBUG rw_lock_create(&(block->debug_latch)); rw_lock_set_level(&(block->debug_latch), SYNC_NO_ORDER_CHECK);#endif /* UNIV_SYNC_DEBUG */}/************************************************************************Creates the buffer pool. */buf_pool_t*buf_pool_init(/*==========*/ /* out, own: buf_pool object, NULL if not enough memory or error */ ulint max_size, /* in: maximum size of the buf_pool in blocks */ ulint curr_size, /* in: current size to use, must be <= max_size, currently must be equal to max_size */ ulint n_frames) /* in: number of frames; if AWE is used, this is the size of the address space window where physical memory pages are mapped; if AWE is not used then this must be the same as max_size */{ byte* frame; ulint i; buf_block_t* block; ut_a(max_size == curr_size); ut_a(srv_use_awe || n_frames == max_size); if (n_frames > curr_size) { fprintf(stderr,"InnoDB: AWE: Error: you must specify in my.cnf .._awe_mem_mb larger\n""InnoDB: than .._buffer_pool_size. Now the former is %lu pages,\n""InnoDB: the latter %lu pages.\n", (ulong) curr_size, (ulong) n_frames); return(NULL); } buf_pool = mem_alloc(sizeof(buf_pool_t)); /* 1. Initialize general fields ---------------------------- */ mutex_create(&(buf_pool->mutex)); mutex_set_level(&(buf_pool->mutex), SYNC_BUF_POOL); mutex_enter(&(buf_pool->mutex)); if (srv_use_awe) { /*----------------------------------------*/ /* Allocate the virtual address space window, i.e., the buffer pool frames */ buf_pool->frame_mem = os_awe_allocate_virtual_mem_window( UNIV_PAGE_SIZE * (n_frames + 1)); /* Allocate the physical memory for AWE and the AWE info array for buf_pool */ if ((curr_size % ((1024 * 1024) / UNIV_PAGE_SIZE)) != 0) { fprintf(stderr,"InnoDB: AWE: Error: physical memory must be allocated in full megabytes.\n""InnoDB: Trying to allocate %lu database pages.\n", (ulong) curr_size); return(NULL); } if (!os_awe_allocate_physical_mem(&(buf_pool->awe_info), curr_size / ((1024 * 1024) / UNIV_PAGE_SIZE))) { return(NULL); } /*----------------------------------------*/ } else { buf_pool->frame_mem = os_mem_alloc_large( UNIV_PAGE_SIZE * (n_frames + 1), TRUE, FALSE); } if (buf_pool->frame_mem == NULL) { return(NULL); } buf_pool->blocks = ut_malloc(sizeof(buf_block_t) * max_size); if (buf_pool->blocks == NULL) { return(NULL); } buf_pool->max_size = max_size; buf_pool->curr_size = curr_size; buf_pool->n_frames = n_frames; /* Align pointer to the first frame */ frame = ut_align(buf_pool->frame_mem, UNIV_PAGE_SIZE); buf_pool->frame_zero = frame; buf_pool->high_end = frame + UNIV_PAGE_SIZE * n_frames; if (srv_use_awe) { /*----------------------------------------*/ /* Map an initial part of the allocated physical memory to the window */ os_awe_map_physical_mem_to_window(buf_pool->frame_zero, n_frames * (UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE), buf_pool->awe_info); /*----------------------------------------*/ } buf_pool->blocks_of_frames = ut_malloc(sizeof(void*) * n_frames); if (buf_pool->blocks_of_frames == NULL) { return(NULL); } /* Init block structs and assign frames for them; in the case of AWE there are less frames than blocks. Then we assign the frames to the first blocks (we already mapped the memory above). We also init the awe_info for every block. */ for (i = 0; i < max_size; i++) { block = buf_pool_get_nth_block(buf_pool, i); if (i < n_frames) { frame = buf_pool->frame_zero + i * UNIV_PAGE_SIZE; *(buf_pool->blocks_of_frames + i) = block; } else { frame = NULL; } buf_block_init(block, frame); if (srv_use_awe) { /*----------------------------------------*/ block->awe_info = buf_pool->awe_info + i * (UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE); /*----------------------------------------*/ } } buf_pool->page_hash = hash_create(2 * max_size); buf_pool->n_pend_reads = 0; buf_pool->last_printout_time = time(NULL); buf_pool->n_pages_read = 0; buf_pool->n_pages_written = 0; buf_pool->n_pages_created = 0; buf_pool->n_pages_awe_remapped = 0; buf_pool->n_page_gets = 0; buf_pool->n_page_gets_old = 0; buf_pool->n_pages_read_old = 0; buf_pool->n_pages_written_old = 0; buf_pool->n_pages_created_old = 0; buf_pool->n_pages_awe_remapped_old = 0; /* 2. Initialize flushing fields ---------------------------- */ UT_LIST_INIT(buf_pool->flush_list); for (i = BUF_FLUSH_LRU; i <= BUF_FLUSH_LIST; i++) { buf_pool->n_flush[i] = 0; buf_pool->init_flush[i] = FALSE; buf_pool->no_flush[i] = os_event_create(NULL); } buf_pool->LRU_flush_ended = 0; buf_pool->ulint_clock = 1; buf_pool->freed_page_clock = 0; /* 3. Initialize LRU fields ---------------------------- */ UT_LIST_INIT(buf_pool->LRU); buf_pool->LRU_old = NULL; UT_LIST_INIT(buf_pool->awe_LRU_free_mapped); /* Add control blocks to the free list */ UT_LIST_INIT(buf_pool->free); for (i = 0; i < curr_size; i++) { block = buf_pool_get_nth_block(buf_pool, i); if (block->frame) { /* Wipe contents of frame to eliminate a Purify warning */#ifdef HAVE_purify memset(block->frame, '\0', UNIV_PAGE_SIZE);#endif if (srv_use_awe) { /* Add to the list of blocks mapped to frames */ UT_LIST_ADD_LAST(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } } UT_LIST_ADD_LAST(free, buf_pool->free, block); block->in_free_list = TRUE; } mutex_exit(&(buf_pool->mutex)); if (srv_use_adaptive_hash_indexes) { btr_search_sys_create( curr_size * UNIV_PAGE_SIZE / sizeof(void*) / 64); } else { /* Create only a small dummy system */ btr_search_sys_create(1000); } return(buf_pool);} /************************************************************************Maps the page of block to a frame, if not mapped yet. Unmaps some pagefrom the end of the awe_LRU_free_mapped. */voidbuf_awe_map_page_to_frame(/*======================*/ buf_block_t* block, /* in: block whose page should be mapped to a frame */ ibool add_to_mapped_list) /* in: TRUE if we in the case we need to map the page should also add the block to the awe_LRU_free_mapped list */{ buf_block_t* bck;#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex)));#endif /* UNIV_SYNC_DEBUG */ ut_ad(block); if (block->frame) { return; } /* Scan awe_LRU_free_mapped from the end and try to find a block which is not bufferfixed or io-fixed */ bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped); while (bck) { if (bck->state == BUF_BLOCK_FILE_PAGE && (bck->buf_fix_count != 0 || bck->io_fix != 0)) { /* We have to skip this */ bck = UT_LIST_GET_PREV(awe_LRU_free_mapped, bck); } else { /* We can map block to the frame of bck */ os_awe_map_physical_mem_to_window( bck->frame, UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE, block->awe_info); block->frame = bck->frame; *(buf_pool->blocks_of_frames + (((ulint)(block->frame - buf_pool->frame_zero)) >> UNIV_PAGE_SIZE_SHIFT)) = block; bck->frame = NULL; UT_LIST_REMOVE(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, bck); if (add_to_mapped_list) { UT_LIST_ADD_FIRST(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } buf_pool->n_pages_awe_remapped++; return; } } fprintf(stderr,"InnoDB: AWE: Fatal error: cannot find a page to unmap\n""InnoDB: awe_LRU_free_mapped list length %lu\n", (ulong) UT_LIST_GET_LEN(buf_pool->awe_LRU_free_mapped)); ut_a(0);}/************************************************************************Allocates a buffer block. */UNIV_INLINEbuf_block_t*buf_block_alloc(void)/*=================*/ /* out, own: the allocated block; also if AWE is used it is guaranteed that the page is mapped to a frame */{ buf_block_t* block; block = buf_LRU_get_free_block(); return(block);}/************************************************************************Moves to the block to the start of the LRU list if there is a dangerthat the block would drift out of the buffer pool. */UNIV_INLINEvoidbuf_block_make_young(/*=================*/ buf_block_t* block) /* in: block to make younger */{ if (buf_pool->freed_page_clock >= block->freed_page_clock + 1 + (buf_pool->curr_size / 1024)) { /* There has been freeing activity in the LRU list: best to move to the head of the LRU list */ buf_LRU_make_block_young(block); }}/************************************************************************Moves a page to the start of the buffer pool LRU list. This high-levelfunction can be used to prevent an important page from from slipping out ofthe buffer pool. */voidbuf_page_make_young(/*=================*/ buf_frame_t* frame) /* in: buffer frame of a file page */{ buf_block_t* block; mutex_enter(&(buf_pool->mutex)); block = buf_block_align(frame); ut_a(block->state == BUF_BLOCK_FILE_PAGE); buf_LRU_make_block_young(block); mutex_exit(&(buf_pool->mutex));}/************************************************************************Frees a buffer block which does not contain a file page. */UNIV_INLINEvoidbuf_block_free(/*===========*/ buf_block_t* block) /* in, own: block to be freed */{ ut_a(block->state != BUF_BLOCK_FILE_PAGE); mutex_enter(&(buf_pool->mutex)); buf_LRU_block_free_non_file_page(block); mutex_exit(&(buf_pool->mutex));}/*************************************************************************Allocates a buffer frame. */buf_frame_t*buf_frame_alloc(void)/*=================*/ /* out: buffer frame */{ return(buf_block_alloc()->frame);}/*************************************************************************Frees a buffer frame which does not contain a file page. */voidbuf_frame_free(/*===========*/ buf_frame_t* frame) /* in: buffer frame */{ buf_block_free(buf_block_align(frame));} /************************************************************************Returns the buffer control block if the page can be found in the bufferpool. NOTE that it is possible that the page is not yet readfrom disk, though. This is a very low-level function: use with care! */buf_block_t*buf_page_peek_block(/*================*/ /* out: control block if found from page hash table, otherwise NULL; NOTE that the page is not necessarily yet read from disk! */ 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); mutex_exit(&(buf_pool->mutex)); return(block);}/************************************************************************Resets the check_index_page_at_flush field of a page if found in the bufferpool. */voidbuf_reset_check_index_page_at_flush(/*================================*/ 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->check_index_page_at_flush = FALSE; } mutex_exit(&(buf_pool->mutex));}/************************************************************************Returns the current state of is_hashed of a page. FALSE if the page isnot in the pool. NOTE that this operation does not fix the page in the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -